def __init__(self, *nodes, **opts): # ID for manager reuse and merge global _dataflow_counter self.object_id = _dataflow_counter _dataflow_counter += 1 self.nodes = set(nodes) self.max_stage = 0 self.last_input = None self.last_output = None self.module = opts['module'] if 'module' in opts else None self.clock = opts['clock'] if 'clock' in opts else None self.reset = opts['reset'] if 'reset' in opts else None self.aswire = opts['aswire'] if 'aswire' in opts else True self.seq = None if (self.module is not None and self.clock is not None and self.reset is not None): no_hook = opts['no_hook'] if 'no_hook' in opts else False if not no_hook: self.module.add_hook(self.implement) seq_name = (opts['seq_name'] if 'seq_name' in opts else '_dataflow_seq_%d' % self.object_id) self.seq = Seq(self.module, seq_name, self.clock, self.reset)
def __init__(self, *nodes, **opts): # ID for manager reuse and merge global _stream_counter self.object_id = _stream_counter _stream_counter += 1 self.nodes = set() self.named_numerics = OrderedDict() self.add(*nodes) self.max_stage = 0 self.last_input = None self.last_output = None self.module = opts['module'] if 'module' in opts else None self.clock = opts['clock'] if 'clock' in opts else None self.reset = opts['reset'] if 'reset' in opts else None self.ivalid = opts['ivalid'] if 'ivalid' in opts else None self.iready = opts['iready'] if 'iready' in opts else None self.ovalid = opts['ovalid'] if 'ovalid' in opts else None self.oready = opts['oready'] if 'oready' in opts else None self.aswire = opts['aswire'] if 'aswire' in opts else True self.dump = opts['dump'] if 'dump' in opts else False self.dump_base = opts['dump_base'] if 'dump_base' in opts else 10 self.dump_mode = opts['dump_mode'] if 'dump_mode' in opts else 'all' self.seq = None self.has_control = False self.implemented = False if (self.module is not None and self.clock is not None and self.reset is not None): no_hook = opts['no_hook'] if 'no_hook' in opts else False if not no_hook: self.module.add_hook(self.implement) seq_name = (opts['seq_name'] if 'seq_name' in opts else '_stream_seq_%d' % self.object_id) self.seq = Seq(self.module, seq_name, self.clock, self.reset) if self.dump: dump_enable_name = '_stream_dump_enable_%d' % self.object_id dump_enable = self.module.Reg(dump_enable_name, initval=0) dump_mask_name = '_stream_dump_mask_%d' % self.object_id dump_mask = self.module.Reg(dump_mask_name, initval=0) dump_step_name = '_stream_dump_step_%d' % self.object_id dump_step = self.module.Reg(dump_step_name, 32, initval=0) self.dump_enable = dump_enable self.dump_mask = dump_mask self.dump_step = dump_step if self.seq: self.seq.add_reset(self.dump_enable) self.seq.add_reset(self.dump_mask)
def write(self, fsm, value, *part): if self.seq is None: m = fsm.m clk = fsm.clk rst = fsm.rst name = self._value.name self.seq = Seq(m, '_'.join(['seq', name]), clk, rst) cond = fsm.state == fsm.current def getval(v, p): if isinstance(p, (tuple, list)): return v[p[0], p[1]] return v[p] if len(part) == 0: targ = self._value elif len(part) == 1: targ = getval(self._value, part[0]) elif len(part) == 2: targ = getval(getval(self._value, part[0]), part[1]) else: raise TypeError('unsupported type') self.seq.If(cond)(targ(value)) fsm.goto_next() return 0
def __init__(self, m, name, clk, rst, datawidth=32, addrwidth=10, numports=1, nodataflow=False): self.m = m self.name = name self.clk = clk self.rst = rst self.datawidth = datawidth self.addrwidth = addrwidth self.interfaces = [ RAMInterface(m, name + '_%d' % i, datawidth, addrwidth) for i in range(numports) ] self.definition = mkRAMDefinition(name, datawidth, addrwidth, numports) self.inst = self.m.Instance(self.definition, 'inst_' + name, ports=m.connect_ports(self.definition)) self.seq = Seq(m, name, clk, rst) if nodataflow: self.df = None else: self.df = DataflowManager(self.m, self.clk, self.rst) self._write_disabled = [False for i in range(numports)]
def __init__(self, m, name, clk, rst, datawidth=32, addrwidth=32, nodataflow=False): self.m = m self.name = name self.clk = clk self.rst = rst self.datawidth = datawidth self.addrwidth = addrwidth self.waddr = AxiSlaveWriteAddress(m, name, datawidth, addrwidth) self.wdata = AxiSlaveWriteData(m, name, datawidth, addrwidth) self.raddr = AxiSlaveReadAddress(m, name, datawidth, addrwidth) self.rdata = AxiSlaveReadData(m, name, datawidth, addrwidth) self.seq = Seq(m, name, clk, rst) self.write_counters = [] self.read_counters = [] if nodataflow: self.df = None else: self.df = DataflowManager(self.m, self.clk, self.rst) self._write_disabled = False self._read_disabled = False
def __init__(self, m, name, clk, rst, func): self.m = m self.name = name self.clk = clk self.rst = rst self.func = func self.df = DataflowManager(self.m, self.clk, self.rst) self.seq = Seq(self.m, 'name', self.clk, self.rst) self.start_cond = None self.done_flags = []
def __init__(self, m, clk, rst, thread_name, thread_id, id, sub_id=None, datawidth=32, addrwidth=10, numports=1): self.m = m self.clk = clk self.rst = rst self.thread_name = thread_name self.thread_id = thread_id self.id = id self.sub_id = sub_id self.name = '_'.join([thread_name, 'memory', str(id)]) self.datawidth = datawidth self.addrwidth = addrwidth self.interfaces = [] for i in range(numports): index = i if numports > 1 else None obj = CoramMemoryInterface(m, name=self.name, datawidth=datawidth, addrwidth=addrwidth, index=index) self.interfaces.append(obj) self.definition = get_coram_memory_definition(numports) params = [] params.append(('CORAM_THREAD_NAME', self.thread_name)) params.append(('CORAM_THREAD_ID', self.thread_id)) params.append(('CORAM_ID', self.id)) if self.sub_id is not None: params.append(('CORAM_SUB_ID', self.sub_id)) params.append(('CORAM_ADDR_LEN', self.addrwidth)) params.append(('CORAM_DATA_WIDTH', self.datawidth)) ports = [] ports.append(('CLK', self.clk)) ports.extend(m.connect_ports(self.definition, prefix=self.name + '_')) self.inst = self.m.Instance(self.definition, 'inst_' + self.name, params, ports) self.seq = Seq(m, self.name, clk, rst) self._write_disabled = [False for i in range(numports)]
def __init__(self, m, clk, rst, thread_name, thread_id, id, sub_id=None, datawidth=32, addrwidth=4): self.m = m self.clk = clk self.rst = rst self.thread_name = thread_name self.thread_id = thread_id self.id = id self.sub_id = sub_id self.name = '_'.join([thread_name, 'channel', str(id)]) self.datawidth = datawidth self.addrwidth = addrwidth self.wif = CoramChannelWriteInterface(self.m, self.name, datawidth) self.rif = CoramChannelReadInterface(self.m, self.name, datawidth) self.definition = get_coram_channel_definition() params = [] params.append(('CORAM_THREAD_NAME', self.thread_name)) params.append(('CORAM_THREAD_ID', self.thread_id)) params.append(('CORAM_ID', self.id)) if self.sub_id is not None: params.append(('CORAM_SUB_ID', self.sub_id)) params.append(('CORAM_ADDR_LEN', self.addrwidth)) params.append(('CORAM_DATA_WIDTH', self.datawidth)) ports = [] ports.append(('CLK', self.clk)) ports.append(('RST', self.rst)) ports.extend(m.connect_ports(self.definition, prefix=self.name + '_')) self.inst = self.m.Instance(self.definition, 'inst_' + self.name, params, ports) self.seq = Seq(m, self.name, clk, rst) self._max_size = (2**self.addrwidth - 1 if isinstance( self.addrwidth, int) else vtypes.Int(2)**self.addrwidth - 1) self._count = 0 self._enq_disabled = False self._deq_disabled = False
def __init__(self, m, name, clk, rst, width=32, initname='init', nohook=False, as_module=False): self.m = m self.name = name self.clk = clk self.rst = rst self.width = width self.state_count = 0 self.state = self.m.Reg(name, width) # set initval later self.mark = collections.OrderedDict() # key:index self._set_mark(0, self.name + '_' + initname) self.state.initval = self._get_mark(0) self.body = collections.defaultdict(list) self.jump = collections.defaultdict(list) self.delay_amount = 0 self.delayed_state = collections.OrderedDict() # key:delay self.delayed_body = collections.defaultdict( functools.partial(collections.defaultdict, list)) # key:delay self.delayed_cond = collections.OrderedDict() # key:name self.tmp_count = 0 self.dst_var = collections.OrderedDict() self.dst_visitor = SubstDstVisitor() self.reset_visitor = ResetVisitor() self.seq = Seq(self.m, self.name + '_par', clk, rst, nohook=True) self.done = False self.last_cond = [] self.last_kwargs = {} self.last_if_statement = None self.elif_cond = None self.next_kwargs = {} self.as_module = as_module if not nohook: self.m.add_hook(self.implement)
def __init__(self, m, name, clk, rst, width=32): self.m = m self.name = name self.clk = clk self.rst = rst self.width = width self.tmp_count = 0 self.max_stage_id = 0 self.vars = [] self.seq = Seq(self.m, self.name, clk, rst, nohook=True) self.data_visitor = DataVisitor(self) self.done = False
def __init__(self, m, name, clk, rst, width=32): self.m = m self.name = name self.clk = clk self.rst = rst self.width = width self.seq = Seq(self.m, self.name, self.clk, self.rst) self.lock_reg = self.m.Reg('_'.join(['', self.name, 'lock_reg']), initval=0) self.lock_id = self.m.Reg('_'.join(['', self.name, 'lock_id']), self.width, initval=0) self.id_map = {} self.id_map_count = 0
def mkFifoDefinition(name, datawidth=32, addrwidth=4): m = module.Module(name) clk = m.Input('CLK') rst = m.Input('RST') wif = FifoWriteSlaveInterface(m, name, datawidth) rif = FifoReadSlaveInterface(m, name, datawidth) mem = m.Reg('mem', datawidth, 2**addrwidth) head = m.Reg('head', addrwidth, initval=0) tail = m.Reg('tail', addrwidth, initval=0) is_empty = m.Wire('is_empty') is_almost_empty = m.Wire('is_almost_empty') is_full = m.Wire('is_full') is_almost_full = m.Wire('is_almost_full') mask = (2**addrwidth) - 1 is_empty.assign(head == tail) is_almost_empty.assign(head == ((tail + 1) & mask)) is_full.assign(((head + 1) & mask) == tail) is_almost_full.assign(((head + 2) & mask) == tail) rdata = m.Reg('rdata_reg', datawidth, initval=0) wif.full.assign(is_full) wif.almost_full.assign(vtypes.Ors(is_almost_full, is_full)) rif.empty.assign(is_empty) rif.almost_empty.assign(vtypes.Ors(is_almost_empty, is_empty)) seq = Seq(m, '', clk, rst) seq.If(vtypes.Ands(wif.enq, vtypes.Not(is_full)))(mem[head](wif.wdata), head.inc()) seq.If(vtypes.Ands(rif.deq, vtypes.Not(is_empty)))(rdata(mem[tail]), tail.inc()) rif.rdata.assign(rdata) seq.make_always() return m
def __init__(self, m, name, clk, rst, datawidth=32, addrwidth=4): self.m = m self.name = name self.clk = clk self.rst = rst self.datawidth = datawidth self.addrwidth = addrwidth self.wif = FifoWriteInterface(self.m, name, datawidth) self.rif = FifoReadInterface(self.m, name, datawidth) self.definition = mkFifoDefinition(name, datawidth, addrwidth) self.inst = self.m.Instance(self.definition, 'inst_' + name, ports=m.connect_ports(self.definition)) self.seq = Seq(m, name, clk, rst) # entry counter self._max_size = (2 ** self.addrwidth - 1 if isinstance(self.addrwidth, int) else vtypes.Int(2) ** self.addrwidth - 1) self._count = self.m.Reg( 'count_' + name, self.addrwidth + 1, initval=0) self.seq.If( vtypes.Ands(vtypes.Ands(self.wif.enq, vtypes.Not(self.wif.full)), vtypes.Ands(self.rif.deq, vtypes.Not(self.rif.empty))))( self._count(self._count) ).Elif(vtypes.Ands(self.wif.enq, vtypes.Not(self.wif.full)))( self._count.inc() ).Elif(vtypes.Ands(self.rif.deq, vtypes.Not(self.rif.empty)))( self._count.dec() ) self._enq_disabled = False self._deq_disabled = False self.mutex = None
def __init__(self, *nodes, **opts): # ID for manager reuse and merge global _stream_counter self.object_id = _stream_counter _stream_counter += 1 self.nodes = set() self.named_numerics = OrderedDict() self.add(*nodes) self.max_stage = 0 self.last_input = None self.last_output = None self.module = opts['module'] if 'module' in opts else None self.clock = opts['clock'] if 'clock' in opts else None self.reset = opts['reset'] if 'reset' in opts else None self.ivalid = opts['ivalid'] if 'ivalid' in opts else None self.iready = opts['iready'] if 'iready' in opts else None self.ovalid = opts['ovalid'] if 'ovalid' in opts else None self.oready = opts['oready'] if 'oready' in opts else None self.aswire = opts['aswire'] if 'aswire' in opts else True self.seq = None self.has_control = False self.implemented = False if (self.module is not None and self.clock is not None and self.reset is not None): no_hook = opts['no_hook'] if 'no_hook' in opts else False if not no_hook: self.module.add_hook(self.implement) seq_name = (opts['seq_name'] if 'seq_name' in opts else '_stream_seq_%d' % self.object_id) self.seq = Seq(self.module, seq_name, self.clock, self.reset)
def __init__(self, m, name, clk, rst, numparties): self.m = m self.name = name self.clk = clk self.rst = rst self.numparties = numparties self.width = int(math.ceil(math.log(self.numparties, 2))) + 1 self.seq = Seq(self.m, self.name, self.clk, self.rst) self.count = self.m.Reg('_'.join(['', self.name, 'barrier_count']), self.width, initval=0) self.done = self.m.Reg('_'.join(['', self.name, 'barrier_done']), initval=0) self.mutex = Mutex(self.m, '_'.join(['', self.name, 'barrier_mutex']), self.clk, self.rst) # reset condition self.seq(self.done(0)) self.seq.If(self.count == self.numparties)(self.count(0), self.done(1))
def implement(self, m=None, clock=None, reset=None, aswire=None, seq_name=None): """ implemente actual registers and operations in Verilog """ if self.implemented: if m is None: return self.module raise ValueError('already implemented.') self.implemented = True if m is None: m = self.module if self.module is None: self.module = m if clock is None: clock = self.clock if reset is None: reset = self.reset if self.seq is None: if seq_name is None: seq_name = '_stream_seq_%d' % self.object_id seq = Seq(m, seq_name, clock, reset) else: seq = self.seq if aswire is None: aswire = self.aswire self.add_control(aswire=aswire) self.has_control = True # for mult and div m._clock = clock m._reset = reset stream_nodes = self.nodes input_visitor = visitor.InputVisitor() input_vars = set() for node in sorted(stream_nodes, key=lambda x: x.object_id): input_vars.update(input_visitor.visit(node)) output_visitor = visitor.OutputVisitor() output_vars = set() for node in sorted(stream_nodes, key=lambda x: x.object_id): output_vars.update(output_visitor.visit(node)) # add input ports for input_var in sorted(input_vars, key=lambda x: x.object_id): input_var._implement_input(m, seq, aswire) # schedule sched = scheduler.ASAPScheduler() sched.schedule(output_vars) # balance output stage depth max_stage = 0 for output_var in sorted(output_vars, key=lambda x: x.object_id): max_stage = stypes._max(max_stage, output_var.end_stage) self.max_stage = max_stage output_vars = sched.balance_output(output_vars, max_stage) # get all vars all_visitor = visitor.AllVisitor() all_vars = set() for output_var in sorted(output_vars, key=lambda x: x.object_id): all_vars.update(all_visitor.visit(output_var)) # control (valid and ready) if not self.has_control: self.add_control(aswire) self.implement_control(seq) # allocate (implement signals) alloc = allocator.Allocator() alloc.allocate(m, seq, all_vars, self.valid_list, self.senable) # set default module information for var in sorted(all_vars, key=lambda x: x.object_id): var._set_module(m) var._set_strm(self) if var.seq is not None: seq.update(var.seq) var._set_seq(seq) # add output ports for output_var in sorted(output_vars, key=lambda x: x.object_id): output_var._implement_output(m, seq, aswire) # save schedule result self.last_input = input_vars self.last_output = output_vars if self.dump: self.add_dump(m, seq, input_vars, output_vars, all_vars) return m
def implement(self, m=None, clock=None, reset=None, aswire=None, seq_name=None): """ implemente actual registers and operations in Verilog """ if m is None: m = self.module if clock is None: clock = self.clock if reset is None: reset = self.reset if self.seq is None or self.seq.done: if seq_name is None: seq_name = '_dataflow_seq_%d' % self.object_id seq = Seq(m, seq_name, clock, reset) else: seq = self.seq if aswire is None: aswire = self.aswire # for mult and div m._clock = clock m._reset = reset dataflow_nodes = self.nodes input_visitor = visitor.InputVisitor() input_vars = set() for node in sorted(dataflow_nodes, key=lambda x: x.object_id): input_vars.update(input_visitor.visit(node)) output_visitor = visitor.OutputVisitor() output_vars = set() for node in sorted(dataflow_nodes, key=lambda x: x.object_id): output_vars.update(output_visitor.visit(node)) # add input ports for input_var in sorted(input_vars, key=lambda x: x.object_id): input_var._implement_input(m, seq, aswire) # schedule sched = scheduler.ASAPScheduler() sched.schedule(output_vars) # balance output stage depth max_stage = 0 for output_var in sorted(output_vars, key=lambda x: x.object_id): max_stage = dtypes._max(max_stage, output_var.end_stage) self.max_stage = max_stage output_vars = sched.balance_output(output_vars, max_stage) # get all vars all_visitor = visitor.AllVisitor() all_vars = set() for output_var in sorted(output_vars, key=lambda x: x.object_id): all_vars.update(all_visitor.visit(output_var)) # allocate (implement signals) alloc = allocator.Allocator() alloc.allocate(m, seq, all_vars) # set default module information for var in sorted(all_vars, key=lambda x: x.object_id): var._set_module(m) var._set_df(self) if var.seq is not None: seq.update(var.seq) var._set_seq(seq) # add output ports for output_var in sorted(output_vars, key=lambda x: x.object_id): output_var._implement_output(m, seq, aswire) # save schedule result self.last_input = input_vars self.last_output = output_vars return m