From 78382eaa6f95ad52a9d4f2a92755c1d2f3f687bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Povi=C5=A1er?= Date: Tue, 13 Aug 2024 18:08:21 +0200 Subject: [PATCH 1/5] libparse: Adjust whitespace --- passes/techmap/libparse.h | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/passes/techmap/libparse.h b/passes/techmap/libparse.h index 77e305f0b87..3dcc0535c5f 100644 --- a/passes/techmap/libparse.h +++ b/passes/techmap/libparse.h @@ -46,19 +46,18 @@ namespace Yosys LibertyAst *ast; LibertyParser(std::istream &f) : f(f), line(1), ast(parse()) {} ~LibertyParser() { if (ast) delete ast; } - - /* lexer return values: - 'v': identifier, string, array range [...] -> str holds the token string - 'n': newline - anything else is a single character. - */ + + /* lexer return values: + 'v': identifier, string, array range [...] -> str holds the token string + 'n': newline + anything else is a single character. + */ int lexer(std::string &str); - LibertyAst *parse(); + LibertyAst *parse(); void error(); - void error(const std::string &str); + void error(const std::string &str); }; } #endif - From c35f5e379c2542a8df99aca1711cacbe4121dbee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Povi=C5=A1er?= Date: Tue, 13 Aug 2024 18:36:31 +0200 Subject: [PATCH 2/5] Extend liberty tests --- tests/liberty/.gitignore | 2 + tests/liberty/XNOR2X1.lib.filtered.ok | 15 ++ tests/liberty/XNOR2X1.lib.verilogsim.ok | 6 + tests/liberty/busdef.lib.filtered.ok | 8 + tests/liberty/busdef.lib.verilogsim.ok | 3 + tests/liberty/issue3498_bad.lib.filtered.ok | 4 + tests/liberty/issue3498_bad.lib.verilogsim.ok | 2 + tests/liberty/normal.lib.filtered.ok | 211 ++++++++++++++++++ tests/liberty/normal.lib.verilogsim.ok | 117 ++++++++++ tests/liberty/normal.verilogsim.ok | 117 ++++++++++ tests/liberty/processdefs.lib.filtered.ok | 2 + tests/liberty/processdefs.lib.verilogsim.ok | 0 tests/liberty/run-test.sh | 11 +- tests/liberty/semicolextra.lib.filtered.ok | 20 ++ tests/liberty/semicolextra.lib.verilogsim.ok | 11 + tests/liberty/semicolmissing.lib.filtered.ok | 22 ++ .../liberty/semicolmissing.lib.verilogsim.ok | 9 + 17 files changed, 556 insertions(+), 4 deletions(-) create mode 100644 tests/liberty/XNOR2X1.lib.filtered.ok create mode 100644 tests/liberty/XNOR2X1.lib.verilogsim.ok create mode 100644 tests/liberty/busdef.lib.filtered.ok create mode 100644 tests/liberty/busdef.lib.verilogsim.ok create mode 100644 tests/liberty/issue3498_bad.lib.filtered.ok create mode 100644 tests/liberty/issue3498_bad.lib.verilogsim.ok create mode 100644 tests/liberty/normal.lib.filtered.ok create mode 100644 tests/liberty/normal.lib.verilogsim.ok create mode 100644 tests/liberty/normal.verilogsim.ok create mode 100644 tests/liberty/processdefs.lib.filtered.ok create mode 100644 tests/liberty/processdefs.lib.verilogsim.ok create mode 100644 tests/liberty/semicolextra.lib.filtered.ok create mode 100644 tests/liberty/semicolextra.lib.verilogsim.ok create mode 100644 tests/liberty/semicolmissing.lib.filtered.ok create mode 100644 tests/liberty/semicolmissing.lib.verilogsim.ok diff --git a/tests/liberty/.gitignore b/tests/liberty/.gitignore index e6ec49c4a16..bf5ba57dce0 100644 --- a/tests/liberty/.gitignore +++ b/tests/liberty/.gitignore @@ -1,2 +1,4 @@ *.log test.ys +*.filtered +*.verilogsim diff --git a/tests/liberty/XNOR2X1.lib.filtered.ok b/tests/liberty/XNOR2X1.lib.filtered.ok new file mode 100644 index 00000000000..14e9b625d8d --- /dev/null +++ b/tests/liberty/XNOR2X1.lib.filtered.ok @@ -0,0 +1,15 @@ +library(ls05_stdcells) { + cell(XNOR2X1) { + area : 206080.0 ; + pin(B) { + direction : input ; + } + pin(A) { + direction : input ; + } + pin(Y) { + direction : output ; + function : !(B&!A|!B&A) ; + } + } +} diff --git a/tests/liberty/XNOR2X1.lib.verilogsim.ok b/tests/liberty/XNOR2X1.lib.verilogsim.ok new file mode 100644 index 00000000000..62c9f7ffa9f --- /dev/null +++ b/tests/liberty/XNOR2X1.lib.verilogsim.ok @@ -0,0 +1,6 @@ +module XNOR2X1 (B, A, Y); + input B; + input A; + output Y; + assign Y = !(B&!A|!B&A); // !(B&!A|!B&A) +endmodule diff --git a/tests/liberty/busdef.lib.filtered.ok b/tests/liberty/busdef.lib.filtered.ok new file mode 100644 index 00000000000..55f5b08a3bf --- /dev/null +++ b/tests/liberty/busdef.lib.filtered.ok @@ -0,0 +1,8 @@ +library(supergate) { + cell(SRAM) { + area : 1 ; + pin(CE1) { + direction : input ; + } + } +} diff --git a/tests/liberty/busdef.lib.verilogsim.ok b/tests/liberty/busdef.lib.verilogsim.ok new file mode 100644 index 00000000000..5d7f47f3712 --- /dev/null +++ b/tests/liberty/busdef.lib.verilogsim.ok @@ -0,0 +1,3 @@ +module SRAM (CE1); + input CE1; +endmodule diff --git a/tests/liberty/issue3498_bad.lib.filtered.ok b/tests/liberty/issue3498_bad.lib.filtered.ok new file mode 100644 index 00000000000..e121193df71 --- /dev/null +++ b/tests/liberty/issue3498_bad.lib.filtered.ok @@ -0,0 +1,4 @@ +library(fake) { + cell(bugbad) { + } +} diff --git a/tests/liberty/issue3498_bad.lib.verilogsim.ok b/tests/liberty/issue3498_bad.lib.verilogsim.ok new file mode 100644 index 00000000000..2ce41ea6cd2 --- /dev/null +++ b/tests/liberty/issue3498_bad.lib.verilogsim.ok @@ -0,0 +1,2 @@ +module bugbad (); +endmodule diff --git a/tests/liberty/normal.lib.filtered.ok b/tests/liberty/normal.lib.filtered.ok new file mode 100644 index 00000000000..757f09cabd5 --- /dev/null +++ b/tests/liberty/normal.lib.filtered.ok @@ -0,0 +1,211 @@ +library(supergate) { + cell(inv) { + area : 1 ; + pin(A) { + direction : input ; + } + pin(Y) { + direction : output ; + function : A' ; + } + } + cell(tri_inv) { + area : 4 ; + pin(A) { + direction : input ; + } + pin(S) { + direction : input ; + } + pin(Z) { + direction : output ; + function : A' ; + } + } + cell(buffer) { + area : 5 ; + pin(A) { + direction : input ; + } + pin(Y) { + direction : output ; + function : A ; + } + } + cell(nand2) { + area : 3 ; + pin(A) { + direction : input ; + } + pin(B) { + direction : input ; + } + pin(Y) { + direction : output ; + function : (A * B)' ; + } + } + cell(nor2) { + area : 3 ; + pin(A) { + direction : input ; + } + pin(B) { + direction : input ; + } + pin(Y) { + direction : output ; + function : (A + B)' ; + } + } + cell(xor2) { + area : 6 ; + pin(A) { + direction : input ; + } + pin(B) { + direction : input ; + } + pin(Y) { + direction : output ; + function : (A *B') + (A' * B) ; + } + } + cell(imux2) { + area : 5 ; + pin(A) { + direction : input ; + } + pin(B) { + direction : input ; + } + pin(S) { + direction : input ; + } + pin(Y) { + direction : output ; + function : ( (A * S) + (B * S') )' ; + } + } + cell(dff) { + area : 6 ; + ff(IQ, IQN) { + next_state : D ; + clocked_on : CLK ; + clear : RESET ; + preset : PRESET ; + clear_preset_var1 : L ; + clear_preset_var2 : L ; + } + pin(D) { + direction : input ; + } + pin(CLK) { + direction : input ; + } + pin(RESET) { + direction : input ; + } + pin(PRESET) { + direction : input ; + } + pin(Q) { + direction : output ; + function : IQ ; + } + pin(QN) { + direction : output ; + function : IQN ; + } + } + cell(latch) { + area : 5 ; + latch(IQ, IQN) { + enable : G ; + data_in : D ; + } + pin(D) { + direction : input ; + } + pin(G) { + direction : input ; + } + pin(Q) { + direction : output ; + function : IQ ; + } + pin(QN) { + direction : output ; + function : IQN ; + } + } + cell(aoi211) { + area : 3 ; + pin(A) { + direction : input ; + } + pin(B) { + direction : input ; + } + pin(C) { + direction : input ; + } + pin(Y) { + direction : output ; + function : ((A * B) + C)' ; + } + } + cell(oai211) { + area : 3 ; + pin(A) { + direction : input ; + } + pin(B) { + direction : input ; + } + pin(C) { + direction : input ; + } + pin(Y) { + direction : output ; + function : ((A + B) * C)' ; + } + } + cell(halfadder) { + area : 5 ; + pin(A) { + direction : input ; + } + pin(B) { + direction : input ; + } + pin(C) { + direction : output ; + function : (A * B) ; + } + pin(Y) { + direction : output ; + function : (A *B') + (A' * B) ; + } + } + cell(fulladder) { + area : 8 ; + pin(A) { + direction : input ; + } + pin(B) { + direction : input ; + } + pin(CI) { + direction : input ; + } + pin(CO) { + direction : output ; + function : (((A * B)+(B * CI))+(CI * A)) ; + } + pin(Y) { + direction : output ; + function : ((A^B)^CI) ; + } + } +} diff --git a/tests/liberty/normal.lib.verilogsim.ok b/tests/liberty/normal.lib.verilogsim.ok new file mode 100644 index 00000000000..30f164a3115 --- /dev/null +++ b/tests/liberty/normal.lib.verilogsim.ok @@ -0,0 +1,117 @@ +module inv (A, Y); + input A; + output Y; + assign Y = ~A; // A' +endmodule +module tri_inv (A, S, Z); + input A; + input S; + output Z; + assign Z = ~A; // A' +endmodule +module buffer (A, Y); + input A; + output Y; + assign Y = A; // A +endmodule +module nand2 (A, B, Y); + input A; + input B; + output Y; + assign Y = ~(A&B); // (A * B)' +endmodule +module nor2 (A, B, Y); + input A; + input B; + output Y; + assign Y = ~(A|B); // (A + B)' +endmodule +module xor2 (A, B, Y); + input A; + input B; + output Y; + assign Y = (A&~B)|(~A&B); // (A *B') + (A' * B) +endmodule +module imux2 (A, B, S, Y); + input A; + input B; + input S; + output Y; + assign Y = ~(&(A&S)|(B&~S)&); // ( (A * S) + (B * S') )' +endmodule +module dff (D, CLK, RESET, PRESET, Q, QN); + reg IQ, IQN; + input D; + input CLK; + input RESET; + input PRESET; + output Q; + assign Q = IQ; // IQ + output QN; + assign QN = IQN; // IQN + always @(posedge CLK, posedge RESET, posedge PRESET) begin + if ((RESET) && (PRESET)) begin + IQ <= 0; + IQN <= 0; + end + else if (RESET) begin + IQ <= 0; + IQN <= 1; + end + else if (PRESET) begin + IQ <= 1; + IQN <= 0; + end + else begin + // D + IQ <= D; + IQN <= ~(D); + end + end +endmodule +module latch (D, G, Q, QN); + reg IQ, IQN; + input D; + input G; + output Q; + assign Q = IQ; // IQ + output QN; + assign QN = IQN; // IQN + always @* begin + if (G) begin + IQ <= D; + IQN <= ~(D); + end + end +endmodule +module aoi211 (A, B, C, Y); + input A; + input B; + input C; + output Y; + assign Y = ~((A&B)|C); // ((A * B) + C)' +endmodule +module oai211 (A, B, C, Y); + input A; + input B; + input C; + output Y; + assign Y = ~((A|B)&C); // ((A + B) * C)' +endmodule +module halfadder (A, B, C, Y); + input A; + input B; + output C; + assign C = (A&B); // (A * B) + output Y; + assign Y = (A&~B)|(~A&B); // (A *B') + (A' * B) +endmodule +module fulladder (A, B, CI, CO, Y); + input A; + input B; + input CI; + output CO; + assign CO = (((A&B)|(B&CI))|(CI&A)); // (((A * B)+(B * CI))+(CI * A)) + output Y; + assign Y = ((A^B)^CI); // ((A^B)^CI) +endmodule diff --git a/tests/liberty/normal.verilogsim.ok b/tests/liberty/normal.verilogsim.ok new file mode 100644 index 00000000000..30f164a3115 --- /dev/null +++ b/tests/liberty/normal.verilogsim.ok @@ -0,0 +1,117 @@ +module inv (A, Y); + input A; + output Y; + assign Y = ~A; // A' +endmodule +module tri_inv (A, S, Z); + input A; + input S; + output Z; + assign Z = ~A; // A' +endmodule +module buffer (A, Y); + input A; + output Y; + assign Y = A; // A +endmodule +module nand2 (A, B, Y); + input A; + input B; + output Y; + assign Y = ~(A&B); // (A * B)' +endmodule +module nor2 (A, B, Y); + input A; + input B; + output Y; + assign Y = ~(A|B); // (A + B)' +endmodule +module xor2 (A, B, Y); + input A; + input B; + output Y; + assign Y = (A&~B)|(~A&B); // (A *B') + (A' * B) +endmodule +module imux2 (A, B, S, Y); + input A; + input B; + input S; + output Y; + assign Y = ~(&(A&S)|(B&~S)&); // ( (A * S) + (B * S') )' +endmodule +module dff (D, CLK, RESET, PRESET, Q, QN); + reg IQ, IQN; + input D; + input CLK; + input RESET; + input PRESET; + output Q; + assign Q = IQ; // IQ + output QN; + assign QN = IQN; // IQN + always @(posedge CLK, posedge RESET, posedge PRESET) begin + if ((RESET) && (PRESET)) begin + IQ <= 0; + IQN <= 0; + end + else if (RESET) begin + IQ <= 0; + IQN <= 1; + end + else if (PRESET) begin + IQ <= 1; + IQN <= 0; + end + else begin + // D + IQ <= D; + IQN <= ~(D); + end + end +endmodule +module latch (D, G, Q, QN); + reg IQ, IQN; + input D; + input G; + output Q; + assign Q = IQ; // IQ + output QN; + assign QN = IQN; // IQN + always @* begin + if (G) begin + IQ <= D; + IQN <= ~(D); + end + end +endmodule +module aoi211 (A, B, C, Y); + input A; + input B; + input C; + output Y; + assign Y = ~((A&B)|C); // ((A * B) + C)' +endmodule +module oai211 (A, B, C, Y); + input A; + input B; + input C; + output Y; + assign Y = ~((A|B)&C); // ((A + B) * C)' +endmodule +module halfadder (A, B, C, Y); + input A; + input B; + output C; + assign C = (A&B); // (A * B) + output Y; + assign Y = (A&~B)|(~A&B); // (A *B') + (A' * B) +endmodule +module fulladder (A, B, CI, CO, Y); + input A; + input B; + input CI; + output CO; + assign CO = (((A&B)|(B&CI))|(CI&A)); // (((A * B)+(B * CI))+(CI * A)) + output Y; + assign Y = ((A^B)^CI); // ((A^B)^CI) +endmodule diff --git a/tests/liberty/processdefs.lib.filtered.ok b/tests/liberty/processdefs.lib.filtered.ok new file mode 100644 index 00000000000..d50f0e17bad --- /dev/null +++ b/tests/liberty/processdefs.lib.filtered.ok @@ -0,0 +1,2 @@ +library(processdefs) { +} diff --git a/tests/liberty/processdefs.lib.verilogsim.ok b/tests/liberty/processdefs.lib.verilogsim.ok new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/liberty/run-test.sh b/tests/liberty/run-test.sh index 19ce0667d51..07d2cce1cd5 100755 --- a/tests/liberty/run-test.sh +++ b/tests/liberty/run-test.sh @@ -2,9 +2,12 @@ set -e for x in *.lib; do - echo "Running $x.." - echo "read_verilog small.v" > test.ys - echo "synth -top small" >> test.ys - echo "dfflibmap -info -liberty ${x}" >> test.ys + echo "Testing on $x.." + echo "read_verilog small.v" > test.ys + echo "synth -top small" >> test.ys + echo "dfflibmap -info -liberty ${x}" >> test.ys ../../yosys -ql ${x%.lib}.log -s test.ys + ../../yosys-filterlib - $x 2>/dev/null > $x.filtered + ../../yosys-filterlib -verilogsim $x > $x.verilogsim + diff $x.filtered $x.filtered.ok && diff $x.verilogsim $x.verilogsim.ok done diff --git a/tests/liberty/semicolextra.lib.filtered.ok b/tests/liberty/semicolextra.lib.filtered.ok new file mode 100644 index 00000000000..791b4508454 --- /dev/null +++ b/tests/liberty/semicolextra.lib.filtered.ok @@ -0,0 +1,20 @@ +library(supergate) { + cell(DFF) { + cell_footprint : dff ; + area : 50 ; + pin(D) { + direction : input ; + } + pin(CK) { + direction : input ; + clock : true ; + } + ff(IQ, IQN) { + clocked_on : CK ; + next_state : D ; + } + pin(Q) { + direction : output ; + } + } +} diff --git a/tests/liberty/semicolextra.lib.verilogsim.ok b/tests/liberty/semicolextra.lib.verilogsim.ok new file mode 100644 index 00000000000..c9eebd6ed5a --- /dev/null +++ b/tests/liberty/semicolextra.lib.verilogsim.ok @@ -0,0 +1,11 @@ +module DFF (D, CK, Q); + reg IQ, IQN; + input D; + input CK; + output Q; + always @(posedge CK) begin + // D + IQ <= D; + IQN <= ~(D); + end +endmodule diff --git a/tests/liberty/semicolmissing.lib.filtered.ok b/tests/liberty/semicolmissing.lib.filtered.ok new file mode 100644 index 00000000000..29022cf80c4 --- /dev/null +++ b/tests/liberty/semicolmissing.lib.filtered.ok @@ -0,0 +1,22 @@ +library(supergate) { + cell(fulladder) { + area : 8 ; + pin(A) { + direction : input ; + } + pin(B) { + direction : input ; + } + pin(CI) { + direction : input ; + } + pin(CO) { + direction : output ; + function : (((A * B)+(B * CI))+(CI * A)) ; + } + pin(Y) { + direction : output ; + function : ((A^B)^CI) ; + } + } +} diff --git a/tests/liberty/semicolmissing.lib.verilogsim.ok b/tests/liberty/semicolmissing.lib.verilogsim.ok new file mode 100644 index 00000000000..131ce2fdfe0 --- /dev/null +++ b/tests/liberty/semicolmissing.lib.verilogsim.ok @@ -0,0 +1,9 @@ +module fulladder (A, B, CI, CO, Y); + input A; + input B; + input CI; + output CO; + assign CO = (((A&B)|(B&CI))|(CI&A)); // (((A * B)+(B * CI))+(CI * A)) + output Y; + assign Y = ((A^B)^CI); // ((A^B)^CI) +endmodule From 3057c13a665e89852253b3e9aec4897bf7608120 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Povi=C5=A1er?= Date: Tue, 13 Aug 2024 18:43:31 +0200 Subject: [PATCH 3/5] Improve libparse encapsulation --- frontends/liberty/liberty.cc | 20 +++++------ passes/cmds/stat.cc | 2 +- passes/techmap/dfflibmap.cc | 30 ++++++++-------- passes/techmap/libparse.cc | 70 ++++++++++++++++++------------------ passes/techmap/libparse.h | 22 +++++++----- 5 files changed, 73 insertions(+), 71 deletions(-) diff --git a/frontends/liberty/liberty.cc b/frontends/liberty/liberty.cc index 86bb4c7dcd4..c23dbfa531e 100644 --- a/frontends/liberty/liberty.cc +++ b/frontends/liberty/liberty.cc @@ -226,7 +226,7 @@ static RTLIL::SigSpec create_tristate(RTLIL::Module *module, RTLIL::SigSpec func return cell->getPort(ID::Y); } -static void create_ff(RTLIL::Module *module, LibertyAst *node) +static void create_ff(RTLIL::Module *module, const LibertyAst *node) { RTLIL::SigSpec iq_sig(module->addWire(RTLIL::escape_id(node->args.at(0)))); RTLIL::SigSpec iqn_sig(module->addWire(RTLIL::escape_id(node->args.at(1)))); @@ -303,7 +303,7 @@ static void create_ff(RTLIL::Module *module, LibertyAst *node) log_assert(!cell->type.empty()); } -static bool create_latch(RTLIL::Module *module, LibertyAst *node, bool flag_ignore_miss_data_latch) +static bool create_latch(RTLIL::Module *module, const LibertyAst *node, bool flag_ignore_miss_data_latch) { RTLIL::SigSpec iq_sig(module->addWire(RTLIL::escape_id(node->args.at(0)))); RTLIL::SigSpec iqn_sig(module->addWire(RTLIL::escape_id(node->args.at(1)))); @@ -422,7 +422,7 @@ static bool create_latch(RTLIL::Module *module, LibertyAst *node, bool flag_igno return true; } -void parse_type_map(std::map> &type_map, LibertyAst *ast) +void parse_type_map(std::map> &type_map, const LibertyAst *ast) { for (auto type_node : ast->children) { @@ -604,7 +604,7 @@ struct LibertyFrontend : public Frontend { for (auto node : cell->children) { if (node->id == "pin" && node->args.size() == 1) { - LibertyAst *dir = node->find("direction"); + const LibertyAst *dir = node->find("direction"); if (!dir || (dir->value != "input" && dir->value != "output" && dir->value != "inout" && dir->value != "internal")) { if (!flag_ignore_miss_dir) @@ -625,10 +625,10 @@ struct LibertyFrontend : public Frontend { if (!flag_lib) log_error("Error in cell %s: bus interfaces are only supported in -lib mode.\n", log_id(cell_name)); - LibertyAst *dir = node->find("direction"); + const LibertyAst *dir = node->find("direction"); if (dir == nullptr) { - LibertyAst *pin = node->find("pin"); + const LibertyAst *pin = node->find("pin"); if (pin != nullptr) dir = pin->find("direction"); } @@ -639,7 +639,7 @@ struct LibertyFrontend : public Frontend { if (dir->value == "internal") continue; - LibertyAst *bus_type_node = node->find("bus_type"); + const LibertyAst *bus_type_node = node->find("bus_type"); if (!bus_type_node || !type_map.count(bus_type_node->value)) log_error("Unknown or unsupported type for bus interface %s on cell %s.\n", @@ -681,7 +681,7 @@ struct LibertyFrontend : public Frontend { { if (node->id == "pin" && node->args.size() == 1) { - LibertyAst *dir = node->find("direction"); + const LibertyAst *dir = node->find("direction"); if (flag_lib && dir->value == "internal") continue; @@ -704,7 +704,7 @@ struct LibertyFrontend : public Frontend { if (flag_lib) continue; - LibertyAst *func = node->find("function"); + const LibertyAst *func = node->find("function"); if (func == NULL) { if (dir->value != "inout") { // allow inout with missing function, can be used for power pins @@ -719,7 +719,7 @@ struct LibertyFrontend : public Frontend { } } else { RTLIL::SigSpec out_sig = parse_func_expr(module, func->value.c_str()); - LibertyAst *three_state = node->find("three_state"); + const LibertyAst *three_state = node->find("three_state"); if (three_state) { out_sig = create_tristate(module, out_sig, three_state->value.c_str()); } diff --git a/passes/cmds/stat.cc b/passes/cmds/stat.cc index 379ce209790..951a321e8a0 100644 --- a/passes/cmds/stat.cc +++ b/passes/cmds/stat.cc @@ -361,7 +361,7 @@ void read_liberty_cellarea(dict &cell_area, string libert if (cell->id != "cell" || cell->args.size() != 1) continue; - LibertyAst *ar = cell->find("area"); + const LibertyAst *ar = cell->find("area"); bool is_flip_flop = cell->find("ff") != nullptr; if (ar != nullptr && !ar->value.empty()) cell_area["\\" + cell->args[0]] = {/*area=*/atof(ar->value.c_str()), is_flip_flop}; diff --git a/passes/techmap/dfflibmap.cc b/passes/techmap/dfflibmap.cc index 78bfe1586ff..43eef1ac04a 100644 --- a/passes/techmap/dfflibmap.cc +++ b/passes/techmap/dfflibmap.cc @@ -76,7 +76,7 @@ static void logmap_all() logmap(ID($_DFFSR_PPP_)); } -static bool parse_pin(LibertyAst *cell, LibertyAst *attr, std::string &pin_name, bool &pin_pol) +static bool parse_pin(const LibertyAst *cell, const LibertyAst *attr, std::string &pin_name, bool &pin_pol) { if (cell == nullptr || attr == nullptr || attr->value.empty()) return false; @@ -115,9 +115,9 @@ static bool parse_pin(LibertyAst *cell, LibertyAst *attr, std::string &pin_name, return false; } -static void find_cell(LibertyAst *ast, IdString cell_type, bool clkpol, bool has_reset, bool rstpol, bool rstval, std::vector &dont_use_cells) +static void find_cell(const LibertyAst *ast, IdString cell_type, bool clkpol, bool has_reset, bool rstpol, bool rstval, std::vector &dont_use_cells) { - LibertyAst *best_cell = nullptr; + const LibertyAst *best_cell = nullptr; std::map best_cell_ports; int best_cell_pins = 0; bool best_cell_noninv = false; @@ -131,7 +131,7 @@ static void find_cell(LibertyAst *ast, IdString cell_type, bool clkpol, bool has if (cell->id != "cell" || cell->args.size() != 1) continue; - LibertyAst *dn = cell->find("dont_use"); + const LibertyAst *dn = cell->find("dont_use"); if (dn != nullptr && dn->value == "true") continue; @@ -147,7 +147,7 @@ static void find_cell(LibertyAst *ast, IdString cell_type, bool clkpol, bool has if (dont_use) continue; - LibertyAst *ff = cell->find("ff"); + const LibertyAst *ff = cell->find("ff"); if (ff == nullptr) continue; @@ -174,7 +174,7 @@ static void find_cell(LibertyAst *ast, IdString cell_type, bool clkpol, bool has this_cell_ports[cell_next_pin] = 'D'; double area = 0; - LibertyAst *ar = cell->find("area"); + const LibertyAst *ar = cell->find("area"); if (ar != nullptr && !ar->value.empty()) area = atof(ar->value.c_str()); @@ -186,7 +186,7 @@ static void find_cell(LibertyAst *ast, IdString cell_type, bool clkpol, bool has if (pin->id != "pin" || pin->args.size() != 1) continue; - LibertyAst *dir = pin->find("direction"); + const LibertyAst *dir = pin->find("direction"); if (dir == nullptr || dir->value == "internal") continue; num_pins++; @@ -194,7 +194,7 @@ static void find_cell(LibertyAst *ast, IdString cell_type, bool clkpol, bool has if (dir->value == "input" && this_cell_ports.count(pin->args[0]) == 0) goto continue_cell_loop; - LibertyAst *func = pin->find("function"); + const LibertyAst *func = pin->find("function"); if (dir->value == "output" && func != nullptr) { std::string value = func->value; for (size_t pos = value.find_first_of("\" \t"); pos != std::string::npos; pos = value.find_first_of("\" \t")) @@ -239,9 +239,9 @@ static void find_cell(LibertyAst *ast, IdString cell_type, bool clkpol, bool has } } -static void find_cell_sr(LibertyAst *ast, IdString cell_type, bool clkpol, bool setpol, bool clrpol, std::vector &dont_use_cells) +static void find_cell_sr(const LibertyAst *ast, IdString cell_type, bool clkpol, bool setpol, bool clrpol, std::vector &dont_use_cells) { - LibertyAst *best_cell = nullptr; + const LibertyAst *best_cell = nullptr; std::map best_cell_ports; int best_cell_pins = 0; bool best_cell_noninv = false; @@ -255,7 +255,7 @@ static void find_cell_sr(LibertyAst *ast, IdString cell_type, bool clkpol, bool if (cell->id != "cell" || cell->args.size() != 1) continue; - LibertyAst *dn = cell->find("dont_use"); + const LibertyAst *dn = cell->find("dont_use"); if (dn != nullptr && dn->value == "true") continue; @@ -271,7 +271,7 @@ static void find_cell_sr(LibertyAst *ast, IdString cell_type, bool clkpol, bool if (dont_use) continue; - LibertyAst *ff = cell->find("ff"); + const LibertyAst *ff = cell->find("ff"); if (ff == nullptr) continue; @@ -294,7 +294,7 @@ static void find_cell_sr(LibertyAst *ast, IdString cell_type, bool clkpol, bool this_cell_ports[cell_next_pin] = 'D'; double area = 0; - LibertyAst *ar = cell->find("area"); + const LibertyAst *ar = cell->find("area"); if (ar != nullptr && !ar->value.empty()) area = atof(ar->value.c_str()); @@ -306,7 +306,7 @@ static void find_cell_sr(LibertyAst *ast, IdString cell_type, bool clkpol, bool if (pin->id != "pin" || pin->args.size() != 1) continue; - LibertyAst *dir = pin->find("direction"); + const LibertyAst *dir = pin->find("direction"); if (dir == nullptr || dir->value == "internal") continue; num_pins++; @@ -314,7 +314,7 @@ static void find_cell_sr(LibertyAst *ast, IdString cell_type, bool clkpol, bool if (dir->value == "input" && this_cell_ports.count(pin->args[0]) == 0) goto continue_cell_loop; - LibertyAst *func = pin->find("function"); + const LibertyAst *func = pin->find("function"); if (dir->value == "output" && func != nullptr) { std::string value = func->value; for (size_t pos = value.find_first_of("\" \t"); pos != std::string::npos; pos = value.find_first_of("\" \t")) diff --git a/passes/techmap/libparse.cc b/passes/techmap/libparse.cc index efe00c105e4..ebfb325fcd5 100644 --- a/passes/techmap/libparse.cc +++ b/passes/techmap/libparse.cc @@ -32,9 +32,6 @@ using namespace Yosys; -std::set LibertyAst::blacklist; -std::set LibertyAst::whitelist; - LibertyAst::~LibertyAst() { for (auto child : children) @@ -42,7 +39,7 @@ LibertyAst::~LibertyAst() children.clear(); } -LibertyAst *LibertyAst::find(std::string name) +const LibertyAst *LibertyAst::find(std::string name) const { for (auto child : children) if (child->id == name) @@ -50,7 +47,7 @@ LibertyAst *LibertyAst::find(std::string name) return NULL; } -void LibertyAst::dump(FILE *f, std::string indent, std::string path, bool path_ok) +void LibertyAst::dump(FILE *f, sieve &blacklist, sieve &whitelist, std::string indent, std::string path, bool path_ok) const { if (whitelist.count(path + "/*") > 0) path_ok = true; @@ -77,7 +74,7 @@ void LibertyAst::dump(FILE *f, std::string indent, std::string path, bool path_o if (!children.empty()) { fprintf(f, " {\n"); for (size_t i = 0; i < children.size(); i++) - children[i]->dump(f, indent + " ", path, path_ok); + children[i]->dump(f, blacklist, whitelist, indent + " ", path, path_ok); fprintf(f, "%s}\n", indent.c_str()); } else fprintf(f, " ;\n"); @@ -406,9 +403,9 @@ void LibertyParser::error(const std::string &str) /**** END: http://svn.clairexen.net/tools/trunk/examples/check.h ****/ -LibertyAst *find_non_null(LibertyAst *node, const char *name) +const LibertyAst *find_non_null(const LibertyAst *node, const char *name) { - LibertyAst *ret = node->find(name); + const LibertyAst *ret = node->find(name); if (ret == NULL) fprintf(stderr, "Error: expected to find `%s' node.\n", name); return ret; @@ -455,7 +452,7 @@ std::string func2vl(std::string str) return str; } -void event2vl(LibertyAst *ast, std::string &edge, std::string &expr) +void event2vl(const LibertyAst *ast, std::string &edge, std::string &expr) { edge.clear(); expr.clear(); @@ -489,7 +486,7 @@ void clear_preset_var(std::string var, std::string type) } } -void gen_verilogsim_cell(LibertyAst *ast) +void gen_verilogsim_cell(const LibertyAst *ast) { if (ast->find("statetable") != NULL) return; @@ -522,8 +519,8 @@ void gen_verilogsim_cell(LibertyAst *ast) if (child->id != "pin") continue; CHECK_NV(child->args.size(), == 1); - LibertyAst *dir = find_non_null(child, "direction"); - LibertyAst *func = child->find("function"); + const LibertyAst *dir = find_non_null(child, "direction"); + const LibertyAst *func = child->find("function"); printf(" %s %s;\n", dir->value.c_str(), child->args[0].c_str()); if (func != NULL) printf(" assign %s = %s; // %s\n", child->args[0].c_str(), func2vl(func->value).c_str(), func->value.c_str()); @@ -649,7 +646,7 @@ void gen_verilogsim_cell(LibertyAst *ast) printf("endmodule\n"); } -void gen_verilogsim(LibertyAst *ast) +void gen_verilogsim(const LibertyAst *ast) { CHECK_COND(ast->id == "library"); @@ -668,6 +665,7 @@ void usage() int main(int argc, char **argv) { bool flag_verilogsim = false; + std::set whitelist, blacklist; if (argc > 3) usage(); @@ -678,26 +676,26 @@ int main(int argc, char **argv) flag_verilogsim = true; if (!strcmp(argv[1], "-") || !strcmp(argv[1], "-verilogsim")) { - LibertyAst::whitelist.insert("/library"); - LibertyAst::whitelist.insert("/library/cell"); - LibertyAst::whitelist.insert("/library/cell/area"); - LibertyAst::whitelist.insert("/library/cell/cell_footprint"); - LibertyAst::whitelist.insert("/library/cell/dont_touch"); - LibertyAst::whitelist.insert("/library/cell/dont_use"); - LibertyAst::whitelist.insert("/library/cell/ff"); - LibertyAst::whitelist.insert("/library/cell/ff/*"); - LibertyAst::whitelist.insert("/library/cell/latch"); - LibertyAst::whitelist.insert("/library/cell/latch/*"); - LibertyAst::whitelist.insert("/library/cell/pin"); - LibertyAst::whitelist.insert("/library/cell/pin/clock"); - LibertyAst::whitelist.insert("/library/cell/pin/direction"); - LibertyAst::whitelist.insert("/library/cell/pin/driver_type"); - LibertyAst::whitelist.insert("/library/cell/pin/function"); - LibertyAst::whitelist.insert("/library/cell/pin_opposite"); - LibertyAst::whitelist.insert("/library/cell/pin/state_function"); - LibertyAst::whitelist.insert("/library/cell/pin/three_state"); - LibertyAst::whitelist.insert("/library/cell/statetable"); - LibertyAst::whitelist.insert("/library/cell/statetable/*"); + whitelist.insert("/library"); + whitelist.insert("/library/cell"); + whitelist.insert("/library/cell/area"); + whitelist.insert("/library/cell/cell_footprint"); + whitelist.insert("/library/cell/dont_touch"); + whitelist.insert("/library/cell/dont_use"); + whitelist.insert("/library/cell/ff"); + whitelist.insert("/library/cell/ff/*"); + whitelist.insert("/library/cell/latch"); + whitelist.insert("/library/cell/latch/*"); + whitelist.insert("/library/cell/pin"); + whitelist.insert("/library/cell/pin/clock"); + whitelist.insert("/library/cell/pin/direction"); + whitelist.insert("/library/cell/pin/driver_type"); + whitelist.insert("/library/cell/pin/function"); + whitelist.insert("/library/cell/pin_opposite"); + whitelist.insert("/library/cell/pin/state_function"); + whitelist.insert("/library/cell/pin/three_state"); + whitelist.insert("/library/cell/statetable"); + whitelist.insert("/library/cell/statetable/*"); } else { @@ -723,10 +721,10 @@ int main(int argc, char **argv) if (*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n' || *p == '#') { if (!id.empty()) { if (mode == '-') - LibertyAst::blacklist.insert(id); + blacklist.insert(id); else if (mode == '+') - LibertyAst::whitelist.insert(id); + whitelist.insert(id); else goto syntax_error; } @@ -764,7 +762,7 @@ int main(int argc, char **argv) if (flag_verilogsim) gen_verilogsim(parser.ast); else - parser.ast->dump(stdout); + parser.ast->dump(stdout, blacklist, whitelist); } if (argc == 3) diff --git a/passes/techmap/libparse.h b/passes/techmap/libparse.h index 3dcc0535c5f..ad38ae5f8e0 100644 --- a/passes/techmap/libparse.h +++ b/passes/techmap/libparse.h @@ -33,20 +33,18 @@ namespace Yosys std::vector args; std::vector children; ~LibertyAst(); - LibertyAst *find(std::string name); - void dump(FILE *f, std::string indent = "", std::string path = "", bool path_ok = false); - static std::set blacklist; - static std::set whitelist; + const LibertyAst *find(std::string name) const; + + typedef std::set sieve; + void dump(FILE *f, sieve &blacklist, sieve &whitelist, std::string indent = "", std::string path = "", bool path_ok = false) const; }; - struct LibertyParser + class LibertyParser { + private: std::istream &f; int line; - LibertyAst *ast; - LibertyParser(std::istream &f) : f(f), line(1), ast(parse()) {} - ~LibertyParser() { if (ast) delete ast; } - + /* lexer return values: 'v': identifier, string, array range [...] -> str holds the token string 'n': newline @@ -57,6 +55,12 @@ namespace Yosys LibertyAst *parse(); void error(); void error(const std::string &str); + + public: + const LibertyAst *ast; + + LibertyParser(std::istream &f) : f(f), line(1), ast(parse()) {} + ~LibertyParser() { if (ast) delete ast; } }; } From 309d80885bc8171116ea4f76f184fa24573f9545 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Povi=C5=A1er?= Date: Tue, 13 Aug 2024 18:44:40 +0200 Subject: [PATCH 4/5] read_liberty: Use available gate creation helpers --- frontends/liberty/liberty.cc | 47 +++++------------------------------- 1 file changed, 6 insertions(+), 41 deletions(-) diff --git a/frontends/liberty/liberty.cc b/frontends/liberty/liberty.cc index c23dbfa531e..83a6297fe56 100644 --- a/frontends/liberty/liberty.cc +++ b/frontends/liberty/liberty.cc @@ -53,47 +53,12 @@ static RTLIL::SigSpec parse_func_identifier(RTLIL::Module *module, const char *& return module->wires_.at(id); } -static RTLIL::SigSpec create_inv_cell(RTLIL::Module *module, RTLIL::SigSpec A) -{ - RTLIL::Cell *cell = module->addCell(NEW_ID, ID($_NOT_)); - cell->setPort(ID::A, A); - cell->setPort(ID::Y, module->addWire(NEW_ID)); - return cell->getPort(ID::Y); -} - -static RTLIL::SigSpec create_xor_cell(RTLIL::Module *module, RTLIL::SigSpec A, RTLIL::SigSpec B) -{ - RTLIL::Cell *cell = module->addCell(NEW_ID, ID($_XOR_)); - cell->setPort(ID::A, A); - cell->setPort(ID::B, B); - cell->setPort(ID::Y, module->addWire(NEW_ID)); - return cell->getPort(ID::Y); -} - -static RTLIL::SigSpec create_and_cell(RTLIL::Module *module, RTLIL::SigSpec A, RTLIL::SigSpec B) -{ - RTLIL::Cell *cell = module->addCell(NEW_ID, ID($_AND_)); - cell->setPort(ID::A, A); - cell->setPort(ID::B, B); - cell->setPort(ID::Y, module->addWire(NEW_ID)); - return cell->getPort(ID::Y); -} - -static RTLIL::SigSpec create_or_cell(RTLIL::Module *module, RTLIL::SigSpec A, RTLIL::SigSpec B) -{ - RTLIL::Cell *cell = module->addCell(NEW_ID, ID($_OR_)); - cell->setPort(ID::A, A); - cell->setPort(ID::B, B); - cell->setPort(ID::Y, module->addWire(NEW_ID)); - return cell->getPort(ID::Y); -} - static bool parse_func_reduce(RTLIL::Module *module, std::vector &stack, token_t next_token) { int top = int(stack.size())-1; if (0 <= top-1 && stack[top].type == 0 && stack[top-1].type == '!') { - token_t t = token_t(0, create_inv_cell(module, stack[top].sig)); + token_t t = token_t(0, module->NotGate(NEW_ID, stack[top].sig)); stack.pop_back(); stack.pop_back(); stack.push_back(t); @@ -101,7 +66,7 @@ static bool parse_func_reduce(RTLIL::Module *module, std::vector &stack } if (0 <= top-1 && stack[top].type == '\'' && stack[top-1].type == 0) { - token_t t = token_t(0, create_inv_cell(module, stack[top-1].sig)); + token_t t = token_t(0, module->NotGate(NEW_ID, stack[top-1].sig)); stack.pop_back(); stack.pop_back(); stack.push_back(t); @@ -116,7 +81,7 @@ static bool parse_func_reduce(RTLIL::Module *module, std::vector &stack } if (0 <= top-2 && stack[top-2].type == 1 && stack[top-1].type == '^' && stack[top].type == 1) { - token_t t = token_t(1, create_xor_cell(module, stack[top-2].sig, stack[top].sig)); + token_t t = token_t(1, module->XorGate(NEW_ID, stack[top-2].sig, stack[top].sig)); stack.pop_back(); stack.pop_back(); stack.pop_back(); @@ -132,7 +97,7 @@ static bool parse_func_reduce(RTLIL::Module *module, std::vector &stack } if (0 <= top-1 && stack[top-1].type == 2 && stack[top].type == 2) { - token_t t = token_t(2, create_and_cell(module, stack[top-1].sig, stack[top].sig)); + token_t t = token_t(2, module->AndGate(NEW_ID, stack[top-1].sig, stack[top].sig)); stack.pop_back(); stack.pop_back(); stack.push_back(t); @@ -140,7 +105,7 @@ static bool parse_func_reduce(RTLIL::Module *module, std::vector &stack } if (0 <= top-2 && stack[top-2].type == 2 && (stack[top-1].type == '*' || stack[top-1].type == '&') && stack[top].type == 2) { - token_t t = token_t(2, create_and_cell(module, stack[top-2].sig, stack[top].sig)); + token_t t = token_t(2, module->AndGate(NEW_ID, stack[top-2].sig, stack[top].sig)); stack.pop_back(); stack.pop_back(); stack.pop_back(); @@ -156,7 +121,7 @@ static bool parse_func_reduce(RTLIL::Module *module, std::vector &stack } if (0 <= top-2 && stack[top-2].type == 3 && (stack[top-1].type == '+' || stack[top-1].type == '|') && stack[top].type == 3) { - token_t t = token_t(3, create_or_cell(module, stack[top-2].sig, stack[top].sig)); + token_t t = token_t(3, module->OrGate(NEW_ID, stack[top-2].sig, stack[top].sig)); stack.pop_back(); stack.pop_back(); stack.pop_back(); From ab5d6b06b4fab48c227269c3f2cf2a8de0bbbbf2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Povi=C5=A1er?= Date: Tue, 13 Aug 2024 20:12:38 +0200 Subject: [PATCH 5/5] read_liberty: Fix omitted helper change --- frontends/liberty/liberty.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontends/liberty/liberty.cc b/frontends/liberty/liberty.cc index 83a6297fe56..16fed54f203 100644 --- a/frontends/liberty/liberty.cc +++ b/frontends/liberty/liberty.cc @@ -186,7 +186,7 @@ static RTLIL::SigSpec create_tristate(RTLIL::Module *module, RTLIL::SigSpec func RTLIL::Cell *cell = module->addCell(NEW_ID, ID($tribuf)); cell->setParam(ID::WIDTH, GetSize(func)); cell->setPort(ID::A, func); - cell->setPort(ID::EN, create_inv_cell(module, three_state)); + cell->setPort(ID::EN, module->NotGate(NEW_ID, three_state)); cell->setPort(ID::Y, module->addWire(NEW_ID)); return cell->getPort(ID::Y); }