Jump to content

    

Recommended Posts

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

 

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

Share this post


Link to post
Share on other sites

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

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

 

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

 

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

Share this post


Link to post
Share on other sites
не используйте в проекте latch-и

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

 

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

 

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

 

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

 

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

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites

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

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

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

 

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

 

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

 

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

 

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

Share this post


Link to post
Share on other sites
а чта же там на пине Е стояло ?

что это клок он распознает по этому признаку - 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" :) А если что в проекте с ним делается, то какая разница?

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this