Yosys / ab c использует много ворот вместо лучшей монолитной c ячейки - PullRequest
1 голос
/ 12 января 2020

Для простого дизайна и пользовательской библиотеки я получаю результаты синтеза, в которых Yosys / ab c выбирает результат, который явно (для читателя-человека) хуже, и который игнорирует очевидную альтернативную реализацию. Мне кажется, что результат Yosys / ab c хуже с точки зрения площади и скорости, хотя для последнего я не уверен, потому что в моем .lib файле отсутствует вся информация о задержке / диске / загрузке, и я еще не уверен, какой тип по умолчанию используется. Я хотел бы оптимизировать область, а не скорость.

Дизайн (SevenSegmentDecoder.v):

module SevenSegmentDecoder(
    input[3:0] encoded,
    output reg decoded,
    output[3:0] dummy
);
    assign dummy = ~encoded;
    always @(*) begin
        case (encoded)
            4'd0: decoded = 1;
            4'd1: decoded = 0;
            4'd2: decoded = 1;
            4'd3: decoded = 1;
            4'd4: decoded = 0;
            4'd5: decoded = 1;
            4'd6: decoded = 1;
            4'd7: decoded = 1;
            4'd8: decoded = 1;
            4'd9: decoded = 1;
            4'd10: decoded = 1;
            4'd11: decoded = 0;
            4'd12: decoded = 1;
            4'd13: decoded = 0;
            4'd14: decoded = 1;
            4'd15: decoded = 1;
            default: decoded = 0;
        endcase
    end
endmodule

Это логика c для одного сегмента из семи сегментов декодер. «Пустой» выход обеспечивает наличие ячеек инвертора для входов. Это означает, что вы sh Yosys / ab c намерены реализовать его, но последняя не работает.

Сценарий оболочки для синтеза (build. sh):

rm show.dot
rm show.svg
rm out.v
rm -rf _tmp_yosys-abc-*
yosys -s build.yosys

Синтез-скрипт (build.yosys):

#
# input
#
read_verilog SevenSegmentDecoder.v

#
# synthesis
#
synth -top SevenSegmentDecoder

#
# tech mapping
#
dfflibmap -liberty own.lib
abc -liberty own.lib -nocleanup
clean
stat -liberty own.lib

#
# output
#
write_verilog out.v
read_liberty -lib own.lib
show -format svg -prefix show

Библиотека ячеек (own.lib):

/*
 delay model :       typ
 check model :       typ
 power model :       typ
 capacitance model : typ
 other model :       typ
*/
library(my_cells) {
    cell(Inverter) {
        area: 1;
        pin(a) {
            direction: input;
        }
        pin(out) {
            direction: output;
            function: "(!a)";
        }
    }
    cell(Buffer) {
        area: 2450;
        pin(a) {
            direction: input;
        }
        pin(out) {
            direction: output;
            function: "a";
        }
    }
    cell(Nand3) {
        area: 2940;
        pin(a) {
            direction: input;
        }
        pin(b) {
            direction: input;
        }
        pin(c) {
            direction: input;
        }
        pin(out) {
            direction: output;
            function: "(!(a b c))";
        }
    }
    cell(Nor) {
        area: 2450;
        pin(a) {
            direction: input;
        }
        pin(b) {
            direction: input;
        }
        pin(out) {
            direction: output;
            function: "(!(a+b))";
        }
    }
    cell(OrAndInvert) {
        area: 2940;
        pin(a) {
            direction: input;
        }
        pin(b) {
            direction: input;
        }
        pin(c) {
            direction: input;
        }
        pin(out) {
            direction: output;
            function: "(!((a+b) c))";
        }
    }
    cell(seg0) {
        area: 1;
        pin(a) {
            direction: input;
        }
        pin(b) {
            direction: input;
        }
        pin(c) {
            direction: input;
        }
        pin(d) {
            direction: input;
        }
        pin(na) {
            direction: input;
        }
        pin(out) {
            direction: output;
            function: "(!((na (!b) (!c) d)+(na b (!c) (!d))+(a b (!c) d)+(a (!b) c d)))";
        }
    }
}

Последняя ячейка, seg0, может легко реализовать «декодированный» вывод в сочетании с инвертором для получения (na: =! a), но Yosys / ab c выбирает использование сети 1xNand3, 3xNor, 3xOrAndInvert. Чтобы обеспечить реализацию, присутствие инвертора в любом случае обеспечивается через «фиктивный» выход, а ячейка seg0 имеет площадь 1, но она игнорируется. Кроме того, сгенерированная сеть использует несколько шлюзов последовательно, в то время как seg0 будет одной ступенью logi c. При отсутствии указанных c значений задержки / загрузки, я предполагаю, что ячейка seg0 будет смоделирована таким образом, чтобы она была быстрее.

Теперь попробуйте слегка модифицированную библиотеку ячеек, в которой ячейка seg0 инвертирует "a". :

    cell(seg0) {
        area: 1000000;
        pin(a) {
            direction: input;
        }
        pin(b) {
            direction: input;
        }
        pin(c) {
            direction: input;
        }
        pin(d) {
            direction: input;
        }
        pin(out) {
            direction: output;
            function: "(!(((!a) (!b) (!c) d)+((!a) b (!c) (!d))+(a b (!c) d)+(a (!b) c d)))";
        }
    }

Несмотря на то, что эта ячейка имеет огромную площадь, она захватывается Yosys / ab c и все ворота Nand, Nor и OAI исчезают. Разумеется, все еще присутствуют только инверторы для генерации «фиктивного» выхода.

Почему Yosys / ab c не использует ячейку seg0, когда ее необходимо объединить с инвертором для получения ", даже если этот инвертор уже присутствует?

Версия Yosys: Yosys 0.9 + 1706 (git sha1 58ab9f60, clang 6.0.0-1ubuntu2 -fPI C -Os)

Версия AB C (исполняемый файл yosys-ab c, поставляемый с Yosys): U C Беркли, AB C 1,01 (скомпилировано 12 января 2020 20:46:55)


Поскольку было упомянуто ab c, вот соответствующие файлы, сгенерированные Yosys.

ab c .script:

echo + read_blif _tmp_yosys-abc-jAcBTF/input.blif;
read_blif _tmp_yosys-abc-jAcBTF/input.blif;
echo + read_lib -w /home/martin/git-repos/chipdraw/resource/7seg/own.lib;
read_lib -w /home/martin/git-repos/chipdraw/resource/7seg/own.lib;
echo + strash;
strash;
echo + ifraig;
ifraig;
echo + scorr;
scorr;
echo + dc2;
dc2;
echo + dretime;
dretime;
echo + strash;
strash;
echo + &get -n;
&get -n;
echo + &dch -f;
&dch -f;
echo + &nf ;
&nf ;
echo + &put;
&put;
echo + write_blif _tmp_yosys-abc-jAcBTF/output.blif;
write_blif _tmp_yosys-abc-jAcBTF/output.blif

input.blif:

.model netlist
.inputs ys__n0 ys__n1 ys__n3 ys__n4
.outputs ys__n34 ys__n35 ys__n36 ys__n37 ys__n38
# ys__n0     \encoded [1]
# ys__n1     \encoded [0]
# ys__n2     $abc$258$new_n10_
# ys__n3     \encoded [3]
# ys__n4     \encoded [2]
# ys__n5     $abc$258$new_n11_
# ys__n6     $abc$258$new_n12_
# ys__n7     $abc$258$new_n13_
# ys__n8     $abc$258$new_n14_
# ys__n9     $abc$258$new_n15_
# ys__n10    $abc$258$new_n16_
# ys__n11    $abc$258$new_n17_
# ys__n12    $abc$258$new_n18_
# ys__n13    $abc$258$new_n19_
# ys__n14    $abc$258$new_n20_
# ys__n15    $abc$258$new_n21_
# ys__n16    $abc$258$new_n22_
# ys__n17    $abc$258$new_n23_
# ys__n18    $abc$258$new_n24_
# ys__n19    $abc$258$new_n25_
# ys__n20    $abc$258$new_n26_
# ys__n21    $abc$258$new_n27_
# ys__n22    $abc$258$new_n28_
# ys__n23    $abc$258$new_n29_
# ys__n24    $abc$258$new_n30_
# ys__n25    $abc$258$new_n31_
# ys__n26    $abc$258$new_n32_
# ys__n27    $abc$258$new_n33_
# ys__n28    $abc$258$new_n34_
# ys__n29    $abc$258$new_n35_
# ys__n30    $abc$258$new_n36_
# ys__n31    $abc$258$new_n37_
# ys__n32    $abc$258$new_n38_
# ys__n33    $abc$258$new_n39_
# ys__n34    \decoded
# ys__n35    \dummy [0]
# ys__n36    \dummy [1]
# ys__n37    \dummy [2]
# ys__n38    \dummy [3]
.names ys__n0 ys__n1 ys__n2
00 1
.names ys__n3 ys__n4 ys__n5
00 1
.names ys__n5 ys__n2 ys__n6
11 1
.names ys__n0 ys__n1 ys__n7
10 1
.names ys__n7 ys__n5 ys__n8
11 1
.names ys__n8 ys__n6 ys__n9
-1 1
1- 1
.names ys__n0 ys__n1 ys__n10
11 1
.names ys__n10 ys__n5 ys__n11
11 1
.names ys__n1 ys__n0 ys__n12
10 1
.names ys__n3 ys__n4 ys__n13
1- 1
-0 1
.names ys__n12 ys__n13 ys__n14
10 1
.names ys__n14 ys__n11 ys__n15
-1 1
1- 1
.names ys__n15 ys__n9 ys__n16
-1 1
1- 1
.names ys__n7 ys__n13 ys__n17
10 1
.names ys__n10 ys__n13 ys__n18
10 1
.names ys__n18 ys__n17 ys__n19
-1 1
1- 1
.names ys__n4 ys__n3 ys__n20
1- 1
-0 1
.names ys__n2 ys__n20 ys__n21
10 1
.names ys__n12 ys__n20 ys__n22
10 1
.names ys__n22 ys__n21 ys__n23
-1 1
1- 1
.names ys__n23 ys__n19 ys__n24
-1 1
1- 1
.names ys__n24 ys__n16 ys__n25
-1 1
1- 1
.names ys__n7 ys__n20 ys__n26
10 1
.names ys__n3 ys__n4 ys__n27
0- 1
-0 1
.names ys__n2 ys__n27 ys__n28
10 1
.names ys__n28 ys__n26 ys__n29
-1 1
1- 1
.names ys__n7 ys__n27 ys__n30
10 1
.names ys__n10 ys__n27 ys__n31
10 1
.names ys__n31 ys__n30 ys__n32
-1 1
1- 1
.names ys__n32 ys__n29 ys__n33
-1 1
1- 1
.names ys__n33 ys__n25 ys__n34
-1 1
1- 1
.names ys__n1 ys__n35
0 1
.names ys__n0 ys__n36
0 1
.names ys__n4 ys__n37
0 1
.names ys__n3 ys__n38
0 1
.end

stdcells.genlib:

GATE ZERO    1 Y=CONST0;
GATE ONE     1 Y=CONST1;
GATE BUF    1 Y=A;                  PIN * NONINV  1 999 1 0 1 0
GATE NOT    2 Y=!A;                 PIN * INV     1 999 1 0 1 0
GATE AND    4 Y=A*B;                PIN * NONINV  1 999 1 0 1 0
GATE NAND   4 Y=!(A*B);             PIN * INV     1 999 1 0 1 0
GATE OR     4 Y=A+B;                PIN * NONINV  1 999 1 0 1 0
GATE NOR    4 Y=!(A+B);             PIN * INV     1 999 1 0 1 0
GATE XOR    5 Y=(A*!B)+(!A*B);      PIN * UNKNOWN 1 999 1 0 1 0
GATE XNOR   5 Y=(A*B)+(!A*!B);      PIN * UNKNOWN 1 999 1 0 1 0
GATE ANDNOT 4 Y=A*!B;               PIN * UNKNOWN 1 999 1 0 1 0
GATE ORNOT  4 Y=A+!B;               PIN * UNKNOWN 1 999 1 0 1 0
GATE MUX    4 Y=(A*B)+(S*B)+(!S*A); PIN * UNKNOWN 1 999 1 0 1 0

output.blif:

# Benchmark "netlist" written by ABC on Mon Jan 13 18:44:03 2020
.model netlist
.inputs ys__n0 ys__n1 ys__n3 ys__n4
.outputs ys__n34 ys__n35 ys__n36 ys__n37 ys__n38
.gate Inverter    a=ys__n0 out=ys__n36
.gate Inverter    a=ys__n1 out=ys__n35
.gate Inverter    a=ys__n3 out=ys__n38
.gate Inverter    a=ys__n4 out=ys__n37
.gate Nor         a=ys__n3 b=ys__n37 out=new_n14_
.gate Nor         a=ys__n38 b=ys__n4 out=new_n15_
.gate Nor         a=ys__n0 b=ys__n35 out=new_n16_
.gate OrAndInvert a=new_n14_ b=new_n15_ c=new_n16_ out=new_n17_
.gate OrAndInvert a=ys__n3 b=ys__n37 c=ys__n35 out=new_n18_
.gate OrAndInvert a=ys__n38 b=ys__n4 c=ys__n0 out=new_n19_
.gate Nand3       a=new_n17_ b=new_n18_ c=new_n19_ out=ys__n34
.end
...