def design(self, nand_params: Param, nor_params: Param, pupd_params: Param, export_pins: bool) -> None: self.instances['XNAND'].design(**nand_params) self.instances['XNOR'].design(**nor_params) self.instances['Xpupd'].design(**pupd_params.copy(append=dict( strong=True))) if export_pins: self.add_pin('nand_pu', TermType.output) self.add_pin('nor_pd', TermType.output)
def _get_buf_lv_master(self, buf_params: Param, append: Mapping[str, Any]) -> InvChainCore: buf_params = buf_params.copy(append=dict( dual_output=True, vertical_output=True, **append ), remove=['sig_locs']) buf_master = self.new_template(InvChainCore, params=buf_params) vm_layer = self.conn_layer + 2 out_tidx = buf_master.get_port('out').get_pins()[0].track_id.base_index prev_tidx = self.tr_manager.get_next_track(vm_layer, out_tidx, 'sig', 'sig', up=False) buf_master = buf_master.new_template_with(sig_locs=dict(outb=prev_tidx)) return buf_master
def design(self, dlycell_params: Param, num_insts: int, num_dum: int, flop: bool, flop_char: bool, output_sr_pins: bool) -> None: """To be overridden by subclasses to design this module. This method should fill in values for all parameters in self.parameters. To design instances of this module, you can call their design() method or any other ways you coded. To modify schematic structure, call: rename_pin() delete_instance() replace_instance_master() reconnect_instance_terminal() restore_instance() array_instance() """ if not flop: self.replace_instance_master('XCELL', 'aib_ams', 'aib_dlycell_no_flop', keep_connections=True) self.replace_instance_master('XDUM', 'aib_ams', 'aib_dlycell_no_flop', keep_connections=True) for name in ['RSTb', 'CLKIN', 'iSI', 'SOOUT', 'iSE']: self.remove_pin(name) self.instances['XCELL'].design(**dlycell_params) if num_insts > 2: if output_sr_pins: conn_list = [('in_p', f'a<{num_insts - 2}:0>,dlyin'), ('bk', f'bk<{num_insts - 1}:0>'), ('ci_p', f'b<{num_insts - 1}:0>'), ('out_p', f'b<{num_insts-2}:0>,dlyout'), ('co_p', f'a<{num_insts - 1}:0>'), ('si', f'so<{num_insts-2}:0>,iSI'), ('so', f'SOOUT,so<{num_insts-2}:0>'), ('srqb', f'srqb<{num_insts - 1}:0>'), ('srq', f'srq<{num_insts - 1}:0>')] else: conn_list = [ ('in_p', f'a<{num_insts - 2}:0>,dlyin'), ('bk', f'bk<{num_insts - 1}:0>'), ('ci_p', f'b{num_insts - 1},b<{num_insts - 2}:0>'), ('out_p', f'b<{num_insts - 2}:0>,dlyout'), ('co_p', f'a{num_insts - 1},a<{num_insts - 2}:0>'), ('si', f'so<{num_insts - 2}:0>,iSI'), ('so', f'SOOUT,so<{num_insts - 2}:0>'), ] if flop_char: conn_list.append(('bk1', f'flop_q<{num_insts - 1}:0>')) self.add_pin(f'flop_q<{num_insts - 1}:0>', TermType.output) self.rename_instance('XCELL', f'XCELL<{num_insts - 1}:0>', conn_list) elif num_insts == 2: conn_list = [ ('in_p', f'a,dlyin'), ('bk', f'bk<{num_insts - 1}:0>'), ('ci_p', f'b{num_insts - 1},b'), ('out_p', 'b,dlyout'), ('co_p', f'a{num_insts - 1},a'), ('si', f'so,iSI'), ('so', f'SOOUT,so'), ] if output_sr_pins: conn_list += [('srqb', f'srqb<1:0>'), ('srq', f'srq<1:0>')] if flop_char: conn_list.append(('bk1', f'flop_q<{num_insts - 1}:0>')) self.add_pin(f'flop_q<{num_insts - 1}:0>', TermType.output) self.rename_instance('XCELL', f'XCELL<{num_insts - 1}:0>', conn_list) elif num_insts == 1: if flop_char: self.reconnect_instance_terminal('XCELL', 'bk1', 'flop_q<0>') self.add_pin('flop_q<0>', TermType.output) if output_sr_pins: self.reconnect_instance_terminal('XCELL', 'srq', 'srq') self.reconnect_instance_terminal('XCELL', 'srqb', 'srqb') else: raise ValueError( f'num_insts={num_insts} should be greater than 0.') if num_dum > 0: dc_core_params = dlycell_params['dc_core_params'].copy( remove=['output_sr_pins']) dum_params = dlycell_params.copy( remove=['flop_char', 'output_sr_pins'], append={ 'is_dum': True, 'dc_core_params': dc_core_params }) self.instances['XDUM'].design(**dum_params) if num_dum > 1: suffix = f'<{num_dum - 1}:0>' conn_list = [ ('out_p', 'NC_out' + suffix), ('co_p', 'NC_co' + suffix), ('so', 'NC_so' + suffix), ] self.rename_instance('XDUM', 'XDUM' + suffix, conn_list) if flop: self.rename_instance('XNC_so', 'XNC_so' + suffix, [('noConn', 'NC_so' + suffix)]) else: self.remove_instance('XNC_so') self.rename_instance('XNC_co', 'XNC_co' + suffix, [('noConn', 'NC_co' + suffix)]) self.rename_instance('XNC_out', 'XNC_out' + suffix, [('noConn', 'NC_out' + suffix)]) else: for inst in ['XDUM', 'XNC_so', 'XNC_co', 'XNC_out']: self.remove_instance(inst) if output_sr_pins: if num_insts == 2: raise ValueError('oops not supported') pin_name_list = [ ('bk', f'bk<{num_insts - 1}:0>'), ('b', f'b<{num_insts - 1}:0>'), ('a', f'a<{num_insts - 1}:0>'), ] if num_insts > 1 else [] self.add_pin(f'srq<{num_insts-1}:0>', TermType.output) self.add_pin(f'srqb<{num_insts-1}:0>', TermType.output) else: pin_name_list = [ ('bk', f'bk<{num_insts - 1}:0>'), ('b', f'b{num_insts - 1}'), ('a', f'a{num_insts - 1}'), ] if num_insts > 1 else [] for old_name, new_name in pin_name_list: self.rename_pin(old_name, new_name)
def _create_masters( self, pinfo: MOSBasePlaceInfo, ridx_p: int, ridx_n: int, is_guarded: bool, invp_params_list: Sequence[Param], invn_params_list: Sequence[Param], pg_params: Param, sig_locs: Mapping[str, Union[float, HalfInt]], vertical_out: bool, vertical_in: bool ) -> Tuple[Sequence[InvCore], Sequence[InvCore], PassGateCore]: # configure sig_locs dictionary so we can connect more signals on hm_layer nout_tid = get_adj_tidx_list(self, ridx_n, sig_locs, MOSWireType.DS, 'nout', False) pout_tid = get_adj_tidx_list(self, ridx_p, sig_locs, MOSWireType.DS, 'pout', True) nin_tid = get_adj_tidx_list(self, ridx_n, sig_locs, MOSWireType.G, 'nin', True) pin_tid = get_adj_tidx_list(self, ridx_p, sig_locs, MOSWireType.G, 'pin', False) # TODO: this gate index hack fixes cases where you cannot short adjacent hm_layer # TODO: tracks with vm_layer. Need more rigorous checking later so we can reduce # TODO: gate resistance even_gate_index = int(is_guarded) # create masters append_dict = dict( pinfo=pinfo, ridx_p=ridx_p, ridx_n=ridx_n, is_guarded=is_guarded, ) sig_locs0 = dict( nout=nout_tid[0], pout=pout_tid[0], nin=nin_tid[even_gate_index], pin=pin_tid[even_gate_index], ) sig_locs1 = dict( nout=nout_tid[1], pout=pout_tid[1], nin=nin_tid[1], pin=pin_tid[1], ) invp0 = self.new_template(InvCore, params=invp_params_list[0].copy( append=dict(sig_locs=sig_locs0, vertical_out=not is_guarded, vertical_in=vertical_in, **append_dict))) pg = self.new_template(PassGateCore, params=pg_params.copy(append=dict( sig_locs=dict( nd=nout_tid[0], pd=pout_tid[0], ns=nout_tid[1], ps=pout_tid[1], en=nin_tid[1], enb=pin_tid[1], ), pinfo=pinfo, ridx_p=ridx_p, ridx_n=ridx_n, is_guarded=is_guarded, vertical_out=False, vertical_in=False, ))) invp1 = self.new_template( InvCore, params=invp_params_list[1].copy(append=dict( sig_locs=sig_locs0, vertical_out=vertical_out, **append_dict))) invn0 = self.new_template(InvCore, params=invn_params_list[0].copy( append=dict(sig_locs=sig_locs0, vertical_out=not is_guarded, vertical_in=vertical_in, **append_dict))) invn1 = self.new_template( InvCore, params=invn_params_list[1].copy(append=dict( sig_locs=sig_locs1, vertical_out=not is_guarded, ** append_dict))) invn2 = self.new_template( InvCore, params=invn_params_list[2].copy(append=dict( sig_locs=sig_locs0, vertical_out=vertical_out, **append_dict))) if is_guarded: # make sure vm input pin are on the same track n0_in = invn0.get_port('in').get_pins()[0] p0_in = invp0.get_port('in').get_pins()[0] n0_tidx = n0_in.track_id.base_index p0_tidx = p0_in.track_id.base_index if n0_tidx < p0_tidx: sig_locs0['in'] = n0_tidx invp0 = invp0.new_template_with(sig_locs=sig_locs0) elif p0_tidx < n0_tidx: sig_locs0['in'] = p0_tidx invn0 = invn0.new_template_with(sig_locs=sig_locs0) return [invp0, invp1], [invn0, invn1, invn2], pg