def write_dataflow(self, port, addr, data, length=1, stride=1, cond=None, when=None): """ @return done 'data' and 'when' must be dataflow variables """ if self._write_disabled[port]: raise TypeError('Write disabled.') counter = self.m.TmpReg(length.bit_length() + 1, initval=0) last = self.m.TmpReg(initval=0) ext_cond = make_condition(cond) data_cond = make_condition(counter > 0, vtypes.Not(last)) if when is None or not isinstance(when, df_numeric): raw_data, raw_valid = data.read(cond=data_cond) else: data_list, raw_valid = read_multi(self.m, data, when, cond=data_cond) raw_data = data_list[0] when = data_list[1] when_cond = make_condition(when, ready=data_cond) if when_cond is not None: raw_valid = vtypes.Ands(when_cond, raw_valid) self.seq.If(ext_cond, counter == 0)( self.interfaces[port].addr(addr - stride), counter(length), ) self.seq.If(raw_valid, counter > 0)( self.interfaces[port].addr(self.interfaces[port].addr + stride), self.interfaces[port].wdata(raw_data), self.interfaces[port].wenable(1), counter.dec()) self.seq.If(raw_valid, counter == 1)(last(1)) # de-assert self.seq.Delay(1)(self.interfaces[port].wenable(0), last(0)) done = last return done
def pull_write_data(self, counter=None, cond=None): """ @return data, mask, valid, last """ if self._write_disabled: raise TypeError('Write disabled.') if counter is not None and not isinstance(counter, vtypes.Reg): raise TypeError("counter must be Reg or None.") if counter is None: counter = self.write_counters[-1] ready = make_condition(cond) val = 1 if ready is None else ready prev_subst = self.wdata.wready._get_subst() if not prev_subst: self.wdata.wready.assign(val) else: self.wdata.wready.subst[0].overwrite_right( vtypes.Ors(prev_subst[0].right, val)) ack = vtypes.Ands(self.wdata.wready, self.wdata.wvalid) data = self.wdata.wdata mask = self.wdata.wstrb valid = ack last = self.wdata.wlast self.seq.If(vtypes.Ands(ack, counter > 0))( counter.dec() ) return data, mask, valid, last
def pull_write_dataflow(self, counter=None, cond=None): """ @return data, mask, last, done """ if self._write_disabled: raise TypeError('Write disabled.') if counter is not None and not isinstance(counter, vtypes.Reg): raise TypeError("counter must be Reg or None.") if counter is None: counter = self.write_counters[-1] data_ready = self.m.TmpWire() mask_ready = self.m.TmpWire() last_ready = self.m.TmpWire() data_ready.assign(1) mask_ready.assign(1) last_ready.assign(1) if cond is None: cond = (data_ready, last_ready) elif isinstance(cond, (tuple, list)): cond = tuple(list(cond) + [data_ready, last_ready]) else: cond = (cond, data_ready, last_ready) ready = make_condition(*cond) val = 1 if ready is None else ready prev_subst = self.wdata.wready._get_subst() if not prev_subst: self.wdata.wready.assign(val) else: self.wdata.wready.subst[0].overwrite_right( vtypes.Ors(prev_subst[0].right, val)) ack = vtypes.Ands(self.wdata.wready, self.wdata.wvalid) data = self.wdata.wdata mask = self.wdata.wstrb valid = self.wdata.wvalid last = self.wdata.wlast self.seq.If(vtypes.Ands(ack, counter > 0))( counter.dec() ) df = self.df if self.df is not None else dataflow df_data = df.Variable(data, valid, data_ready) df_mask = df.Variable(mask, valid, mask_ready, width=self.datawidth // 4) df_last = df.Variable(last, valid, last_ready, width=1) done = last return df_data, df_mask, df_last, done
def write_dataflow(self, port, addr, data, length=1, cond=None, when=None): """ @return done """ if self._write_disabled[port]: raise TypeError('Write disabled.') counter = self.m.TmpReg(length.bit_length() + 1, initval=0) last = self.m.TmpReg(initval=0) ext_cond = make_condition(cond) data_cond = make_condition(counter > 0, vtypes.Not(last)) all_cond = make_condition(data_cond, ext_cond) raw_data, raw_valid = data.read(cond=data_cond) when_cond = make_condition(when, ready=data_cond) if when_cond is not None: raw_valid = vtypes.Ands(when_cond, raw_valid) self.seq.If(make_condition(ext_cond, counter == 0))( self.interfaces[port].addr(addr - 1), counter(length), ) self.seq.If(make_condition(raw_valid, counter > 0))( self.interfaces[port].addr.inc(), self.interfaces[port].wdata(raw_data), self.interfaces[port].wenable(1), counter.dec() ) self.seq.If(make_condition(raw_valid, counter == 1))( last(1) ) # de-assert self.seq.Delay(1)( self.interfaces[port].wenable(0), last(0) ) done = last return done
def pull_read_request(self, cond=None, counter=None): """ @return addr, counter, valid """ if self._read_disabled: raise TypeError('Read disabled.') if counter is not None and not isinstance(counter, vtypes.Reg): raise TypeError("counter must be Reg or None.") if counter is None: counter = self.m.TmpReg(self.burst_size_width, initval=0) self.read_counters.append(counter) ready = make_condition(cond) ack = vtypes.Ands(self.raddr.arready, self.raddr.arvalid) addr = self.m.TmpReg(self.addrwidth, initval=0) valid = self.m.TmpReg(initval=0) val = (vtypes.Not(valid) if ready is None else vtypes.Ands(ready, vtypes.Not(valid))) prev_subst = self.raddr.arready._get_subst() if not prev_subst: self.raddr.arready.assign(val) else: self.raddr.arready.subst[0].overwrite_right( vtypes.Ors(prev_subst[0].right, val)) self.seq.If(ack)( addr(self.raddr.araddr), counter(self.raddr.arlen + 1) ) self.seq( valid(ack) ) return addr, counter, valid
def read_dataflow(self, port, addr, length=1, cond=None): """ @return data, last, done """ data_valid = self.m.TmpReg(initval=0) last_valid = self.m.TmpReg(initval=0) data_ready = self.m.TmpWire() last_ready = self.m.TmpWire() data_ready.assign(1) last_ready.assign(1) data_ack = vtypes.Ors(data_ready, vtypes.Not(data_valid)) last_ack = vtypes.Ors(last_ready, vtypes.Not(last_valid)) ext_cond = make_condition(cond) data_cond = make_condition(data_ack, last_ack) prev_data_cond = self.seq.Prev(data_cond, 1) all_cond = make_condition(data_cond, ext_cond) data = self.m.TmpWireLike(self.interfaces[port].rdata) prev_data = self.seq.Prev(data, 1) data.assign( vtypes.Mux(prev_data_cond, self.interfaces[port].rdata, prev_data)) counter = self.m.TmpReg(length.bit_length() + 1, initval=0) next_valid_on = self.m.TmpReg(initval=0) next_valid_off = self.m.TmpReg(initval=0) next_last = self.m.TmpReg(initval=0) last = self.m.TmpReg(initval=0) self.seq.If(make_condition(data_cond, next_valid_off))(last(0), data_valid(0), last_valid(0), next_valid_off(0)) self.seq.If(make_condition(data_cond, next_valid_on))(data_valid(1), last_valid(1), last(next_last), next_last(0), next_valid_on(0), next_valid_off(1)) self.seq.If( make_condition(ext_cond, counter == 0, vtypes.Not(next_last), vtypes.Not(last)))( self.interfaces[port].addr(addr), counter(length - 1), next_valid_on(1), ) self.seq.If(make_condition(data_cond, counter > 0))( self.interfaces[port].addr.inc(), counter.dec(), next_valid_on(1), next_last(0)) self.seq.If(make_condition(data_cond, counter == 1))(next_last(1)) df = self.df if self.df is not None else dataflow df_data = df.Variable(data, data_valid, data_ready) df_last = df.Variable(last, last_valid, last_ready, width=1) done = last return df_data, df_last, done
def read_dataflow_reuse_pattern(self, port, addr, pattern, reuse_size=1, num_outputs=1, cond=None, point=0, signed=False): """ @return data, last, done """ 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, ) if not isinstance(num_outputs, int): raise TypeError('num_outputs must be int') data_valid = [self.m.TmpReg(initval=0) for _ in range(num_outputs)] last_valid = self.m.TmpReg(initval=0) data_ready = [self.m.TmpWire() for _ in range(num_outputs)] last_ready = self.m.TmpWire() for r in data_ready: r.assign(1) last_ready.assign(1) data_ack = vtypes.Ands(*[ vtypes.Ors(r, vtypes.Not(v)) for v, r in zip(data_valid, data_ready) ]) last_ack = vtypes.Ors(last_ready, vtypes.Not(last_valid)) ext_cond = make_condition(cond) data_cond = make_condition(data_ack, last_ack) next_addr = self.m.TmpWire(self.addrwidth) offset_addr = self.m.TmpWire(self.addrwidth) offsets = [ self.m.TmpReg(self.addrwidth, initval=0) for _ in pattern[1:] ] offset_addr_value = addr for offset in offsets: offset_addr_value = offset + offset_addr_value offset_addr.assign(offset_addr_value) offsets.insert(0, None) count_list = [ self.m.TmpReg(out_size.bit_length() + 1, initval=0) for (out_size, out_stride) in pattern ] last = self.m.TmpReg(initval=0) reuse_data = [ self.m.TmpReg(self.datawidth, initval=0) for _ in range(num_outputs) ] next_reuse_data = [ self.m.TmpReg(self.datawidth, initval=0) for _ in range(num_outputs) ] reuse_count = self.m.TmpReg(reuse_size.bit_length() + 1, initval=0) fill_reuse_count = self.m.TmpReg(initval=0) prefetch_done = self.m.TmpReg(initval=0) fetch_done = self.m.TmpReg(initval=0) update_addr = None stride_value = None carry = None for offset, count, (out_size, out_stride) in zip(offsets, count_list, pattern): if update_addr is None: update_addr = count == 0 else: update_addr = vtypes.Mux(carry, count == 0, update_addr) if stride_value is None: stride_value = out_stride else: stride_value = vtypes.Mux(carry, out_stride, stride_value) if carry is None: carry = out_size == 1 else: carry = vtypes.Ands(carry, out_size == 1) next_addr.assign( vtypes.Mux(update_addr, offset_addr, self.interfaces[port].addr + stride_value)) fsm = TmpFSM(self.m, self.clk, self.rst) # initial state fsm.If(ext_cond)(self.interfaces[port].addr(addr - stride_value), prefetch_done(0), fetch_done(0)) first = True for offset, count, (out_size, out_stride) in zip(offsets, count_list, pattern): fsm.If(ext_cond)(count(out_size) if first else count(out_size - 1), ) if offset is not None: fsm.If(ext_cond)(offset(0)) first = False fsm.If(ext_cond).goto_next() # initial prefetch state for n in next_reuse_data: update_count = None update_offset = None last_one = None carry = None for offset, count, (out_size, out_stride) in zip(offsets, count_list, pattern): fsm.If(update_count)(count.dec()) fsm.If(update_count, count == 0)(count(out_size - 1)) fsm(self.interfaces[port].addr(next_addr)) fsm.Delay(2)(n(self.interfaces[port].rdata)) if offset is not None: fsm.If(update_offset, vtypes.Not(carry))(offset(offset + out_stride)) fsm.If(update_offset, count == 0)(offset(0)) if update_count is None: update_count = count == 0 else: update_count = vtypes.Ands(update_count, count == 0) if update_offset is None: update_offset = vtypes.Mux(out_size == 1, 1, count == 1) else: update_offset = vtypes.Ands(update_offset, count == carry) if last_one is None: last_one = count == 0 else: last_one = vtypes.Ands(last_one, count == 0) if carry is None: carry = out_size == 1 else: carry = vtypes.Ands(carry, out_size == 1) fsm.goto_next() fsm.If(last_one)(prefetch_done(1)) fsm.goto_next() fsm.goto_next() # initial update state for r, n in zip(reuse_data, next_reuse_data): fsm(r(n)) fsm(fetch_done(prefetch_done), fill_reuse_count(vtypes.Not(fetch_done))) fsm.Delay(1)(fill_reuse_count(0)) fsm.goto_next() # prefetch state read_start_state = fsm.current for n in next_reuse_data: update_count = None update_offset = None last_one = None carry = None for offset, count, (out_size, out_stride) in zip(offsets, count_list, pattern): fsm.If(update_count)(count.dec()) fsm.If(update_count, count == 0)(count(out_size - 1)) fsm(self.interfaces[port].addr(next_addr)) fsm.Delay(2)(n(self.interfaces[port].rdata)) if offset is not None: fsm.If(update_offset, vtypes.Not(carry))(offset(offset + out_stride)) fsm.If(update_offset, count == 0)(offset(0)) if update_count is None: update_count = count == 0 else: update_count = vtypes.Ands(update_count, count == 0) if update_offset is None: update_offset = vtypes.Mux(out_size == 1, 1, count == 1) else: update_offset = vtypes.Ands(update_offset, count == carry) if last_one is None: last_one = count == 0 else: last_one = vtypes.Ands(last_one, count == 0) if carry is None: carry = out_size == 1 else: carry = vtypes.Ands(carry, out_size == 1) fsm.goto_next() fsm.If(last_one)(prefetch_done(1)) fsm.goto_next() fsm.goto_next() # update state for r, n in zip(reuse_data, next_reuse_data): fsm.If(data_cond, reuse_count == 0)(r(n)) fsm.If(data_cond, reuse_count == 0)(fetch_done(prefetch_done), fill_reuse_count(vtypes.Not(fetch_done))) fsm.Delay(1)(fill_reuse_count(0)) # next -> prefetch state or initial state fsm.If(data_cond, reuse_count == 0, fetch_done).goto_init() fsm.If(data_cond, reuse_count == 0, vtypes.Not(fetch_done)).goto(read_start_state) # output signal control self.seq.If(data_cond, last_valid)(last(0), [d(0) for d in data_valid], last_valid(0)) self.seq.If(fill_reuse_count)(reuse_count(reuse_size)) self.seq.If(data_cond, reuse_count > 0)(reuse_count.dec(), [d(1) for d in data_valid], last_valid(1), last(0)) self.seq.If(data_cond, reuse_count == 1, fetch_done)(last(1)) df = self.df if self.df is not None else dataflow df_last = df.Variable(last, last_valid, last_ready, width=1) done = last df_reuse_data = [ df.Variable(d, v, r, width=self.datawidth, point=point, signed=signed) for d, v, r in zip(reuse_data, data_valid, data_ready) ] return tuple(df_reuse_data + [df_last, done])
def read_dataflow_reuse(self, port, addr, length=1, stride=1, reuse_size=1, num_outputs=1, cond=None, point=0, signed=False): """ @return data, last, done """ if not isinstance(num_outputs, int): raise TypeError('num_outputs must be int') data_valid = [self.m.TmpReg(initval=0) for _ in range(num_outputs)] last_valid = self.m.TmpReg(initval=0) data_ready = [self.m.TmpWire() for _ in range(num_outputs)] last_ready = self.m.TmpWire() for r in data_ready: r.assign(1) last_ready.assign(1) data_ack = vtypes.Ands(*[ vtypes.Ors(r, vtypes.Not(v)) for v, r in zip(data_valid, data_ready) ]) last_ack = vtypes.Ors(last_ready, vtypes.Not(last_valid)) ext_cond = make_condition(cond) data_cond = make_condition(data_ack, last_ack) counter = self.m.TmpReg(length.bit_length() + 1, initval=0) last = self.m.TmpReg(initval=0) reuse_data = [ self.m.TmpReg(self.datawidth, initval=0) for _ in range(num_outputs) ] next_reuse_data = [ self.m.TmpReg(self.datawidth, initval=0) for _ in range(num_outputs) ] reuse_count = self.m.TmpReg(reuse_size.bit_length() + 1, initval=0) fill_reuse_count = self.m.TmpReg(initval=0) fetch_done = self.m.TmpReg(initval=0) fsm = TmpFSM(self.m, self.clk, self.rst) # initial state fsm.If(ext_cond)(self.interfaces[port].addr(addr - stride), fetch_done(0), counter(length)) fsm.If(ext_cond, length > 0).goto_next() # initial prefetch state for n in next_reuse_data: fsm( self.interfaces[port].addr(self.interfaces[port].addr + stride), counter(vtypes.Mux(counter > 0, counter - 1, counter))) fsm.Delay(2)(n(self.interfaces[port].rdata)) fsm.goto_next() fsm.goto_next() fsm.goto_next() # initial update state for n, r in zip(next_reuse_data, reuse_data): fsm(r(n)) fsm(fill_reuse_count(1), fetch_done(counter == 0)) fsm.Delay(1)(fill_reuse_count(0)) fsm.goto_next() # prefetch state read_start_state = fsm.current for n in next_reuse_data: fsm( self.interfaces[port].addr(self.interfaces[port].addr + stride), counter(vtypes.Mux(counter > 0, counter - 1, counter))) fsm.Delay(2)(n(self.interfaces[port].rdata)) fsm.goto_next() fsm.goto_next() fsm.goto_next() # update state for n, r in zip(next_reuse_data, reuse_data): fsm.If(data_cond, reuse_count == 0)(r(n)) fsm.If(data_cond, reuse_count == 0)(fill_reuse_count(vtypes.Not(fetch_done)), fetch_done(counter == 0)) fsm.Delay(1)(fill_reuse_count(0)) # next -> prefetch state or initial state fsm.If(data_cond, reuse_count == 0, counter == 0).goto_init() fsm.If(data_cond, reuse_count == 0, counter > 0).goto(read_start_state) # output signal control self.seq.If(data_cond, last_valid)(last(0), [d(0) for d in data_valid], last_valid(0)) self.seq.If(fill_reuse_count)(reuse_count(reuse_size)) self.seq.If(data_cond, reuse_count > 0)(reuse_count.dec(), [d(1) for d in data_valid], last_valid(1), last(0)) self.seq.If(data_cond, reuse_count == 1, fetch_done)(last(1)) df = self.df if self.df is not None else dataflow df_last = df.Variable(last, last_valid, last_ready, width=1) done = last df_reuse_data = [ df.Variable(d, v, r, width=self.datawidth, point=point, signed=signed) for d, v, r in zip(reuse_data, data_valid, data_ready) ] return tuple(df_reuse_data + [df_last, done])
def read_dataflow_pattern(self, port, addr, pattern, cond=None, point=0, signed=False): """ @return data, last, done """ 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, ) data_valid = self.m.TmpReg(initval=0) last_valid = self.m.TmpReg(initval=0) data_ready = self.m.TmpWire() last_ready = self.m.TmpWire() data_ready.assign(1) last_ready.assign(1) data_ack = vtypes.Ors(data_ready, vtypes.Not(data_valid)) last_ack = vtypes.Ors(last_ready, vtypes.Not(last_valid)) ext_cond = make_condition(cond) data_cond = make_condition(data_ack, last_ack) prev_data_cond = self.seq.Prev(data_cond, 1) data = self.m.TmpWireLike(self.interfaces[port].rdata) prev_data = self.seq.Prev(data, 1) data.assign( vtypes.Mux(prev_data_cond, self.interfaces[port].rdata, prev_data)) next_valid_on = self.m.TmpReg(initval=0) next_valid_off = self.m.TmpReg(initval=0) next_last = self.m.TmpReg(initval=0) last = self.m.TmpReg(initval=0) running = self.m.TmpReg(initval=0) next_addr = self.m.TmpWire(self.addrwidth) offset_addr = self.m.TmpWire(self.addrwidth) offsets = [ self.m.TmpReg(self.addrwidth, initval=0) for _ in pattern[1:] ] offset_addr_value = addr for offset in offsets: offset_addr_value = offset + offset_addr_value offset_addr.assign(offset_addr_value) offsets.insert(0, None) count_list = [ self.m.TmpReg(out_size.bit_length() + 1, initval=0) for (out_size, out_stride) in pattern ] self.seq.If(data_cond, next_valid_off)(last(0), data_valid(0), last_valid(0), next_valid_off(0)) self.seq.If(data_cond, next_valid_on)(data_valid(1), last_valid(1), last(next_last), next_last(0), next_valid_on(0), next_valid_off(1)) self.seq.If(ext_cond, vtypes.Not(running), vtypes.Not(next_last), vtypes.Not(last))(self.interfaces[port].addr(addr), running(1), next_valid_on(1)) self.seq.If(data_cond, running)(self.interfaces[port].addr(next_addr), next_valid_on(1), next_last(0)) update_count = None update_offset = None update_addr = None last_one = None stride_value = None carry = None for offset, count, (out_size, out_stride) in zip(offsets, count_list, pattern): self.seq.If(ext_cond, vtypes.Not(running), vtypes.Not(next_last), vtypes.Not(last))(count(out_size - 1)) self.seq.If(data_cond, running, update_count)(count.dec()) self.seq.If(data_cond, running, update_count, count == 0)(count(out_size - 1)) if offset is not None: self.seq.If(ext_cond, vtypes.Not(running), vtypes.Not(next_last), vtypes.Not(last))(offset(0)) self.seq.If(data_cond, running, update_offset, vtypes.Not(carry))(offset(offset + out_stride)) self.seq.If(data_cond, running, update_offset, count == 0)(offset(0)) if update_count is None: update_count = count == 0 else: update_count = vtypes.Ands(update_count, count == 0) if update_offset is None: update_offset = vtypes.Mux(out_size == 1, 1, count == 1) else: update_offset = vtypes.Ands(update_offset, count == carry) if update_addr is None: update_addr = count == 0 else: update_addr = vtypes.Mux(carry, count == 0, update_addr) if last_one is None: last_one = count == 0 else: last_one = vtypes.Ands(last_one, count == 0) if stride_value is None: stride_value = out_stride else: stride_value = vtypes.Mux(carry, out_stride, stride_value) if carry is None: carry = out_size == 1 else: carry = vtypes.Ands(carry, out_size == 1) next_addr.assign( vtypes.Mux(update_addr, offset_addr, self.interfaces[port].addr + stride_value)) self.seq.If(data_cond, running, last_one)(running(0), next_last(1)) df = self.df if self.df is not None else dataflow df_data = df.Variable(data, data_valid, data_ready, width=self.datawidth, point=point, signed=signed) df_last = df.Variable(last, last_valid, last_ready, width=1) done = last return df_data, df_last, done
def write_dataflow_pattern(self, port, addr, data, pattern, cond=None, when=None): """ @return done 'data' and 'when' must be dataflow variables """ if self._write_disabled[port]: raise TypeError('Write disabled.') 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, ) last = self.m.TmpReg(initval=0) running = self.m.TmpReg(initval=0) ext_cond = make_condition(cond) data_cond = make_condition(running, vtypes.Not(last)) if when is None or not isinstance(when, df_numeric): raw_data, raw_valid = data.read(cond=data_cond) else: data_list, raw_valid = read_multi(self.m, data, when, cond=data_cond) raw_data = data_list[0] when = data_list[1] when_cond = make_condition(when, ready=data_cond) if when_cond is not None: raw_valid = vtypes.Ands(when_cond, raw_valid) offset_addr = self.m.TmpWire(self.addrwidth) offsets = [self.m.TmpReg(self.addrwidth, initval=0) for _ in pattern] offset_addr_value = addr for offset in offsets: offset_addr_value = offset + offset_addr_value offset_addr.assign(offset_addr_value) count_list = [ self.m.TmpReg(out_size.bit_length() + 1, initval=0) for (out_size, out_stride) in pattern ] self.seq.If(ext_cond, vtypes.Not(running))(running(1)) self.seq.If(raw_valid, running)(self.interfaces[port].addr(offset_addr), self.interfaces[port].wdata(raw_data), self.interfaces[port].wenable(1)) update_count = None last_one = None for offset, count, (out_size, out_stride) in zip(offsets, count_list, pattern): self.seq.If(ext_cond, vtypes.Not(running))(count(out_size - 1), offset(0)) self.seq.If(raw_valid, running, update_count)(count.dec(), offset(offset + out_stride)) self.seq.If(raw_valid, running, update_count, count == 0)(count(out_size - 1), offset(0)) if update_count is None: update_count = count == 0 else: update_count = vtypes.Ands(update_count, count == 0) if last_one is None: last_one = count == 0 else: last_one = vtypes.Ands(last_one, count == 0) self.seq.If(raw_valid, last_one)(running(0), last(1)) # de-assert self.seq.Delay(1)(self.interfaces[port].wenable(0), last(0)) done = last return done
def write_dataflow(self, data, counter=None, cond=None, when=None): """ @return done """ if self._write_disabled: raise TypeError('Write disabled.') if counter is not None and not isinstance(counter, vtypes.Reg): raise TypeError("counter must be Reg or None.") if counter is None: counter = self.write_counters[-1] ack = vtypes.Ands(counter > 0, vtypes.Ors(self.wdata.wready, vtypes.Not(self.wdata.wvalid))) last = self.m.TmpReg(initval=0) if cond is None: cond = ack else: cond = (cond, ack) raw_data, raw_valid = data.read(cond=cond) when_cond = make_condition(when, ready=cond) if when_cond is not None: raw_valid = vtypes.Ands(when_cond, raw_valid) # write condition self.seq.If(raw_valid) self.seq.If(vtypes.Ands(ack, counter > 0))( self.wdata.wdata(raw_data), self.wdata.wvalid(1), self.wdata.wlast(0), self.wdata.wstrb(vtypes.Repeat( vtypes.Int(1, 1), (self.wdata.datawidth // 8))), counter.dec() ) self.seq.Then().If(counter == 1)( self.wdata.wlast(1), last(1) ) # de-assert self.seq.Delay(1)( self.wdata.wvalid(0), self.wdata.wlast(0), last(0) ) # retry self.seq.If(vtypes.Ands(self.wdata.wvalid, vtypes.Not(self.wdata.wready)))( self.wdata.wvalid(self.wdata.wvalid), self.wdata.wlast(self.wdata.wlast), last(last) ) done = last return done
def read_dataflow(self, port, addr, length=1, stride=1, cond=None, point=0, signed=True): """ @return data, last, done """ data_valid = self.m.TmpReg(initval=0) last_valid = self.m.TmpReg(initval=0) data_ready = self.m.TmpWire() last_ready = self.m.TmpWire() data_ready.assign(1) last_ready.assign(1) data_ack = vtypes.Ors(data_ready, vtypes.Not(data_valid)) last_ack = vtypes.Ors(last_ready, vtypes.Not(last_valid)) ext_cond = make_condition(cond) data_cond = make_condition(data_ack, last_ack) prev_data_cond = self.seq.Prev(data_cond, 1) data = self.m.TmpWireLike(self.interfaces[port].rdata, signed=True) prev_data = self.seq.Prev(data, 1) data.assign(vtypes.Mux(prev_data_cond, self.interfaces[port].rdata, prev_data)) next_valid_on = self.m.TmpReg(initval=0) next_valid_off = self.m.TmpReg(initval=0) next_last = self.m.TmpReg(initval=0) last = self.m.TmpReg(initval=0) counter = self.m.TmpReg(length.bit_length() + 1, initval=0) self.seq.If(data_cond, next_valid_off)( last(0), data_valid(0), last_valid(0), next_valid_off(0) ) self.seq.If(data_cond, next_valid_on)( data_valid(1), last_valid(1), last(next_last), next_last(0), next_valid_on(0), next_valid_off(1) ) self.seq.If(ext_cond, counter == 0, vtypes.Not(next_last), vtypes.Not(last))( self.interfaces[port].addr(addr), counter(length - 1), next_valid_on(1), next_last(length == 1) ) self.seq.If(data_cond, counter > 0)( self.interfaces[port].addr(self.interfaces[port].addr + stride), counter.dec(), next_valid_on(1), next_last(0) ) self.seq.If(data_cond, counter == 1)( next_last(1) ) df_data = self.df.Variable(data, data_valid, data_ready, width=self.datawidth, point=point, signed=signed) df_last = self.df.Variable( last, last_valid, last_ready, width=1, signed=False) done = last return df_data, df_last, done