Beispiel #1
0
def evaInit(args):  # {{{
    '''Read in EVC and VCD to create result directory like ./foo.eva/
    '''
    assert paths._INITIALIZED

    evc = loadEvc(args.info)
    checkEvc(evc)

    mkDirP(paths.outdir)

    cfg = initCfg(evc["config"], args.info)

    evcx = expandEvc(evc, cfg, args.info)

    # Fully read in and copy then clean input data.
    verb("Cleaning input VCD... ", end='')
    vcdClean(args.input, paths.fname_cln)
    verb("Done")

    # VCD-to-VCD: extract, interpolate, clean
    meaVcd(paths.fname_cln, evcx, cfg, args.info)
    #vcdClean(paths.fname_mea) # Reduce size of varIds
    vcdInfo = evaVcdInfo(paths.fname_mea)
    saveToml(vcdInfo, paths.fname_meainfo)

    # VCD-to-binaries
    meaDbFromVcd()

    # Identicons
    createIdenticons(vcdInfo)

    return 0
Beispiel #2
0
def loadEvc(infoFlag):  # {{{
    '''Read EVC file with only basic checking.
    '''
    def infoEvc(evc):  # {{{
        '''Print information about EVC.
        '''
        if not infoFlag:
            return

        for k, v in evc.get("config", {}).items():
            msg = "%s = %s" % (k, v)
            info(msg, prefix="INFO:EVC:CONFIG: ")

        for m in evc.get("signal", []):
            msg = "%s <-- %s" % (m["name"], m["hook"])
            info(msg, prefix="INFO:EVC:SIGNAL: ")

    # }}} def infoEvc

    verb("Loading EVC... ", end='')

    try:
        # NOTE: loadToml() appends ".toml" to fname.
        assert paths._INITIALIZED
        evc = toml.load(paths.fname_evc)
    except toml.decoder.TomlDecodeError as e:
        raise EVCError_TomlLoad(e)

    verb("Done")

    infoEvc(evc)

    return evc
Beispiel #3
0
def actionReset(device, _args):  # {{{

    verb("Reseting BytePipe FSM...", end='')
    bpReset(device)
    verb("Done")

    return  # No return value
Beispiel #4
0
def checkEvcxWithVcd(evcx, vcd, infoFlag):  # {{{
    '''Check hooks exist in VCD.
    '''
    def infoEvcxWithVcd(evcx):  # {{{
        '''Print information about EVCX.
        '''
        if not infoFlag:
            return

        for nm, v in evcx.items():
            msg = "%s %d %s <-- %s %s %s" % \
                (v["type"], v["idx"], nm,
                 v["hookVarId"], v["hookType"], v["hookBit"])
            info(msg, prefix="INFO:EVCX/VCD: ")

    # }}} def infoEvcxWithVcd

    verb("Checking EVCX with VCD... ", end='')

    plainVarNames = [re.sub(r'\[.*$', '', x) for x in vcd.varNames]

    evcxx_ = {}
    for nm, v in evcx.items():
        hk = v["hook"]

        # Plain hook in VCD, which doesn't have vector select.
        # NOTE: Only limited support. No vectored modules, no multidim.
        # hk -> hkPlain
        # module:TOP.foo.bar[3] -> module:TOP.foo.bar
        hkPlain = re.sub(r'\[.*$', '', hk)

        if hkPlain not in plainVarNames:
            raise EVCError_SignalName(hk, hkPlain)

        hkVarId = vcd.mapVarNameNovectorToVarId[hkPlain]
        hkType = vcd.mapVarIdToType[hkVarId]
        hkSize = vcd.mapVarIdToSize[hkVarId]

        # Check width of VCD signal contains numbered bit.
        if hkType in oneBitTypes and hk.endswith(']'):
            hkBit = int(hk[hk.rfind('['):].strip('[]'), 10)
            if hkBit >= hkSize:
                raise EVCError_SignalName(hk, hkBit)
        else:
            hkBit = None

        evcxx_[nm] = v
        evcxx_[nm].update({
            "hookVarId": hkVarId,
            "hookType": hkType,
            "hookBit": hkBit,
        })
    verb("Done")

    infoEvcxWithVcd(evcxx_)

    return evcxx_
Beispiel #5
0
def meaDbFromVcd():  # {{{
    '''Apply post-processing steps to stage0.

    Extract changes from signals.vcd into fast-to-read binary form.

    signals.vcd has only 2 datatypes: bit, real

    Assume initial state for all measurements is 0.:
    All timestamps are 32b non-negative integers.
    Binary format for bit is different from that of real.
        bit: Ordered sequence of timestamps.
        real: Ordered sequence of (timestamp, value) pairs.
            All values are 32b IEEE754 floats, OR 32b(zext) fx.
    '''
    verb("Creating binary database from VCD... ", end='')

    mkDirP(paths.dname_mea)

    with VcdReader(paths.fname_mea) as vcdi:

        # Stage0 file has bijective map between varId and varName by
        # construction, so take first (only) name for convenience.
        _mapVarIdToName = {varId: detypeVarName(nms[0]) \
                           for varId,nms in vcdi.mapVarIdToNames.items()}
        mapVarIdToName = {varId: nm \
                          for varId,nm in _mapVarIdToName.items() \
                          if isUnitIntervalMeasure(nm)}

        fds = {nm: open(joinP(paths.dname_mea, nm), 'wb') \
             for varId,nm in mapVarIdToName.items()}

        prevValues = {varId: 0 for varId in mapVarIdToName.keys()}

        for newTime, changedVarIds, newValues in vcdi.timechunks:
            for varId, newValue in zip(changedVarIds, newValues):
                nm = mapVarIdToName.get(varId, None)
                if nm is None:
                    continue

                tp, _, structFmt = meaDtype(nm)
                v, p = tp(newValue), prevValues[varId]

                if v != p:
                    _packArgs = [newTime, v] if tp is float else [newTime]
                    bs = struct.pack(structFmt, *_packArgs)
                    fds[nm].write(bs)
                    prevValues[varId] = v

        for _, fd in fds.items():
            fd.close()

    verb("Done")

    return
Beispiel #6
0
def actionPut(device, args):  # {{{

    addr = abs(int(args.addr)) % 128
    nBytes = abs(int(args.nBytes))
    fname = args.file

    verb("Writing %dB @%d from %s..." % (nBytes, addr, fname), end='')
    with open(fname, 'rb') as fd:
        bpWriteAddr(device, addr, nBytes, fd.read(nBytes), args.record_time)
    verb("Done")

    return  # No return value
Beispiel #7
0
def actionGet(device, args):  # {{{

    addr = abs(int(args.addr)) % 128
    nBytes = abs(int(args.nBytes))
    fname = args.file

    verb("Reading %dB @%d to %s..." % (nBytes, addr, fname), end='')
    with open(fname, 'wb') as fd:
        fd.write(bytes(bpReadAddr(device, addr, nBytes, args.record_time)))
    verb("Done")

    return  # No return value
Beispiel #8
0
def actionDump(device, _args):  # {{{
    rd: Callable = functools.partial(bpReadSequential, device)
    wr: Callable = functools.partial(bpWriteSequential, device)
    mem: Callable = bpAddrValuesToMem

    verb("Reading all register locations...", end='')
    init0: BpMem = mem(rd(list(range(128))))
    verb("Done")

    bpPrintMem("Dump", init0)

    return  # No return value
Beispiel #9
0
def loadEvcx():  # {{{
    '''Return dict of measurement names to VCD hook names.
    '''
    assert paths._INITIALIZED

    verb("Loading EVCX... ", end='')

    evcx = toml.load(paths.fname_evcx)

    verb("Done")

    return evcx
Beispiel #10
0
def actionPeek(device, args):  # {{{
    rd: Callable = functools.partial(bpReadSequential, device)

    addr = abs(int(args.addr)) % 128

    verb("Peeking @%d..." % addr, end='')
    addrValue: BpAddrValue = rd([addr])[0]
    rdAddr, value = addrValue
    assert addr == rdAddr, (addr, rdAddr)
    verb("Done")

    print("%02x" % value)

    return  # No return value
Beispiel #11
0
def actionPoke(device, args):  # {{{
    wr: Callable = functools.partial(bpWriteSequential, device)

    addr = abs(int(args.addr)) % 128
    value = abs(int(args.data)) % 256

    assert 0 != addr, "Writing @0 reserved for burst."

    verb("Poking %d@%d..." % (value, addr), end='')
    addrValue: BpAddrValue = wr([(addr, value)])[0]
    rdAddr, value = addrValue
    assert addr == rdAddr, (addr, rdAddr)
    verb("Done")

    return  # No return value
Beispiel #12
0
def loadCfg():  # {{{
    '''Return config extracted from EVC and VCD.

    CFG is assumed to be sane, written by initCfg().
    '''
    assert paths._INITIALIZED

    verb("Loading CFG... ", end='')

    cfg = Bunch()
    cfg.__dict__.update(toml.load(paths.fname_cfg))

    verb("Done")

    return cfg
Beispiel #13
0
def main(args) -> int:  # {{{
    '''
    1. Upload bitfile to TinyFPGA-BX (optional).
    2. Open connection to device.
    3. Discover writable bits.
    '''

    locale.setlocale(locale.LC_ALL, '')

    if args.prog:
        bitfile = getBitfilePath(args.bitfile)
        verb("Uploading bitfile %s ..." % bitfile, end='')
        assert 0 == uploadBitfile(bitfile)
        verb("Done")

        # Allow OS time to enumerate USB before looking for device.
        nAttempts = 10
        waitTime = 1  # seconds
        verb("Waiting up to %0.01fs..." % (nAttempts * waitTime), end='')

        maybeDevicePath_: Optional[str] = None
        for _ in range(nAttempts):
            time.sleep(waitTime)
            try:
                maybeDevicePath_ = getDevicePath(args.device)
                break
            except OSError:
                pass

        if maybeDevicePath_ is None:
            return 1
        else:
            devicePath = maybeDevicePath_

        verb("Done")
    else:
        devicePath = getDevicePath(args.device)

    # Keep lock on device to prevent other processes from accidentally messing
    # with the state machine.
    verb("Connecting to device %s" % devicePath)
    with serial.Serial(devicePath, timeout=1.0, write_timeout=1.0) as device:
        actions[args.action](device, args)

    return 0
Beispiel #14
0
def createIdenticons(vcdInfo):  # {{{
    '''Produce an identicon for each signal in VCD.
    '''
    verb("Creating identicons... ", end='')

    mkDirP(paths.dname_identicon)

    measureNames = vcdInfo["unitIntervalVarNames"]

    for nm in measureNames:
        measureType, siblingType, baseName = measureNameParts(nm)

        svgStr = identiconSpriteSvg(baseName, fill="darkgray")

        fname = joinP(paths.dname_identicon, baseName + ".svg")
        with open(fname, 'w') as fd:
            fd.write(svgStr)

    verb("Done")

    return
Beispiel #15
0
def initCfg(evcConfig, infoFlag):  # {{{
    '''Fill in and save CFG.
    '''
    def infoCfg(cfg):  # {{{
        '''Print information about CFG.
        '''
        if not infoFlag:
            return

        for k, v in cfg.__dict__.items():
            msg = "%s = %s" % (k, v)
            info(msg, prefix="INFO:CFG: ")

    # }}} def infoCfg

    verb("Initializing CFG... ", end='')

    cfg = Bunch()
    cfg.__dict__.update(loadToml(appPaths.configDefault))
    cfg.__dict__.update(evcConfig)

    verb("Saving... ", end='')
    saveToml(cfg.__dict__, paths.fname_cfg)
    verb("Done")

    infoCfg(cfg)

    return cfg
Beispiel #16
0
    def __enter__(self):

        exception_ = None

        for i in range(self.connectNAttempt):
            if 0 != i:
                time.sleep(self.connectTimeout)

            verb("Attempt %d/%d connecting SerialDevice %s ... " % \
                 (i+1, self.connectNAttempt, self.path), end='')
            try:

                self.port = serial.Serial(self.path,
                                          timeout=self.rdTimeout,
                                          write_timeout=self.wrTimeout,
                                          exclusive=self.exclusive)
                self.port.open()
            except Exception as e:
                exception_ = e

            if hasattr(self, "port") and self.port.is_open:
                verb("Success")
                break
            else:
                verb("Failure")

        if not (hasattr(self, "port") and self.port.is_open):
            raise exception_

        return self.port
Beispiel #17
0
def info(src, showTime):  # {{{
    fnamei = fnameAppendExt(src, "vcd")

    verb("Opening file and reading header...", end='')
    with VcdReader(fnamei) as vd:
        verb("DONE")

        print("__version__", __version__)
        print("filename", vd.filename)

        vs = zip(vd.varIds, vd.varNames, vd.varSizes, vd.varTypes)
        print("<id> <name> <size> <type>:")
        for varId, varName, varSize, varType in vs:
            print(" ", varId, varName, varSize, varType)

        if showTime:
            print("<timechunkNumber> <#changes> <time>:")
            for i, tc in enumerate(vd.timechunks, start=1):
                newTime, changedVarIds, newValues = tc

                print(" ", i, len(changedVarIds), newTime)

    return 0
Beispiel #18
0
def runHttpDaemon(args, cfg):  # {{{
    '''Run local HTTP/HTML daemon serving data visualization pages on request.
    '''

    verb("Starting HTTPD on TCP port %d..." % args.httpd_port, end='')

    httpd = EvaHTTPServer(('', args.httpd_port), EvaHTTPRequestHandler)

    verb("Running...")

    try:
        tm_start = time.time()
        httpd.serve_forever(args, cfg)
    except KeyboardInterrupt:
        tm_stop = time.time()
        verb("Stopped HTTPD server [%s]" % \
            tmdiff(tm_stop - tm_start))

    return
Beispiel #19
0
def main(args) -> int:  # {{{
    '''
    1. Open connection to device.
    2. Read config RO registers.
    3. Write config RW registers if --init-* is used.
    4. Read/check config RW registers.
    5. Record data with burst reads from pktfifo.
    '''

    locale.setlocale(locale.LC_ALL, '')

    devicePath = getDevicePath(args.device)

    # Keep lock on device to prevent other processes from accidentally messing
    # with the state machine.
    with SerialDevice(devicePath,
                      exclusive=True,
                      rdTimeout=args.timeout,
                      wrTimeout=args.timeout,
                      connectNAttempt=50,
                      connectTimeout=0.2) as device:
        rdBytePipe: Callable = functools.partial(bpReadSequential, device)
        wrBytePipe: Callable = functools.partial(bpWriteSequential, device)
        rd: Callable = functools.partial(hwReadRegs, rdBytePipe)
        wr: Callable = functools.partial(hwWriteRegs, wrBytePipe)

        verb("Detecting number of engines...", end='')
        nEngine: int = detectNEngine(rd)
        assert args.engine < nEngine, "--engine must be less than %d" % nEngine
        engineNum: int = args.engine
        verb("Done")

        verb("Reading RO registers...", end='')
        hwRegsRO: Dict[HwReg, Any] = rd(engineNum, (
            HwReg.PktfifoDepth,
            HwReg.MaxWindowLengthExp,
            HwReg.WindowPrecision,
            HwReg.MaxSamplePeriodExp,
            HwReg.MaxSampleJitterExp,
        ))
        verb("Done")

        # Gather registers required for initialization.
        initRegsRW: Dict[HwReg, Any] = {}
        if args.init_windowLengthExp is not None:
            initRegsRW[HwReg.WindowLengthExp] = args.init_windowLengthExp
        if args.init_windowShape is not None:
            initRegsRW[HwReg.WindowShape] = args.init_windowShape
        if args.init_samplePeriodExp is not None:
            initRegsRW[HwReg.SamplePeriodExp] = args.init_samplePeriodExp
        if args.init_sampleJitterExp is not None:
            initRegsRW[HwReg.SampleJitterExp] = args.init_sampleJitterExp
        if args.init_pwmSelect is not None:
            initRegsRW[HwReg.PwmSelect] = args.init_pwmSelect
        if args.init_xSelect is not None:
            initRegsRW[HwReg.XSelect] = args.init_xSelect
        if args.init_ySelect is not None:
            initRegsRW[HwReg.YSelect] = args.init_ySelect

        if 0 < len(initRegsRW):
            verb("Initializing RW registers...", end='')
            wr(engineNum, initRegsRW)
            verb("Checking...", end='')
            hwRegsRW: Dict[HwReg, Any] = rd(engineNum, initRegsRW.keys())
            assert all(initRegsRW[k] == v
                       for k, v in hwRegsRW.items()), hwRegsRW
            verb("Done")

        if args.prng_seed is not None:
            seed: int = abs(args.prng_seed)
            verb("Initializing PRNG (xoshiro128+ %s)..." % hex(seed), end='')
            bpWriteAddr(device, HwReg.PrngSeed.value, 16, [0] * 16)
            bpWriteAddr(device, HwReg.PrngSeed.value, 4, [
                (seed >> 3 * 8) & 0xff,
                (seed >> 2 * 8) & 0xff,
                (seed >> 1 * 8) & 0xff,
                (seed >> 0 * 8) & 0xff,
            ])
            verb("Done")

        verb("Reading RW registers...", end='')
        hwRegsRW: Dict[HwReg, Any] = rd(engineNum, [
            HwReg.WindowLengthExp,
            HwReg.WindowShape,
            HwReg.SamplePeriodExp,
            HwReg.SampleJitterExp,
            HwReg.PwmSelect,
            HwReg.XSelect,
            HwReg.YSelect,
        ])
        verb("Done")

        try:
            verb("Recording...")
            nLinesWritten, wrSuccess = \
                wrLines(args.output, pktLines(device,
                                              args.nWindows, engineNum,
                                              {**hwRegsRO, **hwRegsRW}))
            verb("Recording %s" %
                 ("complete" if wrSuccess else "FAILURE nLinesWritten=%d" %
                  nLinesWritten))
        except KeyboardInterrupt:
            verb("KeyboardInterrupt. Exiting.")

    return 0
Beispiel #20
0
def main(args) -> int: # {{{
    '''
    1. Upload bitfile to FPGA.
    2. Open connection to device.
    3. Read config RO registers.
    4. Write config RW registers.
    5. Read/check config RW registers.
    6. Initialize TUI
    7. TUI output loop:
        1. Sleep for refresh period.
        2. Read results RO registers.
        2. Update results section.
    8. TUI config loop:
        1. Wait for <Enter>
        2. Write config RW registers.
        3. Read config RW registers, check they're what was written.
    9. TUI input loop:
        1. Wait for keypress.
        2. Handle keypress by moving highlighted line or changing value.
    '''

    locale.setlocale(locale.LC_ALL, '')

    if args.prog:
        bitfile = getBitfilePath(args.bitfile)
        verb("Uploading bitfile %s ..." % bitfile, end='')
        assert 0 == uploadBitfile(bitfile)
        verb("Done")

        # Allow OS time to enumerate USB before looking for device.
        nAttempts = 10
        waitTime = 1 # seconds
        verb("Waiting up to %0.01fs..." % (nAttempts * waitTime), end='')

        maybeDevicePath_:Optional[str] = None
        for _ in range(nAttempts):
            time.sleep(waitTime)
            try:
                maybeDevicePath_ = getDevicePath(args.device)
                break
            except OSError:
                pass

        if maybeDevicePath_ is None:
            return 1
        else:
            devicePath = maybeDevicePath_

        verb("Done")
    else:
        devicePath = getDevicePath(args.device)


    # Keep lock on device to prevent other processes from accidentally messing
    # with the state machine.
    with SerialDevice(devicePath, exclusive=True,
                       rdTimeout=args.timeout, wrTimeout=args.timeout,
                       connectNAttempt=50, connectTimeout=0.2) as device:
        rdBytePipe:Callable = functools.partial(bpReadSequential, device)
        wrBytePipe:Callable = functools.partial(bpWriteSequential, device)
        rd:Callable = functools.partial(hwReadRegs, rdBytePipe)
        wr:Callable = functools.partial(hwWriteRegs, wrBytePipe)

        verb("Detecting number of engines...", end='')
        global nEngine_
        nEngine_ = detectNEngine(rd)
        engineNum = args.engine if (args.engine < nEngine_) else 0
        verb("Done")

        verb("Reading engine %d RO registers..." % engineNum, end='')
        hwRegsRO:Dict[HwReg, Any] = rd(engineNum, (
            HwReg.PktfifoDepth,
            HwReg.MaxWindowLengthExp,
            HwReg.WindowPrecision,
            HwReg.MaxSamplePeriodExp,
            HwReg.MaxSampleJitterExp,
        ))
        verb("Done")

        # Fill in missing values of parameter domains.
        global mapTuiRegToDomain_
        mapTuiRegToDomain_.update({
            TuiReg.Engine: mapTuiRegToDomain_[TuiReg.Engine] % nEngine_,
            TuiReg.WindowLength: mapTuiRegToDomain_[TuiReg.WindowLength] %
                hwRegsRO[HwReg.MaxWindowLengthExp],
            TuiReg.SampleRate: mapTuiRegToDomain_[TuiReg.SampleRate] %
                hwRegsRO[HwReg.MaxSamplePeriodExp],
            TuiReg.SampleJitter: mapTuiRegToDomain_[TuiReg.SampleJitter] %
                (2**hwRegsRO[HwReg.MaxSampleJitterExp], hwRegsRO[HwReg.MaxSampleJitterExp]),
        })


        # Gather registers required for TUI.
        initRegsRW:Dict[HwReg, Any] = {
            HwReg.WindowLengthExp:      args.init_windowLengthExp,
            HwReg.WindowShape:          args.init_windowShape,
            HwReg.SamplePeriodExp:      args.init_samplePeriodExp,
            HwReg.SampleJitterExp:      args.init_sampleJitterExp,
            HwReg.PwmSelect:            args.init_pwmSelect,
            HwReg.XSelect:              args.init_xSelect,
            HwReg.YSelect:              args.init_ySelect,
        }

        if args.no_init:
            verb("Reading RW registers...", end='')
            hwRegsRW:Dict[HwReg, Any] = rd(engineNum, initRegsRW.keys())
            verb("Done")
        else:
            verb("Initializing RW registers...", end='')
            wr(0, initRegsRW)
            verb("Checking...", end='')
            hwRegsRW:Dict[HwReg, Any] = rd(engineNum, initRegsRW.keys())
            assert all(initRegsRW[k] == v for k,v in hwRegsRW.items()), hwRegsRW
            verb("Done")

            seed:int = abs(args.prng_seed)
            verb("Initializing PRNG (xoshiro128+ %s)..." % hex(seed), end='')
            bpWriteAddr(device, HwReg.PrngSeed.value, 16, [0]*16)
            bpWriteAddr(device, HwReg.PrngSeed.value, 4, [
                (seed >> 3*8) & 0xff,
                (seed >> 2*8) & 0xff,
                (seed >> 1*8) & 0xff,
                (seed >> 0*8) & 0xff,
            ])
            verb("Done")

        try:
            verb("Starting TUI (curses)...")
            curses.wrapper(tui, device.name, rd, wr, engineNum, {**hwRegsRO, **hwRegsRW})
            verb("TUI Done")
        except KeyboardInterrupt:
            verb("KeyboardInterrupt. Exiting.")

    return 0
Beispiel #21
0
def main(args):  # {{{
    '''
    '''

    mkDirP(args.output_dir)
    fdir = args.output_dir + sep

    f = partial(cs0, gamma=args.gamma)

    verb("cs0...", end='')
    makePng(f, fdir + "cs0.png")
    verb("DONE")

    verb("cs0_invOrigin...", end='')
    makePng(partial(f, invOrigin=True), fdir + "cs0_invOrigin.png")
    verb("DONE")

    verb("cs0_magB...", end='')
    makePng(partial(f, gamma=args.gamma, magColor='b'), fdir + "cs0_magB.png")
    verb("DONE")

    verb("cs0_magG...", end='')
    makePng(partial(f, gamma=args.gamma, magColor='g'), fdir + "cs0_magG.png")
    verb("DONE")

    return 0
Beispiel #22
0
def actionBits(device, _args):  # {{{
    rd: Callable = functools.partial(bpReadSequential, device)
    wr: Callable = functools.partial(bpWriteSequential, device)
    mem: Callable = bpAddrValuesToMem

    verb("Writing ones to all register locations...", end='')
    _ = mem(wr(list((addr, 0xff) for addr in range(1, 128))))
    verb("Done")

    verb("Writing zeros to all register locations...", end='')
    ones: BpMem = mem(wr(list((addr, 0x00) for addr in range(1, 128))))
    verb("Done")

    verb("Reading all register locations...", end='')
    zeros: BpMem = mem(rd(list(range(1, 128))))
    verb("Checking writable bits...", end='')
    symdiff: BpMem = cast(BpMem, tuple(o ^ z for o, z in zip(ones, zeros)))
    verb("Done")

    bpPrintMem("Writable bits", symdiff)

    return  # No return value
Beispiel #23
0
def meaVcd(instream, evcx, cfg, infoFlag):  # {{{
    '''Filter input data to sanitized VCD (signals.vcd).

    Extract measurements of interest, at times of interest.
    Perform interpolation for normal measurements.
    Time becomes a straightforward sample index.
    Hierarchy shows raw measures and refl/rise/fall.

    NOTE: This initial extraction to filter/clean the dataset is probably the
    most complex part of eva!
    '''
    assert paths._INITIALIZED

    def twoStateBool(v, hookbit):  # {{{
        if isinstance(v, int):
            ret = (0 != v)
        else:
            assert isinstance(v, str), (type(v), v)
            intValue = int(v, 2)
            if hookBit is None:
                ret = (intValue != 0)
            else:
                ret = ((intValue & 1 << hookBit) != 0)

        assert isinstance(ret, bool), type(ret)

        return ret

    # }}} def twoStateBool

    def vcdoVarlist(evcx):  # {{{
        '''Create varlist for vcdo.wrHeader from EVCX.

        structure:  [ (<name:str>, <width:int>,  <type:str>), ... ]
        example:    [ ("aName", 1,  "bit"), ... ]

        All signals are of either "bit" or "real" VCD type.
        '''
        measuresEvent = (nm for nm, v in evcx.items() if "event" == v["type"])
        measuresBstate = (nm for nm, v in evcx.items()
                          if "bstate" == v["type"])
        measuresThreshold = (nm for nm, v in evcx.items()
                             if "threshold" == v["type"])
        measuresNormal = (nm for nm, v in evcx.items()
                          if "normal" == v["type"])

        # Sibling measurements denoted by prefix.
        prefixesEvent = ("orig", )
        prefixesBstate = (
            "orig",
            "refl",
            "rise",
            "fall",
        )
        prefixesNormal = (
            "raw",
            "smooth",
            "orig",
        )
        prefixesThreshold = (
            "orig",
            "refl",
            "rise",
            "fall",
        )

        namesEvent = \
            ('.'.join(("event", pfx, nm)) \
             for nm in sorted(measuresEvent) for pfx in prefixesEvent)
        namesBstate = \
            ('.'.join(("bstate", pfx, nm)) \
             for nm in sorted(measuresBstate) for pfx in prefixesBstate)
        namesThreshold = \
            ('.'.join(("threshold", pfx, nm)) \
             for nm in sorted(measuresThreshold) for pfx in prefixesThreshold)
        namesNormal = \
            ('.'.join(("normal", pfx, nm)) \
             for nm in sorted(measuresNormal) for pfx in prefixesNormal)

        varlist = [(nm, 1, "bit") \
                   for nms in (namesEvent, namesBstate, namesThreshold,) \
                   for nm in nms] + \
                  [(nm, 64, "real") \
                   for nms in (namesNormal,) \
                   for nm in nms]

        return varlist

    # }}} def vcdoVarlist

    def interpolateNormal(iVarId,
                          oTime,
                          mea,
                          mapVarIdToHistory_,
                          nq_,
                          bq_,
                          newValue=None):  # {{{
        nm = mea["name"]
        geq = mea["geq"]
        leq = mea["leq"]

        prevIpolTime, prevIpolValues_ = mapVarIdToHistory_[iVarId]

        for t in range(prevIpolTime + 1, oTime):
            assert t < oTime, (t, oTime)

            zs = [prevIpolValues_[0]] + prevIpolValues_
            prevIpolValues_ = zs[:-1]

            assert len(zs) == len(cfg.fir), zs
            smoothValue = dotp(zs, cfg.fir)
            clipnormValue = clipNorm(smoothValue, geq, leq)

            bq_.append((t, "normal.smooth." + nm, smoothValue))
            bq_.append((t, "normal.orig." + nm, clipnormValue))

        zs = [prevIpolValues_[0] if newValue is None else newValue
              ] + prevIpolValues_
        mapVarIdToHistory_[iVarId] = (oTime, zs[:-1])

        assert len(zs) == len(cfg.fir), zs
        smoothValue = dotp(zs, cfg.fir)
        clipnormValue = clipNorm(smoothValue, geq, leq)

        nq_.append(("normal.smooth." + nm, smoothValue))
        nq_.append(("normal.orig." + nm, clipnormValue))

    # }}} def interpolateNormal

    # NOTE: VCD input may come from STDIN ==> only read once.
    with VcdReader(instream) as vcdi, VcdWriter(paths.fname_mea) as vcdo:
        evcxx = checkEvcxWithVcd(evcx, vcdi, infoFlag)

        verb("Extracting measurements to VCD ... ", end='')

        evcxVarIds = tuple(sorted(list(set(v["hookVarId"] \
                                           for nm,v in evcxx.items()))))

        meaSortKey = (lambda mea: mea["name"])
        mapVarIdToMeasures = \
            {varId: sorted([{"name": nm,
                             "type": v["type"],
                             "hookType": v["hookType"],
                             "hookBit": v["hookBit"],
                             "geq": v.get("geq"),
                             "leq": v.get("leq")} \
                            for nm,v in evcxx.items() \
                            if varId == v["hookVarId"]], key=meaSortKey) \
             for varId in evcxVarIds}

        # Initialize previous values to 0.
        # {varId: (time, value), ...}
        mapVarIdToPrev_ = {varId: (0, 0) for varId in evcxVarIds}

        # Initialise previous values for normals to 0 for filter history.
        # {varId: (time, values), ...}
        mapVarIdToHistory_ = \
            {varId: (0, [0.0 for _ in cfg.fir[1:]]) \
             for varId in evcxVarIds \
             if "normal" in [mea["type"] for mea in mapVarIdToMeasures[varId]]}

        vcdo.wrHeader(vcdoVarlist(evcx),
                      comment=' '.join(
                          (vcdi.vcdComment, "<<< Extracted by evaInit >>>")),
                      date=vcdi.vcdDate,
                      version=vcdi.vcdVersion,
                      timescale=' '.join(vcdi.vcdTimescale))

        # Forward (future) queue of speculative changes which may need to be
        # interleaved with timechunks from vcdi.
        # E.g. event->bit conversion inferring 1 then 0 in consecutive times.
        # Or rise/fall on bstate.
        # [ (time, name, value) ... ]
        # Initialise all measurements to 0, except reflections to 1.
        fq_ = [(0, nm, int(re.match(r"^[^\.]*\.refl\.", nm) is not None)) \
               for nm in vcdo.varNames]

        lastTime_ = 0

        # Work through vcdi timechunks putting values into vcdo.
        for iTc in vcdi.timechunks:
            iTime, iChangedVarIds, iNewValues = iTc

            if iTime < cfg.timestart:
                continue

            if cfg.timestop != 0 and iTime > cfg.timestop:
                break

            tQuotient, tRemainder = divmod(iTime, cfg.timestep)
            if 0 != tRemainder:
                continue

            # Index in EVent Sample (EVS) array of this time.
            oTime = (iTime - cfg.timestart) // cfg.timestep
            assert isinstance(oTime, int), type(oTime)
            assert 0 <= oTime, (oTime, iTime, cfg.timestart, cfg.timestep)

            # Current (now) queue of changes which may contain duplicate
            # varnames with different values.
            # Only the last appended will be used.
            # No time field is necessary, all use current timechunk (oTime).
            # [ (name, value) ... ]
            nq_ = [(nm, v) for t, nm, v in fq_ if t == oTime]

            # Extract proper changes from fq_ and put into current queue.
            # Changes are proper if they are for time before this timechunk.
            # fq_ may still contain future speculative changes.
            bq_ = [(t, nm, v) for t, nm, v in fq_ if t < oTime]
            fq_ = [(t, nm, v) for t, nm, v in fq_ if t > oTime]

            for iVarId, iNewValue in zip(iChangedVarIds, iNewValues):  # {{{
                if not iVarId in evcxVarIds:
                    continue

                assert isinstance(iNewValue, str)  # VcdReader only gives str.
                newValueClean = iNewValue.replace('x', '0').replace('z', '1')

                prevTime, prevValue = mapVarIdToPrev_[iVarId]  # Always clean.
                assert prevTime <= oTime, (prevTime, oTime)

                # Each iVarId may refer to multiple measurements, such as
                # vectored wires or wires used in multiple ways.
                for mea in mapVarIdToMeasures[iVarId]:
                    nm = mea["name"]
                    tp = mea["type"]
                    hookType = mea["hookType"]
                    hookBit = mea["hookBit"]

                    if "event" == tp:  # {{{
                        if "event" == hookType:
                            # vcdi implies event only occurring at this time.
                            nq_.append(("event.orig." + nm, 1))

                            # Speculatively reset to 0 in next time.
                            fq_.append((oTime + 1, "event.orig." + nm, 0))
                        elif hookType in oneBitTypes:
                            newValue = int(twoStateBool(
                                newValueClean, hookBit))
                            nq_.append(("event.orig." + nm, newValue))
                        else:
                            # Event measure only made from VCD event, or
                            # 2-state (bit), 4-state types (wire, reg, logic)
                            assert False, hookType
                    # }}} event

                    elif "bstate" == tp:  # {{{
                        if hookType in oneBitTypes:
                            newValue = twoStateBool(newValueClean, hookBit)

                            if prevValue != newValue:
                                nq_.append(
                                    ("bstate.orig." + nm, int(newValue)))
                                nq_.append(
                                    ("bstate.refl." + nm, int(not newValue)))

                                if newValue:
                                    nq_.append(("bstate.rise." + nm, 1))
                                    fq_.append(
                                        (oTime + 1, "bstate.rise." + nm, 0))
                                else:
                                    nq_.append(("bstate.fall." + nm, 1))
                                    fq_.append(
                                        (oTime + 1, "bstate.fall." + nm, 0))
                            else:
                                pass  # No change
                        else:
                            # Bstate measure only made from VCD 2-state (bit) or
                            # 4-state types (wire, reg, logic, etc)
                            assert False, hookType
                    # }}} bstate

                    elif "threshold" == tp:  # {{{
                        if (hookType in oneBitTypes and hookBit is None) or \
                           (hookType in ["real", "integer"]):

                            geq = mea["geq"]
                            leq = mea["leq"]

                            newValueFloat = float(newValueClean) \
                                if "real" == hookType else \
                                float(int(newValueClean, 2))

                            if geq is None:
                                # Is measurement under threshold?
                                newValue = (newValueFloat <= leq)
                            elif leq is None:
                                # Is measurement over threshold?
                                newValue = (geq <= newValueFloat)
                            elif geq < leq:
                                # Is measurement inside interval?
                                newValue = \
                                    (newValueFloat <= leq and \
                                     geq <= newValueFloat)
                            else:
                                # Is measurement outside interval?
                                newValue = \
                                    (newValueFloat <= leq or \
                                     geq <= newValueFloat)

                            if prevValue != newValue:
                                nq_.append(
                                    ("threshold.orig." + nm, int(newValue)))
                                nq_.append(("threshold.refl." + nm,
                                            int(not newValue)))

                                if newValue:
                                    nq_.append(("threshold.rise." + nm, 1))
                                    fq_.append(
                                        (oTime + 1, "threshold.rise." + nm, 0))
                                else:
                                    nq_.append(("threshold.fall." + nm, 1))
                                    fq_.append(
                                        (oTime + 1, "threshold.fall." + nm, 0))
                            else:
                                pass  # No change

                        else:
                            # Threshold (number to bstate) measure only made
                            # from VCD 2-state (bit) vector, 4-state (wire, reg,
                            # logic) vector, integer, or real.
                            assert False, (hookType, hookBit)
                    # }}} threshold

                    elif "normal" == tp:  # {{{
                        if (hookType in oneBitTypes and hookBit is None) or \
                           (hookType in ["real", "integer"]):

                            newValue = float(newValueClean) \
                                if "real" == hookType else \
                                float(int(newValueClean, 2))

                            # NOTE: normal.raw values are not necessarily
                            # in [0, 1]; rather than (-inf, +inf).
                            nq_.append(("normal.raw." + nm, newValue))

                            interpolateNormal(iVarId,
                                              oTime,
                                              mea,
                                              mapVarIdToHistory_,
                                              nq_,
                                              bq_,
                                              newValue=newValue)

                        else:
                            # Normal (real number) measure only made
                            # from VCD 2-state (bit) vector, 4-state (wire, reg,
                            # logic) vector, integer, or real.
                            assert False, (hookType, hookBit)
                    # }}} normal

                    else:
                        assert False, tp

                # Track previous value in vcdi
                try:
                    mapVarIdToPrev_[iVarId] = oTime, newValue
                except UnboundLocalError:
                    pass

            # }}} for iVarId,iNewValue in zip(iChangedVarIds, iNewValues)

            # Interpolate normal/smooth values up to current timechunk for
            # measurements which aren't sampled in this timechunk.
            for iVarId, (prevIpolTime,
                         prevIpolValues_) in mapVarIdToHistory_.items():
                if prevIpolTime == oTime:
                    continue

                for mea in mapVarIdToMeasures[iVarId]:
                    if "normal" != mea["type"] or 0 >= oTime:
                        continue

                    interpolateNormal(iVarId,
                                      oTime,
                                      mea,
                                      mapVarIdToHistory_,
                                      nq_,
                                      bq_,
                                      newValue=None)

            # Resolve conflicts from fq_/bq_.
            # Forward queue is speculative so a proper value from the current
            # timechunk will take precedence.
            # I.e. Always use the last appended change.
            bq_.sort()
            for fqTime, fqGroup in groupby(bq_, key=(lambda x: x[0])):
                fqChangedVars, fqNewValues = \
                    list(zip(*[(nm,v) for _,nm,v in fqGroup]))
                assert fqTime < oTime, (fqTime, oTime)
                vcdo.wrTimechunk((fqTime, fqChangedVars, fqNewValues))

            # Flush out current (now) queue.
            if 0 < len(nq_):
                dedupVars = []
                for nm, v in nq_:
                    dedupVars = appendNonDuplicate(dedupVars, (nm, v),
                                                   replace=True)
                nqChangedVars, nqNewValues = zip(*dedupVars)
                vcdo.wrTimechunk((oTime, nqChangedVars, nqNewValues))

            lastTime_ = oTime

        # Events from oneBitTypes cannot be interpolated until after last
        # timechunk.
        fq_ += [(lastTime_+1, nm, 0) \
                for nm in vcdo.varNames \
                if re.match(r"^event.orig\.", nm) is not None]

        # Flush out forward queue after input VCD has been fully processed.
        # Time is set to only one greater than last time in input VCD,
        # regardless of what the time in each fq_ item says.
        if 0 < len(fq_):
            dedupVars = []
            for _, nm, v in fq_:
                dedupVars = appendNonDuplicate(dedupVars, (nm, v),
                                               replace=True)
            nqChangedVars, nqNewValues = zip(*dedupVars)
            vcdo.wrTimechunk((lastTime_ + 1, nqChangedVars, nqNewValues))

        verb("Done")  # with

    return
Beispiel #24
0
def actionTest(device, _args):  # {{{
    rd: Callable = functools.partial(bpReadSequential, device)
    wr: Callable = functools.partial(bpWriteSequential, device)
    mem: Callable = bpAddrValuesToMem

    verb("Reading all register locations...", end='')
    init0: BpMem = mem(rd(list(range(128))))
    verb("Done")
    bpPrintMem("Initial values", init0)

    verb("Writing ones to all register locations...", end='')
    init1: BpMem = mem(wr(list((addr, 0xff) for addr in range(1, 128))))
    verb("Done")
    bpPrintMem("Initial values (again)", init1)
    verb("Checking previous unchanged...", end='')
    allUnchanged: bool = all(
        (i0 == i1) for i0, i1 in zip(init0[1:], init1[1:]))
    verb("Done")
    if not allUnchanged:
        verb("Warning: Some values changed!")

    verb("Writing zeros to all register locations...", end='')
    ones: BpMem = mem(wr(list((addr, 0x00) for addr in range(1, 128))))
    verb("Done")
    bpPrintMem("Ones", ones)

    verb("Reading all register locations...", end='')
    zeros: BpMem = mem(rd(list(range(1, 128))))
    verb("Checking writable bits...", end='')
    symdiff: BpMem = cast(BpMem, tuple(o ^ z for o, z in zip(ones, zeros)))
    verb("Done")
    bpPrintMem("Zeros", zeros)
    bpPrintMem("Writable bits", symdiff)

    verb("Writing unique values to all register locations...", end='')
    _ = mem(wr(list((addr, addr + 10) for addr in range(1, 128))))
    verb("Reading back...", end='')
    addrPlus10: BpMem = mem(rd(list(range(1, 128))))
    verb("Done")
    bpPrintMem("mem[addr] <-- (addr+10)", addrPlus10)

    return  # No return value
Beispiel #25
0
def expandEvc(evc, cfg, infoFlag):  # {{{
    '''Perform substitutions in EVC to create and save EVCX.

    Does not include config since that goes into a separate file.
    '''
    def infoEvcx(evcx):  # {{{
        '''Print information about EVCX.
        '''
        if not infoFlag:
            return

        for nm, v in evcx.items():
            hk = v["hook"]
            geq = v.get("geq")
            leq = v.get("leq")
            if v["type"] in ["threshold", "normal"]:
                hk = hk if geq is None else ("%s <= " % geq + hk)
                hk = hk if leq is None else (hk + " <= %s" % leq)

            msg = "%s %d %s <-- %s" % (v["type"], v["idx"], nm, hk)
            info(msg, prefix="INFO:EVCX: ")

    # }}} def infoEvcx

    reInt = r"[+-]?\d+"
    reEvcRange = re.compile(r"^" + reInt + r"\s*\.\.\s*" + reInt +
                            r"(\s*\.\.\s*" + reInt + r")?$")

    def evcSubstitute(instr, choices):  # {{{
        reEvcSubstitution = re.compile(r'({\d*})')

        ret_ = instr

        found = reEvcSubstitution.search(ret_)
        i = -1
        while found is not None:
            found_str = ret_[found.start():found.end()].strip("{}")
            if len(found_str) > 0:
                i = int(found_str)
            else:
                i += 1

            ret_ = reEvcSubstitution.sub(choices[i], ret_, count=1)

            found = reEvcSubstitution.search(ret_)

        return ret_

    # }}} def evcSubstitute

    verb("Expanding EVC to EVCX... ", end='')

    evsIdxEvent_, evsIdxBstate_, evsIdxNormal_, evsIdxThreshold_ = 0, 0, 0, 0
    evcx = {}
    signals = evc.get("signal", [])
    for m in signals:
        subs = m["subs"] if "subs" in m else []
        tp = m["type"]

        if "normal" == tp:
            # Values of geq,leq define clipNorm interval.
            geq = m.get("geq", 0)
            leq = m.get("leq", 1)
            assert isinstance(geq, (int, float)), (type(geq), geq)
            assert isinstance(leq, (int, float)), (type(leq), leq)
            assert geq < leq, (geq, leq)
        elif "threshold" == tp:
            # At least one of geq, leq must be a number.
            # Values of geq,leq used for boundary checks.
            geq = m.get("geq", None)
            leq = m.get("leq", None)
            assert (geq is not None) or (leq is not None), (geq, leq)
            assert isinstance(geq,
                              (int, float)) or geq is None, (type(geq), geq)
            assert isinstance(leq,
                              (int, float)) or leq is None, (type(leq), leq)
        else:
            # Event and bstate don't use geq or leq.
            pass

        # `subs` guaranteed to be list of lists
        # Each `sub` guaranteed to be homogenous list.
        # Each `s` guaranteed to be string or int, but string may be a range.
        assert isinstance(subs, list)
        for sub in subs:
            assert isinstance(sub, list)
            for s in sub:
                # Unsure how practical other types are.
                assert isinstance(s, (int, str, unicode))

        # Build up new list of lists of usable strings.
        subs_ = []
        for sub in subs:
            sub_ = []
            for s in sub:
                # Range <start>..<stop>..<step>
                if isinstance(s, (str, unicode)) and reEvcRange.match(s):
                    sub_ += [str(i) for i in range(*[int(x) \
                                                     for x in s.split("..")])]
                else:
                    s_ = str(s)
                    sub_.append(s_)
            subs_.append(sub_)

        # `subs_` guaranteed to be list of lists
        # Each `sub_` guaranteed to be homogenous list.
        # Each `s_` guaranteed to be usable string.
        assert isinstance(subs_, list)
        for sub_ in subs_:
            assert isinstance(sub_, list)
            for s_ in sub_:
                assert isinstance(s_, str)

        subsProd = product(*subs_)
        for subsList in subsProd:
            fullName = evcSubstitute(m["name"], subsList)

            fullHook = cfg.vcdhierprefix + \
                evcSubstitute(m["hook"], subsList)

            if "event" == tp:
                evsIdx = evsIdxEvent_
                evsIdxEvent_ += 1
            elif "bstate" == tp:
                evsIdx = evsIdxBstate_
                evsIdxBstate_ += 1
            elif "threshold" == tp:
                evsIdx = evsIdxThreshold_
                evsIdxThreshold_ += 1
            elif "normal" == tp:
                evsIdx = evsIdxNormal_
                evsIdxNormal_ += 1
            else:
                evsIdx = evsIdxEvent_
                assert False, tp

            evcx[fullName] = {
                "hook": fullHook,
                "type": tp,
                "idx": evsIdx,
            }
            if tp in ["threshold", "normal"]:
                evcx[fullName]["geq"] = geq
                evcx[fullName]["leq"] = leq

    verb("Saving... ", end='')
    # Unittests don't setup everything.
    try:
        saveToml(evcx, paths.fname_evcx)
    except AttributeError:
        pass
    verb("Done")

    infoEvcx(evcx)

    return evcx
Beispiel #26
0
def main(args) -> int:  # {{{
    '''
    1. Read in all regexs and precompile filters into memory.
    2. Read STDIN line by line.
    3. If line does not match any regex then print on STDOUT.
    '''

    verb("Reading and compiling regex filters ...", end='')
    regexLines:Iterable = \
        rdLines(args.filterFile,
                commentLines=True,
                commentMark='#',
                expandTabs=True,
                deduplicateSpaces=True,
                leftStrip=True,
                rightStrip=True,
                caseFold=False,
                raiseIOError=True)
    regexes: List = [re.compile(line) for line in regexLines if len(line) > 0]
    verb("Done")

    verb("Opening STDIN with optional whitespace preprocessing ...", end='')
    inputLines:Iterable = \
        rdLines(None, # STDIN
                commentLines=False,
                expandTabs=args.expand_tabs,
                deduplicateSpaces=args.deduplicate_spaces,
                leftStrip=args.left_strip,
                rightStrip=args.right_strip,
                caseFold=args.case_fold)
    verb("Done")

    verb("Filtering ...", end='')
    for line in inputLines:
        reMatch: bool = any(r.search(line) for r in regexes)

        if reMatch == args.invert_match:
            print(line, end='')
    verb("Done")

    return 0
Beispiel #27
0
def pktLines(device, nWindows: int, engineNum: int,
             hwRegs: Dict[HwReg, Any]) -> None:  # {{{
    '''Generator yielding lines to be written to output.
    - Display progress/status line.
    - Read up to 50 packets in each burst.
      - pktPerBurst = maxRdBurst // nBytesPerWindow
      - 50 = 255B // 5B
    - Update progress/status line after each burst.
    - Append to output after each burst.
    '''
    rpt_ = ' '.join((
        '#',
        "device=%s" % device.name,
    ))
    yield rpt_
    rpt_ = ' '.join((
        '#',
        "HwRegRO",
        "PktfifoDepth=%d" % hwRegs[HwReg.PktfifoDepth],
        "MaxWindowLengthExp=%d" % hwRegs[HwReg.MaxWindowLengthExp],
        "WindowPrecision=%d" % hwRegs[HwReg.WindowPrecision],
        "MaxSamplePeriodExp=%d" % hwRegs[HwReg.MaxSamplePeriodExp],
        "MaxSampleJitterExp=%d" % hwRegs[HwReg.MaxSampleJitterExp],
    ))
    yield rpt_
    rpt_ = ' '.join((
        '#',
        "HwRegRW",
        "WindowLengthExp=%d" % hwRegs[HwReg.WindowLengthExp],
        "SamplePeriodExp=%d" % hwRegs[HwReg.SamplePeriodExp],
        "SampleJitterExp=%d" % hwRegs[HwReg.SampleJitterExp],
        "PwmSelect=%s" % hwRegs[HwReg.PwmSelect].name,
        "XSelect=%d" % hwRegs[HwReg.XSelect],
        "YSelect=%d" % hwRegs[HwReg.YSelect],
    ))
    yield rpt_

    #rdBytePipe:Callable = functools.partial(bpReadSequential, device)
    wrBytePipe: Callable = functools.partial(bpWriteSequential, device)
    #rd:Callable = functools.partial(hwReadRegs, rdBytePipe)
    wr: Callable = functools.partial(hwWriteRegs, wrBytePipe)

    nBytesPerWindow: int = 5
    maxRdBurst: int = 255

    # NOTE: The term "rate" is used instead of "frequency" to reinforce that the
    # duty cycle is unbalanced so Fourier analysis will have high power in the
    # upper frequencies.
    samplePeriod_cycles: int = 2**hwRegs[HwReg.SamplePeriodExp]
    samplePeriod_ms: float = samplePeriod_cycles / float(maxSampleRate_kHz)
    sampleRate_kHz: float = 1.0 / samplePeriod_ms
    rpt_ = ' '.join((
        '#',
        "sampleStrobe",
        "averageRegularity=%d_cycles" % samplePeriod_cycles,
        "averagePeriod=%0.06f_ms" % samplePeriod_ms,
        "approximateRate=%0.06f_kHz" % sampleRate_kHz,
    ))
    yield rpt_

    windowLength_samples: int = 2**hwRegs[HwReg.WindowLengthExp]
    windowPeriod_ms: float = windowLength_samples * samplePeriod_ms
    windowRate_kHz: float = 1.0 / windowPeriod_ms
    rpt_ = ' '.join((
        '#',
        'window',
        "length=%d_samples" % windowLength_samples,
        "period_ms=%0.06f_ms" % windowPeriod_ms,
        "rate=%0.06f_kHz" % windowRate_kHz,
    ))
    yield rpt_

    totalNSamples: int = nWindows * windowLength_samples
    totalNBytes: int = nWindows * nBytesPerWindow
    totalTime_ms: float = nWindows * windowPeriod_ms
    totalBitrate_kbps: float = (8 * totalNBytes) / (1000 * totalTime_ms)
    rpt_ = ' '.join((
        '#',
        'dataset',
        "nWindows=%d" % nWindows,
        "time=%0.06f_ms" % totalTime_ms,
        "nSamples=%d" % totalNSamples,
        "pktfifoNBytes=%d" % totalNBytes,
        "pktfifoBitrate=%0.06f_kbps" % totalBitrate_kbps,
    ))
    yield rpt_

    nWindowPerBurst: int = maxRdBurst // nBytesPerWindow
    burstTime_ms: float = nWindowPerBurst * windowPeriod_ms
    nBytesPerBurst: int = nWindowPerBurst * nBytesPerWindow

    yield "winNum,countX,countY,countIsect,countSymdiff"
    lineFmt: str = ','.join(["%03d"] * 5)

    # Flush the packet fifo.
    # The cycle this arrives at bpReg is the beginning of time for this dataset.
    verb("Flushing to begin dataset...", end='')
    wr(engineNum, {HwReg.PktfifoFlush: 1})
    verb("Done")

    nWindowsRemaining_ = nWindows
    burstNum_ = 0
    while (0 < nWindowsRemaining_):
        nBytesRemaining: int = nWindowsRemaining_ * nBytesPerWindow
        nBytesThisBurst: int = min(nBytesRemaining, nBytesPerBurst)

        assert ((nBytesThisBurst // nBytesPerWindow) == \
                int(nBytesThisBurst / nBytesPerWindow)), \
               (nBytesThisBurst, nBytesPerWindow)

        # Read burst from packet fifo.
        verb("Reading burst %d..." % burstNum_, end='')
        bs = bpReadAddr(device, HwReg.PktfifoRd.value, nBytesThisBurst)
        verb("Done")
        assert len(bs) == nBytesThisBurst, (len(bs), nBytesThisBurst)
        assert all(isinstance(b, int) for b in bs), bs
        assert all((0 <= b <= 255) for b in bs), bs

        # Translate bs to output line.
        for pkt in grouper(bs, nBytesPerWindow):
            assert len(pkt) == nBytesPerWindow, (len(pkt), nBytesPerWindow)
            assert all(isinstance(b, int) for b in pkt), pkt
            line = lineFmt % tuple(pkt)
            yield line

        nWindowsRemaining_ -= nWindowPerBurst
        burstNum_ += 1
Beispiel #28
0
def main(args) -> int:  # {{{
    '''
    '''

    ###########################################################################
    # 1. Setup plot
    ###########################################################################

    fignum = 0

    # figsize used to set dimensions in inches.
    # ax.set_aspect() doesn't work for KDE where Y-axis is scaled.
    figsize = tuple(int(a) for a in args.figsize.split(','))
    assert 2 == len(figsize)
    assert all(0 < i for i in figsize)

    fig = plt.figure(fignum, figsize=figsize)

    if args.title:
        plt.title(args.title)

    if args.xlabel:
        plt.xlabel(args.xlabel)

    if args.ylabel:
        plt.ylabel(args.ylabel)

    if args.xlim:
        xLo, xHi = args.xlim.split(',')
        plt.xlim(float(xLo), float(xHi))

    if args.ylim:
        yLo, yHi = args.ylim.split(',')
        plt.ylim(float(yLo), float(yHi))

    markers = list(args.markers)

    labels = list(l for l in args.labels.split(',') if 0 < len(l))

    ###########################################################################
    # 2. Populate data
    ###########################################################################

    a = np.loadtxt(rdLines(args.input),
                   skiprows=args.skiprows,
                   delimiter=args.delimiter,
                   unpack=True)

    x = a[0]

    if args.baseX:
        args.addX = x[0] * -1

    if args.addX:
        verb("Add constant to X axis. (+ %0.05f)" % args.addX)
        x += args.addX

    if args.mulX:
        verb("Multiply X axis by constant. (* %0.05f)" % args.mulX)
        x *= args.mulX

    if args.intX:
        verb("Reduce X axis to integers.")
        x = x.astype(np.int)

    if args.product:
        prdX = np.copy(x)

        if args.diffX:
            verb("Product difference X axis.")
            tmpX = np.zeros(prdX.shape)
            tmpX[1:] = np.diff(prdX)
            prdX = tmpX

        if args.invX:
            verb("Product X**-1 axis.")
            prdX = prdX.astype(np.float)
            prdX **= -1

    ys = a[1:]
    for i, y in enumerate(ys):

        if args.baseY:
            args.addY = y[0] * -1

        if args.addY:
            verb("Add constant to Y axis[%d]. (+ %0.05f)" % (i, args.addY))
            y += args.addY

        if args.mulY:
            verb("Multiply Y axis (%d) by constant. (%0.05f)" % (i, args.mulY))
            y *= args.mulY

        if args.intY:
            verb("Reduce Y axis (%d) to integers.")
            y = y.astype(np.int)

        if args.product:
            prdY = np.copy(y)

            if args.diffY:
                verb("Product difference Y axis.")
                tmpY = np.zeros(prdY.shape)
                tmpY[1:] = np.diff(prdY)
                prdY = tmpY

            if args.invY:
                verb("Product Y**-1 axis.")
                prdY = prdY.astype(np.float)
                prdY **= -1

            y = prdX * prdY

    ###########################################################################
    # 3. Draw plot
    ###########################################################################

    for i, y in enumerate(ys):
        marker = markers[i] if i < len(markers) else ''
        label = labels[i] if i < len(labels) else None

        kwargsPlot = {"marker": marker}
        if label is not None:
            kwargsPlot.update({"label": label})

        plt.plot(x, y, **kwargsPlot)

    if 0 < len(labels):
        plt.legend()

    if args.vlines:
        for line in args.vlines.split(','):
            plt.axvline(y=float(line),
                        color="green",
                        linestyle='-',
                        linewidth=1)

    if args.hlines:
        for line in args.hlines.split(','):
            plt.axhline(y=float(line),
                        color="green",
                        linestyle='-',
                        linewidth=1)

    ###########################################################################
    # 4. Save plot to file
    ###########################################################################

    if args.pdf:
        plt.savefig(fnameAppendExt(args.output, "pdf"), bbox_inches="tight")
    else:
        plt.savefig(fnameAppendExt(args.output, "png"), bbox_inches="tight")

    plt.close()

    return 0
Beispiel #29
0
def main(args) -> int:  # {{{
    '''
    '''

    ###########################################################################
    # 1. Setup plot
    ###########################################################################

    fignum = 0

    # figsize used to set dimensions in inches.
    # ax.set_aspect() doesn't work for KDE where Y-axis is scaled.
    figsize = tuple(int(a) for a in args.figsize.split(','))
    assert 2 == len(figsize)
    assert all(0 < i for i in figsize)

    fig = plt.figure(fignum, figsize=figsize)

    if args.xlabel:
        plt.xlabel(args.xlabel)

    if args.ylabel:
        plt.ylabel(args.ylabel)

    if args.title:
        plt.title(args.title)

    if args.xlim:
        xLo, xHi = args.xlim.split(',')
        plt.xlim(float(xLo), float(xHi))

    _xLo, _xHi = args.xlim.split(',')
    xLo, xHi = float(_xLo), float(_xHi)
    plt.xlim(xLo, xHi)

    if args.ylim:
        yLo, yHi = args.ylim.split(',')
        plt.ylim(float(yLo), float(yHi))

    if args.title:
        plt.title(args.title)

    markers = list(args.markers)

    ###########################################################################
    # 2. Populate data
    ###########################################################################

    x = np.linspace(xLo, xHi, args.nsamples)
    ys = (np.apply_along_axis(eval("lambda x: " + e), 0, x) for e in args.expr)

    ###########################################################################
    # 3. Draw plot
    ###########################################################################

    for i, y in enumerate(ys):
        verb("Plotting `%s`" % args.expr[i])
        marker = markers[i] if i < len(markers) else ''
        label = args.expr[i]

        kwargsPlot = {"marker": marker}
        if label is not None:
            kwargsPlot.update({"label": label})

        plt.plot(x, y, **kwargsPlot)

    plt.legend()

    if args.vlines:
        for line in args.vlines.split(','):
            plt.axvline(y=float(line),
                        color="green",
                        linestyle='-',
                        linewidth=1)

    if args.hlines:
        for line in args.hlines.split(','):
            plt.axhline(y=float(line),
                        color="green",
                        linestyle='-',
                        linewidth=1)

    ###########################################################################
    # 4. Save plot to file
    ###########################################################################

    if args.pdf:
        plt.savefig(fnameAppendExt(args.output, "pdf"), bbox_inches="tight")
    else:
        plt.savefig(fnameAppendExt(args.output, "png"), bbox_inches="tight")

    plt.close()

    return 0
Beispiel #30
0
    def do_GET(self):  # {{{

        # Remove leading / which is usually (always?) present.
        self.path = self.path.lstrip('/')

        # Send response.
        if len(self.path) and not self.path.startswith("?") and \
            (self.path.endswith(".css") or self.path.endswith(".js")):

            # Strip off any relative paths to only find CSS and JS files.
            fname = joinP(appPaths.share, os.path.basename(self.path))

            try:
                response = rdTxt(fname)

                self.send_response(200)

                if fname.endswith(".js"):
                    self.send_header("Content-Type",
                                     "application/javascript; charset=utf-8")
                elif fname.endswith(".css"):
                    self.send_header("Content-Type", "text/css; charset=utf-8")

                responseBytes = response.encode("utf-8")

            except:
                self.send_error(404, "Invalid JS or CSS GET request!")
                return

        elif len(self.path) and self.path.endswith("favicon.ico"):
            # Bug in Chrome requests favicon.ico with every request until it
            # gets 404'd.
            # https://bugs.chromium.org/p/chromium/issues/detail?id=39402
            try:
                faviconFpath = joinP(appPaths.share, "eva_logo.png")
                responseBytes = open(faviconFpath, 'rb').read()

                self.send_response(200)
                self.send_header("Content-Type", "image/x-icon")
            except:
                self.send_error(404, "Cannot read favicon!")

        elif len(self.path) and not self.path.startswith("?"):
            # Unknown requests.
            self.send_response(404)
            return

        else:

            # Generate HTML string and send OK if inputs are valid.
            try:

                request = self.parseGetRequest(self.path)

                verb("Calculating {a,b}(x|y;u) <-- {%s,%s}(%s|%s;%s)..." % (
                    request['a'],
                    request['b'],
                    request['x'],
                    request['y'],
                    request['u'],
                ),
                     end='')
                response = evaHtmlString(self.args, self.cfg, request)
                verb("DONE")

                self.send_response(200)
                self.send_header("Content-Type", "text/html; charset=utf-8")

                responseBytes = response.encode("utf-8")

            except EvaHTMLException:
                self.send_error(404, "Invalid GET request!")
                return

        # Send HTTP headers.
        # https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers
        self.send_header("Content-Length", "%d" % len(responseBytes))
        self.end_headers()

        # Send HTML.
        self.wfile.write(responseBytes)

        return