Для простого дизайна и пользовательской библиотеки я получаю результаты синтеза, в которых 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