Перейти к содержанию
    

Как заставить Synopsys DC

Как заставить DC проанализировать один регистр-защелку (с асинхронным enable) как комбинаторный элемент? Суть в том, что он стоит на пути шины данных от входного пада до внутренних регистров. Он в нормальном режиме всегда разрешен "насквозь". Мне надо обконстрейнить сетап по этой шине данных - и соответственно как-то сказать DC, что на этой самой гребаной защелке путь не окончен, и ее задержка D->Q при активном E есть часть пути. Как это сделать? Я что-то втупил не на шутку... Разрешение на эту защелку идет вообще снаружи (с аналоговой части, там формирователь импульсов, это изврат для low power), и оно не объявлено клоком.

 

ЗЫ в проекте еще куча защелок, так вот мне надо такое поведение сделать для одной. Остальные честные - управляются через gated clock.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

не используйте в проекте latch-и

это закон. Нет причин чтобы их использовать, площадь - это в случае если много регистровых файлов - тогда да. Но в случае управляющей логики - flip-flop ничем не хуже.

 

Если не можете его убрать в принципе, то другого пути, кроме как залезть в lib файл этого latch-a и убрать свойство clock с пина G который и является клоком.

 

в принципе наверное есть какие-то стандартные методы - у вас sold есть - руководство по синтезу ?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

не используйте в проекте latch-и

это закон. Нет причин чтобы их использовать, площадь - это в случае если много регистровых файлов - тогда да.

 

Не могу не использовать. Площадь - центы денег :), один латч чуть больше пол-триггера. Далее - регистровый файл (он же внутреннее ОЗУ) построен на асинхронной двухпортовке (опять из соображения min_area) - так что формирователи импульсов записи все равно есть. Регистры внешних устройств находятся в том-же адресном пространстве, так что их совершенно безопасно сделать на латчах. Еще один забытый важный фактор - потребление. Латч имеет и меньшие утечки, и меньший жрач в динамике. Это для меня на втором месте после area. Ну а частота - на третьем, тем более что ее ограничивает внешняя ПЗУ.

 

Теперь - именно в этом месте латч просто необходим. Поясню - это микропроцессор, который может работать от двух клоков - высокочастотного и низкочастотного. Программа всегда исполняется из внешнего ПЗУ. При работе на высокой частоте этот латч находится в хронически разрешенном состоянии, пропуская данные насквозь, внешняя ПЗУ все время выбрана. Итого я получаю 12 мгц (и мипс) при 75-нс ПЗУ. При работе от низкочастотного включается в работу формирователь короткого (150 нс) импульса по спаду клока. При этом адрес на ПЗУ выставляется по фронту клока, а сама ПЗУ выбирается на те самые 150 нс по спаду. В это же время тот самый латч запоминает считанные данные, после чего ПЗУ отключается, а даные остаются, принимаясь ядром в буфер предвыборки по следующему фронту. Это дает громадное уменьшение тока потребления внешней ПЗУхой (150 нс выборки при 32768 гц тактовой - скважность сами посчитайте, если интересно) . Так вот - констрейн-то мне нужен в режиме "открытого" латча, то есть для ВЧ-клока. Кстати, в предыдущей версии этого процессора такой блок работает на ура, но я там констрейнил отдельно путь до латча, и отдельно от латча. Не хочу больше так криво констрейнить, ибо путь там серьезно усложнился, как и весь проц целиком. :)

 

Спасибо за идею покопать .lib, в принципе не проблема сделать копию латча с убранным свойством клока, и их насильно поставить под "dont_touch". Ну и скопировать еще в остальных местах, в LVS-нетлисте, в GDSе, и т.д. До этого сам не догадался.

 

Но, хотелось узнать есть ли нормальный способ. Типа "set_что_нибудь мой_модуль/мой_латч" Все таки латч разрешенный есть буфер, и почему бы его не уметь анализировать таким образом. SOLD есть, сижу вот перекапываю. Начинал с help/man. Пока глухо.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

YESSS! Проблема решена красивым путем.

 

В .lib добавил в описание латчей:

 

        mode_definition(latch) {
          mode_value(transparent) {
            when : "E";
            sdf_cond : "E == 1";
          }
          mode_value(trigger) {
            when : "!E";
            sdf_cond : "E == 0";
          }
        }

 

и расставил в либе в timig {} свойства mode. Для пути D->Q transparent, остальные - холды, сетапы на trigger.

 

Далее в скрипте указал

set_mode transparent [get_cells fetch_dbus_latch*]

 

После чего все было синтезировано и проанализировано как мной задумано.

 

ЗЫ, для Михаил А, не было на пине "E" свойства clock в либе. Наверное оно автоматом ставится или от группы "latch{}", или из наличия таймингов типа setup/hold. Хотя это догадки.

 

ЗЗЫ А все таки гады эти вендоры, либра-виза. Могли бы и сами это продумать. А тут сиди-копай мануалы на library compiler. Хорошо хоть есть опыт изготовления самодельных IO-падов, копать не долго пришлось и знал структуру .lib

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Еще засада :) Он почему-то при compile сбрасывал у некоторых разрядов этой защелки признак "mode". Пришлось еще set_register_type сказать... Воистину пути синтезатора неисповедимы.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

а чта же там на пине Е стояло ?

что это клок он распознает по этому признаку - clock

или по функции описанной на пине Q - выходе latch-a

 

ну и разумеется - убрав clock свойство или изменив функцию latch-a в него надо было просто вставить функцию из ячейки AND

 

можно сюда вклюнуть header этого lacth-a и внизу описание функции на пине Q

 

мда - большая экономия площади на 10 триггерах, замененых latch- ем

 

когда вот так - ограничены внешним протоколом, то да - приходится ставить, иначе это гимор.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

а чта же там на пине Е стояло ?

что это клок он распознает по этому признаку - clock

или по функции описанной на пине Q - выходе latch-a

 

ну и разумеется - убрав clock свойство или изменив функцию latch-a в него надо было просто вставить функцию из ячейки AND

 

Да в том то и дело, что ничего там не стояло. Там было описание ф-ции в виде групы latch {}, тайминги, потребление. И все. Для того, чтобы он "E" перестал анализировать как клок оказалось достаточно убрать тайминги типа "setup_falling" и "hold_falling". Что я и сделал, введя свойство "mode" и группы таймингов, зависящих от "mode".

 

можно сюда вклюнуть header этого lacth-a и внизу описание функции на пине Q

пжалста, вот одна из них. Прям целиком из либы в нарушение NDA :). Правда ужо с добавлением моей mode_definition.

cell(lanhq1) {

        mode_definition(latch) { 
          mode_value(transparent) {}
          mode_value(trigger) {}
        }            

    cell_footprint : lanhq_4;
    area : 3.66;
    routing_track(metal1){
        tracks : 0;
        total_track_area : 0;
    }
    routing_track(metal2){
        tracks : 11;
        total_track_area : 1.57;
    }
    routing_track(metal3){
        tracks : 9;
        total_track_area : 1.83;
    }
    routing_track(metal4){
        tracks : 8;
        total_track_area : 1.90;
    }
    scaling_factors : lanhq1_factors;
    cell_leakage_power : 516.559;
    latch (IQ,IQN){
        enable : "E";
        data_in : "D";
    }

    internal_power(power_inputs_1) {  
    related_input : "E";
    values( " 0.174 0.182 0.258");
    }
    pin(E) {
        direction : input;
        capacitance : 0.006;
        fanout_load : 1;
        min_pulse_width_high : 0.340;
    }
    internal_power(power_inputs_1) {  
    related_input : "D";
    values( " 0.0745 0.0900 0.182");
    }
    pin(D) {
        direction : input;
        capacitance : 0.006;
        fanout_load : 1;
        timing() {
                        mode(latch,trigger);
            timing_type     : setup_falling;
            related_pin     : "E";
            fall_constraint(vio_0_5_5) {
            values( " 0.200, 0.300, 0.410, 0.620, 0.820",\
                " 0.090, 0.200, 0.320, 0.530, 0.710",\
                " 0.010, 0.100, 0.220, 0.430, 0.620",\
                " -0.150, -0.050, 0.060, 0.260, 0.450",\
                " -0.290, -0.200, -0.100, 0.120, 0.300");
            }
            rise_constraint(vio_0_5_5) {
            values( " 0.040, 0.080, 0.130, 0.170, 0.180",\
                " -0.060, -0.020, 0.030, 0.070, 0.080",\
                " -0.160, -0.130, -0.090, -0.050, -0.030",\
                " -0.360, -0.320, -0.280, -0.240, -0.230",\
                " -0.500, -0.470, -0.460, -0.410, -0.400");
            }
        }
        timing() {
                        mode(latch,trigger);
            timing_type     : hold_falling;
            related_pin     : "E";
            fall_constraint(vio_0_5_5) {
            values( " -0.180, -0.280, -0.380, -0.580, -0.750",\
                " -0.080, -0.190, -0.300, -0.480, -0.650",\
                " 0.010, -0.080, -0.200, -0.390, -0.560",\
                " 0.170, 0.070, -0.040, -0.220, -0.390",\
                " 0.320, 0.210, 0.110, -0.080, -0.240");
            }
            rise_constraint(vio_0_5_5) {
            values( " -0.020, -0.070, -0.120, -0.150, -0.150",\
                " 0.080, 0.030, -0.010, -0.050, -0.040",\
                " 0.180, 0.140, 0.100, 0.070, 0.060",\
                " 0.380, 0.330, 0.290, 0.260, 0.260",\
                " 0.540, 0.490, 0.470, 0.430, 0.430");
            }
        }
    }
    internal_power(power_outputs_16) {  /* average switching power [in pJ] for pin 'Q' */
    related_outputs : "Q";
    related_inputs  : "D E";
    values( " 0.336, 0.325, 0.316, 0.311, 0.306",\
        " 0.331, 0.318, 0.309, 0.304, 0.289",\
        " 0.341, 0.325, 0.312, 0.306, 0.308");
    }
    pin(Q) {
        direction : output;
        max_capacitance : 0.300;
        max_fanout : 30;
        max_transition : 3.0;
                function  : "IQ";
        timing() {
                        mode(latch,transparent);
            timing_type     : rising_edge;
            related_pin     : "E";
            cell_rise(del_16_3_5) {
            values( " 0.570, 0.660, 0.810, 1.050, 1.510",\
                " 0.640, 0.740, 0.890, 1.120, 1.590",\
                " 0.610, 0.710, 0.860, 1.090, 1.560");
            }
            rise_transition(del_16_3_5)  {
            values( " 0.220, 0.390, 0.700, 1.240, 2.330",\
                " 0.220, 0.390, 0.700, 1.240, 2.330",\
                " 0.220, 0.390, 0.700, 1.240, 2.330");
            }
            cell_fall(del_16_3_5) {
            values( " 0.510, 0.600, 0.730, 0.890, 1.160",\
                " 0.590, 0.680, 0.800, 0.970, 1.240",\
                " 0.570, 0.650, 0.780, 0.940, 1.210");
            }
            fall_transition(del_16_3_5)  {
            values( " 0.220, 0.320, 0.490, 0.730, 1.200",\
                " 0.210, 0.320, 0.500, 0.730, 1.200",\
                " 0.220, 0.330, 0.490, 0.730, 1.200");
            }
        }
        timing() {
                        mode(latch,transparent);
            related_pin     : "D";
            timing_sense    : positive_unate;
            cell_fall(del_16_3_5) {
            values( " 0.390, 0.480, 0.600, 0.760, 1.030",\
                " 0.600, 0.680, 0.810, 0.970, 1.240",\
                " 0.960, 1.060, 1.190, 1.360, 1.630");
            }
            fall_transition(del_16_3_5)  {
            values( " 0.220, 0.320, 0.500, 0.730, 1.200",\
                " 0.220, 0.330, 0.500, 0.730, 1.200",\
                " 0.260, 0.370, 0.540, 0.770, 1.220");
            }
            cell_rise(del_16_3_5) {
            values( " 0.360, 0.460, 0.610, 0.840, 1.310",\
                " 0.450, 0.550, 0.700, 0.930, 1.400",\
                " 0.480, 0.580, 0.740, 0.970, 1.430");
            }
            rise_transition(del_16_3_5)  {
            values( " 0.220, 0.390, 0.700, 1.240, 2.330",\
                " 0.220, 0.400, 0.700, 1.240, 2.330",\
                " 0.250, 0.420, 0.730, 1.250, 2.330");
            }
        }
    }
}

мда - большая экономия площади на 10 триггерах, замененых latch- ем

 

Сорри, Вы навреное не так поняли. В данном конкретном месте латч необходим. А в остальных местах - это не 10 триггеров. Это по 30-40 триггеров на каждый блок, подключенный к ядру. Причем не создающих никаких проблем при замене на латчи. В реальных цифрах это примерно 2500 NAND-ячеек по всей микрухе. Вместо которых я могу неплохой операционник например всунуть. И не один. Или еще что-нить полезное. Для сравнения умножитель 17х17 бит 2980 занимает при моих таймингах. Сорри, но каждый цент, сэкономленный на площади - мой. И просто так, ради уменьшения геморроя при разработке, терять его я не намерен. И, даже, пусть первая итерация не складется (тьфу-тьфу не дай бог). Но все равно, оно в моем случае того стоит.

 

P.S. А что Вы имели в виду под "ф-цией на пине Q"? Если .lib-описание, то это "latch" :) А если что в проекте с ним делается, то какая разница?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...