赞
踩
vtags 是一款在gvim下实现类似verdi的信号追踪、显示拓扑等功能的插件。vtags插件完全使用python实现,目前实现功能包括信号追踪、宏定义追踪、显示模块拓扑、快速打开文件、保存和打开gvim快照、添加断点等功能。
支持功能和快捷键:
快捷键 | 功能 |
gi | 进入子模块 |
gu | 回到上层模块 |
<Space><Left> | 追信号源,或宏定义 |
<Space><Right> | 追信号目的 |
<Space><Down> | 回退 |
<Space><Up> | 向前 |
<Space> + v | 显示策略,和展开收回策略条目 |
<Space> + c | 添加记录点 |
<Space> + b | 添加基本模块 |
<Space> + d | 删除记录点或基本模块 |
<Space> +h | 固定当前窗口 |
<Space> | 快速访问 |
<Space> + s | 储存快照 |
gvim/vim | 加载快照 |
详细信息看《二:开始使用及支持功能和快捷键》
注意:
(1)在code目录下通过vtags生成vtags.db后,第一次打开verilog code时需要编译生成的database,所以第一打开code比较慢,之后打开code就会非常迅速。
1. 下载插件代码,解压并复制到自选的安装路径下。下面以安装目录为“~/vtags-1.20/为例”
代码下载地址: (1)https://pan.baidu.com/s/1kVfRXFx
(2)http://www.vim.org/scripts/script.php?script_id=5494
2. 在linux配置文件中添加别名。
~/.cshrc 中添加:alias vtags 'python ~/vtags-1.20/vtags.py'
或 ~/.bashrc 中添加:alias=vtags 'python ~/vtags-1.20/vtags.py'
source ~/.cshrc 或 source ~/.bashre 使设置生效。
3. 在vim配置文件中加入插件。
~/.vimrc 中添加: source ~/vtags-1.20/vtags_vim_api.vim
4. 本步骤可选,可以在vtags-1.20/vim_glb_config.py中设置插件的一些全局设置,
你也可以使用vtags时生成的局部配置文件vim_local_config.py中进行设置。
5. cd 到code目录使用命令:vtags, 在code目录下生成base文件 vtags.db, 用gvim打开代码就可以使用上面定义快捷键中功能。
注: 要求python版本2.7,详情请看《用户使用指南》。
- """
- https://my.oschina.net/u/2520885
- """
- #===============================================================================
- # Copyright (C) 2016 by Jun Cao
-
- # Permission is hereby granted, free of charge, to any person obtaining a copy
- # of this software and associated documentation files (the "Software"), to deal
- # in the Software without restriction, including without limitation the rights
- # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- # copies of the Software, and to permit persons to whom the Software is
- # furnished to do so, subject to the following conditions:
-
- # The above copyright notice and this permission notice shall be included in
- # all copies or substantial portions of the Software.
-
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- # THE SOFTWARE.
- #===============================================================================
-
- # left sidebar window width
- frame_window_width = 20
-
- # right bottom report window height
- report_window_height = 8
-
- # max work window vtags auto opened, not include use self opened window and holded window
- max_open_work_window_number = 1
-
- # when use <Space><left>/<Space><right> the max number of history trace valid
- max_roll_trace_depth = 1000
-
- # when <Space>c add check point, the max number of check point valid
- max_his_check_point_num = 10
-
- # when gen the vtags database, in all verilog modules when some module called more then threshold times,
- # set this module to be base module, then show topo will not list it's inst one by one
- base_module_threshold = 200
- # supported verilog postfix, we only add postfix in below to data base
- support_verilog_postfix = ['v']
- # open debug module or not, open debug module will print a lot debug log at vtags.db
- debug_mode = False
- # when trace source, match bigger than TraceSourceOptimizingThreshold, open opt func, mainly for signal like clk,rst ...
- trace_source_optimizing_threshold = 20
- # frame fold level space, use to set pre space num, if current level is 3 ,
- # and fold level space is ' ', then current line pre space is ' '*3 = ' '
- frame_fold_level_space = ' '
- # weather show report or not
- show_report = True
- # weather show sidebar or not
- show_sidebar = True
- """
- https://my.oschina.net/u/2520885
- """
- #===============================================================================
- # Copyright (C) 2016 by Jun Cao
- # Permission is hereby granted, free of charge, to any person obtaining a copy
- # of this software and associated documentation files (the "Software"), to deal
- # in the Software without restriction, including without limitation the rights
- # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- # copies of the Software, and to permit persons to whom the Software is
- # furnished to do so, subject to the following conditions:
- # The above copyright notice and this permission notice shall be included in
- # all copies or substantial portions of the Software.
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- # THE SOFTWARE.
- #===============================================================================
- __version__ = "1.20"
- __project_url__ = "https://my.oschina.net/u/2520885"
- import os
- import sys
- import re
- import pickle
- #print help
- help = ''
- try:
- help = sys.argv[1]
- except:
- pass
- if help in ['-h','-help']:
- print("(1) generate vtags at code dir, use command \"vtags\" ;" )
- print("(2) config vtags vim at vtags gen dir \"/vtags.db/vim_local_config.py\"," )
- print(" config items and detail look vim_local_config.py notes;" )
- print("(3) support action in vim window:" )
- print(" 1) gi : if cursor on module call, go in submodule;" )
- print(" 2) gu : if cur module called before, go upper module;" )
- print(" 3) <Space><Left> : trace cursor word signal source;" )
- print(" 4) <Space><Right> : trace cursor word signal dest;" )
- print(" 5) <Space><Down> : roll back;" )
- print(" 6) <Space><Up> : go forward;" )
- print(" 7) <Space>v : show current module topo " )
- print(" or fold/unfold sidebar items;" )
- print(" 8) <Space>c : add current cursor as checkpoint, can go back directly;" )
- print(" 9) <Space>b : add current cursor module as basemodule, not show in topo;" )
- print(" 10) <Space> : in sidebar or report win, just go cursor line link;" )
- print(" 11) <Space>h : hold cursor win, will not auto close it;" )
- print(" 12) <Space>d : in sidebar, delete valid items(base_module, checkpoint...);" )
- print(" 13) <Space>s : save current vim snapshort," )
- print(" use \"gvim/vim\" without input file to reload snapshort;" )
- exit()
- def cur_file_dir():
- path = sys.path[0]
- if os.path.isdir(path):
- return path
- elif os.path.isfile(path):
- return os.path.dirname(path)
- vtags_install_path = cur_file_dir()
- sys.path.insert(0,vtags_install_path)
- sed_vtags_install_path = re.sub('/','\/',vtags_install_path)
- os.system('sed -ig \'s/vtags_install_path =.*/vtags_install_path = "%s"/g\' %s/vtags_vim_api.vim' %(sed_vtags_install_path, vtags_install_path) )
- os.system('sed -ig \'s/let is_vtags_installed =.*/let is_vtags_installed = 1/g\' %s/vtags_vim_api.vim' %(vtags_install_path) )
- vtags_folder_path = os.getcwd() + '/vtags.db'
- os.system('mkdir -p %s'%(vtags_folder_path))
- if os.path.isfile(vtags_folder_path + '/vtag_gen_log.txt'):
- os.system('rm -rf '+vtags_folder_path+'/vtag_gen_log.txt')
- import Lib.GLB as GLB
- G = GLB.G
- GLB.vtags_run_log_path[0] = vtags_folder_path + '/vtags_run.log'
- import Lib.Code as Code
- import Lib.View as View
- from Lib.Base import *
- # filelist:
- # use "//" as note sign
- # support dir_path and file path mix
- def get_all_verilog_files_from_filelist(filelist_path):
- verilog_file_paths = []
- # get ~ path
- home_path = os.popen('echo ~').readlines()[0].rstrip('\n').rstrip('/')
- for l in open(filelist_path,'r').readlines():
- l = l.strip('\n')
- l = re.sub('//.*','',l)
- l = re.sub('^~', home_path, l)
- if re.match('\s*$',l):
- continue
- path = l
- if os.path.isdir(path):
- c_files_path = os.popen('find ' + dir_path + ' -type f 2>/dev/null').readlines()
- c_files_path = [ d_l.rstrip('\n') for d_l in c_files_path ]
- for c_f in c_files_path:
- if get_file_path_postfix(c_f) not in G['SupportVerilogPostfix']:
- continue
- verilog_file_paths.append(c_f)
- if os.path.isfile(path):
- if get_file_path_postfix(path) not in G['SupportVerilogPostfix']:
- continue
- verilog_file_paths.append(path)
- return verilog_file_paths
- # get all verilog files inf and merge
- # modules_inf = { module_name: module_inf }
- # defines_inf = { macro_name : [ define_inf ] }
- # files_inf = { file_name : file_inf }
- # module_inf = { 'module_name' : module_name
- # ,'file_path' : f
- # ,'line_range_in_file' : (module_start_line_num, module_end_line_num)
- # ,'sub_modules' : sub_modules }
- # define_inf = { "name" : xxx
- # ,"path" : f
- # ,"pos" : (line_num, colum_num) # name first char pos
- # ,'code_line' : `define xxx .... }
- # file_inf = { 'glb_defines' : [ define_inf ]
- # ,'module_infs' : [ module_inf ]
- # ,'module_calls' : [ call_sub_inf ]
- # ,'file_edit_inf' : { 'create_time': ..., 'last_modify_time': ...}
- # call_sub_inf = { 'inst_name' : inst_name
- # ,'module_name' : modu_name
- # ,'match_range' : match_range }
- def get_verilog_files_code_inf(paths):
- # step 1/2 get all module/define inf
- all_file_module_inf = {}
- all_file_define_inf = {}
- all_module_name = set()
- print('step 1/2:')
- for i,f in enumerate(paths):
- show_progress_bar( i, len(paths))
- PrintDebug(f)
- # gen cur module and define inf
- cur_file_module_inf = get_single_verilog_file_module_inf(f)
- cur_file_define_inf = get_single_verilog_file_define_inf(f)
- # add to result
- all_file_module_inf[f] = cur_file_module_inf
- all_file_define_inf[f] = cur_file_define_inf
- all_module_name = all_module_name | set([ mi['module_name'] for mi in cur_file_module_inf])
- print('')
- # step 2/2 get all file sub call inf
- all_file_subcall_inf = {}
- patten = get_submodule_match_patten(all_module_name)
- print('step 2/2:')
- for i,f in enumerate(paths):
- PrintDebug(f)
- show_progress_bar( i, len(paths))
- all_file_subcall_inf[f] = get_single_verilog_file_subcall_inf(f, patten, all_module_name)
- print('')
- # merge to all_file_inf
- all_file_inf = {}
- for i,f in enumerate(paths):
- add_single_verilog_file_submodule_inf_to_module_inf( all_file_module_inf[f], all_file_subcall_inf[f] )
- all_file_inf[f] = {
- 'glb_defines' : all_file_define_inf[f]
- ,'module_infs' : all_file_module_inf[f]
- ,'module_calls' : all_file_subcall_inf[f]
- ,'file_edit_inf' : { 'create_time': os.path.getctime(f), 'last_modify_time': os.path.getmtime(f)}
- }
- modules_inf , global_defines_inf = gen_modules_and_defines_inf(all_file_inf)
- return {
- 'files_inf' : all_file_inf
- ,'modules_inf' : modules_inf
- ,'defines_inf' : global_defines_inf
- }
- #------------------------function for get module inf--------------------
- filelist_path = ''
- verilog_file_paths = []
- if filelist_path:
- verilog_file_paths = get_all_verilog_files_from_filelist(filelist_path)
- else:
- c_dir_path = os.getcwd()
- c_dir_files_path = os.popen('find ' + c_dir_path + ' -type f 2>/dev/null').readlines()
- c_dir_files_path = [ d_l.rstrip('\n') for d_l in c_dir_files_path ]
- for c_f in c_dir_files_path:
- if get_file_path_postfix(c_f) not in G['SupportVerilogPostfix']:
- continue
- verilog_file_paths.append(c_f)
- # get all code inf
- verilog_code_inf = get_verilog_files_code_inf(verilog_file_paths)
- modules_inf = verilog_code_inf['modules_inf']
- files_inf = verilog_code_inf['files_inf' ]
- defines_inf = verilog_code_inf['defines_inf']
- # set base module
- base_modules = set()
- base_threshold = G['BaseModuleInf']['BaseModuleThreshold']
- module_inst_num = {}
- for m in modules_inf:
- for sm in modules_inf[m]['sub_modules']:
- module_name = sm['module_name']
- module_inst_num.setdefault(module_name,0)
- module_inst_num[module_name] += 1
- for m in module_inst_num:
- if module_inst_num[m] >= base_threshold:
- base_modules.add(m)
- # change vim HDLTags path
- fp = open(vtags_folder_path + '/files_inf.py','w')
- fp.write('FileInf = %s \n'%(files_inf.__str__()))
- fp.write('HDLTagsActive = True \n')
- fp.close()
- if not os.path.isfile(vtags_folder_path + '/vim_local_config.py'):
- os.system('cp %s/vim_glb_config.py %s/vim_local_config.py'%(vtags_install_path, vtags_folder_path))
- if not os.path.isfile(vtags_folder_path+'/base_modules.pkl'):
- output = open(vtags_folder_path+'/base_modules.pkl','wb')
- pickle.dump(base_modules, output)
- output.close()
- """
- " https://my.oschina.net/u/2520885
- """
- "===============================================================================
- " Copyright (C) 2016 by Jun Cao
- " Permission is hereby granted, free of charge, to any person obtaining a copy
- " of this software and associated documentation files (the "Software"), to deal
- " in the Software without restriction, including without limitation the rights
- " to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- " copies of the Software, and to permit persons to whom the Software is
- " furnished to do so, subject to the following conditions:
- " The above copyright notice and this permission notice shall be included in
- " all copies or substantial portions of the Software.
- " THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- " IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- " FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- " AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- " LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- " OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- " THE SOFTWARE.
- "===============================================================================
- function! VimPythonExtend()
- python << EOF
- import os
- import sys
- vtags_install_path = "/mnt/hgfs/VMShare/my_tools/vtags-1.20"
- if os.path.isdir(vtags_install_path):
- sys.path.insert(0,vtags_install_path)
- from Lib.API import *
- EOF
- endfunction
- let is_vtags_installed = 1
- if is_vtags_installed == 1
- "vi_HDLTags_begin-----------------------------------
- call VimPythonExtend()
- map gi :py try_go_into_submodule() <CR>
- map gu :py try_go_upper_module() <CR>
- map <Space><Left> :py try_trace_signal_sources() <CR>
- map <Space><Right> :py try_trace_signal_destinations() <CR>
- map <Space><Down> :py try_roll_back() <CR>
- map <Space><Up> :py try_go_forward() <CR>
- map <Space>v :py try_show_frame() <CR>
- map <Space>c :py try_add_check_point() <CR>
- map <Space>b :py try_add_base_module() <CR>
- map <Space> :py try_space_operation() <CR>
- map <Space>h :py try_hold_current_win() <CR>
- map <Space>d :py try_del_operation() <CR>
- map <Space>s :py try_save_env_snapshort() <CR>
- "vi_HDLTags_end-------------------------------------
- endif
- """
- https://my.oschina.net/u/2520885
- """
- #===============================================================================
- # Copyright (C) 2016 by Jun Cao
- # Permission is hereby granted, free of charge, to any person obtaining a copy
- # of this software and associated documentation files (the "Software"), to deal
- # in the Software without restriction, including without limitation the rights
- # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- # copies of the Software, and to permit persons to whom the Software is
- # furnished to do so, subject to the following conditions:
- # The above copyright notice and this permission notice shall be included in
- # all copies or substantial portions of the Software.
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- # THE SOFTWARE.
- #===============================================================================
- import os
- import sys
- # import vim, when gen vtags it will no vim,so use try
- try:
- import vim
- except:
- pass
- # import normal lib
- import re
- import Lib.Code as Code
- import Lib.View as View
- PrintReport = View.PrintReport
- import Lib.GLB as GLB
- G = GLB.G
- from Lib.Base import *
- # init gen module_inf, and glb define
- if G['HDLTagsActive']:
- G['ModuleInf'], G['CodeDefineInf'] = gen_modules_and_defines_inf(G['FileInf'])
- # open snapshort wins
- if G['HDLTagsActive'] and G['EnvSnapshortWinsInf']:
- OldOpenWinTrace = [p for p in G['WorkWin_Inf']['OpenWinTrace']]
- G['WorkWin_Inf']['OpenWinTrace'].insert(0,vim.current.buffer.name)
- for w_inf in G['EnvSnapshortWinsInf']:
- c_path = w_inf['path']
- c_cursor = w_inf['cursor']
- if os.path.isfile(c_path):
- View.Open(c_path)
- if c_path not in OldOpenWinTrace:
- if G['WorkWin_Inf']['OpenWinTrace'] and G['WorkWin_Inf']['OpenWinTrace'][-1] == c_path:
- del G['WorkWin_Inf']['OpenWinTrace'][-1]
- else:
- PrintDebug('Warning: reload file not exit ! file: %s'%(c_path))
- for w_inf in G['EnvSnapshortWinsInf']:
- c_size = w_inf['size']
- c_path = w_inf['path']
- if os.path.isfile(c_path):
- View.Open(c_path)
- vim.current.window.width = c_size[0]
- vim.current.window.height = c_size[1]
- # because base module may be changed so refresh topo and show base
- if G['Frame_Inf']['Frame_Path'] in [ w.buffer.name for w in vim.windows]:
- View.refresh_topo()
- View.show_base_module()
- PrintReport('reload snapshort finish !')
- elif G['HDLTagsActive']:
- # treat the first win as work win , if cur win is hdl code, and add first trace point
- first_cursor_inf = View.get_cur_cursor_inf()
- if first_cursor_inf['hdl_type'] == 'verilog':
- G['WorkWin_Inf']['OpenWinTrace'].append(first_cursor_inf['file_path'])
- View.add_trace_point()
- PrintDebug('Point: initial new env finish !')
- # shortcut key: gi
- def go_into_submodule():
- cursor_inf = View.get_cur_cursor_inf()
- cur_module_inf = cursor_inf['cur_module_inf']
- if not cur_module_inf:
- PrintReport('Warning: cur cursor not in a valid module, no submodule call !')
- return
- call_module_name = cur_module_inf['module_name']
- sub_call_inf = Code.get_module_call_sub_module_io_inf(cursor_inf['line'], cursor_inf['pos'], cursor_inf['file_path'])
- if not sub_call_inf:
- PrintReport('Warning: cur cursor not on recgnized subcall !')
- return
- sub_module_name = sub_call_inf['sub_module_name']
- sub_module_inf = get_module_inf(sub_module_name)
- if not sub_module_inf:
- PrintReport('Warning: sub module %s no module inf in database !'%(sub_module_name))
- return
- sub_signal_name = sub_call_inf['sub_io_name']
- sub_match_pos = []
- if sub_signal_name:
- sub_match_pos = sub_call_inf['sub_match_pos']
- else:
- sub_signal_name = sub_module_name
- sub_match_pos = sub_module_inf['module_pos']
- call_sub_inf = sub_call_inf['call_sub_inf'] # GLB call sub inf(atom)
- sub_module_path = sub_module_inf['file_path']
- set_module_last_call_inf(sub_module_name, call_module_name, call_sub_inf['inst_name'])
- View.add_trace_point()
- View.go_win( sub_module_path, sub_match_pos, sub_signal_name)
- def try_go_into_submodule():
- if not G['HDLTagsActive']: return
- if G['Debug']:
- go_into_submodule()
- else:
- try: go_into_submodule()
- except: pass
- # shortcut key: gu
- def go_upper_module():
- cursor_inf = View.get_cur_cursor_inf()
- cur_module_inf = cursor_inf['cur_module_inf']
- if not cur_module_inf:
- PrintReport('Warning: cur line not in a valid verilog module, or current module not in database !')
- return
- cur_last_call_inf = get_module_last_call_inf(cur_module_inf['module_name'])
- if not cur_last_call_inf:
- PrintReport('Warning: cur module %s not called by upper module before !'%(cur_module_inf['module_name']))
- return
- upper_module_name = cur_last_call_inf['upper_module_name']
- upper_call_sub_inf = cur_last_call_inf['upper_call_inf']
- upper_match_pos = upper_call_sub_inf['match_pos']
- upper_inst_name = upper_call_sub_inf['inst_name']
- View.add_trace_point()
- View.go_win( upper_module_name, upper_match_pos, upper_inst_name)
- def try_go_upper_module():
- if not G['HDLTagsActive']: return
- if G['Debug']:
- go_upper_module()
- else:
- try: go_upper_module()
- except: pass
- # shortcut key: <Space><Left>
- def trace_signal_sources():
- if G['IgnoreNextSpaceOp']:
- G['IgnoreNextSpaceOp'] = False
- PrintDebug('Care: not do this trace source op ,bucause <space> is come from unknow reason !')
- return
- cursor_inf = View.get_cur_cursor_inf()
- trace_signal_name = cursor_inf['word']
- if not trace_signal_name:
- PrintReport("Warning: Current cursor not on signal name, can not trace source !")
- return
- # case0: if cur cursor on a macro, go macro define
- if Code.trace_glb_define_signal('source', cursor_inf): return
- # case1: if cur cursor on io signal, need cross to upper module
- if Code.trace_io_signal('source', cursor_inf): return
- # case2: if cur cursor on module call io line go to submodule io
- if Code.trace_module_call_io_signal('source', cursor_inf): return
- # case3: trace signal same as pre trace signal, just show next result
- if (G['TraceInf']['LastTraceSource']['Path'] == cursor_inf['file_path']) and (G['TraceInf']['LastTraceSource']['SignalName'] == trace_signal_name) :
- View.show_next_trace_result('source')
- return
- # case4: trace a new normal(not io, sub call io) signal
- if Code.trace_normal_signal('source', cursor_inf): return
- def try_trace_signal_sources():
- if not G['HDLTagsActive']: return
- if G['Debug']:
- trace_signal_sources()
- else:
- try: trace_signal_sources()
- except: pass
- # shortcut key: <Space><Right>
- def trace_signal_destinations():
- if G['IgnoreNextSpaceOp']:
- G['IgnoreNextSpaceOp'] = False
- PrintDebug('Care: not do this trace source op ,bucause <space> is come from unknow reason !')
- return
- cursor_inf = View.get_cur_cursor_inf()
- trace_signal_name = cursor_inf['word']
- if not trace_signal_name:
- PrintReport("Warning: Current cursor not on signal name, can not trace dest!")
- return
- # case0: if cur cursor on io signal, need cross to upper module
- if Code.trace_io_signal('dest', cursor_inf): return
- # case1: if cur cursor on module call io line go to submodule io
- if Code.trace_module_call_io_signal('dest', cursor_inf): return
- # case2: trace signal same as pre trace signal, just show next result
- if (G['TraceInf']['LastTraceDest']['Path'] == cursor_inf['file_path']) and (G['TraceInf']['LastTraceDest']['SignalName'] == trace_signal_name) :
- View.show_next_trace_result('dest')
- return
- # case3: if cur cursor on a macro, go macro define
- if Code.trace_glb_define_signal('dest', cursor_inf): return
- # case4: trace a new normal(not io, sub call io) signal
- Code.trace_normal_signal('dest', cursor_inf)
- def try_trace_signal_destinations():
- if not G['HDLTagsActive']: return
- if G['Debug']:
- trace_signal_destinations()
- else:
- try: trace_signal_destinations()
- except: pass
- # shortcut key: <Space><Down>
- def roll_back():
- if G['IgnoreNextSpaceOp']:
- G['IgnoreNextSpaceOp'] = False
- PrintDebug('Care: not do this trace source op ,bucause <space> is come from unknow reason !')
- return
- cur_nonius = G['OpTraceInf']['Nonius'] - 1
- TracePoints = G['OpTraceInf']['TracePoints']
- # if reach to the oldest trace point just return
- if cur_nonius < 0:
- PrintReport("Warning: roll backed to the oldest trace point now !")
- return
- # go to the trace point
- cur_point = TracePoints[cur_nonius]
- G['OpTraceInf']['Nonius'] = cur_nonius
- View.go_win( cur_point['path'], cur_point['pos'], cur_point['key'])
- return
- def try_roll_back():
- if not G['HDLTagsActive']: return
- if G['Debug']:
- roll_back()
- else:
- try: roll_back()
- except: pass
- # shortcut key: <Space><Up>
- def go_forward():
- if G['IgnoreNextSpaceOp']:
- G['IgnoreNextSpaceOp'] = False
- PrintDebug('Care: not do this trace source op ,bucause <space> is come from unknow reason !')
- return
- cur_nonius = G['OpTraceInf']['Nonius'] + 1
- TracePoints = G['OpTraceInf']['TracePoints']
- if cur_nonius >= len(TracePoints):
- PrintReport("Warning: go forward to the newest trace point now !")
- return
- cur_point = TracePoints[cur_nonius]
- G['OpTraceInf']['Nonius'] = cur_nonius
- View.go_win( cur_point['path'], cur_point['pos'], cur_point['key'])
- return
- def try_go_forward():
- if not G['HDLTagsActive']: return
- if G['Debug']:
- go_forward()
- else:
- try: go_forward()
- except: pass
- # shortcut key: <space>
- def space_operation():
- if G['IgnoreNextSpaceOp']:
- G['IgnoreNextSpaceOp'] = False
- PrintDebug('Care: not do this trace source op ,bucause <space> is come from unknow reason !')
- return
- cursor_inf = View.get_cur_cursor_inf()
- # if cur in Frame or Report, show file link files
- if cursor_inf['file_path'] in [ G['Frame_Inf']['Frame_Path'], G['Report_Inf']['Report_Path'] ]:
- cur_frame_link = G['VimBufferLineFileLink'][cursor_inf['file_path']][cursor_inf['line_num']]
- View.add_trace_point()
- if cur_frame_link and cur_frame_link['path']:
- View.go_win( cur_frame_link['path'], cur_frame_link['pos'], cur_frame_link['key'])
- View.add_trace_point()
- else:
- PrintReport('Warning: No file link in current line ! ')
- else:
- PrintReport('Warning: No space operation in current file ! ')
- def try_space_operation():
- if not G['HDLTagsActive']: return
- if G['Debug']:
- space_operation()
- else:
- try: space_operation()
- except: pass
- # shortcut key: <s-t>
- def show_frame():
- G["IgnoreNextSpaceOp"] = G['FixExtraSpace']
- if cur_in_frame():
- cursor_line = vim.current.window.cursor[0] - 1
- View.frame_line_fold_operation(cursor_line)
- else:
- View.show_topo()
- View.show_check_point(False)
- View.show_base_module(False)
- return
- def try_show_frame():
- if not G['HDLTagsActive']: return
- if G['Debug']:
- show_frame()
- else:
- try: show_frame()
- except: pass
- return
- # shortcut key: <Space>h
- def hold_current_win():
- cur_path = vim.current.buffer.name
- # just del current win frome work win, then will not auto close current win
- for i,path in enumerate(G['WorkWin_Inf']['OpenWinTrace']):
- if cur_path == path:
- del G['WorkWin_Inf']['OpenWinTrace'][i]
- break
- def try_hold_current_win():
- if not G['HDLTagsActive']: return
- if G['Debug']:
- hold_current_win()
- else:
- try: hold_current_win()
- except: pass
- # shortcut key: <Space>c
- def add_check_point():
- G["IgnoreNextSpaceOp"] = G['FixExtraSpace']
- cursor_inf = View.get_cur_cursor_inf()
- level = G['CheckPointInf']['TopFoldLevel'] + 1
- key = G['Frame_Inf']['FoldLevelSpace']*level + cursor_inf['word']
- link = {
- 'type' : 'check_point'
- ,'key' : cursor_inf['word']
- ,'pos' : cursor_inf['pos']
- ,'path' : cursor_inf['file_path']
- ,'fold_inf' : { 'fold_status': 'fix', 'level': level }
- }
- G['CheckPointInf']['CheckPoints'].insert(0, {'key': key, 'link': link })
- if len(G['CheckPointInf']['CheckPoints']) > G['CheckPointInf']['MaxNum']:
- del G['CheckPointInf']['CheckPoints'][-1]
- View.show_check_point()
- def try_add_check_point():
- if not G['HDLTagsActive']: return
- if G['Debug']:
- add_check_point()
- else:
- try: add_check_point()
- except: pass
- # shortcut key: <Space>b
- def add_base_module():
- G["IgnoreNextSpaceOp"] = G['FixExtraSpace']
- cursor_inf = View.get_cur_cursor_inf()
- cursor_module = cursor_inf['word']
- if not cursor_module:
- PrintReport('Warning: cursor not on a valid word ! ')
- return
- if not get_module_inf(cursor_module):
- PrintReport('Warning: cursor words: %s not a recgnized module name ! will no file link ! '%(cursor_module))
- if cursor_module in G['BaseModuleInf']['BaseModules']:
- PrintReport('Care: module %s is already base module ! '%(cursor_module))
- return
- G['BaseModuleInf']['BaseModules'].add(cursor_module)
- update_base_module_pickle()
- View.show_base_module()
- View.refresh_topo()
- def try_add_base_module():
- if not G['HDLTagsActive']: return
- if G['Debug']:
- add_base_module()
- else:
- try: add_base_module()
- except: pass
- #------------------------------
- # shortcut key: <Space>d
- def del_operation():
- if not cur_in_frame():
- PrintReport('Warning: Cur file no del function ! ')
- return
- cur_path = vim.current.buffer.name
- cur_line_num = vim.current.window.cursor[0] - 1
- cur_file_link = G['VimBufferLineFileLink'][cur_path][cur_line_num]
- if not cur_file_link:
- PrintReport('Warning: Cur line no del function ! ')
- return
- # delete a check point, if link has path means a valid link
- if (cur_file_link['type'] == 'check_point') and (cur_file_link['fold_inf']['level'] > G['CheckPointInf']['TopFoldLevel']):
- G["IgnoreNextSpaceOp"] = G['FixExtraSpace']
- check_point_begin_line_num = get_frame_range_inf()['check_point_range'][0]
- del_index = cur_line_num - check_point_begin_line_num - 1
- del G['CheckPointInf']['CheckPoints'][ del_index ]
- View.show_check_point()
- return
- # del a base module
- if (cur_file_link['type'] == 'base_module') and (cur_file_link['fold_inf']['level'] > G['BaseModuleInf']['TopFoldLevel']):
- G["IgnoreNextSpaceOp"] = G['FixExtraSpace']
- G['BaseModuleInf']['BaseModules'].remove(cur_file_link['key'])
- update_base_module_pickle()
- View.show_base_module()
- View.refresh_topo()
- return
- PrintReport('Warning: Cur line no del function ! ')
- def try_del_operation():
- if not G['HDLTagsActive']: return
- if G['Debug']:
- del_operation()
- else:
- try: del_operation()
- except: pass
- #----------------------------------------
- # shortcut key: <Space>s
- def try_save_env_snapshort():
- if not G['HDLTagsActive']: return
- if G['Debug']:
- if G['SaveEnvSnapshort_F']():
- PrintReport('save env snapshort success !')
- else:
- try:
- if G['SaveEnvSnapshort_F']():
- PrintReport('save env snapshort success !')
- except: pass
- """
- https://my.oschina.net/u/2520885
- """
- #===============================================================================
- # Copyright (C) 2016 by Jun Cao
- # Permission is hereby granted, free of charge, to any person obtaining a copy
- # of this software and associated documentation files (the "Software"), to deal
- # in the Software without restriction, including without limitation the rights
- # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- # copies of the Software, and to permit persons to whom the Software is
- # furnished to do so, subject to the following conditions:
- # The above copyright notice and this permission notice shall be included in
- # all copies or substantial portions of the Software.
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- # THE SOFTWARE.
- #===============================================================================
- import sys
- try:
- import vim
- except:
- pass
- import os
- import re
- import pickle
- import GLB
- G = GLB.G
- # function to print debug
- PrintDebug = G['PrintDebug_F']
- def get_valid_code( str ):
- str = re.sub('(^\s*)|(\s*$)', '' ,str)
- str = re.sub('//.*', '' ,str)
- str = re.sub('^`.*', '' ,str) # bug ^\s*`.*
- return str
- def get_valid_code_leave_head_space( str ):
- str = re.sub('\s*$', '' ,str)
- str = re.sub('//.*', '' ,str)
- str = re.sub('^`.*', '' ,str)
- return str
- def cur_in_frame():
- return vim.current.buffer.name == G['Frame_Inf']['Frame_Path']
- def cur_in_report():
- return vim.current.buffer.name == G['Report_Inf']['Report_Path']
- def get_path_for_name(path_or_name):
- if path_or_name == 'Frame':
- return G["Frame_Inf"]["Frame_Path"]
- if path_or_name == 'Report':
- return G["Report_Inf"]["Report_Path"]
- may_module_inf = get_module_inf(path_or_name)
- if may_module_inf:
- return may_module_inf['file_path']
- return path_or_name
- def get_file_name_from_path(path):
- return re.sub('.*/','',path)
- def get_full_word(line, y):
- pre_part = ( re.match('^(?P<pre>\w*)',(line[:y])[::-1]).group('pre') )[::-1]
- post_part = re.match('^(?P<post>\w*)', line[y:]).group('post')
- return pre_part + post_part
- def get_file_path_postfix(file_path):
- if type(file_path) != str:
- return
- split_by_dot = file_path.split('.')
- if len(split_by_dot) < 2 : # which means file_path has no postfix
- return ''
- # post_fix = split_by_dot[-1].lower() # postfix don't care case
- post_fix = split_by_dot[-1] # postfix care case
- return post_fix
-
- def get_file_hdl_type(file_path):
- postfix = get_file_path_postfix(file_path)
- if postfix in G['SupportVHDLPostfix']:
- return 'vhdl'
- elif postfix in G['SupportVerilogPostfix']:
- return 'verilog'
- else:
- return ''
-
- #------------------------------------------------------------
- def get_vhdl_full_line(codes, start_pos, direction):
- pass
-
- def get_verilog_pre_full_line(codes, start_pos):
- pre_full_line = ''
- start_x, start_y = start_pos
- start_line = codes[start_x][:start_y+1]
- start_line = start_line.strip('\n')
- start_line = re.sub('//.*','',start_line)
- colon_y = start_line.rfind(';')
- if colon_y != -1:
- pre_full_line = start_line[colon_y+1:]
- else:
- pre_full_line = start_line
- for i in range(start_x-1,-1,-1):
- t_line = codes[i].strip('\n')
- t_line = re.sub('//.*', '', t_line)
- t_colon_y = t_line.rfind(';')
- if t_colon_y != -1:
- pre_full_line = t_line[t_colon_y+1:] + ' ' + pre_full_line
- break
- else:
- pre_full_line = t_line + ' ' +pre_full_line
- return pre_full_line
-
- def get_verilog_post_full_line(codes, start_pos):
- post_full_line = ''
- start_x, start_y = start_pos
- start_line = codes[start_x][start_y:]
- start_line = start_line.strip('\n')
- start_line = re.sub('//.*','',start_line)
- colon_y = start_line.find(';')
- if colon_y != -1:
- pre_full_line = start_line[:colon_y+1]
- else:
- pre_full_line = start_line
- for i in range(start_x+1,len(codes)):
- t_line = codes[i].strip('\n')
- t_line = re.sub('//.*', '', t_line)
- t_colon_y = t_line.find(';')
- if t_colon_y != -1:
- pre_full_line = pre_full_line + ' ' + t_line[: t_colon_y+1]
- break
- else:
- pre_full_line = pre_full_line + ' ' + t_line
- return pre_full_line
-
- def get_verilog_full_line(codes, start_pos, direction):
- if direction == -1: # 0 <- x
- return get_verilog_pre_full_line(codes, start_pos)
- elif direction == 1: # x -> n
- return get_verilog_post_full_line(codes, start_pos)
- elif direction == 0: # 0 <- x -> n
- return get_verilog_pre_full_line(codes, start_pos) + get_verilog_post_full_line(codes, start_pos)[1:] # [1:] because start char at both part
- else:
- return ''
-
- def get_full_line( codes, hdl_type, start_pos, direction = 0):
- if hdl_type == 'vhdl':
- return get_vhdl_full_line(codes, start_pos, direction)
- elif hdl_type == 'verilog':
- return get_verilog_full_line(codes, start_pos, direction)
- else:
- return ''
-
- # --------------------------------------------------------
- # ok
- def recgnize_io_signal_line(line, line_num):
- # pre check if is not io
- if line.find('input') == -1 and line.find('output') == -1:
- return False
- line = line.strip('\n')
- line = re.sub('//.*','',line) # del notes
- # raw re match
- re_match = re.match('\s*(input|output)\W',line)
- if not re_match:
- re_match = re.match('(?P<prefix>.*\(\s*)(?P<real_io>(input|output)\W.*)',line)
- if re_match:
- prefix = re_match.group('prefix')
- real_io_line = re_match.group('real_io')
- line = ' '*(len(prefix)) + real_io_line
- else:
- return False
- # match used egrep io line decode function
- egrep_io_line = str(line_num)+':'+line
- io_inf = decode_egreped_verilog_io_line(egrep_io_line)['io_infs']
- return io_inf
- # "name" : name
- # , "io_type" : io_type
- # , "left" : left_index
- # , "right" : right_index
- # , "size" : size
- # , 'line_num' : line_num
- # , 'name_pos' : (line_num, colm_num)
- # , 'code_line' : code_line
- # , 'signal_type' : signal_type }
-
- #-----------------------------------------------------------
- # ok
- def search_verilog_code_use_grep(key, path, row_range = ()):
- search_result = []
- if not path:
- path = vim.current.buffer.name
- match_lines = os.popen('egrep -n -h \'(^|\W)%s(\W|$)\' %s'%(key, path)).readlines()
- for l in match_lines:
- l = l.strip('\n')
- split0 = l.split(':')
- line_num = int(split0[0]) - 1
- code_line = ':'.join(split0[1:])
- if row_range and ( line_num not in range(row_range[0], row_range[1]+1 ) ):
- continue
- # del note see if has key
- s0 = re.search('(?P<pre>^|\W)%s(\W|$)'%(key), re.sub('//.*','',code_line) )
- if s0:
- colum_num = s0.span()[0] + len(s0.group('pre'))
- match_pos = (line_num, colum_num)
- line = code_line
- search_result.append( (match_pos, line) )
- return search_result
-
-
- #----------------------------------------------------------
- def get_fram_topo_sub_inf(topo_module, cur_level):
- sub_level = cur_level + 1
- topo_prefix = G['Frame_Inf']['FoldLevelSpace'] * sub_level
- topo_datas = []
- topo_links = []
- sub_func_modules, sub_base_modules = get_sub_func_base_module(topo_module)
- # first deal sub func module, show "inst(module)"
- sub_func_modules_inst_names = list(sub_func_modules)
- sub_func_modules_inst_names.sort()
- for c_sub_inst_name in sub_func_modules_inst_names:
- c_call_sub_inf = sub_func_modules[c_sub_inst_name]
- c_sub_module_name = c_call_sub_inf['module_name']
- # gen show data
- c_str = '%s%s(%s)'%(topo_prefix, c_sub_inst_name, c_sub_module_name)
- topo_datas.append(c_str)
- # gen link
- c_topo_link = {
- 'type' : 'topo'
- ,'topo_inst_name' : ''
- ,'key' : ''
- ,'pos' : ''
- ,'path' : ''
- ,'fold_inf' : {'fold_status':'off', 'level': sub_level}
- }
- c_sub_module_inf = get_module_inf(c_sub_module_name)
- if c_sub_module_inf:
- c_topo_link['topo_inst_name'] = c_sub_inst_name
- c_topo_link['key' ] = c_sub_module_name
- c_topo_link['pos' ] = c_sub_module_inf['module_pos']
- c_topo_link['path' ] = c_sub_module_inf['file_path']
- # show cur module, then all submodule, last call set to cur module
- set_module_last_call_inf(c_sub_module_name, topo_module, c_call_sub_inf['inst_name'])
- topo_links.append(c_topo_link)
- sub_base_modules_names = list(sub_base_modules)
- sub_base_modules_names.sort()
- if len(sub_base_modules_names) > 0:
- # deal base , show "module(n)"
- # add one to sep func and base
- topo_datas.append(topo_prefix+'------')
- c_topo_link = {
- 'type' : 'topo'
- ,'topo_inst_name' : ''
- ,'key' : ''
- ,'pos' : ()
- ,'path' : ''
- ,'fold_inf' : {'fold_status':'on', 'level': sub_level}
- }
- topo_links.append(c_topo_link)
- for c_sub_module_name in sub_base_modules_names:
- # deal data
- c_sub_inst_n = len(sub_base_modules[c_sub_module_name])
- c_str = '%s%s(%d)'%(topo_prefix,c_sub_module_name,c_sub_inst_n)
- topo_datas.append(c_str)
- # deal link
- c_topo_link = {
- 'type' : 'topo'
- ,'topo_inst_name' : ''
- ,'key' : ''
- ,'pos' : ''
- ,'path' : ''
- ,'fold_inf' : {'fold_status':'off', 'level': sub_level}
- }
- c_sub_module_inf = get_module_inf(c_sub_module_name)
- if c_sub_module_inf:
- c_topo_link['key' ] = c_sub_module_name
- c_topo_link['pos' ] = c_sub_module_inf['module_pos']
- c_topo_link['path'] = c_sub_module_inf['file_path']
- topo_links.append(c_topo_link)
- return topo_datas, topo_links
-
- def get_fram_check_point_inf():
- datas = []
- links = []
- for cp in G['CheckPointInf']['CheckPoints']:
- datas.append(cp['key'])
- links.append(cp['link'])
- return datas, links
-
- def get_fram_base_module_inf():
- datas = []
- links = []
- base_module_level = G['BaseModuleInf']['TopFoldLevel'] + 1
- base_module_space = G['Frame_Inf']['FoldLevelSpace'] * base_module_level
- base_modules = list(G['BaseModuleInf']['BaseModules'])
- base_modules.sort()
- for bm in base_modules:
- key = base_module_space + bm
- link = {
- 'type' : 'base_module'
- ,'key' : bm
- ,'pos' : ''
- ,'path' : ''
- ,'fold_inf' : { 'fold_status': 'fix', 'level': base_module_level }
- }
- bm_module_inf = get_module_inf(bm)
- if bm_module_inf:
- link['pos'] = bm_module_inf['module_pos']
- link['path'] = bm_module_inf['file_path']
- datas.append(key)
- links.append(link)
- return datas, links
-
- ###########################################################
- #----------------------------------------------------------
- def decode_egreped_verilog_io_line(o_io_line):
- # exp:
- # 365:output alu_frf_part_p0_w;
- # 366:output [127:0] alu_frf_data_p0_w;
- # 357:output [THR_WIDTH-1:0] alu_dst_cond_tid_w
- # 368:output reg alu_frf_part_p0_w;
- # 369:output wire [127:0] alu_frf_data_p0_w;
- # 370:output reg [THR_WIDTH-1:0] alu_dst_cond_tid_w
- # 388:input [width-1 : 0] A,B;
- # split by ":" | 388:input [width-1 : 0] A,B;
- # split0 | 0 ^ 1 ^ 2
- split0 = o_io_line.split(':')
- line_num = int(split0[0]) - 1 # -1 because egrep form 1, our line from 0
- code_line = ':'.join(split0[1:])
- # valid code line is code_line del note, and change all \s+ to ' '
- valid_code_line = re.sub('(//.*)|(^\s+)|(\s+$)','',code_line)
- valid_code_line = re.sub('\s+',' ',valid_code_line)
- valid_code_line = re.sub('\W*$', '',valid_code_line)# del end ";" or ","
- # io type is the first word in valid_code_line
- match_io_type = re.match('(?P<io_type>\w+)\s*(?P<other>.*)',valid_code_line)
- assert(match_io_type)
- io_type = match_io_type.group('io_type')
- other = match_io_type.group('other').strip(' ')
- # other: [width-1 : 0] A,B | wire [127:0] alu_frf_data_p0_w | alu_frf_part_p0_w
- # get name, name is the last word or words sep by ',' ; reverse it and reverse back
- # exp: A | A,B | A,B,C
- match_name = re.match('\s*(?P<r_names_str>\w+(\s*,\s*\w+)*)\s*(?P<r_other>.*)',other[::-1])
- assert(match_name),'%s | %s'%(other,code_line)
- other = (match_name.group('r_other')[::-1]).strip(' ')
- names_str = match_name.group('r_names_str')[::-1]
- names = re.sub('\s+','',names_str).split(',')
- names_pos = []
- if len(names) == 1:
- colum = re.search('\W%s(\W|$)'%(names[0]),code_line).span()[0] + 1
- names_pos = [ ( line_num, colum ) ]
- else:
- for n in names:
- colum = re.search('\W%s(\W|$)'%(n),code_line).span()[0] + 1
- names_pos.append( (line_num, colum) )
- # signal_type is the first word of other, maybe empty
- # case0 : empty
- # case1 : reg
- # case2 : reg [THR_WIDTH-1:0]
- # case3 : [127:0]
- signal_type = 'wire'
- if other:
- match_signal_type = re.match('\s*(?P<signal_type>\w*)\s*(?P<other>.*)',other)
- assert(match_signal_type)
- m_signal_type = match_signal_type.group('signal_type')
- if m_signal_type:
- signal_type = m_signal_type
- other = match_signal_type.group('other').strip(' ')
- # other is empty or [a : b]
- left_index = ''
- right_index = ''
- size = 1
- if other:
- assert(other[0] == '[' and other[-1] == ']'),'%s'%(other)
- indexs = other[1:-1].split(':')
- if len(indexs) == 2:
- left_index = indexs[0].strip(' ')
- right_index = indexs[1].strip(' ')
- try:
- left_index = int(left_index)
- right_index = int(left_index)
- size = right_index - left_index + 1
- except:
- size = other
- # may a line has mulity names
- io_infs = {}
- for i, name in enumerate(names):
- io_infs[name] = {
- "name" : name
- , "io_type" : io_type
- , "left" : left_index
- , "right" : right_index
- , "size" : size
- , 'line_num' : line_num
- , 'name_pos' : names_pos[i]
- , 'code_line' : code_line
- , 'signal_type' : signal_type
- }
- return {'io_infs':io_infs, 'name_list':names}
-
- #------------------------------------------------
- # for code in verilog modules, from pos to find next pair ")"
- # case 0:
- # if pos is "(" | ( A...B )
- # pos | ^
- # rest | parm_line= A...B, end_pos = B 's pos
- # case 1:
- # if pos not "("| ( A...B )
- # pos | ^
- # rest | parm_line= A...B, end_pos = B 's pos
- def get_str_to_next_right_bracket(module_lines, pos):
- assert(0),'not used not realized '
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- def get_str_to_pre_left_bracket(module_lines, pos):
- assert(0),'not used not realized '
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- #-------------------------------------------
- # for situation:
- # case0 : module_name inst_name (.a(A), .b(B), .c(C)) |
- # | ^ | input pos
- # | ^0 ^1 | module_range[0]
- # case1 : module_name #( .a(A), .b(B), .c(C) ) inst_name ( ... )
- # | ^ | input pos
- # | ^ | module_range[0]
- # case2 : module_name #( A, B, C ) inst_name ( .x(X), .y(Y) )
- # | ^ | input pos
- # | ^ | module_range[0]
- # case3 : module_name ... inst_name[a:b] ...
- # case4 : module_name ... inst_name[a:b] (A,B,C)
- def get_verilog_sub_module_inf_from_dot_line( pos, module_lines, module_start_line_num):
- dot_line = get_valid_code(module_lines[pos[0]])
- assert(dot_line[pos[1]] == '.')
- module_name = ''
- inst_name = ''
- match_range = []
- match_pos = ()
- # first deal pre dot line
- pre_line_end = False
- dot_pre_line = dot_line[:pos[1]+1] # module_name inst_name (.
- pre_next_line_num = pos[0] - 1
- search_case0 = ''
- search_case12 = ''
- while not pre_line_end:
- semicolon_y = dot_pre_line.find(';')
- if semicolon_y != -1:
- pre_line_end = True
- dot_pre_line = dot_pre_line[semicolon_y + 1:]
- search_case0 = re.search('(^|\W)(?P<m_name>\w+)\s+(?P<i_name>\w+(\s*\[[^\[\]]*\])?)\s*\(\s*\.$',dot_pre_line)
- if search_case0:
- module_name = search_case0.group('m_name')
- inst_name = search_case0.group('i_name')
- break
- search_case12 = re.search('(^|\W)(?P<m_name>\w+)\s*#\s*\(', dot_pre_line)
- if search_case12:
- module_name = search_case12.group('m_name')
- match_case2_inst_name = re.match('\.\s*\(\s*(?P<r_i_name>(\s*\][^\[\]]*\[\s*)?\w+)',dot_pre_line[::-1]) # inst_name ( .
- if match_case2_inst_name:
- inst_name = match_case2_inst_name.group('r_i_name')[::-1]
- break
- if pre_next_line_num >= 0:
- dot_pre_line = get_valid_code(module_lines[pre_next_line_num]) + ' ' + dot_pre_line
- pre_next_line_num -= 1
- else:
- pre_line_end = True
- # if not match anyone then unrecgize
- if not (search_case0 or search_case12):
- PrintDebug('Error: 0 cur dot match cannot recgnize ! line: %s , pos: %s'%(dot_line, pos.__str__()))
- return False
- # if no inst name need decode dot back line
- if not inst_name: # case1: module_name #( .a(A), .b(B), .c(C) ) inst_name ( ... )
- back_line_end = False
- dot_back_line = dot_line[pos[1]:] # .a(A), .b(B), .c(C))
- back_next_line_num = pos[0] + 1
- search_case1_inst_name = ''
- while not back_line_end:
- semicolon_y = dot_back_line.find(';')
- if semicolon_y != -1:
- back_line_end = True
- dot_back_line = dot_back_line[:semicolon_y]
- # inst_name ( .x
- search_case1_inst_name = re.search('\)\s*(?P<i_name>\w+(\s*\[[^\[\]]*\])?)\s*\(',dot_back_line)
- if search_case1_inst_name:
- inst_name = search_case1_inst_name.group('i_name')
- break
- if back_next_line_num < len(module_lines):
- dot_back_line = dot_back_line + ' ' +get_valid_code(module_lines[back_next_line_num])
- back_next_line_num += 1
- else:
- back_line_end = True
- if not inst_name:
- PrintDebug('Error: 1 cur dot match cannot recgnize inst name ! line: %s , pos: %s'%(dot_line, pos.__str__()))
- return False
- match_range = [ pre_next_line_num + 1 + module_start_line_num, -1 ]
- module_y = module_lines[pre_next_line_num + 1].find(module_name)
- assert(module_y != -1)
- match_pos = ( pre_next_line_num + 1 + module_start_line_num, module_y )
- return {
- 'inst_name' : inst_name
- ,'module_name' : module_name
- ,'match_range' : match_range
- ,'match_pos' : match_pos
- }
-
- # case 0: dff # (...) my_dff(a, b, c); in only one line
- def get_verilog_sub_module_inf_from_pound_line( pos, module_lines, module_start_line_num):
- pound_line = get_valid_code(module_lines[pos[0]])
- match_sub = re.match('\s*(?P<module_name>\w+)\s+#\s*\(.*\)\s*(?P<inst_name>\w+)\s*\(.*\)\s*;\s*', pound_line)
- if match_sub:
- return {
- 'inst_name' : match_sub.group('inst_name')
- ,'module_name' : match_sub.group('module_name')
- ,'match_range' : [ pos[0] + module_start_line_num, pos[0] + module_start_line_num ]
- ,'match_pos' : ( pos[0] + module_start_line_num, module_lines[pos[0]].find(match_sub.group('module_name')) )
- }
- return False
-
- # for current valid module lines
- # find each pair : (".xxx(...)" ";")
- # get the each pair result :{ 'inst_name' : inst_name
- # ,'module_name' : modu_name
- # ,'match_range' : match_range
- # ,'match_pos' : match_pos}
- # finial result is : [ pair_result0, pair_result1, ... ]
- def get_verilog_sub_module_inf(module_lines, module_start_line_num, gen_vtags_log_path = ''):
- sub_module_inf = []
- has_call_sub_not_end = False
- find_next = True
- for i ,l in enumerate(module_lines):
- if find_next:
- assert(not has_call_sub_not_end),'already start new search, should not has unfinish subcall'
- cur_sub_module_inf = {}
- cur_match_right_part = ''
- if l.find('.') != -1:
- l = get_valid_code(l)
- s0 = re.search('(^|\W)\.\w+\s*\(', l)
- if not s0:
- continue
- # no matter recgnize or not , must wait next ";", continue search
- find_next = False
- # get dot pos
- dot_colm = ''
- if l[0] is '.':
- dot_colm = 0
- else:
- dot_colm = s0.span()[0] + 1
- assert(dot_colm != '')
- cur_match_right_part = l[s0.span()[1]:]
- # get cur sub module inf
- cur_sub_module_inf = get_verilog_sub_module_inf_from_dot_line( (i, dot_colm), module_lines, module_start_line_num)
- elif l.find('#') != -1:
- l = get_valid_code(l)
- s1 = re.search('#\s*\(', l)
- if not s1:
- continue
- # no matter recgnize or not , must wait next ";", continue search
- find_next = False
- # get dot pos
- pound_colm = ''
- dot_colm = s1.span()[0]
- cur_match_right_part = l[s1.span()[1]:]
- # get cur sub module inf
- cur_sub_module_inf = get_verilog_sub_module_inf_from_pound_line( (i, pound_colm), module_lines, module_start_line_num)
- else:
- continue
- # find result in two way
- if cur_sub_module_inf:
- assert(not has_call_sub_not_end)
- sub_module_inf.append(cur_sub_module_inf)
- has_call_sub_not_end = True
- else:
- PrintDebug( 'Error : not recgnize %d: %s '%(i+module_start_line_num, l ), gen_vtags_log_path )
- # no matter find or not , current back line has valid ";", continue find new match
- if cur_match_right_part.find(';') != -1:
- find_next = True
- # if end at current line, set the call range [1]
- if has_call_sub_not_end and cur_match_right_part.find(';') != -1:
- sub_module_inf[-1]['match_range'][1] = i + module_start_line_num # start line and end line the same
- has_call_sub_not_end = False
- continue
- if (not find_next) and l.find(';') != -1:
- if get_valid_code(l).find(';') != -1:
- # if current not find next, and match a valid ";", need continue search
- find_next = True
- # if has unended sub call, and find a valid ";", set last call sub range[1]
- if has_call_sub_not_end:
- sub_module_inf[-1]['match_range'][1] = i + module_start_line_num # end line is the first ; line
- has_call_sub_not_end = False
- # if has_call_sub_not_end and (not find_next) and l.find(';') != -1:
- if has_call_sub_not_end and l.find(';') != -1:
- if get_valid_code(l).find(';') != -1:
- sub_module_inf[-1]['match_range'][1] = i + module_start_line_num # end line is the first ; line
- has_call_sub_not_end = False
- if has_call_sub_not_end:
- PrintDebug('Error : call sub not end at end module , try module end as callsub end ! : %s'%(sub_module_inf[-1].__str__()), gen_vtags_log_path)
- sub_module_inf[-1]['match_range'][1] = len(module_lines) - 1 + module_start_line_num # end line is the first ; line
- return sub_module_inf
-
-
- #-------------------------------------------
- # modules_inf = { module_name: module_inf }
- # defines_inf = { macro_name : [ define_inf ] }
- # files_inf = { file_name : file_inf }
- # module_inf = { 'module_name' : module_name
- # ,'file_path' : f
- # ,'line_range_in_file' : (module_start_line_num, module_end_line_num)
- # ,'module_pos' : module_pos
- # ,'sub_modules' : sub_modules }
- # define_inf = { "name" : xxx
- # ,"path" : f
- # ,"pos" : (line_num, colum_num) # name first char pos
- # ,'code_line' : `define xxx .... }
- # file_inf = { 'glb_defines' : [ define_inf ]
- # ,'module_infs' : [ module_inf ]
- # ,'module_calls' : [ call_sub_inf ]
- # ,'file_edit_inf' : { 'create_time': ..., 'last_modify_time': ...}
- # call_sub_inf = { 'inst_name' : inst_name
- # ,'module_name' : module_name
- # ,'match_range' : match_range
- # ,'match_pos' : match_pos }
- def gen_modules_and_defines_inf(files_inf):
- modules_inf = {}
- global_defines_inf = {}
- for c_file_path in files_inf:
- c_file_inf = files_inf[c_file_path]
- # merge defines
- c_file_glb_defines = c_file_inf['glb_defines']
- for d in c_file_glb_defines:
- d_name = d['name']
- global_defines_inf.setdefault(d_name,[])
- global_defines_inf[d_name].append(d)
- # merge modules_inf
- c_file_module_infs = c_file_inf['module_infs']
- for m in c_file_module_infs:
- mn = m['module_name']
- if mn in modules_inf:
- PrintDebug('Error: module %s has multip defines ! in %s '%(mn, [ modules_inf[mn]['file_path'], m['file_path'] ].__str__() ))
- else:
- modules_inf.setdefault(mn, None)
- modules_inf[mn] = m
- return modules_inf, global_defines_inf
-
- def updata_file_pickle_inf(path):
- PrintDebug('Care: updata database, file: %s'%(path))
- if get_file_path_postfix(path) not in G['SupportVerilogPostfix']:
- PrintDebug('Warning: updata_file_pickle_inf: file not verilog file ! file: %s'%(path))
- return False
- if not os.path.isfile(path):
- PrintDebug('Error: updata_file_pickle_inf: file not exit ! file: %s'%(path))
- return
- new_file_modules_inf = get_single_verilog_file_code_inf(path)
- glb_defines = new_file_modules_inf['glb_defines'] #[ define_inf ]
- module_infs = new_file_modules_inf['module_infs'] #[ module_inf ]
- # updata files_inf
- if path not in G['FileInf']:
- # if add new inf just add
- G['FileInf'][path] = new_file_modules_inf
- # add glb_defines
- for gd in glb_defines:
- gd_name = gd['name']
- G['CodeDefineInf'].setdefault(gd_name,[])
- G['CodeDefineInf'][gd_name].append( gd )
- # add module infs
- for m_inf in module_infs:
- m_name = m_inf['module_name']
- if m_name in G['ModuleInf']:
- PrintDebug('Error: module %s define twice ! used last at %s, %s'%(m_name, G['ModuleInf'][m_name]['file_path'], path))
- G['ModuleInf'][m_name] = m_inf
- else:
- # need refresh old and add new, so just gen new inf
- G['FileInf'][path] = new_file_modules_inf
- G['ModuleInf'], G['CodeDefineInf'] = gen_modules_and_defines_inf(G['FileInf'])
- # update pickles
- if not os.path.isdir(G['VTagsPath']):
- os.system('mkdir -p '+G['VTagsPath'])
- fp = open(G['VTagsPath'] + '/files_inf.py','w')
- fp.write('FileInf = %s \n'%(G['FileInf'].__str__()))
- fp.write('HDLTagsActive = True \n')
- fp.close()
-
- def get_module_inf(module_name):
- if module_name not in G['ModuleInf']:
- PrintDebug('Warning:get_module_inf: "%s" not konwn module !'%(module_name) )
- return False
- module_inf = G['ModuleInf'][module_name]
- module_path = module_inf['file_path']
- cur_inf_time = G['FileInf'][module_path]['file_edit_inf']['last_modify_time']
- last_modify_time = os.path.getmtime(module_path)
- # cur module file not modify, then inf valid and return
- if cur_inf_time == last_modify_time:
- return module_inf
- # if cur module file modify , update Module_inf and return new
- updata_file_pickle_inf(module_path)
- return get_module_inf(module_name)
-
- #----------------------------------------------------
- def get_line_inf_from_cur_file_inf(line_num, file_inf):
- line_module_inf = {}
- line_call_sub_inf = {}
- module_infs = file_inf['module_infs' ] #[ module_inf ]
- module_calls = file_inf['module_calls'] #[ call_sub_inf ]
- # first get current line module inf
- for m_inf in module_infs:
- c_module_range = m_inf['line_range_in_file']
- if c_module_range[1] < line_num:
- continue
- if line_num < c_module_range[0]:
- break
- line_module_inf = m_inf
- # second get current line call sub inf
- for c_inf in module_calls:
- c_call_range = c_inf['match_range']
- if c_call_range[1] < line_num:
- continue
- if line_num < c_call_range[0]:
- break
- line_call_sub_inf = c_inf
- return {
- 'line_module_inf' : line_module_inf
- ,'line_call_sub_inf' : line_call_sub_inf
- }
-
- def get_file_line_inf(line_num, path = ''):
- if not path:
- path = vim.current.buffer.name
- if get_file_path_postfix(path) not in G['SupportVerilogPostfix']:
- PrintDebug('Warning: get_file_line_inf: file not verilog file ! file: %s'%(path))
- return False
- if path not in G['FileInf']:
- updata_file_pickle_inf(path)
- if path not in G['FileInf']:
- PrintDebug('Warning: get_file_line_inf: %s has no file database !'%(path) )
- return False
- cur_inf_time = G['FileInf'][path]['file_edit_inf']['last_modify_time']
- last_modify_time = os.path.getmtime(path)
- # cur module file not modify, then inf valid and return
- if cur_inf_time == last_modify_time:
- return get_line_inf_from_cur_file_inf( line_num, G['FileInf'][path] )
- # if cur module file modify , update Module_inf and return new
- updata_file_pickle_inf(path)
- return get_file_line_inf(line_num, path)
-
- #----------------------------------------------
- # { module_name:'', 'call_inf':atom}
-
- def get_module_last_call_inf(module_name):
- if module_name not in G['ModuleLastCallInf']:
- return False
- upper_module_name = G['ModuleLastCallInf'][module_name]['upper_module_name']
- upper_inst_name = G['ModuleLastCallInf'][module_name]['upper_inst_name']
- if upper_module_name not in G['ModuleInf']:
- return False
- if upper_inst_name not in G['ModuleInf'][upper_module_name]['sub_calls']:
- return False
- upper_call_inf = G['ModuleInf'][upper_module_name]['sub_calls'][upper_inst_name]
- return {'upper_module_name': upper_module_name, 'upper_call_inf': upper_call_inf}
-
- def set_module_last_call_inf(sub_module_name, upper_module_name, upper_inst_name):
- G['ModuleLastCallInf'][sub_module_name] = { 'upper_module_name': upper_module_name, 'upper_inst_name': upper_inst_name }
-
-
- #----------------------------------------------
- # for a module's submodule, sep function module and base module
- def get_sub_func_base_module(module_name):
- func_modules = {} # inst:module
- base_modules = {} # module : [inst0,inst1...]
- sub_modules = []
- if module_name in G['ModuleInf']:
- sub_modules = G['ModuleInf'][module_name]['sub_modules']
- for sm in sub_modules:
- inst_name = sm['inst_name']
- module_name = sm['module_name']
- if module_name in G['BaseModuleInf']['BaseModules']:
- base_modules.setdefault(module_name,[])
- base_modules[module_name].append(inst_name)
- else:
- if inst_name in func_modules: # has to same inst name, may be use `ifdefine sep
- new_inst_name = inst_name+'_'+str(sm['match_range'][0])
- func_modules[new_inst_name] = sm
- continue
- func_modules[inst_name] = sm
- return func_modules, base_modules
- #----------------------------------------------
- # update function base information, no need added each times
- def update_base_module_pickle():
- pkl_output = open(G['VTagsPath'] + '/base_modules.pkl','wb')
- pickle.dump(G['BaseModuleInf']['BaseModules'], pkl_output)
- pkl_output.close()
- #----------------------------------------------
- # topo/checkpoint/basemodule line range ,in frame file
- def get_frame_range_inf():
- fram_file_link = G["VimBufferLineFileLink"][G['Frame_Inf']['Frame_Path']]
- # get topo range , default 0,0
- has_topo = False
- has_check_point = False
- has_base_module = False
- topo_range = [0, 0]
- check_point_range = [0, 0]
- base_module_range = [0, 0]
- for i,link in enumerate(fram_file_link):
- if link and (link['type'] == 'topo'):
- if not has_topo:
- topo_range[0] = i
- has_topo = True
- topo_range[1] = i
- if link and (link['type'] == 'check_point'):
- if not has_check_point:
- check_point_range[0] = i
- has_check_point = True
- check_point_range[1] = i
- if link and (link['type'] == 'base_module'):
- if not has_base_module:
- base_module_range[0] = i
- has_base_module = True
- base_module_range[1] = i
- # if no topo ,next topo start at [0,0]
- if not has_topo:
- topo_range = [0, 0]
- # check point initial start at topo end + 2
- if not has_check_point:
- check_point_range[0] = topo_range[1] + 2
- check_point_range[1] = topo_range[1] + 2
- # base module initial at check point end + 2
- if not has_base_module:
- base_module_range[0] = check_point_range[1] + 2
- base_module_range[1] = check_point_range[1] + 2
- return { 'topo_range' : tuple(topo_range)
- ,'check_point_range' : tuple(check_point_range)
- ,'base_module_range' : tuple(base_module_range)
- ,'has_topo' : has_topo
- ,'has_check_point' : has_check_point
- ,'has_base_module' : has_base_module }
- #----------------------------------------------------
- def get_submodule_match_patten(all_module_name):
- patten_char_set_list = []
- len_2_modules = {}
- for m_n in all_module_name:
- l = len(m_n)
- len_2_modules.setdefault(l,[])
- len_2_modules[l].append(m_n)
- l_pattens = []
- for l in len_2_modules:
- l_m = len_2_modules[l]
- l_patten = '(['+ (']['.join(map(''.join, map(set,zip(*l_m))))) + '])'
- l_pattens.append(l_patten)
- patten = '(' + '|'.join(l_pattens) + ')'
- return patten
- #----------------------------------------------------
- def get_single_verilog_file_module_inf(f):
- all_module_start_end_lines = os.popen('egrep -n -h \'^\s*(module|endmodule)\>\' %s'%(f)).readlines()
- cur_file_module_inf = []
- has_module_not_end = False
- i = 0
- while i < len(all_module_start_end_lines):
- cur_start_end_line = all_module_start_end_lines[i]
- cur_start_end_line_num = int(cur_start_end_line.split(':')[0]) - 1
- cur_start_end_line_code = ':'.join( cur_start_end_line.split(':')[1:] )
- match_module_start = re.match('\s*module\s+(?P<name>(|`)\w+)', cur_start_end_line_code) # some module use macro as name so (|`)
- if match_module_start:
- module_name = match_module_start.group('name')
- module_start_line_num = cur_start_end_line_num
- module_pos = ( module_start_line_num, cur_start_end_line_code.find(module_name) )
- # if pre module not end, set new module start pre line as pre module end line
- if has_module_not_end:
- PrintDebug('Error: module:"%s" in file:"%s", no "endmodule" !'%(cur_file_module_inf[-1]['module_name'],f) )
- cur_file_module_inf[-1]['line_range_in_file'][1] = module_start_line_num - 1
- cur_file_module_inf.append(
- { 'module_name' : module_name
- ,'file_path' : f
- ,'line_range_in_file' : [module_start_line_num, -1]
- ,'sub_modules' : None # []
- ,'module_pos' : module_pos
- }
- )
- has_module_not_end = True
- i += 1
- continue
- match_module_end = re.match('\s*endmodule(\W|$)', cur_start_end_line_code)
- if match_module_end:
- if not has_module_not_end:
- PrintDebug( 'Error: line: %s "endmodule" has no correlation module define ! file: %s '%(match_module_end,f) )
- continue
- module_end_line_num = cur_start_end_line_num
- cur_file_module_inf[-1]['line_range_in_file'][1] = module_end_line_num
- has_module_not_end = False
- i += 1
- continue
- i += 1
- if has_module_not_end:
- PrintDebug( 'Error: module:"%s" in file:"%s", no "endmodule" !'%(cur_file_module_inf[-1]['module_name'],f) )
- return cur_file_module_inf
- # for current file line match all patten: `define xxx ....
- # patten_result = {
- # "name" : xxx
- # ,"path" : f
- # ,"pos" : (line_num, colum_num) # name first char pos
- # ,'code_line' : `define xxx ....
- # }
- # finial return [ patten_result0, patten_result1 ]
- def get_single_verilog_file_define_inf(f):
- global_define_inf = []
- global_define_lines = os.popen('egrep -n -h \'^\s*`define\W\' %s'%(f)).readlines()
- for l in global_define_lines:
- split0 = l.split(':')
- line_num = int(split0[0]) - 1
- code_line = ':'.join(split0[1:])
- match_name = re.match('\s*`define\s*(?P<name>\w+)',code_line)
- name = ''
- colum_num = -1
- if match_name:
- name = match_name.group('name')
- colum_num = code_line.find(name)
- if colum_num != -1:
- global_define_inf.append(
- { "name" : name
- ,"path" : f
- ,"pos" : (line_num, colum_num)
- ,'code_line' : code_line }
- )
- return global_define_inf
- def get_single_line_sub_call_inf(egrep_line, all_module_names):
- sp = egrep_line.split(':')
- l_num = int(sp[0]) - 1
- l_code = re.sub('//.*', '', ':'.join(sp[1:]))
- if l_code.find(';') == -1:
- return False
- # match_name = re.match('\s*(?P<m_n>(|`)\w+)\s*(?P<other>.*;)\s*$',l_code)
- match_name = re.match('\s*(?P<m_n>(|`)\w+)\s*(?P<other>.*;)',l_code)
- assert(match_name),'%s,%s'%(egrep_line, l_code)
- module_name = match_name.group('m_n')
- if module_name not in all_module_names:
- return False
- other = match_name.group('other')
- inst_name_patten = '\w+((\s*\[[^\[\]]*\])|)'
- search_i_n = re.search('(^(?P<i_n0>%s))|(#.*\)\s*(?P<i_n1>%s)\s*\()'%(inst_name_patten,inst_name_patten),other)
- if not search_i_n:
- PrintDebug( 'Warning: match module name %s, but no inst name !' )
- return False
- inst_name = search_i_n.group('i_n0')
- if not inst_name:
- inst_name = search_i_n.group('i_n1')
- assert(inst_name)
- return {
- 'module_name': module_name
- ,'inst_name' : inst_name
- ,'match_range': [l_num, l_num]
- ,'match_pos' : [l_num, l_code.find(module_name)]
- }
- def get_mult_line_sub_call_inf(egrep_line, f_lines, all_module_names):
- sp = egrep_line.split(':')
- l_num = int(sp[0]) - 1
- code_line = re.sub('//.*', '', ':'.join(sp[1:]))
- # get module name
- module_name = ''
- module_pos = (-1,-1)
- match_name = re.match('^\s*(?P<m_n>(|`)\w+)\s*(?P<other>.*)',code_line)
- assert(match_name)
- module_name = match_name.group('m_n')
- if module_name not in all_module_names:
- return False
- module_pos = (l_num, code_line.find(module_name))
- # get inst name
- inst_name = ''
- inst_name_patten = '\w+((\s*\[[^\[\]]*\])|)'
- other = match_name.group('other')
- i = l_num + 1
- max_i = len(f_lines)
- line_end = False
- while not other and i < max_i and not line_end:
- next_code_line_with_semi = re.sub('((^\s+)|(^\s*`.*)|(//.*))','',f_lines[i].strip('\n'))
- next_code_line_no_semi = re.sub(';.*','',next_code_line_with_semi)
- other = next_code_line_no_semi
- if len(next_code_line_no_semi) != len(next_code_line_with_semi):
- line_end = True
- i += 1
- match_inst_name_no_parm = re.match('^(?P<i_n>%s)'%(inst_name_patten),other)
- if match_inst_name_no_parm:
- inst_name = match_inst_name_no_parm.group('i_n')
- elif other[0] != '#':
- PrintDebug('Warning: un recgnize 0 module match ! %s ||| %s'%(egrep_line, other))
- return False
- # del has parm inst_name
- search_inst_name_has_parm = re.search('#\s*\(.*\)\s*(?P<i_n>%s)\s*\('%(inst_name_patten),other)
- if search_inst_name_has_parm:
- inst_name = search_inst_name_has_parm.group('i_n')
- while i < max_i and not line_end:
- next_code_line_with_semi = re.sub('((^\s+)|(^\s*`.*)|(//.*))','',f_lines[i].strip('\n'))
- next_code_line_no_semi = re.sub(';.*','',next_code_line_with_semi)
- other = other +' '+next_code_line_no_semi
- if len(next_code_line_no_semi) != len(next_code_line_with_semi):
- line_end = True
- i += 1
- search_inst_name_has_parm = re.search('#\s*\(.*\)\s*(?P<i_n>%s)\s*\('%(inst_name_patten),other)
- if search_inst_name_has_parm:
- inst_name = search_inst_name_has_parm.group('i_n')
- break
- if not inst_name:
- PrintDebug('Warning: un recgnize 1 module match ! %s ||| %d ||| %s '%(egrep_line, i, str(line_end) ) )
- return False
- # get cur call end line
- end_line_num = max_i
- while i < max_i and not line_end:
- next_code_line = re.sub('(^`.*)|(//.*)','',f_lines[i])
- if next_code_line.find(';') != -1:
- line_end = True
- break
- i += 1
- if not line_end:
- PrintDebug('Warning: cur sub call no end ";" ! %s'%(egrep_line))
- else:
- end_line_num = i
- # return result
- return {
- 'module_name': module_name
- ,'inst_name' : inst_name
- ,'match_range': [l_num, end_line_num]
- ,'match_pos' : module_pos
- }
- def get_single_verilog_file_subcall_inf(f, patten, all_module_names):
- egrep_match_lines = os.popen('egrep -n -h \'^\s*(%s)\>\' %s'%(patten,f)).readlines()
- # start get sub call inf
- if not egrep_match_lines:
- return []
- file_sub_call_infs = []
- c0_cnt = 0
- c1_cnt = 0
- f_lines = open(f,'r').readlines()
- for egrep_l in egrep_match_lines:
- # case0: signal line call
- c0_rst = get_single_line_sub_call_inf(egrep_l, all_module_names)
- if c0_rst:
- c0_cnt += 1
- file_sub_call_infs.append(c0_rst)
- continue
- # case1: mult line call
- c1_rst = get_mult_line_sub_call_inf(egrep_l, f_lines, all_module_names)
- if c1_rst:
- c1_cnt += 1
- file_sub_call_infs.append(c1_rst)
- continue
- PrintDebug('subcall: one_line/mult_line = %d/%d'%( c0_cnt,c1_cnt) )
- return file_sub_call_infs
- def add_single_verilog_file_submodule_inf_to_module_inf( file_module_inf, file_subcall_inf ):
- s_inf_i = 0
- for m_inf in file_module_inf:
- m_inf['sub_modules'] = []
- m_inf['sub_calls'] = {}
- m_range = m_inf['line_range_in_file']
- while s_inf_i < len(file_subcall_inf):
- s_range = file_subcall_inf[s_inf_i]['match_range']
- # cur subcall in cur module
- if m_range[0] <= s_range[0] and s_range[1] <= m_range[1]:
- m_inf['sub_modules'].append(file_subcall_inf[s_inf_i])
- m_inf['sub_calls'][file_subcall_inf[s_inf_i]['inst_name']] = file_subcall_inf[s_inf_i]
- s_inf_i += 1
- continue
- elif s_range[0] < m_range[0]:
- PrintDebug('Error: subcall %s not in valid module !'%(file_subcall_inf[s_inf_i].__str__()))
- s_inf_i += 1
- elif s_range[1] > m_range[1]:
- if s_range[0] < m_range[0]:
- PrintDebug('Error: subcall %s cross two module !'%(file_subcall_inf[s_inf_i].__str__()))
- break
- else:
- assert(0)
- return
- def get_single_verilog_file_code_inf(f):
- # gen cur module and define inf
- new_file_module_inf = get_single_verilog_file_module_inf(f)
- new_file_define_inf = get_single_verilog_file_define_inf(f)
- # gen new all_module_names, del old current file add new
- new_module_names = set([ mi['module_name'] for mi in new_file_module_inf ])
- old_file_module_inf = G['FileInf'][f]['module_infs']
- old_module_names = set([ mi['module_name'] for mi in old_file_module_inf ])
- all_module_name = ( set(G['ModuleInf']) - old_module_names ) | new_module_names
- # get file sub call inf
- patten = get_submodule_match_patten(all_module_name)
- new_file_subcall_inf = get_single_verilog_file_subcall_inf(f, patten, all_module_name)
- # merge to file_inf
- add_single_verilog_file_submodule_inf_to_module_inf( new_file_module_inf, new_file_subcall_inf )
- new_file_inf = {
- 'glb_defines' : new_file_define_inf
- ,'module_infs' : new_file_module_inf
- ,'module_calls' : new_file_subcall_inf
- ,'file_edit_inf' : { 'create_time': os.path.getctime(f), 'last_modify_time': os.path.getmtime(f)}
- }
- return new_file_inf
- def show_progress_bar( i, i_max, show_char = '#', show_width = 20):
- i += 1 # count from 1
- i_max_len = len(str(i_max))
- i_len = len(str(i))
- i_str = ' '*(i_max_len-i_len)+str(i)
- i_max_str = str(i_max)
- prefix = '%s/%s: '%(i_str,i_max_str)
- pass_str = show_char*((i*show_width)/i_max)
- empty_str = ' '*(show_width - len(pass_str))
- progress_bar = '[%s%s]'%(pass_str,empty_str)
- tool_len = len(prefix) + show_width
- sys.stdout.write(' '*tool_len + '\r')
- sys.stdout.flush()
- sys.stdout.write(prefix + progress_bar)
- """
- https://my.oschina.net/u/2520885
- """
- #===============================================================================
- # Copyright (C) 2016 by Jun Cao
- # Permission is hereby granted, free of charge, to any person obtaining a copy
- # of this software and associated documentation files (the "Software"), to deal
- # in the Software without restriction, including without limitation the rights
- # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- # copies of the Software, and to permit persons to whom the Software is
- # furnished to do so, subject to the following conditions:
- # The above copyright notice and this permission notice shall be included in
- # all copies or substantial portions of the Software.
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- # THE SOFTWARE.
- #===============================================================================
- import sys
- import re
- import os
- try:
- import vim
- except:
- pass
- import GLB
- G = GLB.G
- from Base import*
- import View
- PrintReport = View.PrintReport
- ########################################################
- def get_sub_io_signal_name_from_sub_call_line(call_line, y):
- word = get_full_word(call_line, y)
- # if | .xxx(xxxx)
- # y | ^
- # | ^ ^ // call_sub_assign_signal_str
- # cur_word is sub_io_signal_name
- if re.match('\w+\.', call_line[:y+1][::-1]):
- call_sub_assign_signal_str = re.sub('(^\w*)|(\.\w+\(.*)', '', call_line[y:])
- call_sub_signals = set( re.findall('\w+',call_sub_assign_signal_str) )
- sub_call_io = word
- return { 'call_sub_signals': call_sub_signals
- ,'sub_call_io' : word
- ,'sub_call_io_num' : None }
- # if | .xxx(xxxx)
- # y | ^
- # | ^ ^ // call_sub_assign_signal_str
- s0 = re.search('\(\s*(?P<sub_call_io>\w+)\.',call_line[:y+1][::-1])
- if s0:
- sub_call_io = s0.group('sub_call_io')[::-1]
- call_sub_assign_and_right = call_line[y-s0.span()[0]:]
- assert(call_sub_assign_and_right[0] == '(')
- call_sub_assign_signal_str = re.sub('\.\w+\s*\(.*', '', call_line[y:])
- call_sub_signals = set( re.findall('\w+',call_sub_assign_signal_str) )
- return { 'call_sub_signals': call_sub_signals
- ,'sub_call_io' : sub_call_io
- ,'sub_call_io_num' : None }
- # if module_name #(parm) inst_name( a, b, c)
- # if module_name inst_name( a, b, c)
- # y
- # call_sub_signals set(b)
- # sub_call_io_num 1
- # sub_call_io ''
- if word:
- s1 = re.search('\)\s*\w+\s*\(',call_line[:y+1])
- if not s1:
- s1 = re.match('\s*\w+\s*\w+\s*\(',call_line[:y+1])
- full_match_s1 = True
- if s1:
- pre_sub_call_signal_str = call_line[s1.span()[1]:y+1]
- pre_sub_call_signals = pre_sub_call_signal_str.split(',')
- assert(pre_sub_call_signals)
- for sc in pre_sub_call_signals:
- if not re.match('\s*(\w+)|(\w+\s*\[[^\[\]]+\])\s*$',sc):
- full_match_s1 = False
- if full_match_s1:
- return { 'call_sub_signals': set([word])
- ,'sub_call_io' : ''
- ,'sub_call_io_num' : len(pre_sub_call_signals) - 1 }
- return None
- # if has io_name return cur io inf
- # else return all io inf of current module
- #io_inf =
- # "name" : name
- # , "io_type" : io_type
- # , "left" : left_index
- # , "right" : right_index
- # , "size" : size
- # , 'line_num' : line_num
- # , 'name_pos' : (line_num, colm_num)
- # , 'code_line' : code_line
- # , 'signal_type' : signal_type }
- def get_io_inf(module_name, io_name = ''):
- module_inf = get_module_inf(module_name)
- if not module_inf:
- return False
- module_path = module_inf['file_path']
- module_range = module_inf['line_range_in_file']
- if io_name: # get cur io inf
- io_inf = {}
- io_lines = os.popen('sed -n \'%d,%dp\' %s | egrep -n -h \'^\s*(input|output)\>.*\<%s\>\''%(module_range[0]+1, module_range[1]+1, module_path, io_name)).readlines()
- if len(io_lines) == 0:
- PrintDebug('Error: module: %s \'s io: %s define not found !'%(module_name,io_name))
- return False
- if len(io_lines) > 1:
- l_i = 0
- while l_i < len(io_lines):
- if not re.search('\W%s(\W|)'%(io_name), re.sub('//.*','',io_lines[l_i])):
- del io_lines[l_i]
- continue
- l_i += 1
- continue
- if len(io_lines) > 1:
- PrintDebug('Error: module: %s \'s io: %s define multiple times !'%(module_name,io_name))
- line = io_lines[0]
- assert(line.find(io_name) != -1)
- io_inf = decode_egreped_verilog_io_line(line)['io_infs']
- if io_name in io_inf:
- # because use "sed ... | grep ..." so the line number is not the real number need add sed started line num
- io_inf[io_name]['line_num'] = io_inf[io_name]['line_num'] + module_range[0]
- io_inf[io_name]['name_pos'] = ( io_inf[io_name]['line_num'], io_inf[io_name]['name_pos'][1] )
- return io_inf[io_name]
- else:
- PrintDebug('Warning: get_io_inf, io_name is parm name ,not a io !')
- return False
- else: # get module all io inf
- all_io_inf = []
- cur_module_code_range = module_inf['line_range_in_file']
- all_io_lines = os.popen('sed -n \'%d,%dp\' %s | egrep -n -h \'^\s*(input|output)\>\''%(cur_module_code_range[0]+1, cur_module_code_range[1]+1, module_path)).readlines()
- for line in all_io_lines:
- line = line.rstrip('\n')
- egrep_io_infs = decode_egreped_verilog_io_line(line)
- io_inf = egrep_io_infs['io_infs']
- name_list = egrep_io_infs['name_list']
- if not io_inf:
- PrintDebug('Error: module: %s, line: %s, can not decode by decode_egreped_verilog_io_line() ! file: %s'(module_name, line, module_path))
- continue
- for io_name in name_list:
- assert(io_name in io_inf)
- c_io_inf = io_inf[io_name]
- c_io_inf['line_num'] = c_io_inf['line_num'] + cur_module_code_range[0]
- c_io_inf['name_pos'] = (c_io_inf['line_num'], c_io_inf['name_pos'][1])
- all_io_inf.append( c_io_inf )
- return all_io_inf
- def get_module_call_sub_module_io_inf(call_line, io_pos, call_file_path):
- call_line_num = io_pos[0]
- # if database has no this file return
- if call_file_path not in G['FileInf']:
- PrintDebug("Warning: get_module_call_sub_module_io_inf : cur file has not in hdltags database, file: %s !"%(call_file_path))
- return False
- file_line_inf = get_file_line_inf(call_line_num, call_file_path)
- line_call_sub_inf = {}
- line_module_inf = {}
- if file_line_inf:
- line_call_sub_inf = file_line_inf['line_call_sub_inf']
- line_module_inf = file_line_inf['line_module_inf']
- # if cursor line not no sub call , return
- if not line_call_sub_inf:
- PrintDebug("Warning: get_module_call_sub_module_io_inf: cur line %d not on sub call ! "%(call_line_num))
- return False
- sub_call_signal_inf = get_sub_io_signal_name_from_sub_call_line(call_line, io_pos[1]) # may be parm
- # call module name
- assert(line_module_inf),'is in sub call, must be valid mudule'
- call_module_name = line_module_inf['module_name']
- # valid cursor on sub call
- sub_module_name = line_call_sub_inf['module_name']
- sub_module_path = ''
- sub_module_inf = get_module_inf(sub_module_name)
- if sub_module_inf:
- sub_module_path = sub_module_inf['file_path']
- # sub_match_pos means cursor call io signal in sub module io pos
- sub_io_inf = {}
- call_sub_signals = set()
- if sub_call_signal_inf:
- call_sub_signals = sub_call_signal_inf['call_sub_signals']
- sub_call_io = sub_call_signal_inf['sub_call_io']
- sub_call_io_num = sub_call_signal_inf['sub_call_io_num']
- if sub_call_io:
- sub_io_inf = get_io_inf(sub_module_name, sub_call_io)
- elif sub_call_io_num != None:
- all_io_inf = get_io_inf(sub_module_name)
- assert(sub_call_io_num < len(all_io_inf))
- sub_io_inf = all_io_inf[sub_call_io_num]
- sub_match_pos = ()
- sub_io_type = ''
- sub_io_line = ''
- sub_io_name = ''
- if sub_io_inf:
- sub_io_name = sub_io_inf['name']
- sub_match_pos = sub_io_inf['name_pos']
- sub_io_type = sub_io_inf['io_type']
- sub_io_line = sub_io_inf['code_line']
- return {
- 'sub_io_name' : sub_io_name
- ,'sub_module_name' : sub_module_name
- ,'sub_module_path' : sub_module_path
- ,'sub_match_pos' : sub_match_pos
- ,'sub_io_type' : sub_io_type
- ,'sub_io_line' : sub_io_line
- ,'sub_io_inf' : sub_io_inf
- ,'call_sub_signals' : call_sub_signals
- ,'call_sub_inf' : line_call_sub_inf
- ,'call_module_name' : call_module_name }
- #########################function for trace##############################
- # ok
- def get_upper_module_call_io_inf(cur_module_name , cur_io_name):
- cur_module_last_call_inf = get_module_last_call_inf(cur_module_name)
- if not cur_module_last_call_inf:
- PrintDebug("Warning: get_upper_module_call_io_inf: module %s, not called before, no upper module !"%(cur_module_name))
- return False
- upper_module_name = cur_module_last_call_inf['upper_module_name']
- upper_call_inf = cur_module_last_call_inf['upper_call_inf']
- upper_module_inf = get_module_inf(upper_module_name)
- assert(upper_module_inf),'upper module %s call %s before, upper should has inf in database !'%(upper_module_name, cur_module_name)
- upper_module_path = upper_module_inf['file_path']
- # get upper call, match this signal pos
- upper_call_lines = open(upper_module_path,'r').readlines()
- upper_call_pos = upper_call_inf['match_pos'] # initial to call inst line
- upper_matched = False
- for i in range( upper_call_inf['match_range'][0] , upper_call_inf['match_range'][1] + 1 ):
- f0 = upper_call_lines[i].find(cur_io_name)
- if f0 == -1:
- continue
- s0 = re.search('(?P<pre>^|\W)%s(\W|$)'%(cur_io_name) , re.sub('//.*','',upper_call_lines[i]))
- if s0:
- colum_num = s0.span()[0] + len(s0.group('pre'))
- upper_call_pos = (i, colum_num)
- upper_matched = True
- break
- assert(upper_matched),'upper called so should be match, cur_io_name:%s, %s '%(upper_call_inf['match_range'].__str__(), cur_io_name)
- upper_call_line = upper_call_lines[upper_call_pos[0]]
- return {
- 'module_name' : upper_module_name
- ,'call_pos' : upper_call_pos
- ,'call_line' : upper_call_line
- ,'module_path' : upper_module_path
- }
- def get_cur_appear_is_source_or_dest(key, code_lines, appear_pos):
- a_x, a_y = appear_pos
- appear_code_line = re.sub('(//.*)|(^\s*`.*)', '', code_lines[a_x] )
- # case 0 cur pos in note return not source and dest
- if len(appear_code_line) - 1 < a_y:
- return 'None'
- # case 1 is io
- if (appear_code_line.find('input') != -1) or (appear_code_line.find('output') != -1):
- match_io_type = re.match('\s*(?P<io_type>(input|output))\W',appear_code_line) # may input a,b,c
- match_io_name = re.match('\s*[;,]?\s*(?P<r_names>\w+(\s*,\s*\w+)*)',appear_code_line[::-1]) # may input a,b,c
- if match_io_type and match_io_name:
- io_type = match_io_type.group('io_type')
- io_names = match_io_name.group('r_names')[::-1]
- io_names = set(re.split('\s*,\s*',io_names))
- if (io_type == 'input') and (key in io_names):
- return 'Source'
- if (io_type == 'output') and (key in io_names):
- return 'Dest'
- elif match_io_type:
- PrintDebug('Error: recgnize_signal_assign_line: unrecgnize io line: '+appear_code_line)
- return 'None'
- # case 2 cur pos in case/casez/for/if (...key...) then it's dest
- match_case2 = False
- c2 = re.search( '(^|\W)(case|casez|for|if|while)\s*\(' , appear_code_line)
- if c2:
- appear_code_right_line = appear_code_line[c2.span()[1]:]
- unmatch_bracket_count = 1
- end_match_patten = '^'
- end_y = len(appear_code_right_line) - 1
- all_brackets = re.findall('\(|\)', appear_code_right_line)
- for b in all_brackets:
- if b == '(':
- unmatch_bracket_count += 1
- else:
- unmatch_bracket_count -= 1
- end_match_patten = end_match_patten + '[^()]*\\'+b
- if unmatch_bracket_count == 0:
- end_y = re.search(end_match_patten, appear_code_right_line).span()[1] - 1
- break
- end_y = c2.span()[1] + end_y
- if end_y >= a_y:
- return 'Dest'
- else:
- # if key not in (...), then use ) right str as real appear_code_line
- match_case2 = True
- appear_code_line = appear_code_line[end_y + 1:]
- # case 3 cur line has = at left or right
- assign_patten = '([^=>!]=[^=<>])'
- # ... =|<= ... key : is dest
- if re.search(assign_patten, appear_code_line[:a_y + 1]):
- return 'Dest'
- # key ... =|<= ... : is source
- if re.search(assign_patten, appear_code_line[a_y:]):
- return 'Source'
- # case 4 if not match case2(if match no pre line) post full line sep by ";" has =|<=, it's dest
- if not match_case2:
- pre_full_line = get_verilog_pre_full_line(code_lines, appear_pos)
- if re.search(assign_patten, pre_full_line):
- return 'Dest'
- # case 5 post full line sep by ";" has =|<=, it's source
- post_full_line = get_verilog_post_full_line(code_lines, appear_pos)
- if re.search(assign_patten, post_full_line[:a_y + 1]):
- return 'Source'
- # case 6 unrecgnize treat as maybe dest/source
- return 'Maybe'
-
-
- # ok
- def clear_last_trace_inf( trace_type ):
- if trace_type in ['source','both']:
- G['TraceInf']['LastTraceSource']['Maybe'] = []
- G['TraceInf']['LastTraceSource']['Sure'] = []
- G['TraceInf']['LastTraceSource']['ShowIndex'] = 0
- G['TraceInf']['LastTraceSource']['SignalName'] = ''
- G['TraceInf']['LastTraceSource']['Path'] = ''
- if trace_type in ['dest','both']:
- G['TraceInf']['LastTraceDest']['Maybe'] = []
- G['TraceInf']['LastTraceDest']['Sure'] = []
- G['TraceInf']['LastTraceDest']['ShowIndex'] = 0
- G['TraceInf']['LastTraceDest']['SignalName'] = ''
- G['TraceInf']['LastTraceDest']['Path'] = ''
-
- # #-------------------trace_io_signal---------------------------
- # del get_cur_module_inf
- def real_trace_io_signal(trace_type, cursor_inf, io_signal_inf):
- assert(trace_type in ['dest', 'source']),'only trace dest/source'
- # verilog
- if (trace_type is 'dest') and (io_signal_inf['io_type'] != 'output'):
- PrintDebug('Warning: real_trace_io_signal: not output signal, not dest')
- return False # not output signal, not dest
- if (trace_type is 'source') and (io_signal_inf['io_type'] != 'input'):
- PrintDebug('Warning: real_trace_io_signal: not input signal, not source')
- return False # not input signal, not source
- # trace a input signal
- clear_last_trace_inf( trace_type ) # clear pre trace dest/source result
- cur_module_inf = cursor_inf['cur_module_inf']
- if not cur_module_inf:
- PrintDebug('Warning: cur file not in database, will not go upper ! file: %s'(cursor_inf['file_path']))
- return True
- cur_module_name = cur_module_inf['module_name']
- upper_module_call_inf = get_upper_module_call_io_inf(cur_module_name , io_signal_inf['name'])
- if not upper_module_call_inf:
- PrintReport('Warning: no upper module call this module before !')
- return True # this dest/source but not found upper module
- # has upper module go to upper module call location
- upper_module_name = upper_module_call_inf['module_name']
- upper_call_pos = upper_module_call_inf['call_pos']
- upper_call_line = upper_module_call_inf['call_line']
- upper_module_path = upper_module_call_inf['module_path']
- show_str = '%s %d : %s'%(upper_module_name, upper_call_pos[0]+1, upper_call_line)
- file_link = {'key':io_signal_inf['name'], 'pos': upper_call_pos, 'path': upper_module_path}
- trace_result = {'show': show_str, 'file_link': file_link}
- if trace_type is 'dest':
- G['TraceInf']['LastTraceDest']['Sure'].append(trace_result)
- G['TraceInf']['LastTraceDest']['SignalName'] = cursor_inf['word']
- G['TraceInf']['LastTraceDest']['Path'] = cursor_inf['file_path']
- else :
- G['TraceInf']['LastTraceSource']['Sure'].append(trace_result)
- G['TraceInf']['LastTraceSource']['SignalName'] = cursor_inf['word']
- G['TraceInf']['LastTraceSource']['Path'] = cursor_inf['file_path']
- # show dest/source to report win, and go first trace
- PrintReport(spec_case = trace_type)
- View.show_next_trace_result(trace_type)
- return True
-
- # ok
- def trace_io_signal(trace_type, cursor_inf):
- trace_signal_name = cursor_inf['word']
- io_signal_infs = recgnize_io_signal_line(cursor_inf['line'], cursor_inf['line_num'])
- if not io_signal_infs:
- PrintDebug('Warning: trace_io_signal: not io signal')
- return False # not io signal
- # if trace_signal_name != io_signal_inf['name']:
- if trace_signal_name not in io_signal_infs:
- PrintDebug('Warning: trace_io_signal: is io signal but not traced signal')
- return False # is io signal but not traced signal
- if trace_type in ['source','dest']:
- return real_trace_io_signal(trace_type, cursor_inf, io_signal_infs[trace_signal_name])
- assert(0),'unkonw tarce type %s' %(trace_type)
-
- #-------------------------------------------------------------
- # ok
- def real_trace_module_call_io_signal(trace_type, sub_call_inf, cursor_inf):
- assert(trace_type in ['source', 'dest'])
- if trace_type == 'source' and sub_call_inf['sub_io_type'] != 'output':
- return False # submodule not source, just pass
- elif trace_type == 'dest' and sub_call_inf['sub_io_type'] != 'input':
- return False # submodule not source, just pass
- # has sub module and in submodule signal is out, then it's source
- sub_module_name = sub_call_inf['sub_module_name']
- sub_module_path = sub_call_inf['sub_module_path']
- sub_module_match_pos = sub_call_inf['sub_match_pos']
- sub_module_match_line = sub_call_inf['sub_io_line']
- sub_module_signal_name = sub_call_inf['sub_io_name']
- show_str = '%s %d : %s'%(sub_module_name, sub_module_match_pos[0]+1, sub_module_match_line)
- file_link = {'key':sub_module_signal_name, 'pos': sub_module_match_pos, 'path': sub_module_path}
- trace_result = {'show': show_str, 'file_link': file_link}
- if trace_type == 'source':
- G['TraceInf']['LastTraceSource']['Sure'].append(trace_result)
- G['TraceInf']['LastTraceSource']['SignalName'] = cursor_inf['word']
- G['TraceInf']['LastTraceSource']['Path'] = cursor_inf['file_path']
- else: # dest
- G['TraceInf']['LastTraceDest']['Sure'].append(trace_result)
- G['TraceInf']['LastTraceDest']['SignalName'] = cursor_inf['word']
- G['TraceInf']['LastTraceDest']['Path'] = cursor_inf['file_path']
- # go to sub module code now, so cur module is the sub module last call
- cur_module_name = sub_call_inf['call_module_name']
- call_sub_inf = sub_call_inf['call_sub_inf']
- set_module_last_call_inf(sub_module_name, cur_module_name, call_sub_inf['inst_name'])
- # show source to report win, and go first trace
- PrintReport(spec_case = trace_type)
- View.show_next_trace_result(trace_type)
- return True
- # ok
- # del is_module_call_range
- def trace_module_call_io_signal(trace_type, cursor_inf):
- sub_call_inf = get_module_call_sub_module_io_inf(cursor_inf['line'], cursor_inf['pos'], cursor_inf['file_path'])
- if not sub_call_inf:
- PrintDebug('Warning: trace_module_call_io_signal: not in module call io')
- return False # not in module call io
- if sub_call_inf['sub_module_name'] == cursor_inf['word']:
- PrintReport('Warning: trace key is a submodule call, module name , no source !')
- return True
- if not sub_call_inf['sub_io_name']:
- PrintDebug('Warning: trace_module_call_io_signal: is module call ,but unrecgnize io name !')
- return False
- clear_last_trace_inf( trace_type )
- return real_trace_module_call_io_signal(trace_type, sub_call_inf, cursor_inf)
- # #---------------------------------------------------------------------
- def real_trace_normal_signal(trace_type, signal_appear_pos_line, cursor_inf):
- assert(trace_type in ['source', 'dest'])
- clear_last_trace_inf(trace_type)
- if trace_type == 'source':
- G['TraceInf']['LastTraceSource']['SignalName'] = cursor_inf['word']
- G['TraceInf']['LastTraceSource']['Path'] = cursor_inf['file_path']
- else:
- G['TraceInf']['LastTraceDest']['SignalName'] = cursor_inf['word']
- G['TraceInf']['LastTraceDest']['Path'] = cursor_inf['file_path']
- trace_signal_name = cursor_inf['word']
- cur_module_inf = cursor_inf['cur_module_inf'] # already qualify
- cur_module_name = cur_module_inf['module_name']
- cur_module_path = cur_module_inf['file_path']
- # add optimizing for signal such like clk, used by many times, but only io, or sub call is source
- input_is_only_source = False
- if trace_type == 'source' and len(signal_appear_pos_line) > G['TraceInf']['TraceSourceOptimizingThreshold']:
- for appear_pos, appear_line in signal_appear_pos_line:
- signal_appear_line = cursor_inf['codes'][appear_pos[0]]
- if signal_appear_line.find('input') == -1:
- continue
- dest_or_source = get_cur_appear_is_source_or_dest(trace_signal_name, [signal_appear_line], (0,appear_pos[1]) )
- if dest_or_source != source:
- continue
- input_is_only_source = True
- show_str = '%s %d : %s'%(cur_module_name, appear_pos[0]+1, appear_line)
- file_link = {'key':trace_signal_name, 'pos': appear_pos, 'path': cur_module_path}
- trace_result = {'show': show_str, 'file_link': file_link}
- G['TraceInf']['LastTraceSource']['Sure'].append(trace_result)
- break
- # if found a input as source, should be the only source, clear appear pos to jump, normal search
- if input_is_only_source:
- signal_appear_pos_line = []
- # appear_pos (line number, column), deal each match to find source
- for appear_pos, appear_line in signal_appear_pos_line:
- appear_dest_or_source = False
- appear_is_dest = False
- appear_is_source = False
- # module call assign range
- sub_call_inf = get_module_call_sub_module_io_inf(appear_line, appear_pos, cur_module_path)
- if sub_call_inf:
- if trace_signal_name in sub_call_inf['call_sub_signals']:
- # cur is subcall but not io name not match trace name go next
- if not sub_call_inf['sub_io_type']:
- appear_dest_or_source = True
- elif sub_call_inf['sub_io_type'] == 'output':
- appear_is_source = True
- elif sub_call_inf['sub_io_type'] == 'input':
- appear_is_dest = True
- else:
- PrintDebug('Warning: subcall match on sub io name, not on assign name ! %s,%s'%(appear_pos.__str__(), appear_line))
- continue
- else:
- # not module call then check if a assign signal
- dest_or_source = get_cur_appear_is_source_or_dest(trace_signal_name, cursor_inf['codes'], appear_pos)
- if dest_or_source == 'Dest':
- appear_is_dest = True
- elif dest_or_source == 'Source':
- appear_is_source = True
- elif dest_or_source == 'Maybe':
- appear_dest_or_source = True
- else:
- PrintDebug('Warning: match not source or dest ! %s : %s'%(appear_pos.__str__(), appear_line))
- # finial add to source/dest
- show_str = '%s %d : %s'%(cur_module_name, appear_pos[0]+1, appear_line)
- file_link = {'key':trace_signal_name, 'pos': appear_pos, 'path': cur_module_path}
- trace_result = {'show': show_str, 'file_link': file_link}
- if trace_type == 'source':
- if appear_dest_or_source:
- G['TraceInf']['LastTraceSource']['Maybe'].append(trace_result)
- elif appear_is_source:
- G['TraceInf']['LastTraceSource']['Sure'].append(trace_result)
- else: # trace dest
- if appear_dest_or_source:
- G['TraceInf']['LastTraceDest']['Maybe'].append(trace_result)
- elif appear_is_dest:
- G['TraceInf']['LastTraceDest']['Sure'].append(trace_result)
- continue
- # finish get all dest/source
- if trace_type == 'source':
- finded_source_num = len(G['TraceInf']['LastTraceSource']['Sure'])
- finded_maybe_source_num = len(G['TraceInf']['LastTraceSource']['Maybe'])
- # not find signal source
- if not (finded_source_num + finded_maybe_source_num):
- PrintReport("Warning: Not find signal source !")
- return True
- else: # dest
- finded_dest_num = len(G['TraceInf']['LastTraceDest']['Sure'])
- finded_maybe_dest_num = len(G['TraceInf']['LastTraceDest']['Maybe'])
- # not find signal dest
- if not (finded_dest_num + finded_maybe_dest_num):
- PrintReport("Warning: Not find signal dest !")
- return True
- # show source to report win, and go first trace
- PrintReport(spec_case = trace_type)
- View.show_next_trace_result(trace_type)
- return True
- def trace_normal_signal(trace_type, cursor_inf):
- cur_module_inf = cursor_inf['cur_module_inf']
- if not cur_module_inf:
- PrintDebug('Warning: cur file has no module inf, may be no database or cur line not in module, file: %s '%(cursor_inf['file_path']))
- return False
- # just use grep get all signal appear in current file to speed up signal search
- signal_appear_pos_line = search_verilog_code_use_grep( cursor_inf['word'], cursor_inf['file_path'], cur_module_inf['line_range_in_file'] )
- return real_trace_normal_signal(trace_type, signal_appear_pos_line, cursor_inf)
- #----------------------------------------------------
- def trace_glb_define_signal(trace_type, cursor_inf):
- assert(trace_type in ['dest', 'source'])
- cur_line = cursor_inf['line']
- cur_word = cursor_inf['word']
- if cur_line.find('`') == -1:
- return False
- s0 = re.search('(?P<prefix>^|\W)%s(\W|$)'%(cur_word),cur_line)
- if not s0:
- return False
- if s0.group('prefix') != '`':
- return False
- if cur_word not in G['CodeDefineInf']:
- PrintReport('Warning: cur macro: \"%s\", not has find in database !'%(cur_word))
- return True
- cur_define_infs = G['CodeDefineInf'][cur_word]
- clear_last_trace_inf(trace_type)
- for inf in cur_define_infs: # {name path pos code_line}
- file_name = re.sub('.*/','',inf['path'])
- show_str = '%s %d : %s'%(file_name, inf['pos'][0]+1, inf['code_line'])
- file_link = {'key':cur_word, 'pos': inf['pos'], 'path': inf['path']}
- trace_result = {'show': show_str, 'file_link': file_link}
- if trace_type == 'source':
- G['TraceInf']['LastTraceSource']['SignalName'] = cursor_inf['word']
- G['TraceInf']['LastTraceSource']['Path'] = cursor_inf['file_path']
- G['TraceInf']['LastTraceSource']['Sure'].append(trace_result)
- else: # dest
- PrintReport('Warning: cur not support trace macro dest !')
- return True
- # show source to report win, and go first trace
- PrintReport(spec_case = trace_type)
- View.show_next_trace_result(trace_type)
- return True
- """
- https://my.oschina.net/u/2520885
- """
- #===============================================================================
- # Copyright (C) 2016 by Jun Cao
- # Permission is hereby granted, free of charge, to any person obtaining a copy
- # of this software and associated documentation files (the "Software"), to deal
- # in the Software without restriction, including without limitation the rights
- # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- # copies of the Software, and to permit persons to whom the Software is
- # furnished to do so, subject to the following conditions:
- # The above copyright notice and this permission notice shall be included in
- # all copies or substantial portions of the Software.
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- # THE SOFTWARE.
- #===============================================================================
- import sys
- sys.path.append('../')
- import vim_glb_config as glb_config
- import os
- import re
- import pickle
- vim_start_open_file = ''
- try:
- import vim
- vim_start_open_file = vim.current.buffer.name
- except:
- vim_start_open_file = '|vim_not_open|'
- pass
- # cur call path
- cur_path = os.getcwd()
- # find most resent vtags path
- hdl_tags_path = ''
- while cur_path and cur_path[0] == '/':
- if os.path.isdir(cur_path + '/vtags.db'):
- hdl_tags_path = cur_path + '/vtags.db'
- break
- cur_path = re.sub('/[^/]*$','',cur_path)
- # get local config
- config = glb_config
- try:
- if hdl_tags_path:
- sys.path.append(hdl_tags_path)
- import vim_local_config as local_config
- config = local_config
- except:
- pass
- # get next empty frame, report,log report index, first try del Frame, Report
- def del_old_logs():
- ls_a_f = [ f.strip('\n') for f in os.popen('ls -a ' + hdl_tags_path).readlines() ]
- used_log_index = set()
- for f in ls_a_f:
- match_swp = re.match('\.(Frame\.HF|Report\.HF|run\.log)(?P<idx>\d+)\.swp',f)
- if match_swp:
- used_log_index.add(int(match_swp.group('idx')))
- ls_f = [ f.strip('\n') for f in os.popen('ls ' + hdl_tags_path).readlines() ]
- for f in ls_f:
- match_idx = re.match('(Frame\.HF|Report\.HF|run\.log)(?P<idx>\d+)', f)
- if not match_idx:
- continue
- cur_index = int(match_idx.group('idx'))
- if cur_index in used_log_index:
- continue
- os.system('rm %s/%s'%(hdl_tags_path,f) )
- return
- empty_log_index = 0
- if hdl_tags_path:
- del_old_logs()
- while os.path.isfile(hdl_tags_path + '/run.log' + str(empty_log_index)) or \
- os.path.isfile(hdl_tags_path + '/Frame.HF' + str(empty_log_index)) or \
- os.path.isfile(hdl_tags_path + '/Report.HF' + str(empty_log_index)):
- empty_log_index += 1
- # if in generate vtags situation, print log to vtags.db/vtags_run.log
- vtags_run_log_path = ['']
- # run log path
- run_log_path = hdl_tags_path + '/run.log'+str(empty_log_index)
- def PrintDebug( str, out_path = ''):
- if vtags_run_log_path[0]:
- output = open( vtags_run_log_path[0], 'a')
- output.write(str+'\n')
- output.close()
- return
- if not config.debug_mode:
- return
- if out_path:
- output = open( out_path, 'a')
- output.write(str+'\n')
- output.close()
- return
- if hdl_tags_path:
- output = open( run_log_path ,'a')
- output.write(str+'\n')
- output.close()
- def get_file_path_postfix(file_path):
- split_by_dot = file_path.split('.')
- if len(split_by_dot) < 2: # which means file_path has no postfix
- return ''
- post_fix = split_by_dot[-1] # postfix care case
- return post_fix
- HDLTagsActive = True
- # if cur open a valid file, and file not verilog file not act vtags
- if vim_start_open_file \
- and (get_file_path_postfix(vim_start_open_file) not in config.support_verilog_postfix):
- HDLTagsActive = False
- # get file inf
- FileInf = {}
- try:
- if hdl_tags_path and HDLTagsActive:
- import files_inf
- HDLTagsActive = files_inf.HDLTagsActive
- FileInf = files_inf.FileInf
- else:
- HDLTagsActive = False
- except:
- HDLTagsActive = False
- BaseModules = set()
- if HDLTagsActive:
- # get base module inf
- try:
- pkl_input = open(hdl_tags_path + '/base_modules.pkl','rb')
- BaseModules = pickle.load(pkl_input)
- pkl_input.close()
- except:
- pass
- # function -------------------------------------------------
- def save_env_snapshort():
- snapshort = {}
- # 0: save cur dir path, used to quality opne snapshort
- snapshort['snapshort_dir_path'] = os.getcwd()
- # 1: save Frame
- snapshort['frame_file_lines'] = []
- if os.path.isfile(G['Frame_Inf']['Frame_Path']):
- snapshort['frame_file_lines'] = open(G['Frame_Inf']['Frame_Path'],'r').readlines()
- # 2: save Report
- snapshort['report_file_lines'] = []
- if os.path.isfile(G['Report_Inf']['Report_Path']):
- snapshort['report_file_lines'] = open(G['Report_Inf']['Report_Path'],'r').readlines()
- # 3: save G
- snapshort['G'] = {}
- snapshort['G']['OpTraceInf'] = {}
- snapshort['G']['OpTraceInf']['TracePoints'] = G['OpTraceInf']['TracePoints']
- snapshort['G']['OpTraceInf']['Nonius' ] = G['OpTraceInf']['Nonius' ]
- snapshort['G']['WorkWin_Inf'] = {}
- snapshort['G']['WorkWin_Inf']['OpenWinTrace'] = G['WorkWin_Inf']['OpenWinTrace']
- snapshort['G']['VimBufferLineFileLink' ] = G["VimBufferLineFileLink" ]
- snapshort['G']["TraceInf" ] = G['TraceInf']
- snapshort['G']['CheckPointInf'] = {}
- snapshort['G']['CheckPointInf']['CheckPoints'] = G['CheckPointInf']['CheckPoints']
- snapshort['G']['TopoInf'] = {}
- snapshort['G']['TopoInf']['CurModule'] = G['TopoInf']['CurModule']
- snapshort['G']['ModuleLastCallInf'] = G['ModuleLastCallInf']
- snapshort['G']['Frame_Inf'] = {}
- snapshort['G']['Frame_Inf']['Frame_Path'] = G['Frame_Inf']['Frame_Path']
- snapshort['G']['Report_Inf'] = {}
- snapshort['G']['Report_Inf']['Report_Path'] = G['Report_Inf']['Report_Path']
- # 4: save act windows inf
- act_win_inf = []
- for w in vim.windows:
- c_file_path = w.buffer.name
- if c_file_path == vim.current.buffer.name:
- continue
- c_cursor = w.cursor
- c_size = (w.width, w.height)
- act_win_inf.append({'path': c_file_path, 'cursor': c_cursor, 'size': c_size })
- # last is current window
- cur_file_path = vim.current.buffer.name
- cur_cursor = vim.current.window.cursor
- cur_size = (vim.current.window.width, vim.current.window.height)
- act_win_inf.append({'path': cur_file_path, 'cursor': cur_cursor, 'size': cur_size })
- snapshort['act_win_inf'] = act_win_inf
- pkl_output = open(hdl_tags_path + '/env_snapshort.pkl','wb')
- pickle.dump(snapshort, pkl_output)
- pkl_output.close()
- return True
- def reload_env_snapshort(snapshort):
- # 1: reload G
- snapshort_G = snapshort['G']
- G['OpTraceInf']['TracePoints'] = snapshort_G['OpTraceInf']['TracePoints']
- G['OpTraceInf']['Nonius' ] = snapshort_G['OpTraceInf']['Nonius' ]
- G['WorkWin_Inf']['OpenWinTrace'] = snapshort_G['WorkWin_Inf']['OpenWinTrace']
- G['VimBufferLineFileLink' ] = snapshort_G["VimBufferLineFileLink" ]
- G["TraceInf" ] = snapshort_G['TraceInf']
- G['CheckPointInf']['CheckPoints'] = snapshort_G['CheckPointInf']['CheckPoints']
- G['TopoInf']['CurModule'] = snapshort_G['TopoInf']['CurModule']
- G['ModuleLastCallInf'] = snapshort_G['ModuleLastCallInf']
- G['Frame_Inf']['Frame_Path'] = snapshort_G['Frame_Inf']['Frame_Path']
- G['Report_Inf']['Report_Path'] = snapshort_G['Report_Inf']['Report_Path']
- # 2: reload Frame
- os.system('touch ' + G['Frame_Inf']['Frame_Path'])
- assert(os.path.isfile(G['Frame_Inf']['Frame_Path']))
- frame_fp = open(G['Frame_Inf']['Frame_Path'],'w')
- for l in snapshort['frame_file_lines']:
- frame_fp.write(l)
- frame_fp.close()
- # 3: reload Report
- os.system('touch ' + G['Report_Inf']['Report_Path'])
- assert(os.path.isfile(G['Report_Inf']['Report_Path']))
- report_fp = open(G['Report_Inf']['Report_Path'],'w')
- for l in snapshort['report_file_lines']:
- report_fp.write(l)
- report_fp.close()
- # 4: reload act windows inf need re open at API.py
- G['EnvSnapshortWinsInf'] = snapshort['act_win_inf']
- return
- # structure -----------------------------------------------------
- # frame file_link = {
- # 'type' : '', topo | check_point | base_module
- # 'key' : '', topo module name | add check point word | base module name
- # 'pos' : '', module def pos | add pos | module pos
- # 'path' : '', module def file path | add file path | module def file path
- # 'fold_inf' : {}, 'fold_status': on/off/fix
- # , 'level' : n
- #
- # }
- Frame_Inf = {
- "Frame_Win_x" : config.frame_window_width # frame window width
- ,"Frame_Path" : ''
- ,"FoldLevelSpace" : config.frame_fold_level_space
- }
- Frame_Inf['Frame_Path'] = hdl_tags_path + '/' + "Frame.HF" + str(empty_log_index)
- # report file_link = {
- # 'key' : '' , signal_name
- # 'pos' : '' , match_pos
- # 'path' : '' , match_path
- # }
- Report_Inf = {
- "Report_Win_y" : config.report_window_height # report window height
- ,"Report_Path" : hdl_tags_path + '/' + "Report.HF"
- }
- Report_Inf['Report_Path'] = hdl_tags_path + '/' + "Report.HF" + str(empty_log_index)
- WorkWin_Inf ={
- "MaxNum" : config.max_open_work_window_number
- ,"OpenWinTrace" : []
- }
- # all vim buffer line file link { path:[...]}
- VimBufferLineFileLink = {}
- TraceInf = {
- 'LastTraceSource' : {'Maybe':[], 'Sure':[], 'ShowIndex': 0, 'SignalName':'', 'Path':'' } # Maybe[{'show':'', 'file_link':{ 'key':'','pos':(l,c),'path':'' } }]
- ,'LastTraceDest' : {'Maybe':[], 'Sure':[], 'ShowIndex': 0, 'SignalName':'', 'Path':'' }
- ,'TraceSourceOptimizingThreshold' : config.trace_source_optimizing_threshold
- }
- # operation trace
- OpTraceInf = {
- 'TracePoints' : [] # {'path':'', "pos":(line, colum), 'key':''}
- ,'TraceDepth' : config.max_roll_trace_depth
- ,'Nonius' : -1 # roll nonius
- }
- TopoInf = {
- 'CurModule' : ''
- ,'TopFoldLevel' : 0
- }
- CheckPointInf = {
- "MaxNum" : config.max_his_check_point_num
- ,"CheckPoints" : [] #{}--- key: '', link: {}
- ,"TopFoldLevel" : 0
- }
- BaseModuleInf = {
- "BaseModuleThreshold" : config.base_module_threshold # when module inst BaseModuleThreshold times, then default set it to base module
- ,"BaseModules" : BaseModules # module name set()
- ,"TopFoldLevel" : 0
- }
- G = {
- 'HDLTagsActive' : HDLTagsActive
- ,'SupportVHDLPostfix' : set([])
- ,'SupportVerilogPostfix' : set(config.support_verilog_postfix)
- ,'ModuleInf' : {}
- ,'ModuleLastCallInf' : {} # {module_name:{ upper_module_name:'', 'upper_inst_name':inst_name} }
- ,'FileInf' : FileInf
- ,'CodeDefineInf' : {} # {name: [ {name path pos code_line} ]}
- ,'OpTraceInf' : OpTraceInf
- ,"Debug" : config.debug_mode # debug mode
- ,"ShowReport" : config.show_report
- ,"ShowFrame" : config.show_sidebar
- ,"PrintDebug_F" : PrintDebug # function to print debug
- ,"Frame_Inf" : Frame_Inf # Frame window inf
- ,"Report_Inf" : Report_Inf # report window inf
- ,"WorkWin_Inf" : WorkWin_Inf # win config
- ,"VimBufferLineFileLink" : VimBufferLineFileLink
- ,"TraceInf" : TraceInf
- ,"CheckPointInf" : CheckPointInf
- ,"BaseModuleInf" : BaseModuleInf
- ,'TopoInf' : TopoInf
- ,"FixExtraSpace" : True # some situation come extra space, need do nonthing
- ,"IgnoreNextSpaceOp" : False # just flod has a else space, not do space op
- ,"EnvSnapshortWinsInf" : []
- ,"SaveEnvSnapshort_F" : save_env_snapshort
- ,"VTagsPath" : hdl_tags_path
- }
- # has save history sence then just repaly it
- start_with_empty_file = False
- if not vim_start_open_file :
- start_with_empty_file = True
- EnvSnapshort = {}
- if HDLTagsActive and start_with_empty_file and os.path.isfile(hdl_tags_path + '/env_snapshort.pkl'):
- pkl_input = open(hdl_tags_path + '/env_snapshort.pkl','rb')
- c_snapshort = pickle.load(pkl_input)
- if c_snapshort['snapshort_dir_path'] == os.getcwd():
- os.system('echo \'do you want reload vim snapshort ? (y/n): \'')
- yes_or_no = raw_input()
- if yes_or_no.lower() in ['y','yes']:
- EnvSnapshort = c_snapshort
- pkl_input.close()
- if EnvSnapshort:
- reload_env_snapshort(EnvSnapshort)
- """
- https://my.oschina.net/u/2520885
- """
- #===============================================================================
- # Copyright (C) 2016 by Jun Cao
- # Permission is hereby granted, free of charge, to any person obtaining a copy
- # of this software and associated documentation files (the "Software"), to deal
- # in the Software without restriction, including without limitation the rights
- # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- # copies of the Software, and to permit persons to whom the Software is
- # furnished to do so, subject to the following conditions:
- # The above copyright notice and this permission notice shall be included in
- # all copies or substantial portions of the Software.
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- # THE SOFTWARE.
- #===============================================================================
- import sys
- import re
- try:
- import vim
- except:
- pass
- import os
- import re
- from Base import *
- from Win import *
- import GLB
- G = GLB.G
- #--------------------------------------
- SnapshotStack = []
- def snapshort_push():
- cur_cursor = vim.current.window.cursor
- cur_pos = (cur_cursor[0]-1, cur_cursor[1]) # minus 1 because cursor start from 1, and lines start from 0
- cur_line_num = cur_pos[0]
- cur_line = vim.current.buffer[cur_line_num]
- cur_word = get_full_word(cur_line, cur_pos[1])
- cur_file_path = vim.current.buffer.name
- cur_snapshort = {"path": cur_file_path, "pos":cur_pos, "key":cur_word}
- SnapshotStack.append(cur_snapshort)
- def snapshort_pop():
- pop_snapshort = SnapshotStack[-1]
- del SnapshotStack[-1]
- go_win( pop_snapshort['path'], pop_snapshort['pos'], pop_snapshort['key'])
- #--------------------------------------
- def Show(path): # just show frame win , and not go to that window
- path = get_path_for_name(path)
- Act_Win = Cur_Act_Win()
- if path not in Act_Win:
- snapshort_push()
- Open(path)
- snapshort_pop()
- return
- #--------------------------------------
- def add_trace_point():
- cur_cursor = vim.current.window.cursor
- cur_file_path = vim.current.buffer.name
- if cur_file_path in [ G['Frame_Inf']['Frame_Path'], G['Report_Inf']['Report_Path'] ]:
- PrintDebug('Warning: Frame and Report not add trace point !')
- return
- cur_pos = (cur_cursor[0]-1, cur_cursor[1]) # minus 1 because cursor start from 1, and lines start from 0
- cur_line_num = cur_pos[0]
- cur_line = vim.current.buffer[cur_line_num]
- cur_word = get_full_word(cur_line, cur_pos[1])
- cur_trace_point = {"path": cur_file_path, "pos":cur_pos, "key":cur_word}
- cur_nonius = G['OpTraceInf']['Nonius']
- TracePoints = G['OpTraceInf']['TracePoints']
- # when roll back, and add from middle of queue, just clear old trace point after cur insert index
- # | 0 | 1 | 2 | 3 | 4 |
- # ^ if len 5, nonius <= 3 then del 4
- if cur_nonius <= (len(TracePoints) - 2):
- del TracePoints[cur_nonius + 1 : ]
- # add a new point to TracePoints
- # if cur add is equ to pre not add
- if not TracePoints:
- TracePoints.append(cur_trace_point)
- else:
- pre_point = TracePoints[-1]
- if cur_trace_point != pre_point:
- TracePoints.append(cur_trace_point)
- # if length bigger than TraceDepth del
- TraceDepth = G['OpTraceInf']['TraceDepth']
- while (len(TracePoints) > TraceDepth):
- del TracePoints[0]
- # if add new point ,nonius assign to len(TracePoints)
- # | 0 | 1 | 2 | 3 | 4 |
- # ^ because roll back will first sub 1
- G['OpTraceInf']['Nonius'] = len(TracePoints)
- def get_cur_cursor_inf():
- cur_cursor = vim.current.window.cursor
- cur_line_num = cur_cursor[0] - 1 # minus 1 because cursor start from 1, and lines start from 0
- cur_colm_num = cur_cursor[1]
- cur_line = vim.current.buffer[cur_line_num]
- cur_word = get_full_word(cur_line, cur_cursor[1])
- cur_codes = vim.current.buffer
- cur_file_path = vim.current.buffer.name
- cur_hdl_type = get_file_hdl_type(cur_file_path)
- cur_call_sub_inf = {}
- cur_module_inf = {}
- cur_line_inf = get_file_line_inf(cur_line_num, cur_file_path)
- if cur_line_inf:
- cur_call_sub_inf = cur_line_inf['line_call_sub_inf']
- cur_module_inf = cur_line_inf['line_module_inf']
- cur_module_name = ''
- if cur_module_inf:
- cur_module_name = cur_module_inf['module_name']
- else:
- PrintDebug('Warning: get_cur_cursor_inf: current cursor %s not in module, file: %s ! '%(cur_cursor.__str__(), cur_file_path ))
- return { 'cursor' : cur_cursor
- ,'pos' : (cur_line_num, cur_colm_num)
- ,'line_num' : cur_line_num
- ,'colm_num' : cur_colm_num
- ,'line' : cur_line
- ,'word' : cur_word
- ,'file_path' : cur_file_path
- ,'hdl_type' : cur_hdl_type
- ,'cur_call_sub_inf' : cur_call_sub_inf
- ,'cur_module_inf' : cur_module_inf
- ,'codes' : cur_codes }
- # ok
- # report file_link = {
- # 'key' : '' , signal_name
- # 'pos' : '' , match_pos
- # 'path' : '' , match_path
- # }
- #----for python edition 2.7 +
- # def PrintReport(*show, file_link = {}, spec_case = '', mode = 'a'):
- # # normal show a string
- # show_str = ' '.join([ i.__str__() for i in show ])
- #----for python edition 2.6
- def PrintReport(show = '', file_link = {}, spec_case = '', mode = 'a'):
- if not G['ShowReport']:
- return
- has_self_snap_short = False
- if not cur_in_report():
- snapshort_push()
- Open('Report')
- has_self_snap_short = True
- show_str = show
- if show_str:
- edit_vim_buffer('Report', [show_str], file_links = [file_link], mode = mode)
- # show trace source result
- if spec_case == 'source':
- edit_vim_buffer('Report', "---------------------------source--------------------------------")
- t_data = []
- t_file_link = []
- for Sure in G['TraceInf']['LastTraceSource']['Sure']:
- t_data.append( Sure['show'] )
- t_file_link.append( Sure['file_link'] )
- edit_vim_buffer('Report', t_data, t_file_link)
- edit_vim_buffer('Report', "------------------------maybe source-----------------------------")
- t_data = []
- t_file_link = []
- for Maybe in G['TraceInf']['LastTraceSource']['Maybe']:
- t_data.append( Maybe['show'] )
- t_file_link.append( Maybe['file_link'] )
- edit_vim_buffer('Report', t_data, t_file_link)
- edit_vim_buffer('Report', "----------------------------END----------------------------------")
- edit_vim_buffer('Report', "")
- # show trace dest result
- if spec_case == 'dest':
- edit_vim_buffer('Report', "---------------------------dest--------------------------------")
- t_data = []
- t_file_link = []
- for Sure in G['TraceInf']['LastTraceDest']['Sure']:
- t_data.append( Sure['show'] )
- t_file_link.append( Sure['file_link'] )
- edit_vim_buffer('Report', t_data, t_file_link)
- edit_vim_buffer('Report', "------------------------maybe dest-----------------------------")
- t_data = []
- t_file_link = []
- for Maybe in G['TraceInf']['LastTraceDest']['Maybe']:
- t_data.append( Maybe['show'] )
- t_file_link.append( Maybe['file_link'] )
- edit_vim_buffer('Report', t_data, t_file_link)
- edit_vim_buffer('Report', "----------------------------END----------------------------------")
- edit_vim_buffer('Report', "")
- # go report to the last line, and return
- assert(cur_in_report())
- # if mode == 'a':
- vim.current.window.cursor = (len(vim.current.buffer) - 1 , 0)
- vim.command('w!')
- if has_self_snap_short:
- snapshort_pop()
- # ok
- def show_next_trace_result( trace_type ):
- if trace_type == 'source':
- cur_show_index = G['TraceInf']['LastTraceSource']["ShowIndex"]
- sure_source_len = len(G['TraceInf']['LastTraceSource']['Sure'])
- maybe_source_len = len(G['TraceInf']['LastTraceSource']['Maybe'])
- if (sure_source_len + maybe_source_len) == 0:
- PrintReport('not find source !')
- return
- cur_file_link = {}
- if cur_show_index < sure_source_len:
- cur_file_link = G['TraceInf']['LastTraceSource']['Sure'][cur_show_index]['file_link']
- else:
- cur_file_link = G['TraceInf']['LastTraceSource']['Maybe'][cur_show_index - sure_source_len]['file_link']
- G['TraceInf']['LastTraceSource']["ShowIndex"] = (cur_show_index + 1) % (sure_source_len + maybe_source_len)
- add_trace_point()
- go_win( cur_file_link['path'], cur_file_link['pos'], cur_file_link['key'] )
- elif trace_type == 'dest':
- cur_show_index = G['TraceInf']['LastTraceDest']["ShowIndex"]
- sure_dest_len = len(G['TraceInf']['LastTraceDest']['Sure'])
- maybe_dest_len = len(G['TraceInf']['LastTraceDest']['Maybe'])
- if (sure_dest_len + maybe_dest_len) == 0:
- PrintReport('not find dest !')
- return
- cur_file_link = {}
- if cur_show_index < sure_dest_len:
- cur_file_link = G['TraceInf']['LastTraceDest']['Sure'][cur_show_index]['file_link']
- else:
- cur_file_link = G['TraceInf']['LastTraceDest']['Maybe'][cur_show_index - sure_dest_len]['file_link']
- G['TraceInf']['LastTraceDest']["ShowIndex"] = (cur_show_index + 1) % (sure_dest_len + maybe_dest_len)
- add_trace_point()
- go_win( cur_file_link['path'], cur_file_link['pos'], cur_file_link['key'])
- else:
- assert(0)
- #--------------------------------------------------------------------------
- def gen_top_topo_data_link(topo_module):
- topo_datas = []
- topo_links = []
- topo_module_inf = get_module_inf(topo_module)
- if not topo_module_inf:
- PrintDebug('Error: get topo module name %s, should has module inf !'%(topo_module))
- return topo_datas, topo_links
- TopTopoLevel = G['TopoInf']['TopFoldLevel']
- TopTopoPrefix = G['Frame_Inf']['FoldLevelSpace'] * TopTopoLevel
- # add first topo line
- topo_datas.append(TopTopoPrefix + 'ModuleTopo:')
- topo_link = {
- 'type' : 'topo'
- ,'topo_inst_name' : ''
- ,'key' : ''
- ,'pos' : ''
- ,'path' : ''
- ,'fold_inf' : {'fold_status':'on', 'level': TopTopoLevel - 1 }
- }
- topo_links.append(topo_link)
- # add cur module name
- topo_datas.append(TopTopoPrefix + topo_module + ':')
- topo_link = {
- 'type' : 'topo'
- ,'topo_inst_name' : ''
- ,'key' : topo_module
- ,'pos' : topo_module_inf['module_pos']
- ,'path' : topo_module_inf['file_path']
- ,'fold_inf' : {'fold_status':'on', 'level': TopTopoLevel}
- }
- topo_links.append(topo_link)
- # gen current module sub function module, and base module topo inf
- sub_module_data, sub_module_link = get_fram_topo_sub_inf(topo_module, 0)
- topo_datas = topo_datas + sub_module_data
- topo_links = topo_links + sub_module_link
- return topo_datas, topo_links
- def edit_frame(data = [], file_links = [], mode = 'a', n = 0, del_range = ()):
- has_self_snap_short = False
- if not cur_in_frame():
- snapshort_push()
- Open('Frame')
- has_self_snap_short = True
- edit_vim_buffer( path_or_name = 'Frame', data = data, file_links = file_links, mode = mode, n = n, del_range = del_range)
- # go frame w! and go back
- assert(cur_in_frame())
- vim.command('w!')
- if has_self_snap_short:
- snapshort_pop()
- #---------------------------------------
- def show_base_module(fold = True):
- frame_data = []
- frame_link = []
- # if frame not show ,show it
- Show("Frame")
- # add initial line
- level = G['BaseModuleInf']['TopFoldLevel']
- key = G['Frame_Inf']['FoldLevelSpace']*level + 'BaseModules:'
- link = {
- 'type' : 'base_module'
- ,'key' : ''
- ,'pos' : ''
- ,'path' : ''
- ,'fold_inf' : { 'fold_status': 'on', 'level': level }
- }
- frame_data.append(key)
- frame_link.append(link)
- # add check points
- range_inf = get_frame_range_inf()
- has_base_module = range_inf['has_base_module']
- base_module_range = range_inf['base_module_range']
- cp_data = []
- cp_link = []
- if fold:
- cp_data, cp_link = get_fram_base_module_inf()
- else:
- frame_link[-1]['fold_inf']['fold_status'] = 'off'
- frame_data = frame_data + cp_data
- frame_link = frame_link + cp_link
- # del old cp, add new cp
- if has_base_module: # del
- edit_frame(mode = 'del', del_range = base_module_range)
- edit_frame(data = frame_data, file_links = frame_link, mode = 'i', n = base_module_range[0])
- return True
- #-------------------------------------
- def show_check_point(fold = True):
- frame_data = []
- frame_link = []
- # if frame not show ,show it
- Show("Frame")
- # add initial line
- level = G['CheckPointInf']['TopFoldLevel']
- key = G['Frame_Inf']['FoldLevelSpace']*level + 'CheckPoints:'
- link = {
- 'type' : 'check_point'
- ,'key' : ''
- ,'pos' : ''
- ,'path' : ''
- ,'fold_inf' : { 'fold_status': 'on', 'level': level }
- }
- frame_data.append(key)
- frame_link.append(link)
- # add check points
- range_inf = get_frame_range_inf()
- has_check_point = range_inf['has_check_point']
- check_point_range = range_inf['check_point_range']
- cp_data = []
- cp_link = []
- if fold:
- cp_data, cp_link = get_fram_check_point_inf()
- else:
- frame_link[-1]['fold_inf']['fold_status'] = 'off'
- frame_data = frame_data + cp_data
- frame_link = frame_link + cp_link
- # del old cp, add new cp
- if has_check_point: # del
- edit_frame(mode = 'del', del_range = check_point_range)
- edit_frame(data = frame_data, file_links = frame_link, mode = 'i', n = check_point_range[0])
- return True
- #---------------------------------------
- def show_topo(topo_module_name = ''):
- if not topo_module_name:
- cursor_inf = get_cur_cursor_inf()
- if cursor_inf['hdl_type'] != 'verilog':
- # if not in support file type(verilog,vhdl) just return
- PrintReport("Warning: Current only support verilog !")
- return False
- # get current module inf
- cur_module_inf = cursor_inf['cur_module_inf']
- # current not at module lines, just return
- if not cur_module_inf:
- PrintReport("Warning: Current cursor not in valid module !")
- return False
- topo_module_name = cur_module_inf['module_name']
- else:
- if topo_module_name not in G['ModuleInf']:
- PrintReport("Warning: show topo module %s not have database !"%(topo_module_name))
- return False
- # if frame not show ,show it
- Show("Frame")
- # current module must has module inf
- G['TopoInf']['CurModule'] = topo_module_name # note cur topo name for refresh
- range_inf = get_frame_range_inf()
- has_topo = range_inf['has_topo']
- topo_range = range_inf['topo_range']
- topo_data, topo_link = gen_top_topo_data_link(topo_module_name)
- # del old topo, add new topo
- if has_topo: # del
- edit_frame(mode = 'del', del_range = topo_range)
- edit_frame(data = topo_data, file_links = topo_link, mode = 'i', n = topo_range[0])
- return True
- def iteration_fold_no_module(inst_module_pairs, base_modules):
- c_frame_range_inf = get_frame_range_inf()
- if not c_frame_range_inf['has_topo']:
- return
- frame_path = G['Frame_Inf']['Frame_Path']
- c_topo_range = c_frame_range_inf['topo_range']
- c_topo_links = G['VimBufferLineFileLink'][frame_path][c_topo_range[0] : c_topo_range[1]]
- for i,lk in enumerate(c_topo_links):
- if not( lk and (lk['fold_inf']['fold_status'] == 'off') and lk['key'] ):
- continue
- if lk['topo_inst_name']:
- c_inst_module_pair = (lk['topo_inst_name'], lk['key'])
- if c_inst_module_pair in inst_module_pairs:
- fold_frame_line(lk, i+c_topo_range[0], lk['fold_inf']['level'], 'topo')
- iteration_fold_no_module(inst_module_pairs, base_modules)
- return
- else:
- if lk['key'] in base_modules:
- fold_frame_line(lk, i+c_topo_range[0], lk['fold_inf']['level'], 'topo')
- iteration_fold_no_module(inst_module_pairs, base_modules)
- return
- return
- def refresh_topo():
- # get all folded module or inst pair
- old_frame_range_inf = get_frame_range_inf()
- if not old_frame_range_inf['has_topo']:
- return
- frame_path = G['Frame_Inf']['Frame_Path']
- old_topo_range = old_frame_range_inf['topo_range']
- old_topo_links = G['VimBufferLineFileLink'][frame_path][old_topo_range[0] + 2 : old_topo_range[1] + 1]
- old_fold_inst_module_pairs = set()
- old_fold_base_modules = set()
- for lk in old_topo_links:
- if not( lk and (lk['fold_inf']['fold_status'] == 'on') and lk['key'] ):
- continue
- if lk['topo_inst_name']:
- old_fold_inst_module_pairs.add( (lk['topo_inst_name'], lk['key']) )
- else:
- if lk['key'] in G['BaseModuleInf']['BaseModules']:
- old_fold_base_modules.add(lk['key'])
- # start new topo
- new_topo_module_name = G['TopoInf']['CurModule']
- show_topo(new_topo_module_name)
- # iteration opened old folded topo
- iteration_fold_no_module(old_fold_inst_module_pairs, old_fold_base_modules)
- #---------------------------------------
- def unfold_frame_line(frame_links, frame_line, cur_frame_level, cur_frame_type):
- assert(frame_links[frame_line]['fold_inf']['fold_status'] == 'on')
- G['VimBufferLineFileLink'][ G['Frame_Inf']['Frame_Path'] ][frame_line]['fold_inf']['fold_status'] = 'off'
- unfold_end_line_num = frame_line
- for i in range(frame_line+1, len(frame_links)):
- # if cur not have file link, then cur is unflod end
- if not frame_links[i]:
- unfold_end_line_num = i - 1
- break
- # if has file link ,but not topo inf then unflod end
- if frame_links[i]['type'] != cur_frame_type:
- unfold_end_line_num = i - 1
- break
- # if is topo , but level <= cur level then unflod end
- if frame_links[i]['fold_inf']['level'] <= cur_frame_level:
- unfold_end_line_num = i - 1
- break
- # if cur module has no sub module then just return
- if unfold_end_line_num == frame_line:
- return True
- # else edit the frame buffer and file link, del the unflod lines
- if unfold_end_line_num > frame_line:
- edit_frame(mode = 'del', del_range = (frame_line + 1, unfold_end_line_num))
- return True
- # else some trouble
- assert(0),'shold not happen !'
- def fold_frame_line(cur_line_link, frame_line, cur_frame_level, cur_frame_type):
- assert(cur_line_link['fold_inf']['fold_status'] == 'off')
- G['VimBufferLineFileLink'][ G['Frame_Inf']['Frame_Path'] ][frame_line]['fold_inf']['fold_status'] = 'on'
- if cur_frame_type == 'topo':
- # if cur is ModuleTopo: line, show refresh topo
- if cur_frame_level == G['TopoInf']['TopFoldLevel'] - 1:
- topo_module_name = G['TopoInf']['CurModule']
- show_topo(topo_module_name)
- return
- # cur_line_link['key'] is the cur topo line module name
- cur_module_name = cur_line_link['key']
- if not cur_module_name:
- PrintReport('Warning: cur topo line has no module name !')
- return
- if cur_module_name not in G['ModuleInf']:
- PrintReport('Warning: cur module: \"%s\" has no database !'%(cur_module_name))
- return
- # get cur module sub module inf
- sub_topo_data, sub_topo_link = get_fram_topo_sub_inf(cur_module_name, cur_frame_level)
- # add cur module topo inf to frame
- edit_frame(data = sub_topo_data, file_links = sub_topo_link, mode = 'i', n = frame_line + 1)
- elif cur_frame_type == 'check_point':
- show_check_point()
- elif cur_frame_type == 'base_module':
- show_base_module()
- else:
- PrintReport('Warning: no operation in this line !')
- return
- def frame_line_fold_operation(frame_line):
- frame_path = G['Frame_Inf']['Frame_Path']
- frame_links = G['VimBufferLineFileLink'][frame_path]
- cur_line_link = frame_links[frame_line]
- if not cur_line_link :
- PrintReport('Warning: cur frame line no fold operation !')
- return
- cur_frame_type = cur_line_link['type']
- cur_frame_level = cur_line_link['fold_inf']['level']
- cur_fold_state = cur_line_link['fold_inf']['fold_status']
- if cur_fold_state == 'off':
- fold_frame_line(cur_line_link, frame_line, cur_frame_level, cur_frame_type)
- elif cur_fold_state == 'on':
- unfold_frame_line(frame_links, frame_line, cur_frame_level, cur_frame_type)
- else:
- PrintReport('Warning: cur frame line no fold operation !')
- return
- """
- https://my.oschina.net/u/2520885
- """
- #===============================================================================
- # Copyright (C) 2016 by Jun Cao
- # Permission is hereby granted, free of charge, to any person obtaining a copy
- # of this software and associated documentation files (the "Software"), to deal
- # in the Software without restriction, including without limitation the rights
- # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- # copies of the Software, and to permit persons to whom the Software is
- # furnished to do so, subject to the following conditions:
- # The above copyright notice and this permission notice shall be included in
- # all copies or substantial portions of the Software.
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- # THE SOFTWARE.
- #===============================================================================
- try:
- import vim
- except:
- pass
- import sys
- import re
- import os
- import GLB
- G = GLB.G
- from Base import *
- def Reset_Win_Size():
- cur_act_wins = Cur_Act_Win()
- if G['Report_Inf']['Report_Path'] in cur_act_wins:
- Jump_To_Win(G['Report_Inf']['Report_Path'])
- vim.command('wincmd J')
- vim.current.window.height = G['Report_Inf']['Report_Win_y']
- if G['Frame_Inf']['Frame_Path'] in cur_act_wins:
- Jump_To_Win(G['Frame_Inf']['Frame_Path'])
- vim.command('wincmd H')
- vim.current.window.width = G['Frame_Inf']['Frame_Win_x']
- return
- def Refresh_OpenWinTrace():
- cur_act_win_path = Cur_Act_Win()
- cur_act_work_win_path = cur_act_win_path - set([ G["Report_Inf"]["Report_Path"], G["Frame_Inf"]["Frame_Path"] ])
- i = 0
- while i < len(G['WorkWin_Inf']['OpenWinTrace']) :
- c_path = G['WorkWin_Inf']['OpenWinTrace'][i]
- if c_path not in cur_act_work_win_path:
- del G['WorkWin_Inf']['OpenWinTrace'][i]
- else:
- i += 1
- return
- def Cur_Act_Win():
- Act_Win = set()
- for w in vim.windows:
- Act_Win.add(w.buffer.name)
- return Act_Win
- def Open(name):
- path = get_path_for_name(name)
- Act_Win = Cur_Act_Win()
- if path in Act_Win: # win has open and just jump to than window
- Jump_To_Win(path)
- elif path == G['Frame_Inf']["Frame_Path"]:
- Open_Frame_Win()
- elif path == G['Report_Inf']["Report_Path"]:
- Open_Report_Win()
- else:
- Open_Work_Win(path)
- Reset_Win_Size()
- Jump_To_Win(path)
- assert(vim.current.buffer.name == path)
- def Jump_To_Win(path):
- cur_act_wins = Cur_Act_Win()
- assert(path in cur_act_wins)
- start_path = vim.current.buffer.name
- if start_path == path:
- return
- vim.command('wincmd w')
- cur_path = vim.current.buffer.name
- while cur_path != start_path:
- if cur_path == path:
- break
- vim.command("wincmd w")
- cur_path = vim.current.buffer.name
- assert(vim.current.buffer.name == path),'vim.current.buffer.name: %s, path: %s'%(vim.current.buffer.name, path)
- def Open_Frame_Win():
- G['VimBufferLineFileLink'].setdefault(G["Frame_Inf"]["Frame_Path"],[{}])
- vim.command("vertical topleft sp " + G["Frame_Inf"]["Frame_Path"])
- def Open_Report_Win():
- G['VimBufferLineFileLink'].setdefault(G["Report_Inf"]["Report_Path"],[{}])
- vim.command("bot sp " + G["Report_Inf"]["Report_Path"])
- if G["Frame_Inf"]["Frame_Path"] in Cur_Act_Win():
- Jump_To_Win(G["Frame_Inf"]["Frame_Path"])
- vim.command('wincmd H')
- Jump_To_Win(G["Report_Inf"]["Report_Path"])
- def Open_Work_Win(path):
- # path must valid
- assert(os.path.isfile(path))
- # refresh open work win trace
- Refresh_OpenWinTrace()
- # leave at most G['WorkWin_Inf']['MaxNum'] work win
- win_num_need_to_close = len(G['WorkWin_Inf']['OpenWinTrace']) - G['WorkWin_Inf']['MaxNum']
- for i in range(win_num_need_to_close):
- win_path_need_close = G['WorkWin_Inf']['OpenWinTrace'][i]
- Jump_To_Win(win_path_need_close)
- vim.command('q')
- del G['WorkWin_Inf']['OpenWinTrace'][i]
- # if has work win
- cur_work_win_num = len(G['WorkWin_Inf']['OpenWinTrace'])
- if cur_work_win_num > 0:
- # case 0: has work win, and num less than max
- # just go last work win, and vsp a new win
- if cur_work_win_num < G['WorkWin_Inf']['MaxNum']:
- Jump_To_Win(G['WorkWin_Inf']['OpenWinTrace'][-1])
- vim.command('vsp '+path)
- else: # case 1: opened all work win, just replace the oldest open work win
- Jump_To_Win(G['WorkWin_Inf']['OpenWinTrace'][0])
- vim.command('e '+path)
- del G['WorkWin_Inf']['OpenWinTrace'][0] # replace [0], just del old
- else: # cur no work win
- cur_act_win_paths = Cur_Act_Win()
- cur_act_hold_wins = cur_act_win_paths - set([G["Report_Inf"]["Report_Path"], G["Frame_Inf"]["Frame_Path"]])
- # if has hold win, go hold win, vsp
- if cur_act_hold_wins:
- Jump_To_Win(list(cur_act_hold_wins)[0])
- vim.command('vsp '+path)
- elif G["Report_Inf"]["Report_Path"] in cur_act_win_paths:
- # if no hold win, has report , go report sp new
- Jump_To_Win(G["Report_Inf"]["Report_Path"])
- vim.command('sp '+path)
- else:
- vim.command('vsp '+path)
- # finial add path to trace
- assert(vim.current.buffer.name == path)
- G['WorkWin_Inf']['OpenWinTrace'].append(path)
- def get_file_vim_buffer(path):
- for i,b in enumerate(vim.buffers):
- if b.name == path:
- return b
- # path buffer not open
- vim.command("bad "+path)
- assert(vim.buffers[ len(vim.buffers) - 1].name == path)
- return vim.buffers[ len(vim.buffers) - 1]
- # edit the vim buffer, with put data at some position
- # mode : a --after : append data after current buffer data
- # b --before : append data before current buffer data
- # w --write : clear old buffer data, and write data
- # i --insert : inster list to n
- # del -- delete : delete del_range lines
- # del_range : (start,end) del range, include end
- def edit_vim_buffer(path_or_name = '', data = [], file_links = [], mode = 'a', n = 0, del_range = ()):
- # weather to edit link buffer
- need_edit_buffer_file_link = False
- if data == [] and mode != 'del':
- PrintDebug('Warning: edit_vim_buffer: edit file with empty data= [], file:%s !'%(path_or_name))
- return
- if type(data) is str:
- data = [data]
- path = get_path_for_name(path_or_name)
- # some time edit other buffer, may change cur window cursor or add empty line to cur buffer file,
- # so must edit current buffer
- assert(vim.current.buffer.name == path),'%s,%s'%(vim.current.buffer.name, path)
- if path in [G['Report_Inf']['Report_Path'], G['Frame_Inf']['Frame_Path']]:
- need_edit_buffer_file_link = True
- if file_links:
- assert(len(data) == len(file_links))
- else:
- file_links = [ {} for i in range(len(data))]
- # PrintDebug('edit_vim_buffer path_or_name:'+path_or_name)
- # PrintDebug('edit_vim_buffer data:'+data.__str__())
- # PrintDebug('edit_vim_buffer file_links:'+file_links.__str__())
- # PrintDebug('edit_vim_buffer mode:'+mode.__str__())
- # PrintDebug('edit_vim_buffer n:'+n.__str__())
- # PrintDebug('edit_vim_buffer del_range:'+del_range.__str__())
- t_buffer = get_file_vim_buffer(path)
- assert(t_buffer)
- if mode is 'w':
- del t_buffer[:]
- t_buffer.append(data)
- del t_buffer[:1]
- if need_edit_buffer_file_link:
- G["VimBufferLineFileLink"][path] = file_links
- elif mode is 'a':
- t_buffer.append(data)
- if need_edit_buffer_file_link:
- G["VimBufferLineFileLink"].setdefault(path,[])
- G["VimBufferLineFileLink"][path] = G["VimBufferLineFileLink"][path] + file_links
- elif mode is 'b':
- t_buffer.append(data, 0)
- if need_edit_buffer_file_link:
- G["VimBufferLineFileLink"].setdefault(path,[])
- G["VimBufferLineFileLink"][path] = file_links + G["VimBufferLineFileLink"][path]
- elif mode is 'i':
- while len(t_buffer) <= n+1:
- t_buffer.append('')
- if need_edit_buffer_file_link:
- G["VimBufferLineFileLink"][path].append({})
- t_buffer.append(data, n)
- if need_edit_buffer_file_link:
- G["VimBufferLineFileLink"].setdefault(path,[])
- G["VimBufferLineFileLink"][path] = G["VimBufferLineFileLink"][path][:n] + file_links + G["VimBufferLineFileLink"][path][n:]
- elif mode is 'del':
- assert(del_range != () )
- if type(del_range) is int:
- del t_buffer[del_range]
- del G["VimBufferLineFileLink"][path][del_range]
- elif type(del_range) in [ tuple, list ]:
- del t_buffer[del_range[0]:del_range[1]+1]
- del G["VimBufferLineFileLink"][path][del_range[0]:del_range[1]+1]
- else:
- assert(0)
- def go_win( path_or_name = '', pos = (), search_word = ''):
- if not path_or_name:
- return
- # path_or_name = vim.current.buffer.name
- Open(path_or_name)
- if re.search('\w+',search_word):
- vim.current.window.cursor = (1,0) # search from top in case match to left vim warning
- vim.command('/\c\<'+search_word+'\>')
- if pos:
- cursor = (pos[0]+1, pos[1])
- vim.current.window.cursor = cursor
- ############################################################################
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。