Exemplo n.º 1
0
    def __init__(self, step_width=None, step_shift=0, **kwargs):
        Filter.__init__(self, **kwargs)

        # required by tests
        self.step_shift = step_shift

        width = len(self.y)
        if step_width is None:
            step_width = width

        self.shift = CSRConstant(step_shift, bits_for(step_shift))
        self.step = CSRStorage(step_width)
        self.min = CSRStorage(width, reset=1 << (width - 1))
        self.max = CSRStorage(width, reset=(1 << (width - 1)) - 1)
        self.run = CSRStorage(1)

        ###

        self.submodules.sweep = Sweep(width + step_shift + 1)
        self.submodules.limit = Limit(width + 1)

        min, max = self.min.storage, self.max.storage
        self.comb += [
            self.sweep.run.eq(~self.clear & self.run.storage),
            self.sweep.hold.eq(self.hold),
            self.limit.x.eq(self.sweep.y >> step_shift),
            self.sweep.step.eq(self.step.storage),
        ]
        self.sync += [
            self.limit.min.eq(Cat(min, min[-1])),
            self.limit.max.eq(Cat(max, max[-1])),
            self.sweep.turn.eq(self.limit.railed),
            self.y.eq(self.limit.y),
        ]
Exemplo n.º 2
0
    def init_csr(self, width, signal_width, chain_factor_width):
        factor_reset = 1 << (chain_factor_width - 1)
        # we use chain_factor_width + 1 for the single channel mode
        self.dual_channel = CSRStorage(1)
        self.chain_a_factor = CSRStorage(chain_factor_width + 1, reset=factor_reset)
        self.chain_b_factor = CSRStorage(chain_factor_width + 1, reset=factor_reset)

        self.chain_a_offset = CSRStorage(width)
        self.chain_b_offset = CSRStorage(width)
        self.chain_a_offset_signed = Signal((width, True))
        self.chain_b_offset_signed = Signal((width, True))
        self.combined_offset = CSRStorage(width)
        self.combined_offset_signed = Signal((width, True))
        self.out_offset = CSRStorage(width)
        self.out_offset_signed = Signal((width, True))

        self.mod_channel = CSRStorage(1)
        self.control_channel = CSRStorage(1)
        self.sweep_channel = CSRStorage(2)

        self.slow_value = CSRStatus(width)

        max_decimation = 16
        self.slow_decimation = CSRStorage(bits_for(max_decimation))

        for i in range(4):
            if i == 0:
                continue
            name = "analog_out_%d" % i
            setattr(self, name, CSRStorage(15, name=name))
Exemplo n.º 3
0
def relabel_with_parts(g, parts):
    peid_offset = 1
    for part in parts:
        if peid_offset < bits_for(len(part)):
            peid_offset = bits_for(len(part))
    relabel_d = {}
    for i, part in enumerate(parts):
        for j, n in enumerate(part):
            if i == 0:
                idx = j + 1
            else:
                idx = j
            assert idx < 2**peid_offset
            relabel_d[n] = (i << peid_offset) | idx
    g = nx.relabel_nodes(g, relabel_d)
    log_stats(g)
    return g, 2**peid_offset
Exemplo n.º 4
0
def relabel_with_parts(g, parts):
    peid_offset = 1
    for part in parts:
        if peid_offset < bits_for(len(part)):
            peid_offset = bits_for(len(part))
    relabel_d = {}
    for i, part in enumerate(parts):
        for j, n in enumerate(part):
            if i == 0:
                idx = j+1
            else:
                idx = j
            assert idx < 2**peid_offset
            relabel_d[n] = (i << peid_offset) | idx
    g = nx.relabel_nodes(g, relabel_d)
    log_stats(g)
    return g, 2**peid_offset
Exemplo n.º 5
0
def cross_connect(gpio, chains):
    state_names = ["force"] + ["di%i" % i for i in range(len(gpio.i))]
    states = [1, gpio.i]
    signal_names = ["zero"]
    signals = Array([0])

    for n, c in chains:
        for s in c.state_out:
            states.append(s)
            state_names.append("%s_%s" % (n, s.backtrace[-1][0]))
        for s in c.signal_out:
            signals.append(s)
            name = s.backtrace[-1][0]
            signal_names.append("%s_%s" % (n, name))
            sig = CSRStatus(len(s), name=name)
            clr = CSR(name="%s_clr" % name)
            max = CSRStatus(len(s), name="%s_max" % name)
            min = CSRStatus(len(s), name="%s_min" % name)
            # setattr(c, sig.name, sig)
            setattr(c, clr.name, clr)
            setattr(c, max.name, max)
            setattr(c, min.name, min)
            c.comb += sig.status.eq(s)
            c.sync += If(clr.re | (max.status < s), max.status.eq(s))
            c.sync += If(clr.re | (min.status > s), min.status.eq(s))

    states = Cat(states)
    state = Signal(len(states))
    gpio.comb += state.eq(states)
    gpio.state = CSRStatus(len(state))
    gpio.state_clr = CSR()
    gpio.sync += [
        If(
            gpio.state_clr.re,
            gpio.state.status.eq(0),
        ).Else(gpio.state.status.eq(gpio.state.status | state), )
    ]

    # connect gpio output to "doi%i_en"
    for i, s in enumerate(gpio.o):
        csr = CSRStorage(len(state), name="do%i_en" % i)
        setattr(gpio, csr.name, csr)
        gpio.sync += s.eq((state & csr.storage) != 0)

    # connect state ins to "%s_en" and signal ins to "%s_sel"
    for n, c in chains:
        for s in c.state_in:
            csr = CSRStorage(len(state), name="%s_en" % s.backtrace[-1][0])
            setattr(c, csr.name, csr)
            c.sync += s.eq((state & csr.storage) != 0)

        for s in c.signal_in:
            csr = CSRStorage(bits_for(len(signals) - 1),
                             name="%s_sel" % s.backtrace[-1][0])
            setattr(c, csr.name, csr)
            c.sync += s.eq(signals[csr.storage])

    return state_names, signal_names
Exemplo n.º 6
0
    def __init__(self, input_bit, max_delay):
        self.delay = Signal(bits_for(max_delay))
        self.restart = Signal()
        self.writing_data_now = Signal()

        self.input = Signal((input_bit, True))
        self.output = Signal((input_bit, True))

        # this ensures that counter overflows / underflows correctly
        assert max_delay == (2**(bits_for(max_delay)) - 1)

        self.mem_rdport, self.mem_wrport = create_memory(
            self, input_bit, max_delay, "dynamic_delay_mem")

        # register all the ports
        self.specials += [self.mem_rdport, self.mem_wrport]

        self.counter = Signal(bits_for(max_delay))
        self.counter_delayed = Signal((bits_for(max_delay)))

        negative_delay = 1

        self.sync += [
            If(self.restart, self.counter.eq(0)).Else(
                If(self.writing_data_now, self.counter.eq(self.counter + 1))),
        ]
        self.comb += [
            self.mem_wrport.we.eq(self.writing_data_now),
            self.mem_wrport.adr.eq(self.counter),
            self.mem_wrport.dat_w.eq(self.input),
            self.mem_rdport.adr.eq(self.counter_delayed),
            self.counter_delayed.eq(self.counter - self.delay +
                                    negative_delay),
            self.mem_rdport.adr.eq(self.counter_delayed),
            If(self.counter < self.delay - negative_delay,
               self.output.eq(0)).Else(self.output.eq(
                   self.mem_rdport.dat_r), ),
        ]
Exemplo n.º 7
0
    def __init__(self, width=14, N_points=16383, max_delay=16383):
        self.restart = Signal()
        self.writing_data_now = Signal()

        self.input = Signal((width, True))
        self.delay_value = Signal(bits_for(N_points))

        sum_value_bits = bits_for(((2**width) - 1) * N_points)
        self.sum_value = Signal((sum_value_bits, True))
        delayed_sum = Signal((sum_value_bits, True))
        current_sum_diff = Signal((sum_value_bits + 1, True))
        self.output = Signal.like(current_sum_diff)

        self.submodules.delayer = DynamicDelay(sum_value_bits,
                                               max_delay=max_delay)

        self.sync += [
            If(
                self.restart,
                self.sum_value.eq(0),
            ).Else(
                If(
                    self.writing_data_now,
                    # not at start
                    self.sum_value.eq(self.sum_value + self.input),
                ))
        ]

        self.comb += [
            self.delayer.writing_data_now.eq(self.writing_data_now),
            self.delayer.restart.eq(self.restart),
            self.delayer.delay.eq(self.delay_value),
            self.delayer.input.eq(self.sum_value),
            delayed_sum.eq(self.delayer.output),
            current_sum_diff.eq(self.sum_value - delayed_sum),
            self.output.eq(current_sum_diff),
        ]
Exemplo n.º 8
0
    def init_csr(self, N_points):
        # CSR storages
        self.time_scale = CSRStorage(bits_for(N_points))
        self.N_instructions = CSRStorage(
            bits_for(AUTOLOCK_MAX_N_INSTRUCTIONS - 1))
        self.final_wait_time = CSRStorage(bits_for(N_points))

        peak_height_bit = len(self.sum_diff_calculator.sum_value)
        self.peak_heights = [
            CSRStorage(peak_height_bit, name="peak_height_%d" % idx)
            for idx in range(AUTOLOCK_MAX_N_INSTRUCTIONS)
        ]
        for idx, peak_height in enumerate(self.peak_heights):
            setattr(self, "peak_height_%d" % idx, peak_height)

        x_data_length_bit = bits_for(N_points)
        self.wait_for = [
            CSRStorage(x_data_length_bit, name="wait_for_%d" % idx)
            for idx in range(AUTOLOCK_MAX_N_INSTRUCTIONS)
        ]
        for idx, wait_for in enumerate(self.wait_for):
            setattr(self, "wait_for_%d" % idx, wait_for)

        return peak_height_bit, x_data_length_bit
Exemplo n.º 9
0
def partition_random(g, pe):
    num_nodes = nx.number_of_nodes(g)
    peid_offset = bits_for((num_nodes + pe - 1) // pe)
    next_number = 0
    next_pe = 1
    relabel_d = {}
    for n in g.nodes():
        if next_pe == pe:
            next_pe = 0
            next_number += 1
        assert next_number < 2**peid_offset
        relabel_d[n] = (next_pe << peid_offset) | next_number
        next_pe += 1

    g = nx.relabel_nodes(g, relabel_d)
    log_stats(g)
    return g, 2**peid_offset
Exemplo n.º 10
0
def partition_random(g, pe):
    num_nodes = nx.number_of_nodes(g)
    peid_offset = bits_for((num_nodes + pe - 1)//pe)
    next_number = 0
    next_pe = 1
    relabel_d = {}
    for n in g.nodes():
        if next_pe == pe:
            next_pe = 0
            next_number += 1
        assert next_number < 2**peid_offset
        relabel_d[n] = (next_pe << peid_offset) | next_number
        next_pe += 1

    g = nx.relabel_nodes(g, relabel_d)
    log_stats(g)
    return g, 2**peid_offset
Exemplo n.º 11
0
def resolve_defaults(config, inverted=False, graphfile=None, num_nodes=None, num_edges=None, digraph=False, graphsave=None, sim=True):
    if not graphfile and not num_nodes:
        if 'graphfile' in config['graph']:
            graphfile = config['graph'].get('graphfile')
        elif 'nodes' in config['graph']:
            num_nodes = eval(config['graph'].get('nodes'))
            if not num_edges:
                if 'edges' in config['graph']:
                    num_edges = eval(config['graph'].get('edges'))
                else:
                    num_edges = num_nodes - 1
        else:
            raise ValueError("Graph not specified")
    if 'approach' in config['graph']:
        approach = config['graph'].get('approach')
    else:
        approach = "random_walk"

    graphfile_basename = os.path.splitext(os.path.basename(graphfile))[0] if graphfile else str(num_nodes)
    log_file_basename = "{}_{}_{}".format(config['logging'].get('log_file_name', fallback='fpgagraphlib'), config['app']['algo'], graphfile_basename)

    logger = logging.getLogger()
    logger.setLevel("DEBUG")
    handler = logging.StreamHandler()
    formatter_args = {"fmt": "{levelname:.1s}: {name:>20.20s}: {message:s}", "style": "{"}
    if sys.stderr.isatty() and sys.platform != 'win32':
        handler.setFormatter(ANSIColorFormatter(**formatter_args))
    else:
        handler.setFormatter(logging.Formatter(**formatter_args))
    handler.setLevel(config['logging'].get('console_log_level', fallback='INFO'))
    logger.addHandler(handler)

    log_file_number = 0
    while os.path.exists("{}_{}.log".format(log_file_basename, log_file_number)):
        log_file_number += 1

    alt_adj_val_data_name = None

    if not config['logging'].get('disable_logfile', fallback=False):
        file_log_level = config['logging'].get('file_log_level', fallback='DEBUG')
        logger.info("Logging to file {}_{}.log with level {}".format(log_file_basename, log_file_number, file_log_level))
        # define a Handler which writes INFO messages or higher to the sys.stderr
        logfile = logging.FileHandler(filename="{}_{}.log".format(log_file_basename, log_file_number),
        mode='w')
        logfile.setLevel(file_log_level)
        # set a format which is simpler for console use
        formatter = logging.Formatter('%(levelname)-8s: %(name)-25s: %(message)s')
        # tell the handler to use this format
        logfile.setFormatter(formatter)
        # add the handler to the root logger
        logger.addHandler(logfile)

        alt_adj_val_data_name = "{}_{}.data".format(log_file_basename, log_file_number)

    # root is set up, now get logger for local logging
    logger = logging.getLogger('init')

    kwargs = dict()
    for k in config['arch']:
        try:
            kwargs[k] = eval(config['arch'].get(k))
        except NameError:
            kwargs[k] = config['arch'].get(k)

    if "num_channels" not in kwargs:
        kwargs["num_channels"] = 3

    kwargs["channel_bits"] = bits_for(kwargs["num_channels"] - 1)

    if "num_fpga" not in kwargs:
        if "num_pe_per_fpga" in kwargs and "num_pe" in kwargs:
            kwargs["num_fpga"] = (kwargs["num_pe"] + kwargs["num_pe_per_fpga"] - 1)//kwargs["num_pe_per_fpga"]
        else:
            kwargs["num_fpga"] = 1

    if "num_pe" not in kwargs:
        if "num_pe_per_fpga" in kwargs:
            kwargs["num_pe"] = kwargs["num_pe_per_fpga"]*kwargs["num_fpga"]
        else:
            kwargs["num_pe"] = 8

    if "num_pe_per_fpga" not in kwargs:
        kwargs["num_pe_per_fpga"] = (kwargs["num_pe"] + kwargs["num_fpga"] - 1)//kwargs["num_fpga"]

    if graphfile:
        logger.info("Reading graph from file {}".format(graphfile))
        g = read_graph(graphfile, digraph=digraph, connected=True)
        num_nodes = nx.number_of_nodes(g)
        num_edges = nx.number_of_edges(g)
    else:
        logger.info("Generating graph with {} nodes and {} edges".format(num_nodes, num_edges))
        g = generate_graph(num_nodes, num_edges, approach=approach, digraph=digraph)

    if graphsave:
        logger.info("Saving graph to file {}".format(graphsave))
        export_graph(g, graphsave)

    if "memtype" not in kwargs:
        kwargs["memtype"] = "BRAM"
        if "use_hmc" in kwargs:
            logger.warning("\"use_hmc\" is deprecated. Use \"memtype = HMC\" instead.")
            if kwargs["use_hmc"]:
                kwargs["memtype"] = "HMC"
        if "use_ddr" in kwargs:
            logger.warning("\"use_ddr\" is deprecated. Use \"memtype = AXI\" instead.")
            if kwargs["use_ddr"]:
                kwargs["memtype"] = "AXI"

    if "updates_in_hmc" not in kwargs:
        kwargs["updates_in_hmc"] = False

    kwargs["inverted"] = inverted

    if kwargs["memtype"] == "HMC" and kwargs["updates_in_hmc"]:
        raise NotImplementedError("Can't use HMC for edges in 2-phase mode")

    updates_in_hmc = kwargs["updates_in_hmc"] if "updates_in_hmc" in kwargs else False

    if "num_nodes_per_pe" in kwargs or "max_edges_per_pe" in kwargs:
        logger.warning("Setting num_nodes_per_pe or max_edges_per_pe manually is no longer supported! Value ignored.")

    if 'partition' in config['graph']:
        kwargs["partition"] = config['graph'].get('partition')
        if 'partition_ufactor' in config['graph']:
            kwargs["partition_ufactor"] = config['graph'].getint('partition_ufactor')
        else:
            kwargs["partition_ufactor"] = 1
    else:
        kwargs["partition"] = "robin"

    if "peidsize" not in kwargs:
        kwargs["peidsize"] = bits_for(kwargs["num_pe"])

    algo_config_module = "{}.config".format(config['app']['algo'])
    algo = import_module(algo_config_module)

    algo_config = algo.Config(g, **kwargs)

    if config['logging'].get('disable_logfile', fallback=False):
        algo_config.vcdname = None
    else:
        algo_config.vcdname = "{}_{}".format(log_file_basename, log_file_number)

    algo_config.alt_adj_val_data_name = alt_adj_val_data_name

    algo_config.hmc_fifo_bits = 20 if sim else 32-bits_for(algo_config.addresslayout.num_pe-1)

    for pe in range(algo_config.addresslayout.num_pe):
        if not inverted:
            assert len(algo_config.adj_idx[pe]) <= algo_config.addresslayout.num_nodes_per_pe
            assert len(algo_config.adj_idx[pe]) <= 2**(algo_config.addresslayout.nodeidsize - algo_config.addresslayout.peidsize)
        if algo_config.memtype == "BRAM":
            assert len(algo_config.adj_val[pe]) <= algo_config.addresslayout.max_edges_per_pe

    return algo_config
Exemplo n.º 12
0
    def __init__(self, width=14, N_points=16383, max_delay=16383):
        self.init_submodules(width, N_points, max_delay)
        peak_height_bit, x_data_length_bit = self.init_csr(N_points)
        self.init_inout_signals(width)

        # is the autolock actively trying to detect peaks? This is set to true
        # if lock is requested and once the ramp is at start
        watching = Signal()

        # the following signals are property of the peak that the autolock is
        # trying to detet right now
        self.current_instruction_idx = Signal(
            bits_for(AUTOLOCK_MAX_N_INSTRUCTIONS - 1))
        current_peak_height = Signal((peak_height_bit, True))
        abs_current_peak_height = Signal.like(current_peak_height)
        current_wait_for = Signal(x_data_length_bit)
        self.comb += [
            current_peak_height.eq(
                Array([
                    peak_height.storage for peak_height in self.peak_heights
                ])[self.current_instruction_idx]),
            current_wait_for.eq(
                Array([wait_for.storage for wait_for in self.wait_for
                       ])[self.current_instruction_idx]),
        ]

        # after detecting the last peak, how many cycles have passed?
        waited_for = Signal(bits_for(N_points))
        # after all peaks have been detected, how many cycles have passed?
        final_waited_for = Signal(bits_for(N_points))

        # this is the signal that's used for detecting peaks
        sum_diff = Signal((len(self.sum_diff_calculator.output), True))
        abs_sum_diff = Signal.like(sum_diff)
        self.comb += [
            self.sum_diff_calculator.writing_data_now.eq(
                self.writing_data_now),
            self.sum_diff_calculator.restart.eq(self.at_start),
            self.sum_diff_calculator.input.eq(self.input),
            self.sum_diff_calculator.delay_value.eq(self.time_scale.storage),
            sum_diff.eq(self.sum_diff_calculator.output),
        ]

        # has this signal at the moment the same sign as the peak we are looking
        # for?
        sign_equal = Signal()
        # is this signal higher than the peak we are looking for?
        over_threshold = Signal()
        # since detecting the previous peak, has enough time passed?
        waited_long_enough = Signal()
        # have we detected all peaks (and can turn on the lock)?
        all_instructions_triggered = Signal()

        self.comb += [
            sign_equal.eq((sum_diff > 0) == (current_peak_height > 0)),
            If(sum_diff >= 0,
               abs_sum_diff.eq(sum_diff)).Else(abs_sum_diff.eq(-1 * sum_diff)),
            If(
                current_peak_height >= 0,
                abs_current_peak_height.eq(current_peak_height),
            ).Else(abs_current_peak_height.eq(-1 * current_peak_height)),
            over_threshold.eq(abs_sum_diff >= abs_current_peak_height),
            waited_long_enough.eq(waited_for > current_wait_for),
            all_instructions_triggered.eq(
                self.current_instruction_idx >= self.N_instructions.storage),
            self.turn_on_lock.eq(
                all_instructions_triggered
                & (final_waited_for >= self.final_wait_time.storage)),
        ]

        self.sync += [
            If(
                self.at_start,
                waited_for.eq(0),
                # fpga robust autolock algorithm registeres trigger events delayed.
                # Therefore, we give it a head start for `final_waited_for`
                final_waited_for.eq(ROBUST_AUTOLOCK_FPGA_DELAY),
                self.current_instruction_idx.eq(0),
                If(self.request_lock, watching.eq(1)).Else(watching.eq(0)),
            ).Else(
                # not at start
                If(
                    ~self.request_lock,
                    # disable `watching` if `request_lock` was disabled while
                    # the ramp is running. This is important for slow scan
                    # speeds when disabling the autolock and enabling it again
                    # with different parameters. In this case we want to take
                    # care that we start watching at start.
                    watching.eq(0),
                ),
                If(
                    self.writing_data_now & ~all_instructions_triggered
                    & self.sweep_up,
                    If(
                        watching & sign_equal & over_threshold
                        & waited_long_enough,
                        self.current_instruction_idx.eq(
                            self.current_instruction_idx + 1),
                        waited_for.eq(0),
                    ).Else(waited_for.eq(waited_for + 1)),
                ),
                If(
                    self.writing_data_now & all_instructions_triggered
                    & self.sweep_up,
                    final_waited_for.eq(final_waited_for + 1),
                ),
            ),
        ]

        self.signal_out = []
        self.signal_in = []
        self.state_out = [
            watching,
            self.turn_on_lock,
            sign_equal,
            over_threshold,
            waited_long_enough,
        ]
        self.state_in = []
Exemplo n.º 13
0
def resolve_defaults(config, graphfile=None, num_nodes=None, num_edges=None, digraph=False, graphsave=None, sim=True, inverted=None):
    if not graphfile and not num_nodes:
        if 'graphfile' in config['graph']:
            graphfile = config['graph'].get('graphfile')
        elif 'nodes' in config['graph']:
            num_nodes = eval(config['graph'].get('nodes'))
            if not num_edges:
                if 'edges' in config['graph']:
                    num_edges = eval(config['graph'].get('edges'))
                else:
                    num_edges = num_nodes - 1
        else:
            raise ValueError("Graph not specified")
    if 'approach' in config['graph']:
        approach = config['graph'].get('approach')
    else:
        approach = "random_walk"

    graphfile_basename = os.path.splitext(os.path.basename(graphfile))[0] if graphfile else str(num_nodes)
    log_file_basename = "{}_{}_{}".format(config['logging'].get('log_file_name', fallback='fpgagraphlib'), config['app']['algo'], graphfile_basename)

    logger = logging.getLogger()
    logger.setLevel("DEBUG")
    handler = logging.StreamHandler()
    formatter_args = {"fmt": "{levelname:.1s}: {name:>20.20s}: {message:s}", "style": "{"}
    if sys.stderr.isatty() and sys.platform != 'win32':
        handler.setFormatter(ANSIColorFormatter(**formatter_args))
    else:
        handler.setFormatter(logging.Formatter(**formatter_args))
    handler.setLevel(config['logging'].get('console_log_level', fallback='INFO'))
    logger.addHandler(handler)

    log_file_number = 0
    while os.path.exists("{}_{}.log".format(log_file_basename, log_file_number)):
        log_file_number += 1

    alt_adj_val_data_name = None

    if not config['logging'].get('disable_logfile', fallback=False):
        file_log_level = config['logging'].get('file_log_level', fallback='DEBUG')
        logger.info("Logging to file {}_{}.log with level {}".format(log_file_basename, log_file_number, file_log_level))
        # define a Handler which writes INFO messages or higher to the sys.stderr
        logfile = logging.FileHandler(filename="{}_{}.log".format(log_file_basename, log_file_number),
        mode='w')
        logfile.setLevel(file_log_level)
        # set a format which is simpler for console use
        formatter = logging.Formatter('%(levelname)-8s: %(name)-25s: %(message)s')
        # tell the handler to use this format
        logfile.setFormatter(formatter)
        # add the handler to the root logger
        logger.addHandler(logfile)

        alt_adj_val_data_name = "{}_{}.data".format(log_file_basename, log_file_number)

    # root is set up, now get logger for local logging
    logger = logging.getLogger('init')

    kwargs = dict()
    for k in config['arch']:
        try:
            kwargs[k] = eval(config['arch'].get(k))
        except NameError:
            kwargs[k] = config['arch'].get(k)

    if "num_channels" not in kwargs:
        kwargs["num_channels"] = 3

    kwargs["channel_bits"] = bits_for(kwargs["num_channels"] - 1)

    if "num_fpga" not in kwargs:
        if "num_pe_per_fpga" in kwargs and "num_pe" in kwargs:
            kwargs["num_fpga"] = (kwargs["num_pe"] + kwargs["num_pe_per_fpga"] - 1)//kwargs["num_pe_per_fpga"]
        else:
            kwargs["num_fpga"] = 1

    if "num_pe" not in kwargs:
        if "num_pe_per_fpga" in kwargs:
            kwargs["num_pe"] = kwargs["num_pe_per_fpga"]*kwargs["num_fpga"]
        else:
            kwargs["num_pe"] = 8

    if "num_pe_per_fpga" not in kwargs:
        kwargs["num_pe_per_fpga"] = (kwargs["num_pe"] + kwargs["num_fpga"] - 1)//kwargs["num_fpga"]

    if graphfile:
        logger.info("Reading graph from file {}".format(graphfile))
        g = read_graph(graphfile, digraph=digraph, connected=True)
        num_nodes = nx.number_of_nodes(g)
        num_edges = nx.number_of_edges(g)
    else:
        logger.info("Generating graph with {} nodes and {} edges".format(num_nodes, num_edges))
        g = generate_graph(num_nodes, num_edges, approach=approach, digraph=digraph)

    if graphsave:
        logger.info("Saving graph to file {}".format(graphsave))
        export_graph(g, graphsave)

    if "memtype" not in kwargs:
        kwargs["memtype"] = "BRAM"
        if "use_hmc" in kwargs:
            logger.warning("\"use_hmc\" is deprecated. Use \"memtype = HMC\" instead.")
            if kwargs["use_hmc"]:
                kwargs["memtype"] = "HMC"
        if "use_ddr" in kwargs:
            logger.warning("\"use_ddr\" is deprecated. Use \"memtype = AXI\" instead.")
            if kwargs["use_ddr"]:
                kwargs["memtype"] = "AXI"

    if "updates_in_hmc" not in kwargs:
        kwargs["updates_in_hmc"] = False

    if inverted != None:
        kwargs["inverted"] = inverted
    elif "arch" in kwargs:
        if kwargs["arch"] == "S":
            kwargs["inverted"] = False
        elif kwargs["arch"] == "M":
            kwargs["inverted"] = True
        else:
            ValueError("Unknown architecture \"{}\"".format(kwargs["arch"]))
    else:
        kwargs["inverted"] = (kwargs["num_fpga"] > 1)

    if kwargs["memtype"] == "HMC" and kwargs["updates_in_hmc"]:
        raise NotImplementedError("Can't use HMC for edges in 2-phase mode")

    updates_in_hmc = kwargs["updates_in_hmc"] if "updates_in_hmc" in kwargs else False

    if "num_nodes_per_pe" in kwargs or "max_edges_per_pe" in kwargs:
        logger.warning("Setting num_nodes_per_pe or max_edges_per_pe manually is no longer supported! Value ignored.")

    if 'partition' in config['graph']:
        kwargs["partition"] = config['graph'].get('partition')
        if 'partition_ufactor' in config['graph']:
            kwargs["partition_ufactor"] = config['graph'].getint('partition_ufactor')
        else:
            kwargs["partition_ufactor"] = 1
    else:
        kwargs["partition"] = "robin"

    if "peidsize" not in kwargs:
        kwargs["peidsize"] = bits_for(kwargs["num_pe"])

    algo_config_module = "{}.config".format(config['app']['algo'])
    algo = import_module(algo_config_module)

    algo_config = algo.Config(g, **kwargs)

    if config['logging'].get('disable_logfile', fallback=False):
        algo_config.vcdname = None
    else:
        algo_config.vcdname = "{}_{}".format(log_file_basename, log_file_number)

    algo_config.alt_adj_val_data_name = alt_adj_val_data_name

    algo_config.hmc_fifo_bits = 20 if sim else 32-bits_for(algo_config.addresslayout.num_pe-1)

    for pe in range(algo_config.addresslayout.num_pe):
        if not kwargs["inverted"]:
            assert len(algo_config.adj_idx[pe]) <= algo_config.addresslayout.num_nodes_per_pe
            assert len(algo_config.adj_idx[pe]) <= 2**(algo_config.addresslayout.nodeidsize - algo_config.addresslayout.peidsize)
        if algo_config.memtype == "BRAM":
            assert len(algo_config.adj_val[pe]) <= algo_config.addresslayout.max_edges_per_pe

    return algo_config
Exemplo n.º 14
0
    def __init__(self, platform, pads, size=2 * 1024 * 1024):
        self.size = size

        self.bus = bus = wishbone.Interface()

        self.reset = Signal()

        self.cfg1 = CSRStorage(fields=[
            CSRField(
                "bb_out", size=4, description="Output bits in bit-bang mode"),
            CSRField("bb_clk",
                     description="Serial clock line in bit-bang mode"),
            CSRField("bb_cs", description="Chip select line in bit-bang mode"),
        ])
        self.cfg2 = CSRStorage(fields=[
            CSRField("bb_oe",
                     size=4,
                     description="Output Enable bits in bit-bang mode"),
        ])
        self.cfg3 = CSRStorage(fields=[
            CSRField(
                "rlat", size=4, description="Read latency/dummy cycle count"),
            CSRField("crm", description="Continuous Read Mode enable bit"),
            CSRField("qspi", description="Quad-SPI enable bit"),
            CSRField("ddr", description="Double Data Rate enable bit"),
        ])
        self.cfg4 = CSRStorage(fields=[
            CSRField(
                "memio",
                offset=7,
                reset=1,
                description=
                "Enable memory-mapped mode (set to 0 to enable bit-bang mode)")
        ])

        self.stat1 = CSRStatus(fields=[
            CSRField(
                "bb_in", size=4, description="Input bits in bit-bang mode"),
        ])
        self.stat2 = CSRStatus(1, fields=[], description="Reserved")
        self.stat3 = CSRStatus(1, fields=[], description="Reserved")
        self.stat4 = CSRStatus(1, fields=[], description="Reserved")

        cfg = Signal(32)
        cfg_we = Signal(4)
        cfg_out = Signal(32)
        self.comb += [
            cfg.eq(
                Cat(self.cfg1.storage, self.cfg2.storage, self.cfg3.storage,
                    self.cfg4.storage)),
            cfg_we.eq(
                Cat(self.cfg1.re, self.cfg2.re, self.cfg3.re, self.cfg4.re)),
            self.stat1.status.eq(cfg_out[0:8]),
            self.stat2.status.eq(cfg_out[8:16]),
            self.stat3.status.eq(cfg_out[16:24]),
            self.stat4.status.eq(cfg_out[24:32]),
        ]

        mosi_pad = TSTriple()
        miso_pad = TSTriple()
        cs_n_pad = TSTriple()
        clk_pad = TSTriple()
        wp_pad = TSTriple()
        hold_pad = TSTriple()
        self.specials += mosi_pad.get_tristate(pads.mosi)
        self.specials += miso_pad.get_tristate(pads.miso)
        self.specials += cs_n_pad.get_tristate(pads.cs_n)
        self.specials += clk_pad.get_tristate(pads.clk)
        self.specials += wp_pad.get_tristate(pads.wp)
        self.specials += hold_pad.get_tristate(pads.hold)

        reset = Signal()
        self.comb += [
            reset.eq(ResetSignal() | self.reset),
            cs_n_pad.oe.eq(~reset),
            clk_pad.oe.eq(~reset),
        ]

        flash_addr = Signal(24)
        # size/4 because data bus is 32 bits wide, -1 for base 0
        mem_bits = bits_for(int(size / 4) - 1)
        pad = Signal(2)
        self.comb += flash_addr.eq(Cat(pad, bus.adr[0:mem_bits - 1]))

        read_active = Signal()
        spi_ready = Signal()
        self.sync += [
            If(
                bus.stb & bus.cyc & ~read_active,
                read_active.eq(1),
                bus.ack.eq(0),
            ).Elif(
                read_active & spi_ready,
                read_active.eq(0),
                bus.ack.eq(1),
            ).Else(
                bus.ack.eq(0),
                read_active.eq(0),
            )
        ]

        o_rdata = Signal(32)
        self.comb += bus.dat_r.eq(o_rdata)

        self.specials += Instance(
            "spimemio",
            o_flash_io0_oe=mosi_pad.oe,
            o_flash_io1_oe=miso_pad.oe,
            o_flash_io2_oe=wp_pad.oe,
            o_flash_io3_oe=hold_pad.oe,
            o_flash_io0_do=mosi_pad.o,
            o_flash_io1_do=miso_pad.o,
            o_flash_io2_do=wp_pad.o,
            o_flash_io3_do=hold_pad.o,
            o_flash_csb=cs_n_pad.o,
            o_flash_clk=clk_pad.o,
            i_flash_io0_di=mosi_pad.i,
            i_flash_io1_di=miso_pad.i,
            i_flash_io2_di=wp_pad.i,
            i_flash_io3_di=hold_pad.i,
            i_resetn=~reset,
            i_clk=ClockSignal(),
            i_valid=bus.stb & bus.cyc,
            o_ready=spi_ready,
            i_addr=flash_addr,
            o_rdata=o_rdata,
            i_cfgreg_we=cfg_we,
            i_cfgreg_di=cfg,
            o_cfgreg_do=cfg_out,
        )
        platform.add_source("rtl/spimemio.v")