示例#1
0
    def open(self):
        dump_filename = self.env.config.setdefault('sim.vcd.dump_file',
                                                   'sim.vcd')
        if 'sim.vcd.timescale' in self.env.config:
            vcd_ts_str = self.env.config.setdefault(
                'sim.vcd.timescale', self.env.config['sim.timescale'])
            vcd_timescale = parse_time(vcd_ts_str)
        else:
            vcd_timescale = self.env.timescale
        self.scale_factor = scale_time(self.env.timescale, vcd_timescale)
        check_values = self.env.config.setdefault('sim.vcd.check_values', True)
        self.dump_file = open(dump_filename, 'w')
        self.vcd = VCDWriter(self.dump_file,
                             timescale=vcd_timescale,
                             check_values=check_values)
        self.save_filename = self.env.config.setdefault(
            'sim.gtkw.file', 'sim.gtkw')
        if self.env.config.setdefault('sim.gtkw.live'):
            from vcd.gtkw import spawn_gtkwave_interactive
            quiet = self.env.config.setdefault('sim.gtkw.quiet', True)
            spawn_gtkwave_interactive(dump_filename,
                                      self.save_filename,
                                      quiet=quiet)

        start_time = self.env.config.setdefault('sim.vcd.start_time', '')
        stop_time = self.env.config.setdefault('sim.vcd.stop_time', '')
        t_start = (scale_time(parse_time(start_time), self.env.timescale)
                   if start_time else None)
        t_stop = (scale_time(parse_time(stop_time), self.env.timescale)
                  if stop_time else None)
        self.env.process(self._start_stop(t_start, t_stop))
示例#2
0
def main():

    global start

    vcdFile = open("out.vcd", "w")
    vcd = VCDWriter(vcdFile, timescale='1 ns')
    gpio1 = vcd.register_var('BLE', 'timer1', 'wire', size=1, ident='!')
    gpio2 = vcd.register_var('BLE', 'timer2', 'wire', size=1, ident='$')
    start = time.perf_counter_ns()

    # event to signal the consumer to stop consuming
    e = threading.Event()

    timer1 = threading.Timer(10e-3, timer1_func, args=(e, vcd, gpio1))
    #timer2 = threading.Timer(15e-3, timer2_func, args=(e, vcd, gpio2))

    timer1.start()
    time.sleep(10e-3)
    #timer2.start()

    # wait until all timers terminate
    e.wait()

    print("Finish")

    vcd.close()
    vcdFile.close()
示例#3
0
    async def interact(self, device, args, iface):
        vcd_writer = VCDWriter(args.file, timescale="1 ns", check_values=False)
        signals = []
        for index in range(self._event_sources[0].width):
            signals.append(vcd_writer.register_var(scope="", name="pin[{}]".format(index),
                var_type="wire", size=1, init=0))

        try:
            overrun = False
            timestamp = 0
            while not overrun:
                for cycle, events in await iface.read():
                    timestamp = cycle * 1_000_000_000 // self._sample_freq

                    if events == "overrun":
                        self.logger.error("FIFO overrun, shutting down")
                        for signal in signals:
                            vcd_writer.change(signal, timestamp, "x")
                        overrun = True
                        break

                    if "pin" in events: # could be also "throttle"
                        value = events["pin"]
                        for bit, signal in enumerate(signals):
                            vcd_writer.change(signal, timestamp, (value >> bit) & 1)

        finally:
            vcd_writer.close(timestamp)
示例#4
0
    def __init__(self, simulation, *, vcd_file):
        vcd_file = open(vcd_file, "wt")
        self.sim = simulation

        self.vcd_file = vcd_file
        self.vcd_writer = VCDWriter(self.vcd_file,
                                    timescale="1 ps",
                                    comment="Generated by nmigen-yosim")

        self.vcd_vars = []
        if self.vcd_writer is None:
            return
示例#5
0
文件: vcd.py 项目: StanfordAHA/delta
class ModelVCD:
    def __init__(self, model, filename):
        self.nodes: Dict[Node, Variable] = {}
        self.model = model
        self._fd = open(filename, "w+")
        self._vcd = VCDWriter(self._fd)
        self._timestamp = 0
        self.__top = "Top"
        # create variables in the model
        for node in model.nodes:
            tile = f"{self.__top}.TILE_X{node.x}Y{node.y}"
            node_name = str(node)
            var = self._vcd.register_var(tile,
                                         node_name,
                                         "integer",
                                         size=node.width,
                                         init=0)
            self.nodes[node] = var
        self.clk = self._vcd.register_var(self.__top,
                                          "clk",
                                          "integer",
                                          size=1,
                                          init=False)
        self.clk_val = 0

    def eval(self, tick=False):
        self._timestamp += 1
        if tick:
            self.clk_val ^= 1
        self._vcd.change(self.clk, self._timestamp, self.clk_val)

        for node, var in self.nodes.items():
            value = self.model.get_value(node)
            self._vcd.change(var, self._timestamp, value)
        if tick:
            self._timestamp += 1
            self.clk_val ^= 1
            self._vcd.change(self.clk, self._timestamp, self.clk_val)

    def close(self):
        self._vcd.close()
        self._fd.close()

    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.close()
示例#6
0
    def open(self):
        dump_filename = self.env.config.setdefault('sim.vcd.dump_file',
                                                   'sim.vcd')
        if 'sim.vcd.timescale' in self.env.config:
            vcd_ts_str = self.env.config.setdefault(
                'sim.vcd.timescale',
                self.env.config['sim.timescale'])
            vcd_timescale = parse_time(vcd_ts_str)
        else:
            vcd_timescale = self.env.timescale
        self.scale_factor = scale_time(self.env.timescale, vcd_timescale)
        check_values = self.env.config.setdefault('sim.vcd.check_values', True)
        self.dump_file = open(dump_filename, 'w')
        self.vcd = VCDWriter(self.dump_file,
                             timescale=vcd_timescale,
                             check_values=check_values)
        self.save_filename = self.env.config.setdefault('sim.gtkw.file',
                                                        'sim.gtkw')
        if self.env.config.setdefault('sim.gtkw.live'):
            from vcd.gtkw import spawn_gtkwave_interactive
            quiet = self.env.config.setdefault('sim.gtkw.quiet', True)
            spawn_gtkwave_interactive(dump_filename, self.save_filename,
                                      quiet=quiet)

        start_time = self.env.config.setdefault('sim.vcd.start_time', '')
        stop_time = self.env.config.setdefault('sim.vcd.stop_time', '')
        t_start = (scale_time(parse_time(start_time), self.env.timescale)
                   if start_time else None)
        t_stop = (scale_time(parse_time(stop_time), self.env.timescale)
                  if stop_time else None)
        self.env.process(self._start_stop(t_start, t_stop))
示例#7
0
    def emit_vcd(self, filename, *, gtkw_filename=None, add_clock=True):
        """ Emits a VCD file containing the ILA samples.

        Parameters:
            filename      -- The filename to write to, or '-' to write to stdout.
            gtkw_filename -- If provided, a gtkwave save file will be generated that
                             automatically displays all of the relevant signals in the
                             order provided to the ILA.
            add_clock     -- If true or not provided, adds a replica of the ILA's sample
                             clock to make change points easier to see.
        """

        # Select the file-like object we're working with.
        if filename == "-":
            stream = sys.stdout
            close_after = False
        else:
            stream = open(filename, 'w')
            close_after = True

        # Create our basic VCD.
        with VCDWriter(stream, timescale=f"1 ns", date='today') as writer:
            first_timestamp = math.inf
            last_timestamp  = 0

            signals = {}

            # If we're adding a clock...
            if add_clock:
                clock_value  = 0
                clock_signal = writer.register_var('ila', 'ila_clock', 'integer', size=1, init=clock_value ^ 1)


            # Create named values for each of our signals.
            for signal in self.ila.signals:
                signals[signal.name] = writer.register_var('ila', signal.name, 'integer', size=len(signal))

            # Dump the each of our samples into the VCD.
            clock_time = 0
            for timestamp, sample in self.enumerate_samples():
                for signal_name, signal_value in sample.items():

                    # If we're adding a clock signal, add any changes necessary since
                    # the last value-change.
                    if add_clock:
                        while clock_time < timestamp:
                            writer.change(clock_signal, clock_time / 1e-9, clock_value)

                            clock_value ^= 1
                            clock_time  += (self.ila.sample_period / 2)

                    # Register the signal change.
                    writer.change(signals[signal_name], timestamp / 1e-9, signal_value.to_int())


        # If we're generating a GTKW, delegate that to our helper function.
        if gtkw_filename:
            assert(filename != '-')
            self._emit_gtkw(gtkw_filename, filename, add_clock=add_clock)
示例#8
0
class VCDWaveformWriter:
    def __init__(self, simulation, *, vcd_file):
        vcd_file = open(vcd_file, "wt")
        self.sim = simulation

        self.vcd_file = vcd_file
        self.vcd_writer = VCDWriter(self.vcd_file,
                                    timescale="1 ps",
                                    comment="Generated by nmigen-yosim")

        self.vcd_vars = []
        if self.vcd_writer is None:
            return

    def update(self):
        timestamp = self.sim.sim_time
        for vcd_var, signal in self.vcd_vars:
            self.vcd_writer.change(vcd_var, timestamp, signal.value)

    def callback(self, signals):
        self.vcd_vars = []
        for signal in signals:
            hierarchy = signal.name.split('.')
            var_type = "wire"
            var_size = signal.width
            var_init = signal.value
            var_name = hierarchy[-1]
            var_scope = '.'.join(hierarchy[:-1])

            vcd_var = self.vcd_writer.register_var(scope=var_scope,
                                                   name=var_name,
                                                   var_type=var_type,
                                                   size=var_size,
                                                   init=var_init)
            self.vcd_vars.append((vcd_var, signal))

        while True:
            self.update()
            yield

    def __del__(self):
        if self.vcd_writer is not None:
            self.vcd_writer.close(self.sim.sim_time)
        if self.vcd_file is not None:
            self.vcd_file.close()
示例#9
0
文件: pysim.py 项目: awygle/nmigen
    def __init__(self, signal_names, *, vcd_file, gtkw_file=None, traces=()):
        if isinstance(vcd_file, str):
            vcd_file = open(vcd_file, "wt")
        if isinstance(gtkw_file, str):
            gtkw_file = open(gtkw_file, "wt")

        self.vcd_vars = SignalDict()
        self.vcd_file = vcd_file
        self.vcd_writer = vcd_file and VCDWriter(self.vcd_file,
            timescale="100 ps", comment="Generated by nMigen")

        self.gtkw_names = SignalDict()
        self.gtkw_file = gtkw_file
        self.gtkw_save = gtkw_file and GTKWSave(self.gtkw_file)

        self.traces = []

        trace_names = SignalDict()
        for trace in traces:
            if trace not in signal_names:
                trace_names[trace] = trace.name
            self.traces.append(trace)

        if self.vcd_writer is None:
            return

        for signal, names in itertools.chain(signal_names.items(), trace_names.items()):
            if signal.decoder:
                var_type = "string"
                var_size = 1
                var_init = self.decode_to_vcd(signal, signal.reset)
            else:
                var_type = "wire"
                var_size = signal.width
                var_init = signal.reset

            for (*var_scope, var_name) in names:
                suffix = None
                while True:
                    try:
                        if suffix is None:
                            var_name_suffix = var_name
                        else:
                            var_name_suffix = "{}${}".format(var_name, suffix)
                        vcd_var = self.vcd_writer.register_var(
                            scope=var_scope, name=var_name_suffix,
                            var_type=var_type, size=var_size, init=var_init)
                        break
                    except KeyError:
                        suffix = (suffix or 0) + 1

                if signal not in self.vcd_vars:
                    self.vcd_vars[signal] = set()
                self.vcd_vars[signal].add(vcd_var)

                if signal not in self.gtkw_names:
                    self.gtkw_names[signal] = (*var_scope, var_name_suffix)
示例#10
0
文件: tracer.py 项目: sytran/desmod
 def open(self):
     dump_filename = self.env.config['sim.vcd.dump_file']
     if 'sim.vcd.timescale' in self.env.config:
         vcd_timescale = parse_time(self.env.config['sim.vcd.timescale'])
     else:
         vcd_timescale = self.env.timescale
     self.scale_factor = scale_time(self.env.timescale, vcd_timescale)
     check_values = self.env.config.get('sim.vcd.check_values', True)
     self.dump_file = open(dump_filename, 'w')
     self.vcd = VCDWriter(self.dump_file,
                          timescale=vcd_timescale,
                          check_values=check_values)
     if self.env.config.get('sim.gtkw.live'):
         from vcd.gtkw import spawn_gtkwave_interactive
         save_filename = self.env.config['sim.gtkw.file']
         quiet = self.env.config.get('sim.gtkw.quiet', True)
         spawn_gtkwave_interactive(dump_filename, save_filename,
                                   quiet=quiet)
示例#11
0
文件: wrf433.py 项目: wingel/wrf433
class Tracer(object):
    """Write trace to a VCD file"""

    def __init__(self, f):
        from vcd import VCDWriter
        self.writer = VCDWriter(f, timescale = '1 us', date = 'today')
        self.t0 = None

    def add(self, dut, name, *args, **kwargs):
        return TracerVar(self, dut, name, *args, **kwargs)

    def register_var(self, dut, name, *args, **kwargs):
        return self.writer.register_var(dut, name, *args, **kwargs)

    def change(self, var, timestamp, value):
        if not timestamp:
            return

        timestamp = int(timestamp * 1E6)
        if self.t0 is None:
            self.t0 = timestamp
        self.writer.change(var, timestamp - self.t0, value)
示例#12
0
    def open(self) -> None:
        dump_filename: str = self.env.config.setdefault(
            'sim.vcd.dump_file', 'sim.vcd')
        if 'sim.vcd.timescale' in self.env.config:
            vcd_ts_str: str = self.env.config.setdefault(
                'sim.vcd.timescale', self.env.config['sim.timescale'])
            mag, unit = parse_time(vcd_ts_str)
        else:
            mag, unit = self.env.timescale
        mag_int = int(mag)
        if mag_int != mag:
            raise ValueError(
                f'sim.timescale magnitude must be an integer, got {mag}')
        vcd_timescale = mag_int, unit
        self.scale_factor = scale_time(self.env.timescale, vcd_timescale)
        check_values: bool = self.env.config.setdefault(
            'sim.vcd.check_values', True)
        self.dump_file = open(dump_filename, 'w')
        self.vcd = VCDWriter(self.dump_file,
                             timescale=vcd_timescale,
                             check_values=check_values)
        self.save_filename: str = self.env.config.setdefault(
            'sim.gtkw.file', 'sim.gtkw')
        if self.env.config.setdefault('sim.gtkw.live'):
            from vcd.gtkw import spawn_gtkwave_interactive

            quiet: bool = self.env.config.setdefault('sim.gtkw.quiet', True)
            spawn_gtkwave_interactive(dump_filename,
                                      self.save_filename,
                                      quiet=quiet)

        start_time: str = self.env.config.setdefault('sim.vcd.start_time', '')
        stop_time: str = self.env.config.setdefault('sim.vcd.stop_time', '')
        t_start = (scale_time(parse_time(start_time), self.env.timescale)
                   if start_time else None)
        t_stop = (scale_time(parse_time(stop_time), self.env.timescale)
                  if stop_time else None)
        self.env.process(self._start_stop(t_start, t_stop))
示例#13
0
文件: vcd.py 项目: StanfordAHA/delta
 def __init__(self, model, filename):
     self.nodes: Dict[Node, Variable] = {}
     self.model = model
     self._fd = open(filename, "w+")
     self._vcd = VCDWriter(self._fd)
     self._timestamp = 0
     self.__top = "Top"
     # create variables in the model
     for node in model.nodes:
         tile = f"{self.__top}.TILE_X{node.x}Y{node.y}"
         node_name = str(node)
         var = self._vcd.register_var(tile,
                                      node_name,
                                      "integer",
                                      size=node.width,
                                      init=0)
         self.nodes[node] = var
     self.clk = self._vcd.register_var(self.__top,
                                       "clk",
                                       "integer",
                                       size=1,
                                       init=False)
     self.clk_val = 0
示例#14
0
    def run_timed(self,testBench, MaxTime, FileName):
        self.CurrentTime = 0
        
        objName = getNameOf(testBench)

            
        with open(FileName,"w") as f:
            self.writer =  VCDWriter(f, timescale='1 ns', date='today')
            testBench.set_simulation_param("", objName, self)
            p_list = self.get_timed_process_list()
            
            while (self.CurrentTime < MaxTime):
                self.run_processor_timed(p_list)

                while (len(self.updateList)):
                    self.run_symbol_change()
                    self.run_processors()
                    


        self.writer= None
        self.CurrentTime =0
示例#15
0
 def write_vcd(self, path="/tmp/ila.vcd"):
     from pathlib import Path
     path = Path(path)
     print(f"writing vcd to {path.absolute()}")
     from vcd import VCDWriter
     with open(path, "w") as f:
         with VCDWriter(f) as writer:
             vcd_vars = [(writer.register_var(
                 'ila_signals',
                 name,
                 'reg' if decoder is None else 'string',
                 size=size), decoder)
                         for name, (size, decoder) in self.probes]
             clk = writer.register_var('ila_signals', 'clk', 'reg', size=1)
             for timestamp, values in enumerate(self.get_values()):
                 writer.change(clk, timestamp * 2, 1)
                 for (var, decoder), value in zip(vcd_vars, values):
                     writer.change(
                         var, timestamp * 2,
                         value if decoder is None else decoder.get(
                             value, str(value)))
                 writer.change(clk, timestamp * 2 + 1, 0)
示例#16
0
	async def _write_raw_vcd(self, file, iface : JTAGPDIInterface):
		vcd_writer = VCDWriter(file, timescale = "1 ns", check_values = False)
		pdiClk = vcd_writer.register_var(scope = "", name = "pdiClk", var_type = "wire", size = 1, init = 1)
		pdiData = vcd_writer.register_var(scope = "", name = "pdiData", var_type = "wire", size = 8)

		cycle = 1
		try:
			while True:
				for byte in await iface.read():
					vcd_writer.change(pdiClk, cycle, 0)
					vcd_writer.change(pdiData, cycle, byte)
					cycle += 1
					vcd_writer.change(pdiClk, cycle, 1)
					cycle += 1
		finally:
			vcd_writer.close(cycle)
示例#17
0
    def __init__(self, str_cfg, result_type_raw, result_path_raw, result_path,
                 float_type=True, emu_time_scaled=True, debug=False,
                 dt_scale=1e-15):
        """

        :param str_cfg: structure config object used in current project.
        :param result_type_raw: filetype of result file to be converted
        :param result_path_raw: path to raw result file
        :param result_path: path to converted result file
        :param float_type: flag to indicate if real signal's data type is fixed-point or floating point
        :param emu_time_scaled: flag to indicate, if signals shall be displayed over cycle count or time
        :param debug: if debug flag is set to true, all signals from result file will be kept, even if they are not a
                        specified probe; keep in mind, that for those signals no fixed to float conversion can be done
        """

        # defaults
        self.result_path_raw = result_path_raw
        scfg = str_cfg
        self.signal_lookup = {}

        # store data from FPGA in a dictionary
        probe_data = {}
        real_signals = set()
        reg_widths = {}

        if result_type_raw == ResultFileTypes.CSV:
            # read CSV file
            with open(self.result_path_raw, 'r') as f:
                first_line = f.readline()

            # split up the first line into comma-delimited names
            signals = first_line.split(',')

            # account for whitespace
            signals = [signal.strip() for signal in signals]

            # strip off the signal indices and add to a lookup table
            for k, signal in enumerate(signals):
                if '[' in signal:
                    signal = signal[:signal.index('[')]
                self.signal_lookup[signal] = k

            # print keys
            print(f'Signals in result file: {[key for key in self.signal_lookup.keys()]}')

            for analog_signal in scfg.analog_probes:
                name = 'trace_port_gen_i/' + analog_signal.name
                if (name) in self.signal_lookup:
                    # add to set of probes with "real" data type
                    real_signals.add(name)

                    # get unscaled data and apply scaling factor
                    probe_data[name] = (2 ** int(analog_signal.exponent)) * self.get_csv_col(name)

                    # convert data to native Python float type (rather than numpy float)
                    # this is required for PyVCD
                    try:
                        probe_data[name] = [float(x) for x in probe_data[name]]
                    except:
                        probe_data[name] = [float(probe_data[name])]

            for digital_signal in scfg.digital_probes + [scfg.dec_cmp] + [scfg.time_probe]:
                name = 'trace_port_gen_i/' + digital_signal.name
                if name in self.signal_lookup:
                    # define width for this probe
                    reg_widths[name] = int(digital_signal.width)

                    # get unscaled data
                    probe_data[name] = self.get_csv_col(name)

                    # convert data to native Python int type (rather than numpy int)
                    # this is required for PyVCD
                    try:
                        probe_data[name] = [int(x) for x in probe_data[name]]
                    except ValueError:
                        print(f'ValueError encountered when converting probe_data[{name}].')
                        print(f'Contents of probe_data[{name}]:')
                        print(f'{probe_data}')
                        print(f'Contents of CSV file {self.result_path_raw}:')
                        print(open(self.result_path_raw, 'r').read())
                        raise

            # Write data to VCD file
            with open(result_path, 'w') as vcd:
                timescale = self.get_pyvcd_timescale(dt_scale)
                with VCDWriter(vcd, timescale=timescale, date=str(datetime.datetime.today())) as writer:
                    # register all of the signals that will be written to VCD
                    reg = {}
                    for sig, scaled_data in probe_data.items():
                        # determine signal scope and name
                        signal_split = sig.split('/')
                        vcd_scope = '.'.join(signal_split[:-1])
                        vcd_name = signal_split[-1]

                        # determine signal type and size
                        if sig in real_signals:
                            vcd_var_type = 'real'
                            vcd_size = None
                        elif sig in reg_widths:
                            vcd_var_type = 'reg'
                            vcd_size = reg_widths[sig]
                        else:
                            raise Exception('Unknown signal type.')

                        # register the signal
                        reg[sig] = writer.register_var(scope=vcd_scope, name=vcd_name,
                                                                    var_type=vcd_var_type,
                                                                    size=vcd_size)

                    # iterate over all timesteps
                    prev_timestep = float('-inf')
                    for k, timestamp in enumerate(probe_data['trace_port_gen_i/' + scfg.time_probe.name]):
                        # break if the current timestep is less than the previous one, since that means
                        # wrapping has occurred.  (only if emu_time_scaled is True, meaning that
                        # we're using emu_time on the x axis, not cycle number)
                        if emu_time_scaled and (timestamp < prev_timestep):
                            break
                        prev_timestep = timestamp

                        # Set the x-axis value according to emu_time_scaled: True means use
                        # emu_time, and False means use the cycle number
                        if emu_time_scaled:
                            chg_val = timestamp
                        else:
                            chg_val = k

                        # iterate over all signals and log their change at this timestamp
                        for sig, scaled_data in probe_data.items():
                            writer.change(reg[sig], chg_val, scaled_data[k])

        elif result_type_raw == ResultFileTypes.VCD:
            vcd_file_name = result_path_raw
            vcd_handle = ParseVCD(vcd_file_name)
            signal_dict = vcd_handle.parse_vcd(update_data=False)

            # print signal names
            signal_names = [(signal_dict[key]["nets"][0]["hier"] + '.' + signal_dict[key]["nets"][0]["name"], key) for key in signal_dict.keys()]
            print(f'Signals in result file: {[sig_name[0] for sig_name in signal_names]}')

            for analog_signal in scfg.analog_probes:
                analog_signal_path = 'top.trace_port_gen_i' + '.' + analog_signal.name
                if analog_signal_path in [sig[0] for sig in signal_names]:
                    # add to set of probes with "real" data type
                    real_signals.add(analog_signal_path)

                    probe_data[analog_signal_path] = {}
                    probe_data[analog_signal_path]['index'] = 0

                    # get the signal identifier from analog_signal used in VCD file
                    signal_identifier = signal_names[[y[0] for y in signal_names].index(analog_signal_path)][1]
                    data = []
                    for c,v in signal_dict[signal_identifier]['cv']:
                        if not isinstance(v, float):
                            for k in range(analog_signal.width - len(v)): # extend binary to full width, some simulators don't do that by default and remove leading zeros in VCD file
                                v = '0' + v
                            if v[0] == '1': # check if number is negative and if so calculate the two's complement
                                v = -1 * (int((''.join('1' if x == '0' else '0' for x in v)), 2) + 1)
                            else:
                                v = int(v, 2)
                        if not float_type:
                            v = 2 ** int(analog_signal.exponent) * v
                        data.append((c, v))
                    probe_data[analog_signal_path]['data'] = np.asarray(data)

                    # convert data to native Python float type (rather than numpy float) this is required for PyVCD
                    probe_data[analog_signal_path]['data'] = [(int(c), float(v)) for c, v in probe_data[analog_signal_path]['data']]

            for digital_signal in scfg.digital_probes + [scfg.dec_cmp] + [scfg.time_probe]:
                digital_signal_path = 'top.trace_port_gen_i' + '.' + digital_signal.name
                if digital_signal_path in [sig[0] for sig in signal_names]:
                    # define width for this probe
                    reg_widths[digital_signal_path] = int(digital_signal.width)

                    probe_data[digital_signal_path] = {}
                    probe_data[digital_signal_path]['index'] = 0

                    # get unscaled data
                    probe_data[digital_signal_path]['data'] = np.asarray([(c, v) for c,v in signal_dict[signal_names[[y[0] for y in signal_names].index(digital_signal_path)][1]]['cv']])

                    # convert data to native Python int type (rather than numpy int) this is required for PyVCD
                    data = []
                    for c, v in probe_data[digital_signal_path]['data']:
                        try:
                            data.append((int(c), int(v, 2)))
                        except: # In case of an x or z value, a 0 will be added; this is necessary for PYVCD
                            data.append((int(c), int(0)))

                    probe_data[digital_signal_path]['data'] = data

            # Write data to VCD file

            with open(result_path, 'w') as vcd:
                timescale = self.get_pyvcd_timescale(dt_scale)
                with VCDWriter(vcd, timescale=timescale, date=str(datetime.datetime.today())) as writer:
                    # register all of the signals that will be written to VCD
                    reg = {}
                    for sig, scaled_data in probe_data.items():
                        # determine signal scope and name
                        signal_split = sig.split('.')
                        vcd_scope = '.'.join(signal_split[:-1])
                        vcd_name = signal_split[-1]

                        # determine signal type and size
                        if sig in real_signals:
                            vcd_var_type = 'real'
                            vcd_size = None
                        elif sig in reg_widths:
                            vcd_var_type = 'reg'
                            vcd_size = reg_widths[sig]
                        else:
                            raise Exception('Unknown signal type.')

                        # register the signal
                        reg[sig] = writer.register_var(scope=vcd_scope, name=vcd_name,
                                                                    var_type=vcd_var_type,
                                                                    size=vcd_size)

                    prev_timestep = float('-inf')
                    # Add all other signals in case debug flag is set
                    if debug:
                        for signal in signal_names:
                            if not signal[0] in probe_data.keys(): # signal was not listed yet
                                var_type = signal_dict[signal[1]]['nets'][0]['type']
                                if var_type != 'parameter':
                                    name = signal_dict[signal[1]]['nets'][0]['name']
                                    scope = signal_dict[signal[1]]['nets'][0]['hier']
                                    path = scope + '.' + name
                                    size = signal_dict[signal[1]]['nets'][0]['size']

                                    # register the signal
                                    reg[path] = writer.register_var(scope=scope, name=name, var_type=var_type, size=int(size))

                    # time probe path
                    time_path = 'top.trace_port_gen_i' + '.' + scfg.time_probe.name

                    # calculate emu_time offset
                    offset = 0
                    for idx, (cycle_count, timestamp) in enumerate(probe_data[time_path]['data']):
                        # break if the current timestep is less than the previous one, since that means
                        # wrapping has occurred
                        if timestamp < prev_timestep:
                            break
                        prev_timestep = timestamp

                        if timestamp > 0:
                            break

                        offset = cycle_count

                    #############################
                    # Represent signals over time
                    #############################

                    if emu_time_scaled:
                        # Add an index to all signals in signal dict, in case debug option was selected:
                        if debug:
                            for sig in signal_dict.keys():
                                signal_dict[sig]['index'] = 0

                        for idx, (cycle_count, timestamp) in enumerate(probe_data[time_path]['data']):
                            # break if timestamp is less than zero since it means that wrapping has occurred
                            if timestamp < 0:
                                break

                            # store all available signals in list, any signal, that is no longer in the list will be skipped
                            # signals, where the cycle_count is nop longer between current and next cycle count of the time
                            # signal will be removed from the list
                            sigs_in_interval = []
                            for sig in probe_data.keys():
                                sigs_in_interval.append((sig, None))

                            # Add all other signals in case debug flag is set
                            if debug:
                                for signal in signal_names:
                                    if not signal[0] in probe_data.keys() and not signal_dict[signal[1]]['nets'][0]['type'] == 'parameter':  # signal was not listed yet
                                        sigs_in_interval.append((signal[0], signal[1]))

                            # list of all activities within time interval
                            timestep_events = []

                            # As soon as all signals are no longer in the interval, timestep will advance
                            while sigs_in_interval:
                                for sig in sigs_in_interval:
                                    if sig[0] in probe_data.keys():
                                        sig_tuple = probe_data[sig[0]]['data'][probe_data[sig[0]]['index']]
                                    else: # debug signals
                                        sig_tuple = signal_dict[sig[1]]['cv'][signal_dict[sig[1]]['index']]

                                    if cycle_count == sig_tuple[0]:
                                        timestep_events.append([sig, timestamp, sig_tuple[1]])

                                        if sig[0] in probe_data.keys():
                                            probe_data[sig[0]]['index'] += 1
                                        else:
                                            signal_dict[sig[1]]['index'] += 1

                                        # This signal no longer needs to be observed
                                        sigs_in_interval.remove(sig)
                                    else:
                                        try: # Check if time signal is already at the end
                                            next_timestamp = probe_data[time_path]['data'][idx + 1][0]
                                        except: # Time signal has finished the end, finish conversion
                                            sigs_in_interval = []
                                            break
                                        if round(next_timestamp - offset) > sig_tuple[0]:
                                            # Note: There is always an offset between cycle count and timestamp  -> substract offset
                                            # The cycle count from data signal does not have a match with emu_time signal's cycle count
                                            # -> we need to apply interpolation in order to assign the timestamp properly
                                            cycles_in_dt = probe_data[time_path]['data'][idx+1][0] - cycle_count
                                            dt = probe_data[time_path]['data'][idx+1][1] - timestamp
                                            interp_timestamp = int(dt/cycles_in_dt * (sig_tuple[0] - cycle_count + offset) + timestamp)

                                            timestep_events.append([sig, interp_timestamp, sig_tuple[1]])

                                            if sig[0] in probe_data.keys():
                                                probe_data[sig[0]]['index'] += 1
                                            else:
                                                signal_dict[sig[1]]['index'] += 1
                                        else:
                                            # This signal no longer needs to be observed
                                            sigs_in_interval.remove(sig)

                            # Register events in time interval in chronological order
                            timestep_events = sorted(timestep_events, key=self.sort_timestamp)
                            for [name, timestamp, value] in timestep_events:
                                writer.change(reg[name[0]], timestamp, value)

                    ####################################
                    # Represent signals over cycle count
                    ####################################

                    else:
                        time_events = []  # store all events from result file
                        for signal in probe_data.keys():
                            for sig_tuple in probe_data[signal]['data']:
                                time_events.append([signal, sig_tuple[0], sig_tuple[1]])

                        # Add all other signals in case debug flag is set
                        if debug:
                            for signal in signal_names:
                                if not signal[0] in probe_data.keys() and not signal_dict[signal[1]]['nets'][0]['type'] == 'parameter':  # signal was not listed yet
                                    name = signal_dict[signal[1]]['nets'][0]['name']
                                    hier = signal_dict[signal[1]]['nets'][0]['hier']
                                    path = hier + '.' + name
                                    for sig_tuple in signal_dict[signal[1]]['cv']:
                                        time_events.append([path, sig_tuple[0], sig_tuple[1]])

                        # Register events in chronological order
                        time_events = sorted(time_events, key=self.sort_timestamp)
                        for [sig_name, timestamp, value] in time_events:
                            writer.change(reg[sig_name], timestamp, value)



        else:
            raise Exception(f'ERROR: No supported Result file format selected:{result_type_raw}')
示例#18
0
文件: wrf433.py 项目: wingel/wrf433
 def __init__(self, f):
     from vcd import VCDWriter
     self.writer = VCDWriter(f, timescale = '1 us', date = 'today')
     self.t0 = None
示例#19
0
t_timescale = next(list_tokens[0])
t_module = next(list_tokens[0])

max = 0
oldmax = 0
get_header = 0
prev_max = 0
index = 0

list1 = []
list2 = []
list3 = []
list4 = []

with VCDWriter(w,
               timescale=t_timescale.data,
               version=t_version.data,
               date=t_date.data) as writer:
    for lt in list_tokens:
        token = next(lt)
        print("file : " + str(num_ct_index))
        while 1:
            if (token.kind is TokenKind.DATE or token.kind is TokenKind.VERSION
                    or token.kind is TokenKind.TIMESCALE
                    or token.kind is TokenKind.SCOPE):
                try:
                    token = next(lt)
                    continue
                except StopIteration:
                    index = 0
                    list3.clear()
                    break
示例#20
0
	async def _write_pdi_vcd(self, file, iface : JTAGPDIInterface):
		vcd_writer = VCDWriter(file, timescale = "1 ns", check_values = False)
		pdiClk = vcd_writer.register_var(scope = "", name = "pdiClk", var_type = "wire", size = 1, init = 1)
		pdiData = vcd_writer.register_var(scope = "", name = "pdiData", var_type = "wire", size = 1, init = 1)

		cycle = 1
		operation = 0
		count = 4
		pdiInsn = PDIOpcodes.IDLE
		readCount = 0
		writeCount = 0
		repCount = 0
		repBytes = 0

		try:
			while True:
				for byte in await iface.read():
					if operation == 0:
						operation = byte
						continue
					elif operation == Header.IDCode:
						count -= 1
						if count == 0:
							operation = 0
							count = 4
						continue
					elif operation == Header.PDI and (readCount == 0 and writeCount == 0):
						pdiInsn = (byte & 0xE0) >> 5
						readCount, writeCount = self._decode_counts(pdiInsn, byte & 0x0F, repCount)
						if pdiInsn == PDIOpcodes.LD or pdiInsn == PDIOpcodes.ST:
							repCount = 0
					else:
						if writeCount != 0:
							writeCount -= 1
						else:
							readCount -= 1

						if pdiInsn == PDIOpcodes.REPEAT:
							repCount <<= 8
							repCount |= byte
							repBytes += 1
							if writeCount == 0:
								repCount = self._reverse_count(repCount, repBytes)
								repBytes = 0

						if readCount == 0 and writeCount == 0:
							operation = 0

					vcd_writer.change(pdiClk, cycle, 0)
					vcd_writer.change(pdiData, cycle, 0)
					cycle += 1
					vcd_writer.change(pdiClk, cycle, 1)
					cycle += 1
					parity = 0
					for i in range(8):
						bit = (byte >> i) & 1
						parity ^= bit
						vcd_writer.change(pdiClk, cycle, 0)
						vcd_writer.change(pdiData, cycle, bit)
						cycle += 1
						vcd_writer.change(pdiClk, cycle, 1)
						cycle += 1
					vcd_writer.change(pdiClk, cycle, 0)
					vcd_writer.change(pdiData, cycle, parity)
					cycle += 1
					vcd_writer.change(pdiClk, cycle, 1)
					cycle += 1
					vcd_writer.change(pdiClk, cycle, 0)
					vcd_writer.change(pdiData, cycle, 1)
					cycle += 1
					vcd_writer.change(pdiClk, cycle, 1)
					cycle += 1
					vcd_writer.change(pdiClk, cycle, 0)
					cycle += 1
					vcd_writer.change(pdiClk, cycle, 1)
					cycle += 1
		finally:
			vcd_writer.close(cycle)
示例#21
0
async def _main():
    args = get_argparser().parse_args()
    create_logger(args)

    device = None
    try:
        # TODO(py3.7): use importlib.resources
        firmware_filename = os.path.join(os.path.dirname(__file__),
                                         "glasgow.ihex")
        if args.action in ("build", "test", "tool"):
            pass
        elif args.action == "factory":
            device = GlasgowHardwareDevice(args.serial,
                                           firmware_filename,
                                           _factory_rev=args.factory_rev)
        else:
            device = GlasgowHardwareDevice(args.serial, firmware_filename)

        if args.action == "voltage":
            if args.voltage is not None:
                await device.reset_alert(args.ports)
                await device.poll_alert()  # clear any remaining alerts
                try:
                    await device.set_voltage(args.ports, args.voltage)
                except:
                    await device.set_voltage(args.ports, 0.0)
                    raise
                if args.set_alert and args.voltage != 0.0:
                    await asyncio.sleep(
                        0.050)  # let the output capacitor discharge a bit
                    await device.set_alert_tolerance(args.ports, args.voltage,
                                                     args.tolerance / 100)

            print("Port\tVio\tVlimit\tVsense\tMonitor")
            alerts = await device.poll_alert()
            for port in args.ports:
                vio = await device.get_voltage(port)
                vlimit = await device.get_voltage_limit(port)
                vsense = await device.measure_voltage(port)
                alert = await device.get_alert(port)
                notice = ""
                if port in alerts:
                    notice += " (ALERT)"
                print("{}\t{:.2}\t{:.2}\t{:.3}\t{:.2}-{:.2}\t{}".format(
                    port, vio, vlimit, vsense, alert[0], alert[1], notice))

        if args.action == "safe":
            await device.reset_alert("AB")
            await device.set_voltage("AB", 0.0)
            await device.poll_alert()  # clear any remaining alerts
            logger.info("all ports safe")

        if args.action == "voltage-limit":
            if args.voltage is not None:
                await device.set_voltage_limit(args.ports, args.voltage)

            print("Port\tVio\tVlimit")
            for port in args.ports:
                vio = await device.get_voltage(port)
                vlimit = await device.get_voltage_limit(port)
                print("{}\t{:.2}\t{:.2}".format(port, vio, vlimit))

        if args.action in ("run", "run-repl", "run-prebuilt"):
            target, applet = _applet(device.revision, args)
            device.demultiplexer = DirectDemultiplexer(
                device, target.multiplexer.pipe_count)
            plan = target.build_plan()

            if args.action in ("run", "run-repl"):
                await device.download_target(plan, rebuild=args.rebuild)
            if args.action == "run-prebuilt":
                bitstream_file = args.bitstream or open(
                    "{}.bin".format(args.applet), "rb")
                with bitstream_file:
                    logger.warn("downloading prebuilt bitstream from %r",
                                bitstream_file.name)
                    await device.download_bitstream(bitstream_file.read())

            do_trace = hasattr(args, "trace") and args.trace
            if do_trace:
                logger.info("starting applet analyzer")
                await device.write_register(target.analyzer.addr_done, 0)
                analyzer_iface = await device.demultiplexer.claim_interface(
                    target.analyzer, target.analyzer.mux_interface, args=None)
                trace_decoder = TraceDecoder(target.analyzer.event_sources)
                vcd_writer = VCDWriter(
                    args.trace,
                    timescale="1 ns",
                    check_values=False,
                    comment='Generated by Glasgow for bitstream ID %s' %
                    plan.bitstream_id.hex())

            async def run_analyzer():
                signals = {}
                strobes = set()
                for field_name, field_trigger, field_width in trace_decoder.events(
                ):
                    if field_trigger == "throttle":
                        var_type = "wire"
                        var_init = 0
                    elif field_trigger == "change":
                        var_type = "wire"
                        var_init = "x"
                    elif field_trigger == "strobe":
                        if field_width > 0:
                            var_type = "tri"
                            var_init = "z"
                        else:
                            var_type = "event"
                            var_init = ""
                    else:
                        assert False
                    signals[field_name] = vcd_writer.register_var(
                        scope="",
                        name=field_name,
                        var_type=var_type,
                        size=field_width,
                        init=var_init)
                    if field_trigger == "strobe":
                        strobes.add(field_name)

                init = True
                while not trace_decoder.is_done():
                    trace_decoder.process(await analyzer_iface.read())
                    for cycle, events in trace_decoder.flush():
                        if events == "overrun":
                            target.analyzer.logger.error(
                                "FIFO overrun, shutting down")

                            for name in signals:
                                vcd_writer.change(signals[name],
                                                  next_timestamp, "x")
                            timestamp += 1e3  # 1us
                            break

                        event_repr = " ".join("{}={}".format(n, v)
                                              for n, v in events.items())
                        target.analyzer.logger.trace("cycle %d: %s", cycle,
                                                     event_repr)

                        timestamp = 1e9 * (cycle + 0) // target.sys_clk_freq
                        next_timestamp = 1e9 * (cycle +
                                                1) // target.sys_clk_freq
                        if init:
                            init = False
                            vcd_writer._timestamp = timestamp
                        for name, value in events.items():
                            vcd_writer.change(signals[name], timestamp, value)
                        for name, _value in events.items():
                            if name in strobes:
                                vcd_writer.change(signals[name],
                                                  next_timestamp, "z")
                        vcd_writer.flush()

                vcd_writer.close(timestamp)

            async def run_applet():
                logger.info("running handler for applet %r", args.applet)
                if applet.preview:
                    logger.warn(
                        "applet %r is PREVIEW QUALITY and may CORRUPT DATA",
                        args.applet)
                try:
                    iface = await applet.run(device, args)
                    if args.action in ("run", "run-prebuilt"):
                        await applet.interact(device, args, iface)
                    if args.action == "run-repl":
                        if applet.has_custom_repl:
                            logger.warn(
                                "applet provides customized REPL(s); consider using `run "
                                "{} ...-repl` subcommands".format(applet.name))
                        logger.info(
                            "dropping to REPL; use 'help(iface)' to see available APIs"
                        )
                        await AsyncInteractiveConsole(locals={
                            "iface": iface
                        }).interact()
                except GlasgowAppletError as e:
                    applet.logger.error(str(e))
                except asyncio.CancelledError:
                    pass  # terminate gracefully
                finally:
                    await device.demultiplexer.flush()

            async def wait_for_sigint():
                await wait_for_signal(signal.SIGINT)
                logger.debug("Ctrl+C pressed, terminating")

            if do_trace:
                analyzer_task = asyncio.ensure_future(run_analyzer())

            applet_task = asyncio.ensure_future(run_applet())
            sigint_task = asyncio.ensure_future(wait_for_sigint())

            tasks = [applet_task, sigint_task]
            done, pending = await asyncio.wait(
                tasks, return_when=asyncio.FIRST_COMPLETED)
            for task in pending:
                task.cancel()
            for task in tasks:
                try:
                    await task
                except asyncio.CancelledError:
                    pass

            if do_trace:
                await device.write_register(target.analyzer.addr_done, 1)
                await analyzer_task

            await device.demultiplexer.cancel()

        if args.action == "tool":
            tool = GlasgowApplet.all_applets[args.applet].tool_cls()
            try:
                await tool.run(args)
            except GlasgowAppletError as e:
                tool.logger.error(e)
                raise SystemExit()

        if args.action == "flash":
            logger.info("reading device configuration")
            header = await device.read_eeprom("fx2", 0,
                                              8 + 4 + GlasgowConfig.size)
            header[0] = 0xC2  # see below

            fx2_config = FX2Config.decode(header, partial=True)
            if (len(fx2_config.firmware) != 1
                    or fx2_config.firmware[0][0] != 0x4000 - GlasgowConfig.size
                    or len(fx2_config.firmware[0][1]) != GlasgowConfig.size):
                raise SystemExit(
                    "Unrecognized or corrupted configuration block")
            glasgow_config = GlasgowConfig.decode(fx2_config.firmware[0][1])

            logger.info("device has serial %s-%s", glasgow_config.revision,
                        glasgow_config.serial)
            if fx2_config.disconnect:
                logger.info("device has flashed firmware")
            else:
                logger.info("device does not have flashed firmware")
            if glasgow_config.bitstream_size:
                logger.info("device has flashed bitstream ID %s",
                            glasgow_config.bitstream_id.hex())
            else:
                logger.info("device does not have flashed bitstream")

            new_bitstream = b""
            if args.remove_bitstream:
                logger.info("removing bitstream")
                glasgow_config.bitstream_size = 0
                glasgow_config.bitstream_id = b"\x00" * 16
            elif args.bitstream:
                logger.info("using bitstream from %s", args.bitstream.name)
                with args.bitstream as f:
                    new_bitstream = f.read()
                    glasgow_config.bitstream_size = len(new_bitstream)
                    glasgow_config.bitstream_id = b"\xff" * 16
            elif args.applet:
                logger.info("building bitstream for applet %s", args.applet)
                target, applet = _applet(device.revision, args)
                plan = target.build_plan()
                new_bitstream_id = plan.bitstream_id
                new_bitstream = plan.execute()

                # We always build and reflash the bitstream in case the one currently
                # in EEPROM is corrupted. If we only compared the ID, there would be
                # no easy way to recover from that case. There's also no point in
                # storing the bitstream hash (as opposed to Verilog hash) in the ID,
                # as building the bitstream takes much longer than flashing it.
                logger.info("built bitstream ID %s", new_bitstream_id.hex())
                glasgow_config.bitstream_size = len(new_bitstream)
                glasgow_config.bitstream_id = new_bitstream_id

            fx2_config.firmware[0] = (0x4000 - GlasgowConfig.size,
                                      glasgow_config.encode())

            if args.remove_firmware:
                logger.info("removing firmware")
                fx2_config.disconnect = False
                new_image = fx2_config.encode()
                new_image[0] = 0xC0  # see below
            else:
                logger.info(
                    "using firmware from %r",
                    args.firmware.name if args.firmware else firmware_filename)
                with (args.firmware or open(firmware_filename, "rb")) as f:
                    for (addr, chunk) in input_data(f, fmt="ihex"):
                        fx2_config.append(addr, chunk)
                fx2_config.disconnect = True
                new_image = fx2_config.encode()

            if new_bitstream:
                logger.info("programming bitstream")
                old_bitstream = await device.read_eeprom(
                    "ice", 0, len(new_bitstream))
                if old_bitstream != new_bitstream:
                    for (addr, chunk) in diff_data(old_bitstream,
                                                   new_bitstream):
                        await device.write_eeprom("ice", addr, chunk)

                    logger.info("verifying bitstream")
                    if await device.read_eeprom(
                            "ice", 0, len(new_bitstream)) != new_bitstream:
                        logger.critical("bitstream programming failed")
                        return 1
                else:
                    logger.info("bitstream identical")

            logger.info("programming configuration and firmware")
            old_image = await device.read_eeprom("fx2", 0, len(new_image))
            if old_image != new_image:
                for (addr, chunk) in diff_data(old_image, new_image):
                    await device.write_eeprom("fx2", addr, chunk)

                logger.info("verifying configuration and firmware")
                if await device.read_eeprom("fx2", 0,
                                            len(new_image)) != new_image:
                    logger.critical(
                        "configuration/firmware programming failed")
                    return 1
            else:
                logger.info("configuration and firmware identical")

        if args.action == "build":
            target, applet = _applet(args.rev, args)
            plan = target.build_plan()
            if args.type in ("il", "rtlil"):
                logger.info("building RTLIL for applet %r", args.applet)
                with open(args.filename or args.applet + ".il", "wt") as f:
                    f.write(plan.rtlil)
            if args.type in ("bin", "bitstream"):
                logger.info("building bitstream for applet %r", args.applet)
                with open(args.filename or args.applet + ".bin", "wb") as f:
                    f.write(plan.execute())
            if args.type in ("zip", "archive"):
                logger.info("building archive for applet %r", args.applet)
                plan.archive(args.filename or args.applet + ".zip")

        if args.action == "test":
            logger.info("testing applet %r", args.applet)
            applet = GlasgowApplet.all_applets[args.applet]()
            loader = unittest.TestLoader()
            stream = unittest.runner._WritelnDecorator(sys.stderr)
            result = unittest.TextTestResult(stream=stream,
                                             descriptions=True,
                                             verbosity=2)
            result.failfast = True

            def startTest(test):
                unittest.TextTestResult.startTest(result, test)
                result.stream.write("\n")

            result.startTest = startTest
            if args.tests == []:
                suite = loader.loadTestsFromTestCase(applet.test_cls)
                suite.run(result)
            else:
                for test in args.tests:
                    suite = loader.loadTestsFromName(test,
                                                     module=applet.test_cls)
                    suite.run(result)
            if not result.wasSuccessful():
                for _, traceback in result.errors + result.failures:
                    print(traceback, end="", file=sys.stderr)
                return 1

        if args.action == "factory":
            logger.info("reading device configuration")
            header = await device.read_eeprom("fx2", 0,
                                              8 + 4 + GlasgowConfig.size)
            if not re.match(rb"^\xff+$", header):
                if args.force:
                    logger.warning(
                        "device already factory-programmed, proceeding anyway")
                else:
                    logger.error("device already factory-programmed")
                    return 1

            fx2_config = FX2Config(vendor_id=VID_QIHW,
                                   product_id=PID_GLASGOW,
                                   device_id=GlasgowConfig.encode_revision(
                                       args.rev),
                                   i2c_400khz=True)
            glasgow_config = GlasgowConfig(args.factory_rev,
                                           args.factory_serial)
            fx2_config.append(0x4000 - GlasgowConfig.size,
                              glasgow_config.encode())

            image = fx2_config.encode()
            # Let FX2 hardware enumerate. This won't load the configuration block
            # into memory automatically, but the firmware has code that does that
            # if it detects a C0 load.
            image[0] = 0xC0

            logger.info("programming device configuration")
            await device.write_eeprom("fx2", 0, image)

            logger.info("verifying device configuration")
            if await device.read_eeprom("fx2", 0, len(image)) != image:
                logger.critical("factory programming failed")
                return 1

    except GlasgowDeviceError as e:
        logger.error(e)
        return 1

    except GatewareBuildError as e:
        applet.logger.error(e)
        return 1

    finally:
        if device is not None:
            device.close()

    return 0
示例#22
0
文件: cli.py 项目: sd-fritze/Glasgow
async def _main():
    args = get_argparser().parse_args()
    create_logger(args)

    try:
        firmware_file = os.path.join(os.path.dirname(__file__), "glasgow.ihex")
        if args.action in ("build", "test", "tool"):
            pass
        elif args.action == "factory":
            device = GlasgowHardwareDevice(firmware_file, VID_CYPRESS, PID_FX2)
        else:
            device = GlasgowHardwareDevice(firmware_file)

        if args.action == "voltage":
            if args.voltage is not None:
                await device.reset_alert(args.ports)
                await device.poll_alert()  # clear any remaining alerts
                try:
                    await device.set_voltage(args.ports, args.voltage)
                except:
                    await device.set_voltage(args.ports, 0.0)
                    raise
                if args.set_alert and args.voltage != 0.0:
                    await asyncio.sleep(
                        0.050)  # let the output capacitor discharge a bit
                    await device.set_alert_tolerance(args.ports, args.voltage,
                                                     args.tolerance / 100)

            print("Port\tVio\tVlimit\tVsense\tMonitor")
            alerts = await device.poll_alert()
            for port in args.ports:
                vio = await device.get_voltage(port)
                vlimit = await device.get_voltage_limit(port)
                vsense = await device.measure_voltage(port)
                alert = await device.get_alert(port)
                notice = ""
                if port in alerts:
                    notice += " (ALERT)"
                print("{}\t{:.2}\t{:.2}\t{:.3}\t{:.2}-{:.2}\t{}".format(
                    port, vio, vlimit, vsense, alert[0], alert[1], notice))

        if args.action == "voltage-limit":
            if args.voltage is not None:
                await device.set_voltage_limit(args.ports, args.voltage)

            print("Port\tVio\tVlimit")
            for port in args.ports:
                vio = await device.get_voltage(port)
                vlimit = await device.get_voltage_limit(port)
                print("{}\t{:.2}\t{:.2}".format(port, vio, vlimit))

        if args.action == "run":
            if args.applet:
                target, applet = _applet(device.revision, args)
                device.demultiplexer = DirectDemultiplexer(device)

                await device.download_target(
                    target,
                    rebuild=args.rebuild,
                    toolchain_opts=_toolchain_opts(args))

                if args.trace:
                    logger.info("starting applet analyzer")
                    await device.write_register(target.analyzer.addr_done, 0)
                    analyzer_iface = await device.demultiplexer.claim_interface(
                        target.analyzer,
                        target.analyzer.mux_interface,
                        args=None)
                    trace_decoder = TraceDecoder(target.analyzer.event_sources)
                    vcd_writer = VCDWriter(
                        args.trace,
                        timescale="1 ns",
                        check_values=False,
                        comment='Generated by Glasgow for bitstream ID %s' %
                        target.get_bitstream_id().hex())

                async def run_analyzer():
                    if not args.trace:
                        return

                    signals = {}
                    strobes = set()
                    for field_name, field_trigger, field_width in trace_decoder.events(
                    ):
                        if field_trigger == "throttle":
                            var_type = "wire"
                            var_init = 0
                        elif field_trigger == "change":
                            var_type = "wire"
                            var_init = "x"
                        elif field_trigger == "strobe":
                            if field_width > 0:
                                var_type = "tri"
                                var_init = "z"
                            else:
                                var_type = "event"
                                var_init = ""
                        else:
                            assert False
                        signals[field_name] = vcd_writer.register_var(
                            scope="",
                            name=field_name,
                            var_type=var_type,
                            size=field_width,
                            init=var_init)
                        if field_trigger == "strobe":
                            strobes.add(field_name)

                    init = True
                    while not trace_decoder.is_done():
                        trace_decoder.process(await analyzer_iface.read())
                        for cycle, events in trace_decoder.flush():
                            if events == "overrun":
                                target.analyzer.logger.error(
                                    "FIFO overrun, shutting down")

                                for name in signals:
                                    vcd_writer.change(signals[name],
                                                      next_timestamp, "x")
                                timestamp += 1e3  # 1us
                                break

                            event_repr = " ".join("{}={}".format(n, v)
                                                  for n, v in events.items())
                            target.analyzer.logger.trace(
                                "cycle %d: %s", cycle, event_repr)

                            timestamp = 1e9 * (cycle +
                                               0) // target.sys_clk_freq
                            next_timestamp = 1e9 * (cycle +
                                                    1) // target.sys_clk_freq
                            if init:
                                init = False
                                vcd_writer._timestamp = timestamp
                            for name, value in events.items():
                                vcd_writer.change(signals[name], timestamp,
                                                  value)
                            for name, _value in events.items():
                                if name in strobes:
                                    vcd_writer.change(signals[name],
                                                      next_timestamp, "z")
                            vcd_writer.flush()

                    vcd_writer.close(timestamp)

                async def run_applet():
                    logger.info("running handler for applet %r", args.applet)
                    try:
                        iface = await applet.run(device, args)
                        await applet.interact(device, args, iface)
                    except GlasgowAppletError as e:
                        applet.logger.error(str(e))
                    finally:
                        if args.trace:
                            await device.write_register(
                                target.analyzer.addr_done, 1)

                done, pending = await asyncio.wait(
                    [run_analyzer(), run_applet()],
                    return_when=asyncio.FIRST_EXCEPTION)
                for task in done:
                    await task

                # Work around bugs in python-libusb1 that cause segfaults on interpreter shutdown.
                await device.demultiplexer.flush()

            else:
                with args.bitstream as f:
                    logger.info("downloading bitstream from %r", f.name)
                    await device.download_bitstream(f.read())

        if args.action == "tool":
            tool = GlasgowApplet.all_applets[args.applet].tool_cls()
            await tool.run(args)

        if args.action == "flash":
            logger.info("reading device configuration")
            header = await device.read_eeprom("fx2", 0,
                                              8 + 4 + GlasgowConfig.size)
            header[0] = 0xC2  # see below

            fx2_config = FX2Config.decode(header, partial=True)
            if (len(fx2_config.firmware) != 1
                    or fx2_config.firmware[0][0] != 0x4000 - GlasgowConfig.size
                    or len(fx2_config.firmware[0][1]) != GlasgowConfig.size):
                raise SystemExit(
                    "Unrecognized or corrupted configuration block")
            glasgow_config = GlasgowConfig.decode(fx2_config.firmware[0][1])

            logger.info("device has serial %s-%s", glasgow_config.revision,
                        glasgow_config.serial)
            if fx2_config.disconnect:
                logger.info("device has flashed firmware")
            else:
                logger.info("device does not have flashed firmware")
            if glasgow_config.bitstream_size:
                logger.info("device has flashed bitstream ID %s",
                            glasgow_config.bitstream_id.hex())
            else:
                logger.info("device does not have flashed bitstream")

            new_bitstream = b""
            if args.remove_bitstream:
                logger.info("removing bitstream")
                glasgow_config.bitstream_size = 0
                glasgow_config.bitstream_id = b"\x00" * 16
            elif args.bitstream:
                logger.info("using bitstream from %s", args.bitstream.name)
                with args.bitstream as f:
                    new_bitstream = f.read()
                    glasgow_config.bitstream_size = len(new_bitstream)
                    glasgow_config.bitstream_id = b"\xff" * 16
            elif args.applet:
                logger.info("building bitstream for applet %s", args.applet)
                target, applet = _applet(device.revision, args)
                new_bitstream_id = target.get_bitstream_id()
                new_bitstream = target.get_bitstream(**_toolchain_opts(args))

                # We always build and reflash the bitstream in case the one currently
                # in EEPROM is corrupted. If we only compared the ID, there would be
                # no easy way to recover from that case. There's also no point in
                # storing the bitstream hash (as opposed to Verilog hash) in the ID,
                # as building the bitstream takes much longer than flashing it.
                logger.info("built bitstream ID %s", new_bitstream_id.hex())
                glasgow_config.bitstream_size = len(new_bitstream)
                glasgow_config.bitstream_id = new_bitstream_id

            fx2_config.firmware[0] = (0x4000 - GlasgowConfig.size,
                                      glasgow_config.encode())

            if args.remove_firmware:
                logger.info("removing firmware")
                fx2_config.disconnect = False
                new_image = fx2_config.encode()
                new_image[0] = 0xC0  # see below
            else:
                logger.info(
                    "using firmware from %r",
                    args.firmware.name if args.firmware else firmware_file)
                with (args.firmware or open(firmware_file, "rb")) as f:
                    for (addr, chunk) in input_data(f, fmt="ihex"):
                        fx2_config.append(addr, chunk)
                fx2_config.disconnect = True
                new_image = fx2_config.encode()

            if new_bitstream:
                logger.info("programming bitstream")
                old_bitstream = await device.read_eeprom(
                    "ice", 0, len(new_bitstream))
                if old_bitstream != new_bitstream:
                    for (addr, chunk) in diff_data(old_bitstream,
                                                   new_bitstream):
                        await device.write_eeprom("ice", addr, chunk)

                    logger.info("verifying bitstream")
                    if await device.read_eeprom(
                            "ice", 0, len(new_bitstream)) != new_bitstream:
                        logger.critical("bitstream programming failed")
                        return 1
                else:
                    logger.info("bitstream identical")

            logger.info("programming configuration and firmware")
            old_image = await device.read_eeprom("fx2", 0, len(new_image))
            if old_image != new_image:
                for (addr, chunk) in diff_data(old_image, new_image):
                    await device.write_eeprom("fx2", addr, chunk)

                logger.info("verifying configuration and firmware")
                if await device.read_eeprom("fx2", 0,
                                            len(new_image)) != new_image:
                    logger.critical(
                        "configuration/firmware programming failed")
                    return 1
            else:
                logger.info("configuration and firmware identical")

        if args.action == "build":
            target, applet = _applet(args.rev, args)
            if args.type in ("v", "verilog"):
                logger.info("building Verilog for applet %r", args.applet)
                target.get_verilog().write(args.filename or args.applet + ".v")
            if args.type in ("bin", "bitstream"):
                logger.info("building bitstream for applet %r", args.applet)
                with open(args.filename or args.applet + ".bin", "wb") as f:
                    f.write(target.get_bitstream(**_toolchain_opts(args)))
            if args.type in ("zip", "archive"):
                logger.info("building archive for applet %r", args.applet)
                with target.get_build_tree() as tree:
                    if args.filename:
                        basename, = os.path.splitext(args.filename)
                    else:
                        basename = args.applet
                    shutil.make_archive(basename,
                                        format="zip",
                                        root_dir=tree,
                                        logger=logger)

        if args.action == "test":
            logger.info("testing applet %r", args.applet)
            applet = GlasgowApplet.all_applets[args.applet]()
            loader = unittest.TestLoader()
            stream = unittest.runner._WritelnDecorator(sys.stderr)
            result = unittest.TextTestResult(stream=stream,
                                             descriptions=True,
                                             verbosity=2)
            result.failfast = True

            def startTest(test):
                unittest.TextTestResult.startTest(result, test)
                result.stream.write("\n")

            result.startTest = startTest
            if args.tests == []:
                suite = loader.loadTestsFromTestCase(applet.test_cls)
                suite.run(result)
            else:
                for test in args.tests:
                    suite = loader.loadTestsFromName(test,
                                                     module=applet.test_cls)
                    suite.run(result)
            if not result.wasSuccessful():
                for _, traceback in result.errors + result.failures:
                    print(traceback, end="", file=sys.stderr)
                return 1

        if args.action == "factory":
            logger.info("reading device configuration")
            header = await device.read_eeprom("fx2", 0,
                                              8 + 4 + GlasgowConfig.size)
            if not re.match(rb"^\xff+$", header):
                if args.force:
                    logger.warning(
                        "device already factory-programmed, proceeding anyway")
                else:
                    logger.error("device already factory-programmed")
                    return 1

            fx2_config = FX2Config(vendor_id=VID_QIHW,
                                   product_id=PID_GLASGOW,
                                   device_id=1 + ord(args.rev) - ord('A'),
                                   i2c_400khz=True)
            glasgow_config = GlasgowConfig(args.rev, args.serial)
            fx2_config.append(0x4000 - GlasgowConfig.size,
                              glasgow_config.encode())

            image = fx2_config.encode()
            # Let FX2 hardware enumerate. This won't load the configuration block
            # into memory automatically, but the firmware has code that does that
            # if it detects a C0 load.
            image[0] = 0xC0

            logger.info("programming device configuration")
            await device.write_eeprom("fx2", 0, image)

            logger.info("verifying device configuration")
            if await device.read_eeprom("fx2", 0, len(image)) != image:
                logger.critical("factory programming failed")
                return 1

    except GlasgowDeviceError as e:
        logger.error(e)
        return 1

    except GatewareBuildError as e:
        applet.logger.error(e)
        return 1

    return 0
示例#23
0
class VCDTracer(Tracer):

    name = 'vcd'

    def open(self):
        dump_filename = self.env.config.setdefault('sim.vcd.dump_file',
                                                   'sim.vcd')
        if 'sim.vcd.timescale' in self.env.config:
            vcd_ts_str = self.env.config.setdefault(
                'sim.vcd.timescale',
                self.env.config['sim.timescale'])
            vcd_timescale = parse_time(vcd_ts_str)
        else:
            vcd_timescale = self.env.timescale
        self.scale_factor = scale_time(self.env.timescale, vcd_timescale)
        check_values = self.env.config.setdefault('sim.vcd.check_values', True)
        self.dump_file = open(dump_filename, 'w')
        self.vcd = VCDWriter(self.dump_file,
                             timescale=vcd_timescale,
                             check_values=check_values)
        self.save_filename = self.env.config.setdefault('sim.gtkw.file',
                                                        'sim.gtkw')
        if self.env.config.setdefault('sim.gtkw.live'):
            from vcd.gtkw import spawn_gtkwave_interactive
            quiet = self.env.config.setdefault('sim.gtkw.quiet', True)
            spawn_gtkwave_interactive(dump_filename, self.save_filename,
                                      quiet=quiet)

        start_time = self.env.config.setdefault('sim.vcd.start_time', '')
        stop_time = self.env.config.setdefault('sim.vcd.stop_time', '')
        t_start = (scale_time(parse_time(start_time), self.env.timescale)
                   if start_time else None)
        t_stop = (scale_time(parse_time(stop_time), self.env.timescale)
                  if stop_time else None)
        self.env.process(self._start_stop(t_start, t_stop))

    def vcd_now(self):
        return self.env.now * self.scale_factor

    def flush(self):
        self.dump_file.flush()

    def _close(self):
        self.vcd.close(self.vcd_now())
        self.dump_file.close()

    def remove_files(self):
        if os.path.isfile(self.dump_file.name):
            os.remove(self.dump_file.name)
        if os.path.isfile(self.save_filename):
            os.remove(self.save_filename)

    def activate_probe(self, scope, target, **hints):
        assert self.enabled
        var_type = hints.get('var_type')
        if var_type is None:
            if isinstance(target, (simpy.Container, Pool)):
                if isinstance(target.level, float):
                    var_type = 'real'
                else:
                    var_type = 'integer'
            elif isinstance(target, (simpy.Resource, simpy.Store, Queue)):
                var_type = 'integer'
            else:
                raise ValueError(
                    'Could not infer VCD var_type for {}'.format(scope))

        kwargs = {k: hints[k]
                  for k in ['size', 'init', 'ident']
                  if k in hints}

        if 'init' not in kwargs:
            if isinstance(target, (simpy.Container, Pool)):
                kwargs['init'] = target.level
            elif isinstance(target, simpy.Resource):
                kwargs['init'] = len(target.users) if target.users else 'z'
            elif isinstance(target, (simpy.Store, Queue)):
                kwargs['init'] = len(target.items)

        parent_scope, name = scope.rsplit('.', 1)
        var = self.vcd.register_var(parent_scope, name, var_type, **kwargs)

        def probe_callback(value):
            self.vcd.change(var, self.vcd_now(), value)

        return probe_callback

    def activate_trace(self, scope, **hints):
        assert self.enabled
        var_type = hints['var_type']
        kwargs = {k: hints[k]
                  for k in ['size', 'init', 'ident']
                  if k in hints}

        parent_scope, name = scope.rsplit('.', 1)
        var = self.vcd.register_var(parent_scope, name, var_type, **kwargs)

        if isinstance(var.size, tuple):
            def trace_callback(*value):
                self.vcd.change(var, self.vcd_now(), value)
        else:
            def trace_callback(value):
                self.vcd.change(var, self.vcd_now(), value)

        return trace_callback

    def _start_stop(self, t_start, t_stop):
        # Wait for simulation to start to ensure all variable registration is
        # complete before doing and dump_on()/dump_off() calls.
        yield self.env.timeout(0)

        if t_start is None and t_stop is None:
            # |vvvvvvvvvvvvvv|
            pass
        elif t_start is None:
            # |vvvvvv--------|
            yield self.env.timeout(t_stop)
            self.vcd.dump_off(self.vcd_now())
        elif t_stop is None:
            # |--------vvvvvv|
            self.vcd.dump_off(self.vcd_now())
            yield self.env.timeout(t_start)
            self.vcd.dump_on(self.vcd_now())
        elif t_start <= t_stop:
            # |---vvvvvv-----|
            self.vcd.dump_off(self.vcd_now())
            yield self.env.timeout(t_start)
            self.vcd.dump_on(self.vcd_now())
            yield self.env.timeout(t_stop - t_start)
            self.vcd.dump_off(self.vcd_now())
        else:
            # |vvv-------vvvv|
            yield self.env.timeout(t_stop)
            self.vcd.dump_off(self.vcd_now())
            yield self.env.timeout(t_start - t_stop)
            self.vcd.dump_on(self.vcd_now())
示例#24
0
class VCDTracer(Tracer):

    name = 'vcd'

    def open(self):
        dump_filename = self.env.config.setdefault('sim.vcd.dump_file',
                                                   'sim.vcd')
        if 'sim.vcd.timescale' in self.env.config:
            vcd_ts_str = self.env.config.setdefault(
                'sim.vcd.timescale', self.env.config['sim.timescale'])
            vcd_timescale = parse_time(vcd_ts_str)
        else:
            vcd_timescale = self.env.timescale
        self.scale_factor = scale_time(self.env.timescale, vcd_timescale)
        check_values = self.env.config.setdefault('sim.vcd.check_values', True)
        self.dump_file = open(dump_filename, 'w')
        self.vcd = VCDWriter(self.dump_file,
                             timescale=vcd_timescale,
                             check_values=check_values)
        self.save_filename = self.env.config.setdefault(
            'sim.gtkw.file', 'sim.gtkw')
        if self.env.config.setdefault('sim.gtkw.live'):
            from vcd.gtkw import spawn_gtkwave_interactive
            quiet = self.env.config.setdefault('sim.gtkw.quiet', True)
            spawn_gtkwave_interactive(dump_filename,
                                      self.save_filename,
                                      quiet=quiet)

        start_time = self.env.config.setdefault('sim.vcd.start_time', '')
        stop_time = self.env.config.setdefault('sim.vcd.stop_time', '')
        t_start = (scale_time(parse_time(start_time), self.env.timescale)
                   if start_time else None)
        t_stop = (scale_time(parse_time(stop_time), self.env.timescale)
                  if stop_time else None)
        self.env.process(self._start_stop(t_start, t_stop))

    def vcd_now(self):
        return self.env.now * self.scale_factor

    def flush(self):
        self.dump_file.flush()

    def _close(self):
        self.vcd.close(self.vcd_now())
        self.dump_file.close()

    def remove_files(self):
        if os.path.isfile(self.dump_file.name):
            os.remove(self.dump_file.name)
        if os.path.isfile(self.save_filename):
            os.remove(self.save_filename)

    def activate_probe(self, scope, target, **hints):
        assert self.enabled
        var_type = hints.get('var_type')
        if var_type is None:
            if isinstance(target, simpy.Container):
                if isinstance(target.level, float):
                    var_type = 'real'
                else:
                    var_type = 'integer'
            elif isinstance(target, (simpy.Resource, simpy.Store, Queue)):
                var_type = 'integer'
            else:
                raise ValueError(
                    'Could not infer VCD var_type for {}'.format(scope))

        kwargs = {k: hints[k] for k in ['size', 'init', 'ident'] if k in hints}

        if 'init' not in kwargs:
            if isinstance(target, simpy.Container):
                kwargs['init'] = target.level
            elif isinstance(target, simpy.Resource):
                kwargs['init'] = len(target.users) if target.users else 'z'
            elif isinstance(target, (simpy.Store, Queue)):
                kwargs['init'] = len(target.items)

        parent_scope, name = scope.rsplit('.', 1)
        var = self.vcd.register_var(parent_scope, name, var_type, **kwargs)

        def probe_callback(value):
            self.vcd.change(var, self.vcd_now(), value)

        return probe_callback

    def activate_trace(self, scope, **hints):
        assert self.enabled
        var_type = hints['var_type']
        kwargs = {k: hints[k] for k in ['size', 'init', 'ident'] if k in hints}

        parent_scope, name = scope.rsplit('.', 1)
        var = self.vcd.register_var(parent_scope, name, var_type, **kwargs)

        if isinstance(var.size, tuple):

            def trace_callback(*value):
                self.vcd.change(var, self.vcd_now(), value)
        else:

            def trace_callback(value):
                self.vcd.change(var, self.vcd_now(), value)

        return trace_callback

    def _start_stop(self, t_start, t_stop):
        # Wait for simulation to start to ensure all variable registration is
        # complete before doing and dump_on()/dump_off() calls.
        yield self.env.timeout(0)

        if t_start is None and t_stop is None:
            # |vvvvvvvvvvvvvv|
            pass
        elif t_start is None:
            # |vvvvvv--------|
            yield self.env.timeout(t_stop)
            self.vcd.dump_off(self.vcd_now())
        elif t_stop is None:
            # |--------vvvvvv|
            self.vcd.dump_off(self.vcd_now())
            yield self.env.timeout(t_start)
            self.vcd.dump_on(self.vcd_now())
        elif t_start <= t_stop:
            # |---vvvvvv-----|
            self.vcd.dump_off(self.vcd_now())
            yield self.env.timeout(t_start)
            self.vcd.dump_on(self.vcd_now())
            yield self.env.timeout(t_stop - t_start)
            self.vcd.dump_off(self.vcd_now())
        else:
            # |vvv-------vvvv|
            yield self.env.timeout(t_stop)
            self.vcd.dump_off(self.vcd_now())
            yield self.env.timeout(t_start - t_stop)
            self.vcd.dump_on(self.vcd_now())
示例#25
0
for i in range(0, len(D1_timestamp)):
    # print(D_timestamp.index(D1_timestamp[i]))
    D_data[D_timestamp.index(D1_timestamp[i])][2] = D1_Value[i]

# 把D2_timestamp对应的value填入D_data中
for i in range(0, len(D2_timestamp)):
    # print(D_timestamp.index(D2_timestamp[i]))
    D_data[D_timestamp.index(D2_timestamp[i])][3] = D2_Value[i]
'''D_data = [ [3,1,None],    # len(D0_data)算的是最外层[]的长度
           [6,0,1],
           [9,1,0],
           [18,0,1]]'''

with VCDWriter(
        sys.stdout,
        timescale='1 ns',
        date='today',
        comment='Acquisition with 8/8 channels at 20 kHz',
        version='libsigrok 0.5.1') as writer:  # timescale='1 ns'这里单位不对有问题
    counter_var0 = writer.register_var('libsigrok',
                                       'D0',
                                       'wire',
                                       size=1,
                                       init=D0_init,
                                       ident='#')  # init是这个var的初始值
    counter_var1 = writer.register_var('libsigrok',
                                       'D1',
                                       'wire',
                                       size=1,
                                       init=D1_init,
                                       ident='!')  # init是这个var的初始值
    counter_var2 = writer.register_var('libsigrok',
示例#26
0
文件: vcd.py 项目: jesseclin/pygears
class VCD(SimExtend):
    @inject
    def __init__(self,
                 trace_fn='pygears.vcd',
                 include=Inject('debug/trace'),
                 tlm=False,
                 shmidcat=Inject('sim_extens/vcd/shmidcat'),
                 vcd_fifo=Inject('sim_extens/vcd/vcd_fifo'),
                 sim=Inject('sim/simulator'),
                 outdir=Inject('results-dir')):

        super().__init__()
        self.sim = sim
        self.finished = False
        self.vcd_fifo = vcd_fifo
        self.shmidcat = shmidcat
        self.outdir = outdir
        self.trace_fn = None
        self.shmid_proc = None

        vcd_visitor = VCDHierVisitor(include, tlm)
        vcd_visitor.visit(find('/'))

        if not vcd_visitor.vcd_vars:
            self.deactivate()
            return

        self.trace_fn = os.path.abspath(os.path.join(self.outdir, trace_fn))
        atexit.register(self.finish)

        try:
            subprocess.call(f"rm -f {self.trace_fn}", shell=True)
        except OSError:
            pass

        if self.vcd_fifo:
            subprocess.call(f"mkfifo {self.trace_fn}", shell=True)
        else:
            log.info(f'Main VCD dump to "{self.trace_fn}"')

        if self.shmidcat:
            self.shmid_proc = subprocess.Popen(f'shmidcat {self.trace_fn}',
                                               shell=True,
                                               stdout=subprocess.PIPE)

            # Wait for shmidcat to actually open the pipe, which is necessary
            # to happen prior to init of the verilator. If shmidcat does not
            # open the pipe, verilator will get stuck
            import time
            time.sleep(0.1)

        self.vcd_file = open(self.trace_fn, 'w')

        if self.shmidcat:
            self.shmid = self.shmid_proc.stdout.readline().decode().strip()
            log.info(f'Main VCD dump to shared memory at 0x{self.shmid}')

        self.writer = VCDWriter(self.vcd_file, timescale='1 ns', date='today')

        reg['VCDWriter'] = self.writer
        reg['VCD'] = self

        self.clk_var = self.writer.register_var('', 'clk', 'wire', size=1, init=1)

        self.timestep_var = self.writer.register_var('', 'timestep', 'integer', init=0)

        self.handhake = set()

        self.vcd_vars = {
            p: register_traces_for_intf(p.dtype, scope, self.writer)
            for p, scope in vcd_visitor.vcd_vars.items()
        }

        self.writer.flush()

    def before_run(self, sim):
        vcd_intf_vars = {}
        for p, v in self.vcd_vars.items():
            intf = p.consumer
            intf.events['put'].append(self.intf_put)
            intf.events['ack'].append(self.intf_ack)
            vcd_intf_vars[intf] = v

        self.vcd_vars = vcd_intf_vars

    def intf_put(self, intf, val):
        if intf not in self.vcd_vars:
            return True

        v = self.vcd_vars[intf]

        if typeof(intf.dtype, TLM):
            self.writer.change(v['data'], timestep() * 10, str(val))
        else:
            visitor = VCDValVisitor(v, self.writer, timestep() * 10)
            visitor.visit(intf.dtype, 'data', val=val)

        self.writer.change(v['valid'], timestep() * 10, 1)
        return True

    def intf_ack(self, intf):
        if intf not in self.vcd_vars:
            return True

        v = self.vcd_vars[intf]
        self.writer.change(v['ready'], timestep() * 10, 1)

        self.handhake.add(intf)
        return True

    def before_timestep(self, sim, timestep):
        self.writer.change(self.clk_var, timestep * 10 + 5, 0)
        return True

    def after_timestep(self, sim, timestep):
        timestep += 1
        self.writer.change(self.timestep_var, timestep * 10, timestep)
        self.writer.change(self.clk_var, timestep * 10, 1)
        for intf, v in self.vcd_vars.items():
            if intf in self.handhake:
                self.writer.change(v['ready'], timestep * 10, 0)
                self.writer.change(v['valid'], timestep * 10, 0)
                self.handhake.remove(intf)

        self.writer.flush()

        return True

    def finish(self):
        if not self.finished:
            self.writer.close()
            self.vcd_file.close()
            self.finished = True

            if self.shmid_proc:
                self.shmid_proc.terminate()

    def after_cleanup(self, sim):
        self.finish()
示例#27
0
def log_to_vcd(cfg):
    """
    Cyclically poll heating and log results to VCD file.
    """
    global SIGINT

    # set up VCD logging
    now_utc = datetime.datetime.now(datetime.timezone.utc)
    vcdwriter = VCDWriter(open('vitopy1.vcd', 'w'),
                          timescale='1s',
                          init_timestamp=now_utc.timestamp())
    vcdvars = {}
    for v in config['datapoints']:
        if not 'addr' in v:
            continue
        if not 'id' in v:
            v['id'] = 'NOID'
        if type(v['addr']) is str:
            v['addr'] = int(v['addr'], 0)  # parse non-decimal numbers
        name = '%s_%s' % (v['id'], v['addr'])
        if 'uint8' == v['type']:
            logging.info('Adding variable %s' % v['addr'])
            vcdvars.update({
                v['addr']:
                vcdwriter.register_var('vitopy', name, 'integer', size=8)
            })
        if 'int8' == v['type']:
            logging.info('Adding variable %s' % v['addr'])
            vcdvars.update({
                v['addr']:
                vcdwriter.register_var('vitopy', name, 'integer', size=8)
            })
        if 'uint16' == v['type']:
            logging.info('Adding variable %s' % v['addr'])
            vcdvars.update({
                v['addr']:
                vcdwriter.register_var('vitopy', name, 'integer', size=16)
            })
        if 'uint32' == v['type']:
            logging.info('Adding variable %s' % v['addr'])
            vcdvars.update({
                v['addr']:
                vcdwriter.register_var('vitopy', name, 'integer', size=32)
            })

    # poll heating
    o = optolink.OptoLink()
    o.open_port(args.port)
    o.init()
    while True:
        logging.info('-- start of query --')
        now_utc = datetime.datetime.now(datetime.timezone.utc)
        allreadings = retrieve_all_readings_as_per_configuration(o, config)
        print(allreadings)

        for k in allreadings.keys():
            r = allreadings[k]
            if k in vcdvars:
                vcdwriter.change(vcdvars[k], now_utc.timestamp(), r)
                if args.publishmqtt:
                    mqttc.publish(str(k), r)

        vcdwriter.flush()

        for i in range(10):
            time.sleep(1)
            if SIGINT:
                break
        if SIGINT:
            break
        logging.info('-- end of query --')

    o.deinit()
    o.close_port()
    vcdwriter.close()

    return
示例#28
0
    def __enter__(self):
        if self._vcd_file:
            self._vcd_writer = VCDWriter(self._vcd_file, timescale="100 ps",
                                         comment="Generated by nMigen")

        root_fragment = self._fragment.prepare()
        self._domains = root_fragment.domains

        hierarchy = {}
        def add_fragment(fragment, scope=()):
            hierarchy[fragment] = scope
            for index, (subfragment, name) in enumerate(fragment.subfragments):
                if name is None:
                    add_fragment(subfragment, (*scope, "U{}".format(index)))
                else:
                    add_fragment(subfragment, (*scope, name))
        add_fragment(root_fragment, scope=("top",))

        def add_signal(signal):
            if signal not in self._signals:
                self._signals.add(signal)

                signal_slot = self._state.add(normalize(signal.reset, signal.shape()))
                self._signal_slots[signal] = signal_slot
                self._slot_signals.append(signal)

                self._comb_signals.append(False)
                self._sync_signals.append(False)
                self._user_signals.append(False)
                for domain in self._domains:
                    if domain not in self._domain_signals:
                        self._domain_signals[domain] = bitarray()
                    self._domain_signals[domain].append(False)

                self._funclets.append(set())

                self._domain_triggers.append(None)
                if self._vcd_writer:
                    self._vcd_signals.append(set())
                    self._vcd_names.append(None)

            return self._signal_slots[signal]

        def add_domain_signal(signal, domain):
            signal_slot = add_signal(signal)
            self._domain_triggers[signal_slot] = domain

        for fragment, fragment_scope in hierarchy.items():
            for signal in fragment.iter_signals():
                add_signal(signal)

            for domain, cd in fragment.domains.items():
                add_domain_signal(cd.clk, domain)
                if cd.rst is not None:
                    add_domain_signal(cd.rst, domain)

        for fragment, fragment_scope in hierarchy.items():
            for signal in fragment.iter_signals():
                if not self._vcd_writer:
                    continue

                signal_slot = self._signal_slots[signal]

                for i, (subfragment, name) in enumerate(fragment.subfragments):
                    if signal in subfragment.ports:
                        var_name = "{}_{}".format(name or "U{}".format(i), signal.name)
                        break
                else:
                    var_name = signal.name

                if signal.decoder:
                    var_type = "string"
                    var_size = 1
                    var_init = signal.decoder(signal.reset).replace(" ", "_")
                else:
                    var_type = "wire"
                    var_size = signal.nbits
                    var_init = signal.reset

                suffix = None
                while True:
                    try:
                        if suffix is None:
                            var_name_suffix = var_name
                        else:
                            var_name_suffix = "{}${}".format(var_name, suffix)
                        self._vcd_signals[signal_slot].add(self._vcd_writer.register_var(
                            scope=".".join(fragment_scope), name=var_name_suffix,
                            var_type=var_type, size=var_size, init=var_init))
                        if self._vcd_names[signal_slot] is None:
                            self._vcd_names[signal_slot] = \
                                ".".join(fragment_scope + (var_name_suffix,))
                        break
                    except KeyError:
                        suffix = (suffix or 0) + 1

            for domain, signals in fragment.drivers.items():
                signals_bits = bitarray(len(self._signals))
                signals_bits.setall(False)
                for signal in signals:
                    signals_bits[self._signal_slots[signal]] = True

                if domain is None:
                    self._comb_signals |= signals_bits
                else:
                    self._sync_signals |= signals_bits
                    self._domain_signals[domain] |= signals_bits

            statements = []
            for domain, signals in fragment.drivers.items():
                reset_stmts = []
                hold_stmts  = []
                for signal in signals:
                    reset_stmts.append(signal.eq(signal.reset))
                    hold_stmts .append(signal.eq(signal))

                if domain is None:
                    statements += reset_stmts
                else:
                    if self._domains[domain].async_reset:
                        statements.append(Switch(self._domains[domain].rst,
                            {0: hold_stmts, 1: reset_stmts}))
                    else:
                        statements += hold_stmts
            statements += fragment.statements

            compiler = _StatementCompiler(self._signal_slots)
            funclet = compiler(statements)

            def add_funclet(signal, funclet):
                if signal in self._signal_slots:
                    self._funclets[self._signal_slots[signal]].add(funclet)

            for signal in compiler.sensitivity:
                add_funclet(signal, funclet)
            for domain, cd in fragment.domains.items():
                add_funclet(cd.clk, funclet)
                if cd.rst is not None:
                    add_funclet(cd.rst, funclet)

        self._user_signals = bitarray(len(self._signals))
        self._user_signals.setall(True)
        self._user_signals &= ~self._comb_signals
        self._user_signals &= ~self._sync_signals

        return self
示例#29
0
class Simulator:
    def __init__(self, fragment, vcd_file=None, gtkw_file=None, traces=()):
        self._fragment        = Fragment.get(fragment, platform=None)

        self._signal_slots    = SignalDict()  # Signal -> int/slot
        self._slot_signals    = list()        # int/slot -> Signal

        self._domains         = dict()        # str/domain -> ClockDomain
        self._domain_triggers = list()        # int/slot -> str/domain

        self._signals         = SignalSet()   # {Signal}
        self._comb_signals    = bitarray()    # {Signal}
        self._sync_signals    = bitarray()    # {Signal}
        self._user_signals    = bitarray()    # {Signal}
        self._domain_signals  = dict()        # str/domain -> {Signal}

        self._started         = False
        self._timestamp       = 0.
        self._delta           = 0.
        self._epsilon         = 1e-10
        self._fastest_clock   = self._epsilon
        self._state           = _State()

        self._processes       = set()         # {process}
        self._process_loc     = dict()        # process -> str/loc
        self._passive         = set()         # {process}
        self._suspended       = set()         # {process}
        self._wait_deadline   = dict()        # process -> float/timestamp
        self._wait_tick       = dict()        # process -> str/domain

        self._funclets        = list()        # int/slot -> set(lambda)

        self._vcd_file        = vcd_file
        self._vcd_writer      = None
        self._vcd_signals     = list()        # int/slot -> set(vcd_signal)
        self._vcd_names       = list()        # int/slot -> str/name
        self._gtkw_file       = gtkw_file
        self._traces          = traces

        self._run_called      = False

    @staticmethod
    def _check_process(process):
        if inspect.isgeneratorfunction(process):
            process = process()
        if not inspect.isgenerator(process):
            raise TypeError("Cannot add a process '{!r}' because it is not a generator or "
                            "a generator function"
                            .format(process))
        return process

    def _name_process(self, process):
        if process in self._process_loc:
            return self._process_loc[process]
        else:
            frame = process.gi_frame
            return "{}:{}".format(inspect.getfile(frame), inspect.getlineno(frame))

    def add_process(self, process):
        process = self._check_process(process)
        self._processes.add(process)

    def add_sync_process(self, process, domain="sync"):
        process = self._check_process(process)
        def sync_process():
            try:
                cmd = None
                while True:
                    if cmd is None:
                        cmd = Tick(domain)
                    result = yield cmd
                    self._process_loc[sync_process] = self._name_process(process)
                    cmd = process.send(result)
            except StopIteration:
                pass
        sync_process = sync_process()
        self.add_process(sync_process)

    def add_clock(self, period, phase=None, domain="sync"):
        if self._fastest_clock == self._epsilon or period < self._fastest_clock:
            self._fastest_clock = period

        half_period = period / 2
        if phase is None:
            phase = half_period
        clk = self._domains[domain].clk
        def clk_process():
            yield Passive()
            yield Delay(phase)
            while True:
                yield clk.eq(1)
                yield Delay(half_period)
                yield clk.eq(0)
                yield Delay(half_period)
        self.add_process(clk_process)

    def __enter__(self):
        if self._vcd_file:
            self._vcd_writer = VCDWriter(self._vcd_file, timescale="100 ps",
                                         comment="Generated by nMigen")

        root_fragment = self._fragment.prepare()
        self._domains = root_fragment.domains

        hierarchy = {}
        def add_fragment(fragment, scope=()):
            hierarchy[fragment] = scope
            for index, (subfragment, name) in enumerate(fragment.subfragments):
                if name is None:
                    add_fragment(subfragment, (*scope, "U{}".format(index)))
                else:
                    add_fragment(subfragment, (*scope, name))
        add_fragment(root_fragment, scope=("top",))

        def add_signal(signal):
            if signal not in self._signals:
                self._signals.add(signal)

                signal_slot = self._state.add(normalize(signal.reset, signal.shape()))
                self._signal_slots[signal] = signal_slot
                self._slot_signals.append(signal)

                self._comb_signals.append(False)
                self._sync_signals.append(False)
                self._user_signals.append(False)
                for domain in self._domains:
                    if domain not in self._domain_signals:
                        self._domain_signals[domain] = bitarray()
                    self._domain_signals[domain].append(False)

                self._funclets.append(set())

                self._domain_triggers.append(None)
                if self._vcd_writer:
                    self._vcd_signals.append(set())
                    self._vcd_names.append(None)

            return self._signal_slots[signal]

        def add_domain_signal(signal, domain):
            signal_slot = add_signal(signal)
            self._domain_triggers[signal_slot] = domain

        for fragment, fragment_scope in hierarchy.items():
            for signal in fragment.iter_signals():
                add_signal(signal)

            for domain, cd in fragment.domains.items():
                add_domain_signal(cd.clk, domain)
                if cd.rst is not None:
                    add_domain_signal(cd.rst, domain)

        for fragment, fragment_scope in hierarchy.items():
            for signal in fragment.iter_signals():
                if not self._vcd_writer:
                    continue

                signal_slot = self._signal_slots[signal]

                for i, (subfragment, name) in enumerate(fragment.subfragments):
                    if signal in subfragment.ports:
                        var_name = "{}_{}".format(name or "U{}".format(i), signal.name)
                        break
                else:
                    var_name = signal.name

                if signal.decoder:
                    var_type = "string"
                    var_size = 1
                    var_init = signal.decoder(signal.reset).replace(" ", "_")
                else:
                    var_type = "wire"
                    var_size = signal.nbits
                    var_init = signal.reset

                suffix = None
                while True:
                    try:
                        if suffix is None:
                            var_name_suffix = var_name
                        else:
                            var_name_suffix = "{}${}".format(var_name, suffix)
                        self._vcd_signals[signal_slot].add(self._vcd_writer.register_var(
                            scope=".".join(fragment_scope), name=var_name_suffix,
                            var_type=var_type, size=var_size, init=var_init))
                        if self._vcd_names[signal_slot] is None:
                            self._vcd_names[signal_slot] = \
                                ".".join(fragment_scope + (var_name_suffix,))
                        break
                    except KeyError:
                        suffix = (suffix or 0) + 1

            for domain, signals in fragment.drivers.items():
                signals_bits = bitarray(len(self._signals))
                signals_bits.setall(False)
                for signal in signals:
                    signals_bits[self._signal_slots[signal]] = True

                if domain is None:
                    self._comb_signals |= signals_bits
                else:
                    self._sync_signals |= signals_bits
                    self._domain_signals[domain] |= signals_bits

            statements = []
            for domain, signals in fragment.drivers.items():
                reset_stmts = []
                hold_stmts  = []
                for signal in signals:
                    reset_stmts.append(signal.eq(signal.reset))
                    hold_stmts .append(signal.eq(signal))

                if domain is None:
                    statements += reset_stmts
                else:
                    if self._domains[domain].async_reset:
                        statements.append(Switch(self._domains[domain].rst,
                            {0: hold_stmts, 1: reset_stmts}))
                    else:
                        statements += hold_stmts
            statements += fragment.statements

            compiler = _StatementCompiler(self._signal_slots)
            funclet = compiler(statements)

            def add_funclet(signal, funclet):
                if signal in self._signal_slots:
                    self._funclets[self._signal_slots[signal]].add(funclet)

            for signal in compiler.sensitivity:
                add_funclet(signal, funclet)
            for domain, cd in fragment.domains.items():
                add_funclet(cd.clk, funclet)
                if cd.rst is not None:
                    add_funclet(cd.rst, funclet)

        self._user_signals = bitarray(len(self._signals))
        self._user_signals.setall(True)
        self._user_signals &= ~self._comb_signals
        self._user_signals &= ~self._sync_signals

        return self

    def _update_dirty_signals(self):
        """Perform the statement part of IR processes (aka RTLIL case)."""
        # First, for all dirty signals, use sensitivity lists to determine the set of fragments
        # that need their statements to be reevaluated because the signals changed at the previous
        # delta cycle.
        funclets = set()
        for signal_slot in self._state.flush_curr_dirty():
            funclets.update(self._funclets[signal_slot])

        # Second, compute the values of all signals at the start of the next delta cycle, by
        # running precompiled statements.
        for funclet in funclets:
            funclet(self._state)

    def _commit_signal(self, signal_slot, domains):
        """Perform the driver part of IR processes (aka RTLIL sync), for individual signals."""
        # Take the computed value (at the start of this delta cycle) of a signal (that could have
        # come from an IR process that ran earlier, or modified by a simulator process) and update
        # the value for this delta cycle.
        old, new = self._state.commit(signal_slot)
        if old == new:
            return

        # If the signal is a clock that triggers synchronous logic, record that fact.
        if new == 1 and self._domain_triggers[signal_slot] is not None:
            domains.add(self._domain_triggers[signal_slot])

        if self._vcd_writer:
            # Finally, dump the new value to the VCD file.
            for vcd_signal in self._vcd_signals[signal_slot]:
                signal = self._slot_signals[signal_slot]
                if signal.decoder:
                    var_value = signal.decoder(new).replace(" ", "_")
                else:
                    var_value = new
                vcd_timestamp = (self._timestamp + self._delta) / self._epsilon
                self._vcd_writer.change(vcd_signal, vcd_timestamp, var_value)

    def _commit_comb_signals(self, domains):
        """Perform the comb part of IR processes (aka RTLIL always)."""
        # Take the computed value (at the start of this delta cycle) of every comb signal and
        # update the value for this delta cycle.
        for signal_slot in self._state.iter_next_dirty():
            if self._comb_signals[signal_slot]:
                self._commit_signal(signal_slot, domains)

    def _commit_sync_signals(self, domains):
        """Perform the sync part of IR processes (aka RTLIL posedge)."""
        # At entry, `domains` contains a list of every simultaneously triggered sync update.
        while domains:
            # Advance the timeline a bit (purely for observational purposes) and commit all of them
            # at the same timestamp.
            self._delta += self._epsilon
            curr_domains, domains = domains, set()

            while curr_domains:
                domain = curr_domains.pop()

                # Wake up any simulator processes that wait for a domain tick.
                for process, wait_domain in list(self._wait_tick.items()):
                    if domain == wait_domain:
                        del self._wait_tick[process]
                        self._suspended.remove(process)

                        # Immediately run the process. It is important that this happens here,
                        # and not on the next step, when all the processes will run anyway,
                        # because Tick() simulates an edge triggered process. Like DFFs that latch
                        # a value from the previous clock cycle, simulator processes observe signal
                        # values from the previous clock cycle on a tick, too.
                        self._run_process(process)

                # Take the computed value (at the start of this delta cycle) of every sync signal
                # in this domain and update the value for this delta cycle. This can trigger more
                # synchronous logic, so record that.
                for signal_slot in self._state.iter_next_dirty():
                    if self._domain_signals[domain][signal_slot]:
                        self._commit_signal(signal_slot, domains)

            # Unless handling synchronous logic above has triggered more synchronous logic (which
            # can happen e.g. if a domain is clocked off a clock divisor in fabric), we're done.
            # Otherwise, do one more round of updates.

    def _run_process(self, process):
        try:
            cmd = process.send(None)
            while True:
                if type(cmd) is Delay:
                    if cmd.interval is None:
                        interval = self._epsilon
                    else:
                        interval = cmd.interval
                    self._wait_deadline[process] = self._timestamp + interval
                    self._suspended.add(process)
                    break

                elif type(cmd) is Tick:
                    self._wait_tick[process] = cmd.domain
                    self._suspended.add(process)
                    break

                elif type(cmd) is Passive:
                    self._passive.add(process)

                elif type(cmd) is Assign:
                    lhs_signals = cmd.lhs._lhs_signals()
                    for signal in lhs_signals:
                        if not signal in self._signals:
                            raise ValueError("Process '{}' sent a request to set signal '{!r}', "
                                             "which is not a part of simulation"
                                             .format(self._name_process(process), signal))
                        signal_slot = self._signal_slots[signal]
                        if self._comb_signals[signal_slot]:
                            raise ValueError("Process '{}' sent a request to set signal '{!r}', "
                                             "which is a part of combinatorial assignment in "
                                             "simulation"
                                             .format(self._name_process(process), signal))

                    if type(cmd.lhs) is Signal and type(cmd.rhs) is Const:
                        # Fast path.
                        self._state.set(self._signal_slots[cmd.lhs],
                                        normalize(cmd.rhs.value, cmd.lhs.shape()))
                    else:
                        compiler = _StatementCompiler(self._signal_slots)
                        funclet = compiler(cmd)
                        funclet(self._state)

                    domains = set()
                    for signal in lhs_signals:
                        self._commit_signal(self._signal_slots[signal], domains)
                    self._commit_sync_signals(domains)

                elif type(cmd) is Signal:
                    # Fast path.
                    cmd = process.send(self._state.curr[self._signal_slots[cmd]])
                    continue

                elif isinstance(cmd, Value):
                    compiler = _RHSValueCompiler(self._signal_slots)
                    funclet = compiler(cmd)
                    cmd = process.send(funclet(self._state))
                    continue

                else:
                    raise TypeError("Received unsupported command '{!r}' from process '{}'"
                                    .format(cmd, self._name_process(process)))

                cmd = process.send(None)

        except StopIteration:
            self._processes.remove(process)
            self._passive.discard(process)

        except Exception as e:
            process.throw(e)

    def step(self, run_passive=False):
        # Are there any delta cycles we should run?
        if self._state.curr_dirty.any():
            # We might run some delta cycles, and we have simulator processes waiting on
            # a deadline. Take care to not exceed the closest deadline.
            if self._wait_deadline and \
                    (self._timestamp + self._delta) >= min(self._wait_deadline.values()):
                # Oops, we blew the deadline. We *could* run the processes now, but this is
                # virtually certainly a logic loop and a design bug, so bail out instead.d
                raise DeadlineError("Delta cycles exceeded process deadline; combinatorial loop?")

            domains = set()
            while self._state.curr_dirty.any():
                self._update_dirty_signals()
                self._commit_comb_signals(domains)
            self._commit_sync_signals(domains)
            return True

        # Are there any processes that haven't had a chance to run yet?
        if len(self._processes) > len(self._suspended):
            # Schedule an arbitrary one.
            process = (self._processes - set(self._suspended)).pop()
            self._run_process(process)
            return True

        # All processes are suspended. Are any of them active?
        if len(self._processes) > len(self._passive) or run_passive:
            # Are any of them suspended before a deadline?
            if self._wait_deadline:
                # Schedule the one with the lowest deadline.
                process, deadline = min(self._wait_deadline.items(), key=lambda x: x[1])
                del self._wait_deadline[process]
                self._suspended.remove(process)
                self._timestamp = deadline
                self._delta = 0.
                self._run_process(process)
                return True

        # No processes, or all processes are passive. Nothing to do!
        return False

    def run(self):
        self._run_called = True

        while self.step():
            pass

    def run_until(self, deadline, run_passive=False):
        self._run_called = True

        while self._timestamp < deadline:
            if not self.step(run_passive):
                return False

        return True

    def __exit__(self, *args):
        if not self._run_called:
            warnings.warn("Simulation created, but not run", UserWarning)

        if self._vcd_writer:
            vcd_timestamp = (self._timestamp + self._delta) / self._epsilon
            self._vcd_writer.close(vcd_timestamp)

        if self._vcd_file and self._gtkw_file:
            gtkw_save = GTKWSave(self._gtkw_file)
            if hasattr(self._vcd_file, "name"):
                gtkw_save.dumpfile(self._vcd_file.name)
            if hasattr(self._vcd_file, "tell"):
                gtkw_save.dumpfile_size(self._vcd_file.tell())

            gtkw_save.treeopen("top")
            gtkw_save.zoom_markers(math.log(self._epsilon / self._fastest_clock) - 14)

            def add_trace(signal, **kwargs):
                signal_slot = self._signal_slots[signal]
                if self._vcd_names[signal_slot] is not None:
                    if len(signal) > 1:
                        suffix = "[{}:0]".format(len(signal) - 1)
                    else:
                        suffix = ""
                    gtkw_save.trace(self._vcd_names[signal_slot] + suffix, **kwargs)

            for domain, cd in self._domains.items():
                with gtkw_save.group("d.{}".format(domain)):
                    if cd.rst is not None:
                        add_trace(cd.rst)
                    add_trace(cd.clk)

            for signal in self._traces:
                add_trace(signal)

        if self._vcd_file:
            self._vcd_file.close()
        if self._gtkw_file:
            self._gtkw_file.close()
示例#30
0
class VCDTracer(Tracer):

    name = 'vcd'

    def open(self):
        dump_filename = self.env.config['sim.vcd.dump_file']
        if 'sim.vcd.timescale' in self.env.config:
            vcd_timescale = parse_time(self.env.config['sim.vcd.timescale'])
        else:
            vcd_timescale = self.env.timescale
        self.scale_factor = scale_time(self.env.timescale, vcd_timescale)
        check_values = self.env.config.get('sim.vcd.check_values', True)
        self.dump_file = open(dump_filename, 'w')
        self.vcd = VCDWriter(self.dump_file,
                             timescale=vcd_timescale,
                             check_values=check_values)
        if self.env.config.get('sim.gtkw.live'):
            from vcd.gtkw import spawn_gtkwave_interactive
            save_filename = self.env.config['sim.gtkw.file']
            quiet = self.env.config.get('sim.gtkw.quiet', True)
            spawn_gtkwave_interactive(dump_filename, save_filename,
                                      quiet=quiet)

    def vcd_now(self):
        return self.env.now * self.scale_factor

    def _close(self):
        self.vcd.close(self.vcd_now())
        self.dump_file.close()

    def activate_probe(self, scope, target, **hints):
        assert self.enabled
        var_type = hints.get('var_type')
        if var_type is None:
            if isinstance(target, simpy.Container):
                if isinstance(target.level, float):
                    var_type = 'real'
                else:
                    var_type = 'integer'
            elif isinstance(target, (simpy.Resource, simpy.Store, Queue)):
                var_type = 'integer'
            else:
                raise ValueError(
                    'Could not infer VCD var_type for {}'.format(scope))

        kwargs = {k: hints[k]
                  for k in ['size', 'init', 'ident']
                  if k in hints}

        if 'init' not in kwargs:
            if isinstance(target, simpy.Container):
                kwargs['init'] = target.level
            elif isinstance(target, simpy.Resource):
                kwargs['init'] = len(target.users) if target.users else 'z'
            elif isinstance(target, (simpy.Store, Queue)):
                kwargs['init'] = len(target.items)

        parent_scope, name = scope.rsplit('.', 1)
        var = self.vcd.register_var(parent_scope, name, var_type, **kwargs)

        def probe_callback(value):
            self.vcd.change(var, self.vcd_now(), value)

        return probe_callback

    def activate_trace(self, scope, **hints):
        assert self.enabled
        var_type = hints['var_type']
        kwargs = {k: hints[k]
                  for k in ['size', 'init', 'ident']
                  if k in hints}

        parent_scope, name = scope.rsplit('.', 1)
        var = self.vcd.register_var(parent_scope, name, var_type, **kwargs)

        if isinstance(var.size, tuple):
            def trace_callback(*value):
                self.vcd.change(var, self.vcd_now(), value)
        else:
            def trace_callback(value):
                self.vcd.change(var, self.vcd_now(), value)

        return trace_callback
示例#31
0
文件: pysim.py 项目: zignig/nmigen
class Simulator:
    def __init__(self, fragment, vcd_file=None, gtkw_file=None, traces=()):
        self._fragment        = Fragment.get(fragment, platform=None)

        self._signal_slots    = SignalDict()  # Signal -> int/slot
        self._slot_signals    = list()        # int/slot -> Signal

        self._domains         = list()        # [ClockDomain]
        self._clk_edges       = dict()        # ClockDomain -> int/edge
        self._domain_triggers = list()        # int/slot -> ClockDomain

        self._signals         = SignalSet()   # {Signal}
        self._comb_signals    = bitarray()    # {Signal}
        self._sync_signals    = bitarray()    # {Signal}
        self._user_signals    = bitarray()    # {Signal}
        self._domain_signals  = dict()        # ClockDomain -> {Signal}

        self._started         = False
        self._timestamp       = 0.
        self._delta           = 0.
        self._epsilon         = 1e-10
        self._fastest_clock   = self._epsilon
        self._all_clocks      = set()         # {str/domain}
        self._state           = _State()

        self._processes       = set()         # {process}
        self._process_loc     = dict()        # process -> str/loc
        self._passive         = set()         # {process}
        self._suspended       = set()         # {process}
        self._wait_deadline   = dict()        # process -> float/timestamp
        self._wait_tick       = dict()        # process -> str/domain

        self._funclets        = list()        # int/slot -> set(lambda)

        self._vcd_file        = vcd_file
        self._vcd_writer      = None
        self._vcd_signals     = list()        # int/slot -> set(vcd_signal)
        self._vcd_names       = list()        # int/slot -> str/name
        self._gtkw_file       = gtkw_file
        self._traces          = traces

        self._run_called      = False

    @staticmethod
    def _check_process(process):
        if inspect.isgeneratorfunction(process):
            process = process()
        if not (inspect.isgenerator(process) or inspect.iscoroutine(process)):
            raise TypeError("Cannot add a process '{!r}' because it is not a generator or "
                            "a generator function"
                            .format(process))
        return process

    def _name_process(self, process):
        if process in self._process_loc:
            return self._process_loc[process]
        else:
            if inspect.isgenerator(process):
                frame = process.gi_frame
            if inspect.iscoroutine(process):
                frame = process.cr_frame
            return "{}:{}".format(inspect.getfile(frame), inspect.getlineno(frame))

    def add_process(self, process):
        process = self._check_process(process)
        self._processes.add(process)

    def add_sync_process(self, process, domain="sync"):
        process = self._check_process(process)
        def sync_process():
            try:
                cmd = None
                while True:
                    if cmd is None:
                        cmd = Tick(domain)
                    result = yield cmd
                    self._process_loc[sync_process] = self._name_process(process)
                    cmd = process.send(result)
            except StopIteration:
                pass
        sync_process = sync_process()
        self.add_process(sync_process)

    def add_clock(self, period, *, phase=None, domain="sync", if_exists=False):
        if self._fastest_clock == self._epsilon or period < self._fastest_clock:
            self._fastest_clock = period
        if domain in self._all_clocks:
            raise ValueError("Domain '{}' already has a clock driving it"
                             .format(domain))

        half_period = period / 2
        if phase is None:
            phase = half_period
        for domain_obj in self._domains:
            if not domain_obj.local and domain_obj.name == domain:
                clk = domain_obj.clk
                break
        else:
            if if_exists:
                return
            else:
                raise ValueError("Domain '{}' is not present in simulation"
                                 .format(domain))
        def clk_process():
            yield Passive()
            yield Delay(phase)
            while True:
                yield clk.eq(1)
                yield Delay(half_period)
                yield clk.eq(0)
                yield Delay(half_period)
        self.add_process(clk_process)
        self._all_clocks.add(domain)

    def __enter__(self):
        if self._vcd_file:
            self._vcd_writer = VCDWriter(self._vcd_file, timescale="100 ps",
                                         comment="Generated by nMigen")

        root_fragment = self._fragment.prepare()

        hierarchy = {}
        domains = set()
        def add_fragment(fragment, scope=()):
            hierarchy[fragment] = scope
            domains.update(fragment.domains.values())
            for index, (subfragment, name) in enumerate(fragment.subfragments):
                if name is None:
                    add_fragment(subfragment, (*scope, "U{}".format(index)))
                else:
                    add_fragment(subfragment, (*scope, name))
        add_fragment(root_fragment, scope=("top",))
        self._domains = list(domains)
        self._clk_edges = {domain: 1 if domain.clk_edge == "pos" else 0 for domain in domains}

        def add_signal(signal):
            if signal not in self._signals:
                self._signals.add(signal)

                signal_slot = self._state.add(normalize(signal.reset, signal.shape()))
                self._signal_slots[signal] = signal_slot
                self._slot_signals.append(signal)

                self._comb_signals.append(False)
                self._sync_signals.append(False)
                self._user_signals.append(False)
                for domain in self._domains:
                    if domain not in self._domain_signals:
                        self._domain_signals[domain] = bitarray()
                    self._domain_signals[domain].append(False)

                self._funclets.append(set())

                self._domain_triggers.append(None)
                if self._vcd_writer:
                    self._vcd_signals.append(set())
                    self._vcd_names.append(None)

            return self._signal_slots[signal]

        def add_domain_signal(signal, domain):
            signal_slot = add_signal(signal)
            self._domain_triggers[signal_slot] = domain

        for fragment, fragment_scope in hierarchy.items():
            for signal in fragment.iter_signals():
                add_signal(signal)

            for domain_name, domain in fragment.domains.items():
                add_domain_signal(domain.clk, domain)
                if domain.rst is not None:
                    add_domain_signal(domain.rst, domain)

        for fragment, fragment_scope in hierarchy.items():
            for signal in fragment.iter_signals():
                if not self._vcd_writer:
                    continue

                signal_slot = self._signal_slots[signal]

                for i, (subfragment, name) in enumerate(fragment.subfragments):
                    if signal in subfragment.ports:
                        var_name = "{}_{}".format(name or "U{}".format(i), signal.name)
                        break
                else:
                    var_name = signal.name

                if signal.decoder:
                    var_type = "string"
                    var_size = 1
                    var_init = signal.decoder(signal.reset).expandtabs().replace(" ", "_")
                else:
                    var_type = "wire"
                    var_size = signal.nbits
                    var_init = signal.reset

                suffix = None
                while True:
                    try:
                        if suffix is None:
                            var_name_suffix = var_name
                        else:
                            var_name_suffix = "{}${}".format(var_name, suffix)
                        self._vcd_signals[signal_slot].add(self._vcd_writer.register_var(
                            scope=".".join(fragment_scope), name=var_name_suffix,
                            var_type=var_type, size=var_size, init=var_init))
                        if self._vcd_names[signal_slot] is None:
                            self._vcd_names[signal_slot] = \
                                ".".join(fragment_scope + (var_name_suffix,))
                        break
                    except KeyError:
                        suffix = (suffix or 0) + 1

            for domain_name, signals in fragment.drivers.items():
                signals_bits = bitarray(len(self._signals))
                signals_bits.setall(False)
                for signal in signals:
                    signals_bits[self._signal_slots[signal]] = True

                if domain_name is None:
                    self._comb_signals |= signals_bits
                else:
                    self._sync_signals |= signals_bits
                    self._domain_signals[fragment.domains[domain_name]] |= signals_bits

            statements = []
            for domain_name, signals in fragment.drivers.items():
                reset_stmts = []
                hold_stmts  = []
                for signal in signals:
                    reset_stmts.append(signal.eq(signal.reset))
                    hold_stmts .append(signal.eq(signal))

                if domain_name is None:
                    statements += reset_stmts
                else:
                    if fragment.domains[domain_name].async_reset:
                        statements.append(Switch(fragment.domains[domain_name].rst,
                            {0: hold_stmts, 1: reset_stmts}))
                    else:
                        statements += hold_stmts
            statements += fragment.statements

            compiler = _StatementCompiler(self._signal_slots)
            funclet = compiler(statements)

            def add_funclet(signal, funclet):
                if signal in self._signal_slots:
                    self._funclets[self._signal_slots[signal]].add(funclet)

            for signal in compiler.sensitivity:
                add_funclet(signal, funclet)
            for domain in fragment.domains.values():
                add_funclet(domain.clk, funclet)
                if domain.rst is not None:
                    add_funclet(domain.rst, funclet)

        self._user_signals = bitarray(len(self._signals))
        self._user_signals.setall(True)
        self._user_signals &= ~self._comb_signals
        self._user_signals &= ~self._sync_signals

        return self

    def _update_dirty_signals(self):
        """Perform the statement part of IR processes (aka RTLIL case)."""
        # First, for all dirty signals, use sensitivity lists to determine the set of fragments
        # that need their statements to be reevaluated because the signals changed at the previous
        # delta cycle.
        funclets = set()
        for signal_slot in self._state.flush_curr_dirty():
            funclets.update(self._funclets[signal_slot])

        # Second, compute the values of all signals at the start of the next delta cycle, by
        # running precompiled statements.
        for funclet in funclets:
            funclet(self._state)

    def _commit_signal(self, signal_slot, domains):
        """Perform the driver part of IR processes (aka RTLIL sync), for individual signals."""
        # Take the computed value (at the start of this delta cycle) of a signal (that could have
        # come from an IR process that ran earlier, or modified by a simulator process) and update
        # the value for this delta cycle.
        old, new = self._state.commit(signal_slot)
        if old == new:
            return

        # If the signal is a clock that triggers synchronous logic, record that fact.
        if (self._domain_triggers[signal_slot] is not None and
                self._clk_edges[self._domain_triggers[signal_slot]] == new):
            domains.add(self._domain_triggers[signal_slot])

        if self._vcd_writer:
            # Finally, dump the new value to the VCD file.
            for vcd_signal in self._vcd_signals[signal_slot]:
                signal = self._slot_signals[signal_slot]
                if signal.decoder:
                    var_value = signal.decoder(new).expandtabs().replace(" ", "_")
                else:
                    var_value = new
                vcd_timestamp = (self._timestamp + self._delta) / self._epsilon
                self._vcd_writer.change(vcd_signal, vcd_timestamp, var_value)

    def _commit_comb_signals(self, domains):
        """Perform the comb part of IR processes (aka RTLIL always)."""
        # Take the computed value (at the start of this delta cycle) of every comb signal and
        # update the value for this delta cycle.
        for signal_slot in self._state.iter_next_dirty():
            if self._comb_signals[signal_slot]:
                self._commit_signal(signal_slot, domains)

    def _commit_sync_signals(self, domains):
        """Perform the sync part of IR processes (aka RTLIL posedge)."""
        # At entry, `domains` contains a set of every simultaneously triggered sync update.
        while domains:
            # Advance the timeline a bit (purely for observational purposes) and commit all of them
            # at the same timestamp.
            self._delta += self._epsilon
            curr_domains, domains = domains, set()

            while curr_domains:
                domain = curr_domains.pop()

                # Wake up any simulator processes that wait for a domain tick.
                for process, wait_domain_name in list(self._wait_tick.items()):
                    if domain.name == wait_domain_name:
                        del self._wait_tick[process]
                        self._suspended.remove(process)

                        # Immediately run the process. It is important that this happens here,
                        # and not on the next step, when all the processes will run anyway,
                        # because Tick() simulates an edge triggered process. Like DFFs that latch
                        # a value from the previous clock cycle, simulator processes observe signal
                        # values from the previous clock cycle on a tick, too.
                        self._run_process(process)

                # Take the computed value (at the start of this delta cycle) of every sync signal
                # in this domain and update the value for this delta cycle. This can trigger more
                # synchronous logic, so record that.
                for signal_slot in self._state.iter_next_dirty():
                    if self._domain_signals[domain][signal_slot]:
                        self._commit_signal(signal_slot, domains)

            # Unless handling synchronous logic above has triggered more synchronous logic (which
            # can happen e.g. if a domain is clocked off a clock divisor in fabric), we're done.
            # Otherwise, do one more round of updates.

    def _run_process(self, process):
        try:
            cmd = process.send(None)
            while True:
                if type(cmd) is Delay:
                    if cmd.interval is None:
                        interval = self._epsilon
                    else:
                        interval = cmd.interval
                    self._wait_deadline[process] = self._timestamp + interval
                    self._suspended.add(process)
                    break

                elif type(cmd) is Tick:
                    self._wait_tick[process] = cmd.domain
                    self._suspended.add(process)
                    break

                elif type(cmd) is Passive:
                    self._passive.add(process)

                elif type(cmd) is Assign:
                    lhs_signals = cmd.lhs._lhs_signals()
                    for signal in lhs_signals:
                        if not signal in self._signals:
                            raise ValueError("Process '{}' sent a request to set signal '{!r}', "
                                             "which is not a part of simulation"
                                             .format(self._name_process(process), signal))
                        signal_slot = self._signal_slots[signal]
                        if self._comb_signals[signal_slot]:
                            raise ValueError("Process '{}' sent a request to set signal '{!r}', "
                                             "which is a part of combinatorial assignment in "
                                             "simulation"
                                             .format(self._name_process(process), signal))

                    if type(cmd.lhs) is Signal and type(cmd.rhs) is Const:
                        # Fast path.
                        self._state.set(self._signal_slots[cmd.lhs],
                                        normalize(cmd.rhs.value, cmd.lhs.shape()))
                    else:
                        compiler = _StatementCompiler(self._signal_slots)
                        funclet = compiler(cmd)
                        funclet(self._state)

                    domains = set()
                    for signal in lhs_signals:
                        self._commit_signal(self._signal_slots[signal], domains)
                    self._commit_sync_signals(domains)

                elif type(cmd) is Signal:
                    # Fast path.
                    cmd = process.send(self._state.curr[self._signal_slots[cmd]])
                    continue

                elif isinstance(cmd, Value):
                    compiler = _RHSValueCompiler(self._signal_slots)
                    funclet = compiler(cmd)
                    cmd = process.send(funclet(self._state))
                    continue

                else:
                    raise TypeError("Received unsupported command '{!r}' from process '{}'"
                                    .format(cmd, self._name_process(process)))

                cmd = process.send(None)

        except StopIteration:
            self._processes.remove(process)
            self._passive.discard(process)

        except Exception as e:
            process.throw(e)

    def step(self, run_passive=False):
        # Are there any delta cycles we should run?
        if self._state.curr_dirty.any():
            # We might run some delta cycles, and we have simulator processes waiting on
            # a deadline. Take care to not exceed the closest deadline.
            if self._wait_deadline and \
                    (self._timestamp + self._delta) >= min(self._wait_deadline.values()):
                # Oops, we blew the deadline. We *could* run the processes now, but this is
                # virtually certainly a logic loop and a design bug, so bail out instead.d
                raise DeadlineError("Delta cycles exceeded process deadline; combinatorial loop?")

            domains = set()
            while self._state.curr_dirty.any():
                self._update_dirty_signals()
                self._commit_comb_signals(domains)
            self._commit_sync_signals(domains)
            return True

        # Are there any processes that haven't had a chance to run yet?
        if len(self._processes) > len(self._suspended):
            # Schedule an arbitrary one.
            process = (self._processes - set(self._suspended)).pop()
            self._run_process(process)
            return True

        # All processes are suspended. Are any of them active?
        if len(self._processes) > len(self._passive) or run_passive:
            # Are any of them suspended before a deadline?
            if self._wait_deadline:
                # Schedule the one with the lowest deadline.
                process, deadline = min(self._wait_deadline.items(), key=lambda x: x[1])
                del self._wait_deadline[process]
                self._suspended.remove(process)
                self._timestamp = deadline
                self._delta = 0.
                self._run_process(process)
                return True

        # No processes, or all processes are passive. Nothing to do!
        return False

    def run(self):
        self._run_called = True

        while self.step():
            pass

    def run_until(self, deadline, run_passive=False):
        self._run_called = True

        while self._timestamp < deadline:
            if not self.step(run_passive):
                return False

        return True

    def __exit__(self, *args):
        if not self._run_called:
            warnings.warn("Simulation created, but not run", UserWarning)

        if self._vcd_writer:
            vcd_timestamp = (self._timestamp + self._delta) / self._epsilon
            self._vcd_writer.close(vcd_timestamp)

        if self._vcd_file and self._gtkw_file:
            gtkw_save = GTKWSave(self._gtkw_file)
            if hasattr(self._vcd_file, "name"):
                gtkw_save.dumpfile(self._vcd_file.name)
            if hasattr(self._vcd_file, "tell"):
                gtkw_save.dumpfile_size(self._vcd_file.tell())

            gtkw_save.treeopen("top")
            gtkw_save.zoom_markers(math.log(self._epsilon / self._fastest_clock) - 14)

            def add_trace(signal, **kwargs):
                signal_slot = self._signal_slots[signal]
                if self._vcd_names[signal_slot] is not None:
                    if len(signal) > 1 and not signal.decoder:
                        suffix = "[{}:0]".format(len(signal) - 1)
                    else:
                        suffix = ""
                    gtkw_save.trace(self._vcd_names[signal_slot] + suffix, **kwargs)

            for domain in self._domains:
                with gtkw_save.group("d.{}".format(domain.name)):
                    if domain.rst is not None:
                        add_trace(domain.rst)
                    add_trace(domain.clk)

            for signal in self._traces:
                add_trace(signal)

        if self._vcd_file:
            self._vcd_file.close()
        if self._gtkw_file:
            self._gtkw_file.close()
示例#32
0
#machine_name = os.path.split(os.path.dirname(dpath))[1]
machine_name = os.path.split(dpath)[1]

# this card supports upto two 'machines' pods can be assigned between them
machine_name = "HP16555A." + machine_name

#print machine_name
file_list = []  # full relative path of ascii files
var_list = []
signal_list = []
file_handle_list = []
prev_line = []

try:
    with VCDWriter(sys.stdout,
                   timescale='1 ns',
                   date='today',
                   init_timestamp=0) as writer:
        # figure out what signals ther are
        # each signal has its own file
        for filename in glob.glob(os.path.join(dpath, '*.txt')):
            if os.path.basename(filename) != "1st_line.txt":
                file_list.append(os.path.basename(filename))
        # re-order list so line number and absolute time at start
        #find line number
        old_index = file_list.index("line_num.txt")
        #then move it:
        file_list.insert(0, file_list.pop(old_index))
        #find time
        old_index = file_list.index("time_abs.txt")
        #then move it:
        file_list.insert(1, file_list.pop(old_index))
示例#33
0
文件: pysim.py 项目: zignig/nmigen
    def __enter__(self):
        if self._vcd_file:
            self._vcd_writer = VCDWriter(self._vcd_file, timescale="100 ps",
                                         comment="Generated by nMigen")

        root_fragment = self._fragment.prepare()

        hierarchy = {}
        domains = set()
        def add_fragment(fragment, scope=()):
            hierarchy[fragment] = scope
            domains.update(fragment.domains.values())
            for index, (subfragment, name) in enumerate(fragment.subfragments):
                if name is None:
                    add_fragment(subfragment, (*scope, "U{}".format(index)))
                else:
                    add_fragment(subfragment, (*scope, name))
        add_fragment(root_fragment, scope=("top",))
        self._domains = list(domains)
        self._clk_edges = {domain: 1 if domain.clk_edge == "pos" else 0 for domain in domains}

        def add_signal(signal):
            if signal not in self._signals:
                self._signals.add(signal)

                signal_slot = self._state.add(normalize(signal.reset, signal.shape()))
                self._signal_slots[signal] = signal_slot
                self._slot_signals.append(signal)

                self._comb_signals.append(False)
                self._sync_signals.append(False)
                self._user_signals.append(False)
                for domain in self._domains:
                    if domain not in self._domain_signals:
                        self._domain_signals[domain] = bitarray()
                    self._domain_signals[domain].append(False)

                self._funclets.append(set())

                self._domain_triggers.append(None)
                if self._vcd_writer:
                    self._vcd_signals.append(set())
                    self._vcd_names.append(None)

            return self._signal_slots[signal]

        def add_domain_signal(signal, domain):
            signal_slot = add_signal(signal)
            self._domain_triggers[signal_slot] = domain

        for fragment, fragment_scope in hierarchy.items():
            for signal in fragment.iter_signals():
                add_signal(signal)

            for domain_name, domain in fragment.domains.items():
                add_domain_signal(domain.clk, domain)
                if domain.rst is not None:
                    add_domain_signal(domain.rst, domain)

        for fragment, fragment_scope in hierarchy.items():
            for signal in fragment.iter_signals():
                if not self._vcd_writer:
                    continue

                signal_slot = self._signal_slots[signal]

                for i, (subfragment, name) in enumerate(fragment.subfragments):
                    if signal in subfragment.ports:
                        var_name = "{}_{}".format(name or "U{}".format(i), signal.name)
                        break
                else:
                    var_name = signal.name

                if signal.decoder:
                    var_type = "string"
                    var_size = 1
                    var_init = signal.decoder(signal.reset).expandtabs().replace(" ", "_")
                else:
                    var_type = "wire"
                    var_size = signal.nbits
                    var_init = signal.reset

                suffix = None
                while True:
                    try:
                        if suffix is None:
                            var_name_suffix = var_name
                        else:
                            var_name_suffix = "{}${}".format(var_name, suffix)
                        self._vcd_signals[signal_slot].add(self._vcd_writer.register_var(
                            scope=".".join(fragment_scope), name=var_name_suffix,
                            var_type=var_type, size=var_size, init=var_init))
                        if self._vcd_names[signal_slot] is None:
                            self._vcd_names[signal_slot] = \
                                ".".join(fragment_scope + (var_name_suffix,))
                        break
                    except KeyError:
                        suffix = (suffix or 0) + 1

            for domain_name, signals in fragment.drivers.items():
                signals_bits = bitarray(len(self._signals))
                signals_bits.setall(False)
                for signal in signals:
                    signals_bits[self._signal_slots[signal]] = True

                if domain_name is None:
                    self._comb_signals |= signals_bits
                else:
                    self._sync_signals |= signals_bits
                    self._domain_signals[fragment.domains[domain_name]] |= signals_bits

            statements = []
            for domain_name, signals in fragment.drivers.items():
                reset_stmts = []
                hold_stmts  = []
                for signal in signals:
                    reset_stmts.append(signal.eq(signal.reset))
                    hold_stmts .append(signal.eq(signal))

                if domain_name is None:
                    statements += reset_stmts
                else:
                    if fragment.domains[domain_name].async_reset:
                        statements.append(Switch(fragment.domains[domain_name].rst,
                            {0: hold_stmts, 1: reset_stmts}))
                    else:
                        statements += hold_stmts
            statements += fragment.statements

            compiler = _StatementCompiler(self._signal_slots)
            funclet = compiler(statements)

            def add_funclet(signal, funclet):
                if signal in self._signal_slots:
                    self._funclets[self._signal_slots[signal]].add(funclet)

            for signal in compiler.sensitivity:
                add_funclet(signal, funclet)
            for domain in fragment.domains.values():
                add_funclet(domain.clk, funclet)
                if domain.rst is not None:
                    add_funclet(domain.rst, funclet)

        self._user_signals = bitarray(len(self._signals))
        self._user_signals.setall(True)
        self._user_signals &= ~self._comb_signals
        self._user_signals &= ~self._sync_signals

        return self
示例#34
0
  field_toks = line.split(",")
  if len(field_toks) != len(field_names):
    break
  for field_i in range(0,len(field_names)):
    field_tok = field_toks[field_i]
    field_value_lists[field_i].append(field_tok)
for field_i in range(0,len(field_names)):
  field_name = field_names[field_i]
  #print("Field:",field_name)
  #print(field_value_lists[field_i])

import tempfile
fp = tempfile.NamedTemporaryFile(mode='w')
#fp = open("out.vcd",'w')
from vcd import VCDWriter
with VCDWriter(fp, timescale='1 ns', date='today') as writer:
  field_types = []
  field_vars = []
  for field_i in range(0,len(field_names)):
    # Setup name and type
    field_name = field_names[field_i]
    try:
      int_val = int(field_value_lists[field_i][0])
      field_type = 'integer' #'real'
      field_size = 64 # hardcode assume big enough for now
      field_var = writer.register_var('debug_probes', field_name, field_type, size=field_size) #init=1.23
    except:
      field_type = 'string'
      field_var = writer.register_var('debug_probes', field_name, field_type)
    field_types.append(field_type)
    field_vars.append(field_var)
示例#35
0
文件: vcd.py 项目: jesseclin/pygears
    def __init__(self,
                 trace_fn='pygears.vcd',
                 include=Inject('debug/trace'),
                 tlm=False,
                 shmidcat=Inject('sim_extens/vcd/shmidcat'),
                 vcd_fifo=Inject('sim_extens/vcd/vcd_fifo'),
                 sim=Inject('sim/simulator'),
                 outdir=Inject('results-dir')):

        super().__init__()
        self.sim = sim
        self.finished = False
        self.vcd_fifo = vcd_fifo
        self.shmidcat = shmidcat
        self.outdir = outdir
        self.trace_fn = None
        self.shmid_proc = None

        vcd_visitor = VCDHierVisitor(include, tlm)
        vcd_visitor.visit(find('/'))

        if not vcd_visitor.vcd_vars:
            self.deactivate()
            return

        self.trace_fn = os.path.abspath(os.path.join(self.outdir, trace_fn))
        atexit.register(self.finish)

        try:
            subprocess.call(f"rm -f {self.trace_fn}", shell=True)
        except OSError:
            pass

        if self.vcd_fifo:
            subprocess.call(f"mkfifo {self.trace_fn}", shell=True)
        else:
            log.info(f'Main VCD dump to "{self.trace_fn}"')

        if self.shmidcat:
            self.shmid_proc = subprocess.Popen(f'shmidcat {self.trace_fn}',
                                               shell=True,
                                               stdout=subprocess.PIPE)

            # Wait for shmidcat to actually open the pipe, which is necessary
            # to happen prior to init of the verilator. If shmidcat does not
            # open the pipe, verilator will get stuck
            import time
            time.sleep(0.1)

        self.vcd_file = open(self.trace_fn, 'w')

        if self.shmidcat:
            self.shmid = self.shmid_proc.stdout.readline().decode().strip()
            log.info(f'Main VCD dump to shared memory at 0x{self.shmid}')

        self.writer = VCDWriter(self.vcd_file, timescale='1 ns', date='today')

        reg['VCDWriter'] = self.writer
        reg['VCD'] = self

        self.clk_var = self.writer.register_var('', 'clk', 'wire', size=1, init=1)

        self.timestep_var = self.writer.register_var('', 'timestep', 'integer', init=0)

        self.handhake = set()

        self.vcd_vars = {
            p: register_traces_for_intf(p.dtype, scope, self.writer)
            for p, scope in vcd_visitor.vcd_vars.items()
        }

        self.writer.flush()