[Из песочницы] Настройка Sublime Text 3 для работы с VHDL файлами
Работа с VHDL в Sublime Text 3
Редактор Sublime Text существенно экономит время при работе с vhdl и verilog файлами. Для тех, кто не работал с редакторами типа Sublime Text, Notepad++ и т.п. опишу основные полезные функции данных редакторов:
- множественное выделение/редактирование строк кода (нажатие средней кнопки мыши или при зажатой клавише Ctrl)
- установка меток (закладок) в коде, помогает ориентироваться в больших файлах. (Ctrl + F2 или через пункт меню Goto→ Bookmarks)
- возможность разделения рабочей области на несколько окон (Alt + Shift + 2 или из меню View→ Layout)
- открытие одного файла несколько раз (File→ New View into File)
- комментирование выделенных строк кода (Ctrl + /)
- поиск и замена (Ctrl + h)
- поиск по всем открытым файлам (Ctrl+Shift+f)
- вставка сниппетов (шаблонов кода) (написать ключевое слово + клавиша Tab)
- написание и использование функций на языке python
- возможность установки различных дополнений
- гибкая настройка
Интеграция Sublime Text
Для начала состыкуем САПР для работы с ПЛИС и редактор Sublime.
- Интеграция Sublime Text с Xilinx ISE:
в ISE идем в меню Edit → Preferences → Editors: Text Editor → Editor = Custom
Вставляем строку в окно «Command line syntax»:{C:\Program Files\Sublime Text 3\sublime_text.exe} $1
- Интеграция Sublime Text с Xilinx Vivado:
Tools → Options → Text Editor → Current Editor: Sublime
или
Tools → Options → Text Editor → Current Editor: Custom Editor
Указываем путь до редактора, например:C:\Program Files\Sublime Text 3\sublime_text.exe [file name]
Плагины
Различные плагины (packages) расширяют функциональность редактора. Packages можно
устанавливать как в онлайн так и оффлайн-режиме.
Для установки плагинов в офлайн-режиме нужно проделать нехитрые манипуляции:
- скачиваем нужный плагин с GitHub
- извлекаем из архива
- переименовываем папку, например, «Sublime-HDL-master» в «Sublime HDL»
- Полученные папки копируем в папку Packages (расположение данной папки легко найти, выбрав в Sublime Text пункт меню Preferences → Browse Packages)
SyncViewScroll — плагин для синхронизации вертикальной и горизонтальной прокрутки при работе в нескольких окнах. Для работы плагина надо для каждого окна выбрать в меню View→ Sync Scroll.
Text Pastry — плагин для автоматической множественной нумерации. Очень помогает при работе с большим количеством нумерованных сигналов/портов.
- выделяем нужные участки строк
- Вызываем меню Ctrl+Shift+P
- Ищем пункт «Text Pasty Command Line»
- В появившемся окне, расположенном в нижней части экрана, вводим:
- 0 — нумерация от 0
- \i (1,10) — нумерация от 1 с инкрементом 10
- 1 end=4 — нумерация 1, 2, 3, 4, 1, 2, 3, 4 и т.д.
- letters a-c upper — A, B, C, A, B, C, и т.д.
- letters a-c upper x3 — A, A, A, B, B, B, C, C, C и т.д.
- 1×3 — 1, 1, 1, 2, 2, 2, 3, 3, 3, и т.д.
- x y z — x, y, z, x, y, z, x, y, z, и т.д.
Sublime Verilog — поддержка синтаксиса языка Verilog
Verilog Gadget — набор функций и сниппетов для работы с Verilog файлами.
SmartVHDL — поддержка синтаксиса языка VHDL. Также при наведении на сигнал или порт в коде появится окно с подсказкой о типе (количество бит) данного сигнала/порта. При наведении на сигнал в контекстном меню появится пункт «Goto Definishion» — переход к месту объявления сигнала.
VHDL Mode — набор функций и сниппетов для работы с VHDL файлами. Основная часть функций запускается, например, сочетанием клавиш Atl+K, C, P, где C и P нажимаются поочередно. Основные функции:
- Копирование данных портов (названия портов, типы данных)
- Вставка данных портов как объявление сигналов
- Вставка данных портов как объявление компонента
- Генерация тестбенча по скопированным данным портов
- Автоформатирование кода (выравнивание табуляции и т.п.)
Поддержка ucf файлов
По умолчанию редактор Sublime не у меет работать с ucf-файлами. Разметка ucf эквивалентна разметке языка tcl. Осталось только объяснить это редактору:
- Создадим в папке Packages новый файл Tcl.sublime-settings
- Заполним файл строкой
{"extensions" : ["ucf"]}
- Сохраним файл
Создание шаблонов кода (snippets)
Пусть нам надо вставить шаблон кода:
My_proc : Process(clk, rst, data_in)
begin
if(clk'event and clk = '1') then
if(rst = '1') then
else then -- rst = 0
end if; -- data_in
end if;--clk
end process My_proc;
Причем нам бы хотелось, чтобы после вставки текста по нажатию Tab курсор устанавливался на позиции My_proc, clk, rst, data_in, для быстрого изменения значений этих данных. Для этого создадим новый сниппет: Tools → Developer → New Snippet. Редактируем данные:
process rst
} : Process(${2:clk}, ${3:rst}, ${4:data_in})
begin
if($2'event and $2 = '1') then
if($3 = '1') then
${5}
else then -- $3 = 0
$0
end if; -- $4
end if;--$2
end process $1;
]]>
procrst
source.vhdl
Сохраняем данный сниппет. Теперь при написании ключевого слова procrst в текущую позицию курсора будет вставлен наш шаблон.
Подробнее о создании шаблонов читайте в статье «Как создать сниппет?».
Написание собственных функций на языке python
Подробно о создании функций (плагинов) описывалось в статьях «Как написать простой плагин», «Как написать сложный плагин».
Вставка сниппетов это, конечно хорошо, но хотелось бы, например, чтобы тот же шаблон создания процесса заполнялся автоматически в зависимости от входных сигналов, а также чтобы процесс модифицировался при наличии таких сигналов как rst и ce. Еще обычно после процесса идет присвоение внешним портам модуля значений внутренних сигналов, пусть тоже делается автоматически.
Для парсинга данных файла VHDL воспользуемся функциями плагина Vhdl mode.
Примерный алгоритм наших действий:
- Получить данные о всех портах модуля
- Все порты типа «in» включить в шапку процесса
- Если есть порты с названием ce и/или rst, то добавить соответствующие условия if else в процесс
- За процессом вставить строки присвоения выходным портам значений внутренних сигналов (обычно такие сигналы называют также как и порт, добавляя приставку «s_» или »_net»)
Для начала создадим новый сниппет:
procclk
source.vhdl
process clk
Здесь ${DATAINPORTS} — метка, куда будет вставлено описание процесса,
${OUTPORTS} — метка, где будет присвоение внешним выходным портам значений внутренних сигналов.
Сохраним его под именем, например, test.sublime-snippet в папку VHDL Mode/Snippets.
Воспользуемся написанными функциями в папке VHDL Mode. Так как знания языка python у меня начальные, то будем модифицировать функции плагина, по аналогии с уже описанными в нем.
Создадим в файле vhdl_lang.py новые функции в классе Interface (), назовем их in_port и out_port:
def in_port(self):
"""
Generate Process depending on the input ports
"""
lines = []
bus_index = ""
max_data = ""
my_ports = ""
is_clk = False
is_ce = False
is_rst = False
if self.if_ports:
for port in self.if_ports:
if port.mode.lower() == 'in':
if port.name.lower() == ('clk'):
is_clk = True
my_ports = port.name
else:
if port.name.lower() == ('ce'):
is_ce = True
elif port.name.lower() == ('rst'):
is_rst = True
my_ports = my_ports + ", " + port.name
lines.append("Process("+ my_ports +')' )
lines.append("begin")
if is_clk:
lines.append(" if(clk'event and clk = '1') then")
lines.append("")
if is_rst and is_ce:
lines.append("if(rst = '1') then")
lines.append("")
lines.append("elsif (ce = '1') then")
lines.append("")
lines.append("end if; -- rst")
elif is_rst:
lines.append("if(rst = '1') then")
lines.append("")
lines.append("else -- working body ")
lines.append("")
lines.append("end if; -- rst")
elif is_ce:
lines.append("if (ce = '1') then")
lines.append("")
lines.append("end if; --
lines.append(" end if;--clk")
lines.append("end process;")
# lines.append(str(testind
indent_vhdl(lines, 1)
return '\n'.join(lines)
else:
return None
def out_port(self):
"""
Generate data after Process
"""
lines = []
if self.if_ports:
for port in self.if_ports:
if port.mode.lower() == 'out':
lines.append("{} <= {}_net;".format(port.name, port.name))
indent_vhdl(lines, 1)
return '\n'.join(lines)
else:
return None
Функция out_port вставляет за процессом строки, например:
data_out1 <= data_out1_net;
data_out2 <= data_out2_net;
Создадим в папке VHDL Mode новый файл, назовем его my_func.py, вставим текст:
import sublime
import sublime_plugin
from.import vhdl_interface as face
class PasteAsProcess(sublime_plugin.TextCommand):
def run(self, edit):
snippet_clk = "Packages/VHDL Mode/Snippets/test.sublime-snippet"
in_port_str = face._interface.in_port()
out_port_str = face._interface.out_port()
self.view.run_command("insert_snippet",
{
"name" : snippet_clk,
"DATAINPORTS" : in_port_str,
"OUTPORTS" : out_port_str
})
print('paste_as_process')
Осталось присвоить горячие клавиши. Так как наш класс называется PasteAsProcess, то команда должна называться paste_as_process (перед символами, кроме первого, написанными в верхнем регистре нужно поставить знак нижнего подчеркивания).
Идем Preferences → Key Bildings. Вставляем строку:
{"keys": ["alt+k", "p", "z"], "command": "paste_as_process", "context": [{"key": "selector", "operand": "source.vhdl"}] },
Теперь для работы нам надо сначала скопировать значения портов vhdl файла сочетанием клавиш «alt+k», «p», «w» (по умолчанию). Затем вызвать нашу функцию клавишами «alt+k», «p», «z».
Вывод
Сниппеты и функции значительно упрощают работу с vhdl файлами.
Даже начальных знаний языка python достаточно для написания простых, но рабочих функций.
P.S.: Оставлю ссылку на папку с моими настройками. Для работы, надо заменить папку Sublime Text 3 по адресу: C:\Users\User\AppData\Roaming\
Мои сниппеты:
- sint (Signal integer), sstd, svector — шаблоны описания сигналов соответствующего типа
- ibuf, ibufds и т.д. — описание буферов
- generichelp — подсказка пример, как правильно применить generic
- teststd, testvector и т.д. — процессы для тестбенча с сответствующими типами данных
Мои функции:
- Cвязка Alt+K, C, P (Copy Ports), Alt+K, P, Z — вставка процесса описанного с этой статье
- Cвязка Alt+K, C, P (Copy Ports), Alt+K, P, T (Paste Testbench) — переделал функцию плагина VHDL MODE, теперь генерируются тестовые процессы для всех входных сигналов
- clk, net, inst — шаблоны для ucf файлов