def fusion_lut_with_mux( lut, counter ): '''将lut和mux进行逻辑混合, 插入扫描逻辑. In = scan_in+str(counter) I(n+1) = scan_en 计算新的init_value ''' assert isinstance(lut, cc.circut_module) and lut.m_type=="LUT" input_num = lut.input_count() assert input_num == int( lut.cellref[3] ) scan_in = cc.port("I"+str(input_num),'input',cc.signal(name="scan_in"+str(counter))) scan_en = cc.port('I'+str(input_num+1),'input',cc.signal(name="scan_en")) lut.port_list.insert(-1,scan_in) lut.port_list.insert(-1,scan_en) assert (not lut.param_list==None) and len(lut.param_list)==1 old_init = lut.param_list[0].value init_legal = re.match('(\d+)\'[hb]([0-9A-F]+)',old_init) assert (init_legal is not None) assert int(init_legal.groups()[0])==2**input_num if input_num == 1: assert (init_legal.groups()[0] == '2' and init_legal.groups()[1] == "1"),\ "Error:find LUT1 .INIT !=2'h1 %s, is %s" % (lut.name,lut.param_list[0].value) NEW_INIT = "8'hC5" else: NEW_INIT = str(2**(input_num+2))+'\'h'+'F'*int(2**(input_num-2)) \ +'0'*int(2**(input_num-2))+(init_legal.groups()[1])*2 lut.param_list[0].edit_param('INIT',NEW_INIT) lut.cellref = re.sub('LUT[1-4]', ( 'LUT'+str(input_num+2) ), lut.cellref ) assert lut.input_count() == (input_num + 2) return None
def p_signal_decl(p): ''' signal_decl : WIRE VECTOR IDENTIFIER ';' | WIRE IDENTIFIER ';' ''' if len(p)==5: p[0]=cc.signal(name=p[3],vector=p[2]) else: p[0]=cc.signal(name=p[2],vector=None)
def p_signal_decl(p): ''' signal_decl : WIRE VECTOR IDENTIFIER ';' | WIRE IDENTIFIER ';' ''' if len(p) == 5: p[0] = cc.signal(name=p[3], vector=p[2]) else: p[0] = cc.signal(name=p[2], vector=None)
def replace_fd_with_scan_fd(fd, counter): '''将FD*替换为 SCAN_FD*, 并且增加三个和扫描有关的端口. ''' assert isinstance(fd, cc.circut_module) and fd.m_type == "FD" fd.cellref = "SCAN_"+fd.cellref SCAN_IN = cc.port( 'SCAN_IN', 'input', cc.signal(name="scan_in"+str(counter)) ) SCAN_EN = cc.port( 'SCAN_EN', 'input', cc.signal(name="scan_en")) SCAN_OUT = cc.port( 'SCAN_OUT', 'output', cc.signal(name='scan_out'+str(counter)) ) fd.port_list.insert(0, SCAN_OUT) fd.port_list.insert(0, SCAN_EN) fd.port_list.insert(0, SCAN_IN) return None
def add_scan_ports_top(top_module): '''在顶层模块增加三个端口 ''' #assert isinstance(top_module, cc.circut_module) _scan_in = cc.signal('input', 'scan_in', None) _scan_en = cc.signal('input', 'scan_en', None) _scan_out = cc.signal('output', 'scan_out', None) port_scan_in = _scan_in.signal_2_port() port_scan_en = _scan_en.signal_2_port() port_scan_out = _scan_out.signal_2_port() top_module.port_list.insert(0,port_scan_in) top_module.port_list.insert(0,port_scan_out) top_module.port_list.insert(0,port_scan_en) return None
def p_port_decl(p): '''port_decl : INPUT IDENTIFIER ';' | INPUT VECTOR IDENTIFIER ';' | OUTPUT IDENTIFIER ';' | OUTPUT VECTOR IDENTIFIER ';' | INOUT IDENTIFIER ';' | INOUT VECTOR IDENTIFIER ';' ''' if len(p)==5: tmp=cc.signal(s_type=p[1],name=p[3],vector=p[2]) p[0]=tmp.signal_2_port() else: tmp=cc.signal(s_type=p[1],name=p[2],vector=None) p[0]=tmp.signal_2_port()
def p_port_decl(p): '''port_decl : INPUT IDENTIFIER ';' | INPUT VECTOR IDENTIFIER ';' | OUTPUT IDENTIFIER ';' | OUTPUT VECTOR IDENTIFIER ';' | INOUT IDENTIFIER ';' | INOUT VECTOR IDENTIFIER ';' ''' if len(p) == 5: tmp = cc.signal(s_type=p[1], name=p[3], vector=p[2]) p[0] = tmp.signal_2_port() else: tmp = cc.signal(s_type=p[1], name=p[2], vector=None) p[0] = tmp.signal_2_port()
def p_signal_element(p): '''signal_element : IDENTIFIER BIT | IDENTIFIER VECTOR | IDENTIFIER ''' if len(p)==3: p[0]=cc.signal(name=p[1],vector=p[2]) else: # 匹配,使得连在一起的 ID-VEC:ID[\d+]等够将ID VEC分开 linked_id_vec = re.match("(.+)(\[\d+\])$",p[1]) if linked_id_vec is not None: iden = linked_id_vec.groups()[0] vec = linked_id_vec.groups()[1] p[0] = cc.signal( name = iden ,vector = vec) else: p[0]=cc.signal(name=p[1])
def p_signal_element(p): '''signal_element : IDENTIFIER BIT | IDENTIFIER VECTOR | IDENTIFIER ''' if len(p) == 3: p[0] = cc.signal(name=p[1], vector=p[2]) else: # 匹配,使得连在一起的 ID-VEC:ID[\d+]等够将ID VEC分开 linked_id_vec = re.match("(.+)(\[\d+\])$", p[1]) if linked_id_vec is not None: iden = linked_id_vec.groups()[0] vec = linked_id_vec.groups()[1] p[0] = cc.signal(name=iden, vector=vec) else: p[0] = cc.signal(name=p[1])
def p_assign_stm(p): ''' assign_stm : ASSIGN signal_element '=' signal_element ';' | ASSIGN signal_element '=' BIN_NUMBER ';' ''' if isinstance(p[4],cc.signal): p[0]=cc.assign("assign",p[2],p[4]) else: p[0]=cc.assign("assign",p[2],cc.signal(name=p[4]))
def p_assign_stm(p): ''' assign_stm : ASSIGN signal_element '=' signal_element ';' | ASSIGN signal_element '=' BIN_NUMBER ';' ''' if isinstance(p[4], cc.signal): p[0] = cc.assign("assign", p[2], p[4]) else: p[0] = cc.assign("assign", p[2], cc.signal(name=p[4]))
def insert_wire(self, signal): '''@param: signal, 一个signal对象, 或者是一个可以转化为signal的字符串.空格分隔,长度为2个词,后一个是向量.或者单个词 @return:如果成功插入则返回一个signal对象,如果失败,则返回None ''' if isinstance(signal, cc.signal): s = signal elif isinstance(signal, str): ss = signal.split() if len(ss) == 2: assert re.match("\[\d+\]|\[\d+:\d+\]", ss[1]) s = cc.signal(name = ss[0], vector = ss[1]) else: s = cc.signal(name = ss[0]) else: raise FormatError,"param type error: not a signal or a string." try: self.__insert_type('wires', s) except RedeclarationError,e: # 已经插入过的线网,如果再次插入,直接保持原模原样不动就好了 print e, "|| so no wire get changed." return None
def insert_wire(self, signal): '''@param: signal, 一个signal对象, 或者是一个可以转化为signal的字符串.空格分隔,长度为2个词,后一个是向量.或者单个词 @return:如果成功插入则返回一个signal对象,如果失败,则返回None ''' if isinstance(signal, cc.signal): s = signal elif isinstance(signal, str): ss = signal.split() if len(ss) == 2: assert re.match("\[\d+\]|\[\d+:\d+\]", ss[1]) s = cc.signal(name=ss[0], vector=ss[1]) else: s = cc.signal(name=ss[0]) else: raise FormatError, "param type error: not a signal or a string." try: self.__insert_type('wires', s) except RedeclarationError, e: # 已经插入过的线网,如果再次插入,直接保持原模原样不动就好了 print e, "|| so no wire get changed." return None
def fusion_lut_with_or(lut): '''将LUT和 or门逻辑混合.功能是: O' = (In == 1'b1) ? 1'b1: O ; ''' input_num = int(lut.cellref[3]) scan_en = cc.port('I'+str(input_num),'input',cc.signal(name="scan_en")) lut.port_list.insert(-1,scan_en) assert (not lut.param_list==None) assert len(lut.param_list)==1 old_init=lut.param_list[0].value init_legal=re.match('(\d+)\'[hb]([0-9A-F]+)',old_init) assert (init_legal is not None) assert int(init_legal.groups()[0])==2**input_num if input_num==1: NEW_INIT="4'hD" else: NEW_INIT=str(2**(input_num+1))+'\'h'+'F'*int(2**(input_num-2))\ +init_legal.groups()[1] lut.param_list[0].edit_param('INIT',NEW_INIT) lut.cellref = re.sub('LUT[1-5]', ('LUT' + str(input_num+1)), lut.cellref) return None
replace_fd_with_scan_fd(eachPrimitive, counter) scan_out_list.append('scan_out' + str(counter)) fd_replace_cnt+=1 #CE时钟使能控制信号的优化. 改LUT,进行时钟使能的插入,就是插入一个或门 elif(eachPrimitive.m_type=='LUT') and (eachPrimitive.name in lut_cnt2_ce): fusion_lut_with_or(eachPrimitive) #-------------------------------------------------------------------------- # 未使用LUT混合来gate 的 ce信号名称应该修改, 和之后assign部分的相同 #-------------------------------------------------------------------------- for eachPrimitive in m_list[1:]: if (eachPrimitive.m_type=='FD') and (eachPrimitive.name in fd_has_ce_list): current_ce = all_fd_dict[eachPrimitive.name]['CE'].string if current_ce in un_opt_ce_list: gatedCE = gate_ce( current_ce ) new_ce_signal = cc.signal('wire', gatedCE) eachPrimitive.edit_spec_port('CE', new_ce_signal) #因为多个FD可能连接到相同的CE, signal_decl_list里面有重复的声明. if not gatedCE in gatedce_list: gatedce_list.append(gatedCE) signal_decl_list.append(new_ce_signal) #-------------------------------------------------------------------------- #扫描链顺序的确定,在结尾处进行assign #-------------------------------------------------------------------------- assign_stm_list.append( cc.assign('assign', cc.signal(name = "scan_in1"), cc.signal(name = "scan_in")) ) for i in range(2,counter+1): tmp_assign = cc.assign('assign',cc.signal(name = "scan_in"+str(i) ), cc.signal( name = scan_out_list[i-2] )) assign_stm_list.append( tmp_assign )