Example #1
0
    def set_sink_pattern(self, fsm, name, ram, offset, pattern, port=0):
        """ intrinsic method to assign RAM property to a sink stream """

        if not self.stream_synthesized:
            self._implement_stream()

        if isinstance(name, str):
            var = self.var_name_map[name]
        elif isinstance(name, vtypes.Str):
            name = name.value
            var = self.var_name_map[name]
        elif isinstance(name, int):
            var = self.var_id_map[name]
        elif isinstance(name, vtypes.Int):
            name = name.value
            var = self.var_id_map[name]
        else:
            raise TypeError('Unsupported index name')

        if name not in self.sinks:
            raise NameError("No such stream '%s'" % name)

        if not isinstance(pattern, (tuple, list)):
            raise TypeError('pattern must be list or tuple.')

        if not pattern:
            raise ValueError(
                'pattern must have one (size, stride) pair at least.')

        if not isinstance(pattern[0], (tuple, list)):
            pattern = (pattern,)

        prefix = self._prefix(name)

        fsm_id = self.fsm_id_count
        fsm_name = '_%s_fsm_%d' % (prefix, fsm_id)
        sink_fsm = FSM(self.module, fsm_name, self.clock, self.reset)
        self.fsm_id_map[fsm_id] = sink_fsm
        self.fsm_id_count += 1

        sink_offset = self.module.Reg('_%s_offset_%d' % (prefix, fsm_id),
                                      ram.addrwidth, initval=0)
        sink_pat_offsets = [self.module.Reg('_%s_pat_offset_%d_%d' % (prefix, fsm_id, i),
                                            ram.addrwidth, initval=0)
                            for i, _ in enumerate(pattern)]
        sink_pat_sizes = [self.module.Reg('_%s_pat_size_%d_%d' % (prefix, fsm_id, i),
                                          ram.addrwidth + 1, initval=0)
                          for i, _ in enumerate(pattern)]
        sink_pat_strides = [self.module.Reg('_%s_pat_stride_%d_%d' % (prefix, fsm_id, i),
                                            ram.addrwidth, initval=0)
                            for i, _ in enumerate(pattern)]
        sink_pat_counts = [self.module.Reg('_%s_pat_count_%d_%d' % (prefix, fsm_id, i),
                                           ram.addrwidth + 1, initval=0)
                           for i, _ in enumerate(pattern)]

        var_id = self.var_name_id_map[name]
        fsm_sel = self.var_id_fsm_sel_map[var_id]

        set_cond = (fsm.state == fsm.current)

        sink_fsm.If(set_cond)(
            sink_offset(offset)
        )
        self.seq.If(set_cond)(
            fsm_sel(fsm_id)
        )

        for sink_pat_offset in sink_pat_offsets:
            sink_fsm.If(set_cond)(
                sink_pat_offset(0)
            )

        for (sink_pat_size, sink_pat_stride, (size, stride)) in zip(
                sink_pat_sizes, sink_pat_strides, pattern):
            sink_fsm.If(set_cond)(
                sink_pat_size(size),
                sink_pat_stride(stride)
            )

        sink_start = vtypes.Ands(self.start, fsm_sel == fsm_id)
        for sink_pat_size in sink_pat_sizes:
            sink_start = vtypes.Ands(sink_start, sink_pat_size > 0)

        for (sink_pat_size, sink_pat_count) in zip(
                sink_pat_sizes, sink_pat_counts):
            sink_fsm.If(sink_start)(
                sink_pat_count(sink_pat_size - 1)
            )

        sink_fsm.If(sink_start).goto_next()

        num_wdelay = self._write_delay()

        for i in range(num_wdelay):
            sink_fsm.goto_next()

        sink_all_offset = self.module.Wire('_%s_all_offset_%d' % (prefix, fsm_id),
                                           ram.addrwidth)
        sink_all_offset_val = sink_offset
        for sink_pat_offset in sink_pat_offsets:
            sink_all_offset_val += sink_pat_offset
        sink_all_offset.assign(sink_all_offset_val)

        waddr = self.module.Reg('_%s_waddr_%d' % (prefix, fsm_id),
                                ram.addrwidth, initval=0)
        wenable = self.module.Reg('_%s_wenable_%d' % (prefix, fsm_id),
                                  initval=0)
        wdata = self.module.Reg('_%s_wdata_%d' % (prefix, fsm_id),
                                ram.datawidth, initval=0, signed=True)
        rdata = var.read()

        ram.write_rtl(waddr, wdata, port=port, cond=wenable)

        if name in self.sink_when_map:
            when = self.sink_when_map[name]
            wcond = when.read()
        else:
            wcond = None

        sink_fsm.If(wcond)(
            waddr(sink_all_offset),
            wdata(rdata),
            wenable(1)
        )
        sink_fsm.Delay(1)(
            wenable(0)
        )

        upcond = None

        for (sink_pat_offset, sink_pat_size,
             sink_pat_stride, sink_pat_count) in zip(
                 sink_pat_offsets, sink_pat_sizes,
                 sink_pat_strides, sink_pat_counts):
            sink_fsm.If(upcond)(
                sink_pat_offset.add(sink_pat_stride),
                sink_pat_count.dec()
            )
            reset_cond = sink_pat_count == 0
            sink_fsm.If(upcond, reset_cond)(
                sink_pat_offset(0),
                sink_pat_count(sink_pat_size - 1)
            )
            upcond = make_condition(upcond, reset_cond)

        fin_cond = upcond

        sink_fsm.If(fin_cond).goto_init()

        sink_fsm._set_index(0)

        fsm.goto_next()
Example #2
0
    def set_source(self, fsm, name, ram, offset, size, stride=1, port=0):
        """ intrinsic method to assign RAM property to a source stream """

        if not self.stream_synthesized:
            self._implement_stream()

        if isinstance(name, str):
            var = self.var_name_map[name]
        elif isinstance(name, vtypes.Str):
            name = name.value
            var = self.var_name_map[name]
        elif isinstance(name, int):
            var = self.var_id_map[name]
        elif isinstance(name, vtypes.Int):
            name = name.value
            var = self.var_id_map[name]
        else:
            raise TypeError('Unsupported index name')

        if name not in self.sources:
            raise NameError("No such stream '%s'" % name)

        prefix = self._prefix(name)

        fsm_id = self.fsm_id_count
        fsm_name = '_%s_fsm_%d' % (prefix, fsm_id)
        source_fsm = FSM(self.module, fsm_name, self.clock, self.reset)
        self.fsm_id_map[fsm_id] = source_fsm
        self.fsm_id_count += 1

        source_idle = self.source_idle_map[name]
        source_offset = self.module.Reg('_%s_offset_%d' % (prefix, fsm_id),
                                        ram.addrwidth, initval=0)
        source_size = self.module.Reg('_%s_size_%d' % (prefix, fsm_id),
                                      ram.addrwidth + 1, initval=0)
        source_stride = self.module.Reg('_%s_stride_%d' % (prefix, fsm_id),
                                        ram.addrwidth, initval=0)
        source_count = self.module.Reg('_%s_count_%d' % (prefix, fsm_id),
                                       ram.addrwidth + 1, initval=0)

        var_id = self.var_name_id_map[name]
        fsm_sel = self.var_id_fsm_sel_map[var_id]

        set_cond = (fsm.state == fsm.current)

        source_fsm.If(set_cond)(
            source_offset(offset),
            source_size(size),
            source_stride(stride)
        )
        self.seq.If(set_cond)(
            fsm_sel(fsm_id)
        )

        self.seq.If(self.start)(
            source_idle(0)
        )

        source_start = vtypes.Ands(
            self.start, fsm_sel == fsm_id, source_size > 0)

        source_fsm.If(source_start)(
            source_count(source_size)
        )
        source_fsm.If(source_start).goto_next()

        raddr = self.module.Reg('_%s_raddr_%d' % (prefix, fsm_id),
                                ram.addrwidth, initval=0)
        renable = self.module.Reg('_%s_renable_%d' % (prefix, fsm_id),
                                  initval=0)

        rdata, rvalid = ram.read_rtl(raddr, port=port, cond=renable)

        wdata = rdata
        wenable = rvalid
        var.write(wdata, wenable)

        source_fsm(
            raddr(source_offset),
            renable(1),
            source_count.dec()
        )
        source_fsm.Delay(1)(
            renable(0)
        )
        self.seq.If(source_fsm.state == source_fsm.current,
                    source_count == 1)(
            source_idle(1)
        )
        source_fsm.If(source_count == 1).goto_init()
        source_fsm.If(source_count > 1).goto_next()

        source_fsm(
            raddr.add(source_stride),
            renable(1),
            source_count.dec()
        )
        source_fsm.Delay(1)(
            renable(0)
        )
        source_fsm.If(source_count == 1).goto_init()

        self.seq.If(source_fsm.state == source_fsm.current,
                    source_count == 1)(
            source_idle(1)
        )

        source_fsm._set_index(0)

        fsm.goto_next()
Example #3
0
    def set_sink(self, fsm, name, ram, offset, size, stride=1, port=0):
        """ intrinsic method to assign RAM property to a sink stream """

        if not self.stream_synthesized:
            self._implement_stream()

        if isinstance(name, str):
            var = self.var_name_map[name]
        elif isinstance(name, vtypes.Str):
            name = name.value
            var = self.var_name_map[name]
        elif isinstance(name, int):
            var = self.var_id_map[name]
        elif isinstance(name, vtypes.Int):
            name = name.value
            var = self.var_id_map[name]
        else:
            raise TypeError('Unsupported index name')

        if name not in self.sinks:
            raise NameError("No such stream '%s'" % name)

        prefix = self._prefix(name)

        fsm_id = self.fsm_id_count
        fsm_name = '_%s_fsm_%d' % (prefix, fsm_id)
        sink_fsm = FSM(self.module, fsm_name, self.clock, self.reset)
        self.fsm_id_map[fsm_id] = sink_fsm
        self.fsm_id_count += 1

        sink_offset = self.module.Reg('_%s_offset_%d' % (prefix, fsm_id),
                                      ram.addrwidth, initval=0)
        sink_size = self.module.Reg('_%s_size_%d' % (prefix, fsm_id),
                                    ram.addrwidth + 1, initval=0)
        sink_stride = self.module.Reg('_%s_stride_%d' % (prefix, fsm_id),
                                      ram.addrwidth, initval=0)
        sink_count = self.module.Reg('_%s_count_%d' % (prefix, fsm_id),
                                     ram.addrwidth + 1, initval=0)

        var_id = self.var_name_id_map[name]
        fsm_sel = self.var_id_fsm_sel_map[var_id]

        set_cond = (fsm.state == fsm.current)

        sink_fsm.If(set_cond)(
            sink_offset(offset),
            sink_size(size),
            sink_stride(stride)
        )
        self.seq.If(set_cond)(
            fsm_sel(fsm_id)
        )

        sink_start = vtypes.Ands(
            self.start, fsm_sel == fsm_id, sink_size > 0)

        sink_fsm.If(sink_start)(
            sink_count(sink_size)
        )
        sink_fsm.If(sink_start).goto_next()

        num_wdelay = self._write_delay()

        for i in range(num_wdelay):
            sink_fsm.goto_next()

        waddr = self.module.Reg('_%s_waddr_%d' % (prefix, fsm_id),
                                ram.addrwidth, initval=0)
        wenable = self.module.Reg('_%s_wenable_%d' % (prefix, fsm_id),
                                  initval=0)
        wdata = self.module.Reg('_%s_wdata_%d' % (prefix, fsm_id),
                                ram.datawidth, initval=0, signed=True)
        rdata = var.read()

        ram.write_rtl(waddr, wdata, port=port, cond=wenable)

        if name in self.sink_when_map:
            when = self.sink_when_map[name]
            wcond = when.read()
        else:
            wcond = None

        sink_fsm.If(wcond)(
            waddr(sink_offset),
            wdata(rdata),
            wenable(1),
            sink_count.dec()
        )
        sink_fsm.Delay(1)(
            wenable(0)
        )
        sink_fsm.If(wcond, sink_count == 1).goto_init()
        sink_fsm.If(wcond, sink_count > 1).goto_next()

        sink_fsm.If(wcond)(
            waddr.add(sink_stride),
            wdata(rdata),
            wenable(1),
            sink_count.dec()
        )
        sink_fsm.Delay(1)(
            wenable(0)
        )
        sink_fsm.If(wcond, sink_count == 1).goto_init()

        sink_fsm._set_index(0)

        fsm.goto_next()
Example #4
0
    def _synthesize_read_fsm_fifo_narrow(self, fifo, fifo_datawidth):
        """ axi.datawidth < fifo.datawidth """

        if fifo_datawidth % self.datawidth != 0:
            raise ValueError(
                'fifo_datawidth must be multiple number of axi.datawidth')

        pack_size = fifo_datawidth // self.datawidth
        dma_size = (self.read_size << int(math.log(pack_size, 2))
                    if math.log(pack_size, 2) % 1.0 == 0.0 else
                    self.read_size * pack_size)

        op_id = self._get_read_op_id_fifo(fifo)

        if op_id in self.read_ops:
            """ already synthesized op """
            return

        if pack_size in self.read_narrow_fsms:
            """ new op """
            self.read_ops.append(op_id)

            fsm = self.read_narrow_fsms[pack_size]
            pack_count = self.read_narrow_pack_counts[pack_size]
            data = self.read_narrow_data_wires[pack_size]
            valid = self.read_narrow_valid_wires[pack_size]
            rest_size = self.read_narrow_rest_size_wires[pack_size]

            # state 0
            fsm.set_index(0)
            cond = vtypes.Ands(self.read_start, self.read_op_sel == op_id)

            fsm.If(cond).goto_next()

            # state 1
            fsm.set_index(1)

            wdata = self.m.Reg('_'.join(['', self.name,
                                         'read_narrow', str(pack_size),
                                         'wdata']),
                               fifo_datawidth, initval=0)
            wvalid = self.m.Reg('_'.join(['', self.name,
                                          'read_narrow', str(pack_size),
                                          'wvalid']))

            valid_cond = vtypes.Ands(valid, self.read_op_sel == op_id)
            ack, _ = fifo.enq_rtl(wdata, cond=wvalid)

            fsm.Delay(1)(
                wvalid(0)
            )
            fsm.If(rest_size == 0, pack_count > 0)(
                wdata(vtypes.Cat(data, wdata[self.datawidth:fifo_datawidth])),
                wvalid(0),
                pack_count.inc()
            )
            fsm.If(valid_cond)(
                wdata(vtypes.Cat(data, wdata[self.datawidth:fifo_datawidth])),
                wvalid(0),
                pack_count.inc()
            )
            fsm.If(rest_size == 0, pack_count == pack_size - 1)(
                wdata(vtypes.Cat(data, wdata[self.datawidth:fifo_datawidth])),
                wvalid(1),
                pack_count(0)
            )
            fsm.If(valid_cond, pack_count == pack_size - 1)(
                wdata(vtypes.Cat(data, wdata[self.datawidth:fifo_datawidth])),
                wvalid(1),
                pack_count(0)
            )
            fsm.If(valid_cond)(
                rest_size.dec()
            )

            return

        """ new op and fsm """
        fsm = FSM(self.m, '_'.join(['', self.name,
                                    'read_narrow', str(pack_size),
                                    'fsm']),
                  self.clk, self.rst, as_module=self.fsm_as_module)
        self.read_narrow_fsms[pack_size] = fsm

        self.read_ops.append(op_id)

        rest_size = self.m.Reg('_'.join(['', self.name,
                                         'read_narrow', str(pack_size),
                                         'rest_size']),
                               self.addrwidth + 1, initval=0)
        self.read_narrow_rest_size_wires[pack_size] = rest_size

        # state 0
        cond = vtypes.Ands(self.read_start, self.read_op_sel == op_id)

        fsm.If(self.read_start)(
            rest_size(dma_size)
        )
        fsm.If(cond).goto_next()

        # state 1
        pack_count = self.m.Reg('_'.join(['', self.name,
                                          'read_narrow', str(pack_size),
                                          'pack_count']),
                                int(math.ceil(math.log(pack_size, 2))), initval=0)
        self.read_narrow_pack_counts[pack_size] = pack_count

        ready = vtypes.Not(fifo.almost_full)
        read_cond = vtypes.Ands(fsm.here, ready)

        data, last, _id, user, dest, valid = self.read_data(cond=read_cond)
        self.read_narrow_data_wires[pack_size] = data
        self.read_narrow_valid_wires[pack_size] = valid

        wdata = self.m.Reg('_'.join(['', self.name,
                                     'read_narrow', str(pack_size),
                                     'wdata']),
                           fifo_datawidth, initval=0)
        wvalid = self.m.Reg('_'.join(['', self.name,
                                      'read_narrow', str(pack_size),
                                      'wvalid']))

        valid_cond = vtypes.Ands(valid, self.read_op_sel == op_id)
        ack, _ = fifo.enq_rtl(wdata, cond=wvalid)

        fsm.Delay(1)(
            wvalid(0)
        )
        fsm.If(rest_size == 0, pack_count > 0)(
            wdata(vtypes.Cat(data, wdata[self.datawidth:fifo_datawidth])),
            wvalid(0),
            pack_count.inc()
        )
        fsm.If(valid_cond)(
            wdata(vtypes.Cat(data, wdata[self.datawidth:fifo_datawidth])),
            wvalid(0),
            pack_count.inc()
        )
        fsm.If(rest_size == 0, pack_count == pack_size - 1)(
            wdata(vtypes.Cat(data, wdata[self.datawidth:fifo_datawidth])),
            wvalid(1),
            pack_count(0)
        )
        fsm.If(valid_cond, pack_count == pack_size - 1)(
            wdata(vtypes.Cat(data, wdata[self.datawidth:fifo_datawidth])),
            wvalid(1),
            pack_count(0)
        )
        fsm.If(valid_cond)(
            rest_size.dec()
        )

        fsm.If(wvalid, rest_size == 0).goto_next()

        # state 2
        set_idle = self._set_flag(fsm)
        self.seq.If(set_idle)(
            self.read_idle(1)
        )

        fsm.goto_init()
Example #5
0
    def _synthesize_read_fsm_wide(self, ram, port, ram_method, ram_datawidth):
        """ axi.datawidth > ram.datawidth """

        if self.datawidth % ram_datawidth != 0:
            raise ValueError(
                'axi.datawidth must be multiple number of ram_datawidth')

        pack_size = self.datawidth // ram_datawidth
        shamt = int(math.log(pack_size, 2))
        res = vtypes.Mux(
            vtypes.And(self.read_size, 2 ** shamt - 1) > 0, 1, 0)
        dma_size = (self.read_size >> shamt) + res

        actual_read_size = dma_size << shamt

        op_id = self._get_read_op_id(ram, port, ram_method)
        port = vtypes.to_int(port)

        if op_id in self.read_ops:
            """ already synthesized op """
            return

        if pack_size in self.read_wide_fsms:
            """ new op """
            self.read_ops.append(op_id)

            fsm = self.read_wide_fsms[pack_size]
            pack_count = self.read_wide_pack_counts[pack_size]
            data = self.read_wide_data_wires[pack_size]
            valid = self.read_wide_valid_wires[pack_size]
            rest_size = self.read_wide_rest_size_wires[pack_size]

            # state 0
            fsm.set_index(0)
            wdata, wvalid, w = self._get_op_write_dataflow(ram_datawidth)
            cond = vtypes.Ands(self.read_start, self.read_op_sel == op_id)
            ram_method(port, self.read_local_addr, w, actual_read_size,
                       stride=self.read_local_stride, cond=cond)

            fsm.If(cond).goto_next()

            # state 1
            fsm.set_index(1)
            valid_cond = vtypes.Ands(valid, self.read_op_sel == op_id)
            stay_cond = self.read_op_sel == op_id

            fsm.Delay(1)(
                wvalid(0)
            )
            fsm.If(pack_count == 0, valid_cond)(
                wdata(data),
                wvalid(1),
                pack_count.inc()
            )
            fsm.If(pack_count > 0, stay_cond)(
                wdata(wdata >> ram_datawidth),
                wvalid(1),
                pack_count.inc()
            )
            fsm.If(valid_cond)(
                rest_size.dec()
            )

            return

        """ new op and fsm """
        fsm = FSM(self.m, '_'.join(['', self.name,
                                    'read_wide', str(pack_size),
                                    'fsm']),
                  self.clk, self.rst, as_module=self.fsm_as_module)
        self.read_wide_fsms[pack_size] = fsm

        self.read_ops.append(op_id)

        rest_size = self.m.Reg('_'.join(['', self.name,
                                         'read_wide', str(pack_size),
                                         'rest_size']),
                               self.addrwidth + 1, initval=0)
        self.read_wide_rest_size_wires[pack_size] = rest_size

        # state 0
        wdata, wvalid, w = self._get_op_write_dataflow(ram_datawidth)
        cond = vtypes.Ands(self.read_start, self.read_op_sel == op_id)
        ram_method(port, self.read_local_addr, w, actual_read_size,
                   stride=self.read_local_stride, cond=cond)

        fsm.If(self.read_start)(
            rest_size(dma_size)
        )
        fsm.If(cond).goto_next()

        # state 1
        pack_count = self.m.Reg('_'.join(['', self.name,
                                          'read_wide', str(pack_size),
                                          'pack_count']),
                                int(math.ceil(math.log(pack_size, 2))), initval=0)
        self.read_wide_pack_counts[pack_size] = pack_count

        cond = vtypes.Ands(fsm.here, pack_count == 0)
        data, last, _id, user, dest, valid = self.read_data(cond=cond)
        self.read_wide_data_wires[pack_size] = data
        self.read_wide_valid_wires[pack_size] = valid

        valid_cond = vtypes.Ands(valid, self.read_op_sel == op_id)
        stay_cond = self.read_op_sel == op_id

        wlast = self.m.Reg('_'.join(['', self.name,
                                     'read_wide', str(pack_size),
                                     'wlast']),
                           initval=0)

        fsm.Delay(1)(
            wvalid(0)
        )
        fsm.If(pack_count == 0, valid_cond)(
            wdata(data),
            wvalid(1),
            wlast(last),
            pack_count.inc()
        )
        fsm.If(pack_count > 0, stay_cond)(
            wdata(wdata >> ram_datawidth),
            wvalid(1),
            pack_count.inc()
        )
        fsm.If(pack_count == pack_size - 1)(
            pack_count(0)
        )

        fsm.If(pack_count == 0, valid_cond)(
            rest_size.dec()
        )

        fsm.If(pack_count == pack_size - 1, rest_size == 0).goto_next()

        for _ in range(self.num_data_delay):
            fsm.goto_next()

        # state 2
        set_idle = self._set_flag(fsm)
        self.seq.If(set_idle)(
            self.read_idle(1)
        )

        fsm.goto_init()
Example #6
0
    def _synthesize_read_fsm_narrow(self, ram, port, ram_method, ram_datawidth):
        """ axi.datawidth < ram.datawidth """

        if ram_datawidth % self.datawidth != 0:
            raise ValueError(
                'ram_datawidth must be multiple number of axi.datawidth')

        pack_size = ram_datawidth // self.datawidth
        dma_size = (self.read_size << int(math.log(pack_size, 2))
                    if math.log(pack_size, 2) % 1.0 == 0.0 else
                    self.read_size * pack_size)

        op_id = self._get_read_op_id(ram, port, ram_method)
        port = vtypes.to_int(port)

        if op_id in self.read_ops:
            """ already synthesized op """
            return

        if pack_size in self.read_narrow_fsms:
            """ new op """
            self.read_ops.append(op_id)

            fsm = self.read_narrow_fsms[pack_size]
            pack_count = self.read_narrow_pack_counts[pack_size]
            data = self.read_narrow_data_wires[pack_size]
            valid = self.read_narrow_valid_wires[pack_size]
            rest_size = self.read_narrow_rest_size_wires[pack_size]

            # state 0
            fsm.set_index(0)
            wdata, wvalid, w = self._get_op_write_dataflow(ram_datawidth)
            cond = vtypes.Ands(self.read_start, self.read_op_sel == op_id)
            ram_method(port, self.read_local_addr, w, self.read_size,
                       stride=self.read_local_stride, cond=cond)

            fsm.If(cond).goto_next()

            # state 1
            fsm.set_index(1)
            valid_cond = vtypes.Ands(valid, self.read_op_sel == op_id)

            fsm.Delay(1)(
                wvalid(0)
            )
            fsm.If(rest_size == 0, pack_count > 0)(
                wdata(vtypes.Cat(data, wdata[self.datawidth:ram_datawidth])),
                wvalid(0),
                pack_count.inc()
            )
            fsm.If(valid_cond)(
                wdata(vtypes.Cat(data, wdata[self.datawidth:ram_datawidth])),
                wvalid(0),
                pack_count.inc()
            )
            fsm.If(rest_size == 0, pack_count == pack_size - 1)(
                wdata(vtypes.Cat(data, wdata[self.datawidth:ram_datawidth])),
                wvalid(1),
                pack_count(0)
            )
            fsm.If(valid_cond, pack_count == pack_size - 1)(
                wdata(vtypes.Cat(data, wdata[self.datawidth:ram_datawidth])),
                wvalid(1),
                pack_count(0)
            )
            fsm.If(valid_cond)(
                rest_size.dec()
            )

            return

        """ new op and fsm """
        fsm = FSM(self.m, '_'.join(['', self.name,
                                    'read_narrow', str(pack_size),
                                    'fsm']),
                  self.clk, self.rst, as_module=self.fsm_as_module)
        self.read_narrow_fsms[pack_size] = fsm

        self.read_ops.append(op_id)

        rest_size = self.m.Reg('_'.join(['', self.name,
                                         'read_narrow', str(pack_size),
                                         'rest_size']),
                               self.addrwidth + 1, initval=0)
        self.read_narrow_rest_size_wires[pack_size] = rest_size

        # state 0
        wdata, wvalid, w = self._get_op_write_dataflow(ram_datawidth)
        cond = vtypes.Ands(self.read_start, self.read_op_sel == op_id)
        ram_method(port, self.read_local_addr, w, self.read_size,
                   stride=self.read_local_stride, cond=cond)

        fsm.If(self.read_start)(
            rest_size(dma_size)
        )
        fsm.If(cond).goto_next()

        # state 1
        pack_count = self.m.Reg('_'.join(['', self.name,
                                          'read_narrow', str(pack_size),
                                          'pack_count']),
                                int(math.ceil(math.log(pack_size, 2))), initval=0)
        self.read_narrow_pack_counts[pack_size] = pack_count

        data, last, _id, user, dest, valid = self.read_data(cond=fsm)
        self.read_narrow_data_wires[pack_size] = data
        self.read_narrow_valid_wires[pack_size] = valid

        valid_cond = vtypes.Ands(valid, self.read_op_sel == op_id)

        fsm.Delay(1)(
            wvalid(0)
        )
        fsm.If(rest_size == 0, pack_count > 0)(
            wdata(vtypes.Cat(data, wdata[self.datawidth:ram_datawidth])),
            wvalid(0),
            pack_count.inc()
        )
        fsm.If(valid_cond)(
            wdata(vtypes.Cat(data, wdata[self.datawidth:ram_datawidth])),
            wvalid(0),
            pack_count.inc()
        )
        fsm.If(rest_size == 0, pack_count == pack_size - 1)(
            wdata(vtypes.Cat(data, wdata[self.datawidth:ram_datawidth])),
            wvalid(1),
            pack_count(0)
        )
        fsm.If(valid_cond, pack_count == pack_size - 1)(
            wdata(vtypes.Cat(data, wdata[self.datawidth:ram_datawidth])),
            wvalid(1),
            pack_count(0)
        )
        fsm.If(valid_cond)(
            rest_size.dec()
        )

        fsm.If(wvalid, rest_size == 0).goto_next()

        for _ in range(self.num_data_delay):
            fsm.goto_next()

        # state 2
        set_idle = self._set_flag(fsm)
        self.seq.If(set_idle)(
            self.read_idle(1)
        )

        fsm.goto_init()
Example #7
0
    def _synthesize_read_fsm_same(self, ram, port, ram_method, ram_datawidth):

        op_id = self._get_read_op_id(ram, port, ram_method)
        port = vtypes.to_int(port)

        if op_id in self.read_ops:
            """ already synthesized op """
            return

        if self.read_fsm is not None:
            """ new op """
            self.read_ops.append(op_id)

            fsm = self.read_fsm
            data = self.read_data_wire
            valid = self.read_valid_wire
            rest_size = self.read_rest_size

            # state 0
            fsm.set_index(0)
            wdata, wvalid, w = self._get_op_write_dataflow(ram_datawidth)
            cond = vtypes.Ands(self.read_start, self.read_op_sel == op_id)
            ram_method(port, self.read_local_addr, w, self.read_size,
                       stride=self.read_local_stride, cond=cond)

            fsm.If(cond).goto_next()

            # state 1
            fsm.set_index(1)
            valid_cond = vtypes.Ands(valid, self.read_op_sel == op_id)

            fsm.Delay(1)(
                wvalid(0)
            )
            fsm.If(valid_cond)(
                wdata(data),
                wvalid(1)
            )
            fsm.If(valid_cond)(
                rest_size.dec()
            )

            return

        """ new op and fsm """
        fsm = FSM(self.m, '_'.join(['', self.name, 'read_fsm']),
                  self.clk, self.rst, as_module=self.fsm_as_module)
        self.read_fsm = fsm

        self.read_ops.append(op_id)

        rest_size = self.m.Reg('_'.join(['', self.name, 'read_rest_size']),
                               self.addrwidth + 1, initval=0)
        self.read_rest_size = rest_size

        # state 0
        wdata, wvalid, w = self._get_op_write_dataflow(ram_datawidth)
        cond = vtypes.Ands(self.read_start, self.read_op_sel == op_id)
        ram_method(port, self.read_local_addr, w, self.read_size,
                   stride=self.read_local_stride, cond=cond)

        fsm.If(self.read_start)(
            rest_size(self.read_size)
        )
        fsm.If(cond).goto_next()

        # state 1
        data, last, _id, user, dest, valid = self.read_data(cond=fsm)
        self.read_data_wire = data
        self.read_valid_wire = valid

        valid_cond = vtypes.Ands(valid, self.read_op_sel == op_id)

        fsm.Delay(1)(
            wvalid(0)
        )
        fsm.If(valid_cond)(
            wdata(data),
            wvalid(1),
        )
        fsm.If(valid_cond)(
            rest_size.dec()
        )

        fsm.If(valid, rest_size <= 1).goto_next()

        for _ in range(self.num_data_delay):
            fsm.goto_next()

        # state 2
        set_idle = self._set_flag(fsm)
        self.seq.If(set_idle)(
            self.read_idle(1)
        )

        fsm.goto_init()
Example #8
0
    def _synthesize_read_fsm_fifo_wide(self, fifo, fifo_datawidth):
        """ axi.datawidth > fifo.datawidth """

        if self.datawidth % fifo_datawidth != 0:
            raise ValueError(
                'axi.datawidth must be multiple number of fifo_datawidth')

        pack_size = self.datawidth // fifo_datawidth
        shamt = int(math.log(pack_size, 2))
        res = vtypes.Mux(
            vtypes.And(self.read_size, 2 ** shamt - 1) > 0, 1, 0)
        dma_size = (self.read_size >> shamt) + res

        actual_read_size = dma_size << shamt

        op_id = self._get_read_op_id_fifo(fifo)

        if op_id in self.read_ops:
            """ already synthesized op """
            return

        if pack_size in self.read_wide_fsms:
            """ new op """
            self.read_ops.append(op_id)

            fsm = self.read_wide_fsms[pack_size]
            pack_count = self.read_wide_pack_counts[pack_size]
            data = self.read_wide_data_wires[pack_size]
            valid = self.read_wide_valid_wires[pack_size]
            rest_size = self.read_wide_rest_size_wires[pack_size]

            # state 0
            fsm.set_index(0)
            cond = vtypes.Ands(self.read_start, self.read_op_sel == op_id)
            fsm.If(cond).goto_next()

            # state 1
            fsm.set_index(1)
            valid_cond = vtypes.Ands(valid, self.read_op_sel == op_id)
            stay_cond = self.read_op_sel == op_id

            fsm.Delay(1)(
                wvalid(0)
            )
            fsm.If(pack_count == 0, valid_cond)(
                wdata(data),
                wvalid(1),
                pack_count.inc()
            )
            fsm.If(pack_count > 0, stay_cond)(
                wdata(wdata >> fifo_datawidth),
                wvalid(1),
                pack_count.inc()
            )
            fsm.If(valid_cond)(
                rest_size.dec()
            )

            return

        """ new op and fsm """
        fsm = FSM(self.m, '_'.join(['', self.name,
                                    'read_wide', str(pack_size),
                                    'fsm']),
                  self.clk, self.rst, as_module=self.fsm_as_module)
        self.read_wide_fsms[pack_size] = fsm

        self.read_ops.append(op_id)

        rest_size = self.m.Reg('_'.join(['', self.name,
                                         'read_wide', str(pack_size),
                                         'rest_size']),
                               self.addrwidth + 1, initval=0)
        self.read_wide_rest_size_wires[pack_size] = rest_size

        # state 0
        cond = vtypes.Ands(self.read_start, self.read_op_sel == op_id)

        fsm.If(self.read_start)(
            rest_size(dma_size)
        )
        fsm.If(cond).goto_next()

        # state 1
        pack_count = self.m.Reg('_'.join(['', self.name,
                                          'read_wide', str(pack_size),
                                          'pack_count']),
                                int(math.ceil(math.log(pack_size, 2))), initval=0)
        self.read_wide_pack_counts[pack_size] = pack_count

        ready = vtypes.Not(fifo.almost_full)
        read_cond = vtypes.Ands(fsm.here, ready)

        cond = vtypes.Ands(fsm.here, pack_count == 0, read_cond)
        data, last, _id, user, dest, valid = self.read_data(cond=cond)
        self.read_wide_data_wires[pack_size] = data
        self.read_wide_valid_wires[pack_size] = valid

        wdata = self.m.Reg('_'.join(['', self.name,
                                     'read_wide', str(pack_size),
                                     'wdata']),
                           self.datawidth, initval=0)
        wvalid = self.m.Reg('_'.join(['', self.name,
                                      'read_wide', str(pack_size),
                                      'wvalid']))

        valid_cond = vtypes.Ands(valid, self.read_op_sel == op_id)
        stay_cond = self.read_op_sel == op_id

        ack, _ = fifo.enq_rtl(wdata, cond=wvalid)

        wlast = self.m.Reg('_'.join(['', self.name,
                                     'read_wide', str(pack_size),
                                     'wlast']),
                           initval=0)

        fsm.Delay(1)(
            wvalid(0)
        )
        fsm.If(pack_count == 0, valid_cond)(
            wdata(data),
            wvalid(1),
            wlast(last),
            pack_count.inc()
        )
        fsm.If(pack_count > 0, stay_cond)(
            wdata(wdata >> fifo_datawidth),
            wvalid(1),
            pack_count.inc()
        )
        fsm.If(pack_count == pack_size - 1)(
            pack_count(0)
        )

        fsm.If(pack_count == 0, valid_cond)(
            rest_size.dec()
        )

        fsm.If(pack_count == pack_size - 1, rest_size == 0).goto_next()

        # state 2
        set_idle = self._set_flag(fsm)
        self.seq.If(set_idle)(
            self.read_idle(1)
        )

        fsm.goto_init()