def _make_masters(cls, template: MOSBase, pinfo: MOSBasePlaceInfo, params: Mapping[str, Any] ) -> Tuple[LevelShifterCoreOutBuffer, LevelShifterCoreOutBuffer, LevelShifterCoreOutBuffer, InvCore, SingleToDiffEnable, DiffBufferEnable, InvChainCore, InvChainCore]: se_params: Param = params['se_params'] match_params: Param = params['match_params'] inv_params: Param = params['inv_params'] data_lv_params: Param = params['data_lv_params'] ctrl_lv_params: Param = params['ctrl_lv_params'] por_lv_params: Param = params['por_lv_params'] buf_ctrl_lv_params: Param = params['buf_ctrl_lv_params'] buf_por_lv_params: Param = params['buf_por_lv_params'] ridx_p: int = params['ridx_p'] ridx_n: int = params['ridx_n'] # setup master parameters append = dict(pinfo=pinfo, ridx_n=ridx_n, ridx_p=ridx_p) data_params = data_lv_params.copy(append=dict(dual_output=True, vertical_rst=['rst_outp', 'rst_outn', 'rst_casc'], **append)) ctrl_params = ctrl_lv_params.copy(append=dict(dual_output=True, **append)) inv_params = inv_params.copy(append=append) data_buf_params = dict(vertical_out=False, **append, **se_params) clk_buf_params = dict(vertical_out=False, **append, **match_params) # create masters lv_data_master = template.new_template(LevelShifterCoreOutBuffer, params=data_params) lv_ctrl_master = template.new_template(LevelShifterCoreOutBuffer, params=ctrl_params) inv_master = template.new_template(InvCore, params=inv_params) data_master = template.new_template(SingleToDiffEnable, params=data_buf_params) clk_master = template.new_template(DiffBufferEnable, params=clk_buf_params) buf_ctrl_lv_master = cls._get_buf_lv_master(template, buf_ctrl_lv_params, append) buf_por_lv_master = cls._get_buf_lv_master(template, buf_por_lv_params, append) # NOTE: Set POR level shifter to 4 columns less than normal level shifter. # Since both level shifter are dual output and symmetric, this means that the POR level # shifter is 2 columns shorter than norma level shifter on left and right side, which # will conveniently shift the vm_layer output wires of POR to not collide with # the control level shifters. # Also, since POR level shifter is usually small (because it doesn't have to be big), # this make sure we have enough routing tracks for differential inputs on vm_layer por_ncol = lv_ctrl_master.num_cols - 4 por_params = por_lv_params.copy(append=dict(dual_output=True, has_rst=False, num_col_tot=por_ncol, **append)) lv_por_master = template.new_template(LevelShifterCoreOutBuffer, params=por_params) return (lv_data_master, lv_ctrl_master, lv_por_master, inv_master, data_master, clk_master, buf_ctrl_lv_master, buf_por_lv_master)
def _get_buf_lv_master(cls, template: MOSBase, 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 = template.new_template(InvChainCore, params=buf_params) vm_layer = template.conn_layer + 2 out_tidx = buf_master.get_port('out').get_pins()[0].track_id.base_index prev_tidx = template.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