diff options
25 files changed, 1171 insertions, 10 deletions
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 000000000..401589cd8 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,87 @@ +name: Build and run tests + +on: [push, pull_request] + +jobs: + test-linux: + runs-on: ubuntu-latest + steps: + + - uses: actions/checkout@v2 + + - name: Install dependencies + run: | + sudo apt-get update + sudo apt-get install g++ gperf build-essential bison flex libreadline-dev gawk tcl-dev libffi-dev git graphviz xdot pkg-config python python3 libboost-system-dev libboost-python-dev libboost-filesystem-dev zlib1g-dev + + - name: Get iverilog + run: | + git clone git://github.com/steveicarus/iverilog.git + + - name: Cache iverilog + id: cache-iverilog + uses: actions/cache@v2 + with: + path: iverilog-bin + key: ${{ runner.os }}-${{ hashFiles('iverilog/.git/refs/heads/master') }} + + - name: Build iverilog + if: steps.cache-iverilog.outputs.cache-hit != 'true' + run: | + mkdir iverilog-bin + cd iverilog + autoconf + CC=gcc CXX=g++ ./configure --prefix=$PWD/../iverilog-bin + make -j$(nproc) + make install + + - name: Build yosys + run: | + make -j$(nproc) + + - name: Run tests + run: | + PATH=$PWD/iverilog-bin/bin:$PATH make -j$(nproc) test + + test-osx: + runs-on: macos-latest + steps: + + - uses: actions/checkout@v2 + + - name: Install dependencies + run: | + brew update + brew tap Homebrew/bundle + brew bundle + + - name: Get iverilog + run: | + git clone git://github.com/steveicarus/iverilog.git + + - name: Cache iverilog + id: cache-iverilog + uses: actions/cache@v2 + with: + path: iverilog-bin + key: ${{ runner.os }}-${{ hashFiles('iverilog/.git/refs/heads/master') }} + + - name: Build iverilog + if: steps.cache-iverilog.outputs.cache-hit != 'true' + run: | + export PATH="$(brew --prefix bison)/bin:$PATH" + mkdir iverilog-bin + cd iverilog + autoconf + CC=gcc CXX=g++ ./configure --prefix=$PWD/../iverilog-bin + make -j$(sysctl -n hw.ncpu) + make install + + - name: Build yosys + run: | + export PATH="$(brew --prefix bison)/bin:$PATH" + make -j$(sysctl -n hw.ncpu) + + - name: Run tests + run: | + PATH=$PWD/iverilog-bin/bin:$PATH make -j$(sysctl -n hw.ncpu) test @@ -816,6 +816,7 @@ test: $(TARGETS) $(EXTRA_TARGETS) +cd tests/arch/gowin && bash run-test.sh $(SEEDOPT) +cd tests/arch/intel_alm && bash run-test.sh $(SEEDOPT) +cd tests/arch/nexus && bash run-test.sh $(SEEDOPT) + +cd tests/arch/quicklogic && bash run-test.sh $(SEEDOPT) +cd tests/rpc && bash run-test.sh +cd tests/memfile && bash run-test.sh +cd tests/verilog && bash run-test.sh diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc index 7aa391c93..84a4de41c 100644 --- a/frontends/ast/ast.cc +++ b/frontends/ast/ast.cc @@ -1575,6 +1575,29 @@ RTLIL::IdString AstModule::derive(RTLIL::Design *design, const dict<RTLIL::IdStr return modname; } +static std::string serialize_param_value(const RTLIL::Const &val) { + std::string res; + if (val.flags & RTLIL::ConstFlags::CONST_FLAG_STRING) + res.push_back('t'); + if (val.flags & RTLIL::ConstFlags::CONST_FLAG_SIGNED) + res.push_back('s'); + if (val.flags & RTLIL::ConstFlags::CONST_FLAG_REAL) + res.push_back('r'); + res += stringf("%d", GetSize(val)); + res.push_back('\''); + for (int i = GetSize(val) - 1; i >= 0; i--) { + switch (val.bits[i]) { + case RTLIL::State::S0: res.push_back('0'); break; + case RTLIL::State::S1: res.push_back('1'); break; + case RTLIL::State::Sx: res.push_back('x'); break; + case RTLIL::State::Sz: res.push_back('z'); break; + case RTLIL::State::Sa: res.push_back('?'); break; + case RTLIL::State::Sm: res.push_back('m'); break; + } + } + return res; +} + // create a new parametric module (when needed) and return the name of the generated module std::string AstModule::derive_common(RTLIL::Design *design, const dict<RTLIL::IdString, RTLIL::Const> ¶meters, AstNode **new_ast_out, bool quiet) { @@ -1594,14 +1617,14 @@ std::string AstModule::derive_common(RTLIL::Design *design, const dict<RTLIL::Id if (it != parameters.end()) { if (!quiet) log("Parameter %s = %s\n", child->str.c_str(), log_signal(it->second)); - para_info += stringf("%s=%s", child->str.c_str(), log_signal(it->second)); + para_info += stringf("%s=%s", child->str.c_str(), serialize_param_value(it->second).c_str()); continue; } it = parameters.find(stringf("$%d", para_counter)); if (it != parameters.end()) { if (!quiet) log("Parameter %d (%s) = %s\n", para_counter, child->str.c_str(), log_signal(it->second)); - para_info += stringf("%s=%s", child->str.c_str(), log_signal(it->second)); + para_info += stringf("%s=%s", child->str.c_str(), serialize_param_value(it->second).c_str()); continue; } } diff --git a/frontends/verilog/verilog_frontend.cc b/frontends/verilog/verilog_frontend.cc index 5907707c8..84ac73e91 100644 --- a/frontends/verilog/verilog_frontend.cc +++ b/frontends/verilog/verilog_frontend.cc @@ -61,11 +61,6 @@ static void add_package_types(dict<std::string, AST::AstNode *> &user_types, std } } } - - // carry over typedefs from previous files, but allow them to be overridden - // note that these type maps are currently never reclaimed - if (user_type_stack.empty() || !user_type_stack.back()->empty()) - user_type_stack.push_back(new UserTypeMap()); } struct VerilogFrontend : public Frontend { @@ -487,6 +482,19 @@ struct VerilogFrontend : public Frontend { // make package typedefs available to parser add_package_types(pkg_user_types, design->verilog_packages); + UserTypeMap *global_types_map = new UserTypeMap(); + for (auto def : design->verilog_globals) { + if (def->type == AST::AST_TYPEDEF) { + (*global_types_map)[def->str] = def; + } + } + + log_assert(user_type_stack.empty()); + // use previous global typedefs as bottom level of user type stack + user_type_stack.push_back(global_types_map); + // add a new empty type map to allow overriding existing global definitions + user_type_stack.push_back(new UserTypeMap()); + frontend_verilog_yyset_lineno(1); frontend_verilog_yyrestart(NULL); frontend_verilog_yyparse(); @@ -509,6 +517,14 @@ struct VerilogFrontend : public Frontend { if (!flag_nopp) delete lexin; + // only the previous and new global type maps remain + log_assert(user_type_stack.size() == 2); + for (auto it : user_type_stack) { + // the global typedefs have to remain valid for future invocations, so just drop the map without deleting values + delete it; + } + user_type_stack.clear(); + delete current_ast; current_ast = NULL; diff --git a/kernel/modtools.h b/kernel/modtools.h index 29c510059..3af5367b1 100644 --- a/kernel/modtools.h +++ b/kernel/modtools.h @@ -395,6 +395,8 @@ struct ModWalker signal_consumers.clear(); signal_inputs.clear(); signal_outputs.clear(); + cell_inputs.clear(); + cell_outputs.clear(); for (auto &it : module->wires_) add_wire(it.second); diff --git a/techlibs/quicklogic/Makefile.inc b/techlibs/quicklogic/Makefile.inc new file mode 100644 index 000000000..9a07c2eed --- /dev/null +++ b/techlibs/quicklogic/Makefile.inc @@ -0,0 +1,9 @@ +OBJS += techlibs/quicklogic/synth_quicklogic.o + +$(eval $(call add_share_file,share/quicklogic,techlibs/quicklogic/pp3_ffs_map.v)) +$(eval $(call add_share_file,share/quicklogic,techlibs/quicklogic/pp3_lut_map.v)) +$(eval $(call add_share_file,share/quicklogic,techlibs/quicklogic/pp3_latches_map.v)) +$(eval $(call add_share_file,share/quicklogic,techlibs/quicklogic/pp3_cells_map.v)) +$(eval $(call add_share_file,share/quicklogic,techlibs/quicklogic/cells_sim.v)) +$(eval $(call add_share_file,share/quicklogic,techlibs/quicklogic/lut_sim.v)) +$(eval $(call add_share_file,share/quicklogic,techlibs/quicklogic/pp3_cells_sim.v)) diff --git a/techlibs/quicklogic/cells_sim.v b/techlibs/quicklogic/cells_sim.v new file mode 100644 index 000000000..f24782ec3 --- /dev/null +++ b/techlibs/quicklogic/cells_sim.v @@ -0,0 +1,36 @@ +module inv ( + output Q, + input A +); + assign Q = A ? 0 : 1; +endmodule + +module buff ( + output Q, + input A +); + assign Q = A; +endmodule + +module logic_0 ( + output A +); + assign A = 0; +endmodule + +module logic_1 ( + output A +); + assign A = 1; +endmodule + +module gclkbuff ( + input A, + output Z +); + specify + (A => Z) = 0; + endspecify + + assign Z = A; +endmodule diff --git a/techlibs/quicklogic/lut_sim.v b/techlibs/quicklogic/lut_sim.v new file mode 100644 index 000000000..851ce4d68 --- /dev/null +++ b/techlibs/quicklogic/lut_sim.v @@ -0,0 +1,76 @@ +(* abc9_lut=1, lib_whitebox *) +module LUT1 ( + output O, + input I0 +); + parameter [1:0] INIT = 0; + parameter EQN = "(I0)"; + + // These timings are for PolarPro 3E; other families will need updating. + specify + (I0 => O) = 698; // FS -> FZ + endspecify + + assign O = I0 ? INIT[1] : INIT[0]; +endmodule + +// TZ TSL TAB +(* abc9_lut=2, lib_whitebox *) +module LUT2 ( + output O, + input I0, I1 +); + parameter [3:0] INIT = 4'h0; + parameter EQN = "(I0)"; + + // These timings are for PolarPro 3E; other families will need updating. + specify + (I0 => O) = 1251; // TAB -> TZ + (I1 => O) = 1406; // TSL -> TZ + endspecify + + wire [1:0] s1 = I1 ? INIT[3:2] : INIT[1:0]; + assign O = I0 ? s1[1] : s1[0]; +endmodule + +(* abc9_lut=2, lib_whitebox *) +module LUT3 ( + output O, + input I0, I1, I2 +); + parameter [7:0] INIT = 8'h0; + parameter EQN = "(I0)"; + + // These timings are for PolarPro 3E; other families will need updating. + specify + (I0 => O) = 1251; // TAB -> TZ + (I1 => O) = 1406; // TSL -> TZ + (I2 => O) = 1699; // ('TA1', 'TA2', 'TB1', 'TB2') -> TZ + endspecify + + wire [3:0] s2 = I2 ? INIT[7:4] : INIT[3:0]; + wire [1:0] s1 = I1 ? s2[3:2] : s2[1:0]; + assign O = I0 ? s1[1] : s1[0]; +endmodule + +(* abc9_lut=4, lib_whitebox *) +module LUT4 ( + output O, + input I0, I1, I2, I3 +); + parameter [15:0] INIT = 16'h0; + parameter EQN = "(I0)"; + + // These timings are for PolarPro 3E; other families will need updating. + specify + (I0 => O) = 995; // TBS -> CZ + (I1 => O) = 1437; // ('TAB', 'BAB') -> CZ + (I2 => O) = 1593; // ('TSL', 'BSL') -> CZ + (I3 => O) = 1887; // ('TA1', 'TA2', 'TB1', 'TB2', 'BA1', 'BA2', 'BB1', 'BB2') -> CZ + endspecify + + wire [7:0] s3 = I3 ? INIT[15:8] : INIT[7:0]; + wire [3:0] s2 = I2 ? s3[7:4] : s3[3:0]; + wire [1:0] s1 = I1 ? s2[3:2] : s2[1:0]; + assign O = I0 ? s1[1] : s1[0]; +endmodule diff --git a/techlibs/quicklogic/pp3_cells_map.v b/techlibs/quicklogic/pp3_cells_map.v new file mode 100644 index 000000000..10e270d4e --- /dev/null +++ b/techlibs/quicklogic/pp3_cells_map.v @@ -0,0 +1,36 @@ +module \$_MUX8_ ( + A, B, C, D, E, F, G, H, S, T, U, Y +); + input A, B, C, D, E, F, G, H, S, T, U; + output Y; + mux8x0 _TECHMAP_REPLACE_ ( + .A(A), + .B(B), + .C(C), + .D(D), + .E(E), + .F(F), + .G(G), + .H(H), + .S0(S), + .S1(T), + .S2(U), + .Q(Y) + ); +endmodule + +module \$_MUX4_ ( + A, B, C, D, S, T, U, Y +); + input A, B, C, D, S, T, U; + output Y; + mux4x0 _TECHMAP_REPLACE_ ( + .A(A), + .B(B), + .C(C), + .D(D), + .S0(S), + .S1(T), + .Q(Y) + ); +endmodule diff --git a/techlibs/quicklogic/pp3_cells_sim.v b/techlibs/quicklogic/pp3_cells_sim.v new file mode 100644 index 000000000..61d1ee314 --- /dev/null +++ b/techlibs/quicklogic/pp3_cells_sim.v @@ -0,0 +1,330 @@ +module inpad ( + output Q, + (* iopad_external_pin *) + input P +); + specify + (P => Q) = 0; + endspecify + assign Q = P; +endmodule + +module outpad ( + (* iopad_external_pin *) + output P, + input A +); + specify + (A => P) = 0; + endspecify + assign P = A; +endmodule + +module ckpad ( + output Q, + (* iopad_external_pin *) + input P +); + specify + (P => Q) = 0; + endspecify + assign Q = P; +endmodule + +module bipad ( + input A, + input EN, + output Q, + (* iopad_external_pin *) + inout P +); + assign Q = P; + assign P = EN ? A : 1'bz; +endmodule + +module dff ( + output reg Q, + input D, + (* clkbuf_sink *) + input CLK +); + parameter [0:0] INIT = 1'b0; + initial Q = INIT; + always @(posedge CLK) Q <= D; +endmodule + +module dffc ( + output reg Q, + input D, + (* clkbuf_sink *) + input CLK, + (* clkbuf_sink *) + input CLR +); + parameter [0:0] INIT = 1'b0; + initial Q = INIT; + + always @(posedge CLK or posedge CLR) + if (CLR) Q <= 1'b0; + else Q <= D; +endmodule + +module dffp ( + output reg Q, + input D, + (* clkbuf_sink *) + input CLK, + (* clkbuf_sink *) + input PRE +); + parameter [0:0] INIT = 1'b0; + initial Q = INIT; + + always @(posedge CLK or posedge PRE) + if (PRE) Q <= 1'b1; + else Q <= D; +endmodule + +module dffpc ( + output reg Q, + input D, + (* clkbuf_sink *) + input CLK, + (* clkbuf_sink *) + input CLR, + (* clkbuf_sink *) + input PRE +); + parameter [0:0] INIT = 1'b0; + initial Q = INIT; + + always @(posedge CLK or posedge CLR or posedge PRE) + if (CLR) Q <= 1'b0; + else if (PRE) Q <= 1'b1; + else Q <= D; +endmodule + +module dffe ( + output reg Q, + input D, + (* clkbuf_sink *) + input CLK, + input EN +); + parameter [0:0] INIT = 1'b0; + initial Q = INIT; + always @(posedge CLK) if (EN) Q <= D; +endmodule + +module dffec ( + output reg Q, + input D, + (* clkbuf_sink *) + input CLK, + input EN, + (* clkbuf_sink *) + input CLR +); + parameter [0:0] INIT = 1'b0; + initial Q = INIT; + + always @(posedge CLK or posedge CLR) + if (CLR) Q <= 1'b0; + else if (EN) Q <= D; +endmodule + +(* lib_whitebox *) +module dffepc ( + output reg Q, + input D, + (* clkbuf_sink *) + input CLK, + input EN, + (* clkbuf_sink *) + input CLR, + (* clkbuf_sink *) + input PRE +); + parameter [0:0] INIT = 1'b0; + + // The CLR => Q and PRE => Q paths are commented out due to YosysHQ/yosys#2530. + specify + if (EN) (posedge CLK => (Q : D)) = 1701; // QCK -> QZ + // if (CLR) (CLR => Q) = 967; // QRT -> QZ + // if (PRE) (PRE => Q) = 1252; // QST -> QZ + $setup(D, posedge CLK, 216); // QCK -> QDS + $setup(EN, posedge CLK, 590); // QCK -> QEN + endspecify + + initial Q = INIT; + always @(posedge CLK or posedge CLR or posedge PRE) + if (CLR) Q <= 1'b0; + else if (PRE) Q <= 1'b1; + else if (EN) Q <= D; +endmodule + +// FZ FS F2 (F1 TO 0) +(* abc9_box, lib_whitebox *) +module AND2I0 ( + output Q, + input A, B +); + specify + (A => Q) = 698; // FS -> FZ + (B => Q) = 639; // F2 -> FZ + endspecify + + assign Q = A ? B : 0; +endmodule + +(* abc9_box, lib_whitebox *) +module mux2x0 ( + output Q, + input S, A, B +); + specify + (S => Q) = 698; // FS -> FZ + (A => Q) = 639; // F1 -> FZ + (B => Q) = 639; // F2 -> FZ + endspecify + + assign Q = S ? B : A; +endmodule + +(* abc9_box, lib_whitebox *) +module mux2x1 ( + output Q, + input S, A, B +); + specify + (S => Q) = 698; // FS -> FZ + (A => Q) = 639; // F1 -> FZ + (B => Q) = 639; // F2 -> FZ + endspecify + + assign Q = S ? B : A; +endmodule + +(* abc9_box, lib_whitebox *) +module mux4x0 ( + output Q, + input S0, S1, A, B, C, D +); + specify + (S0 => Q) = 1251; // TAB -> TZ + (S1 => Q) = 1406; // TSL -> TZ + (A => Q) = 1699; // TA1 -> TZ + (B => Q) = 1687; // TA2 -> TZ + (C => Q) = 1669; // TB1 -> TZ + (D => Q) = 1679; // TB2 -> TZ + endspecify + + assign Q = S1 ? (S0 ? D : C) : (S0 ? B : A); +endmodule + +// S0 BSL TSL +// S1 BAB TAB +// S2 TBS +// A TA1 +// B TA2 +// C TB1 +// D TB2 +// E BA1 +// F BA2 +// G BB1 +// H BB2 +// Q CZ +(* abc9_box, lib_whitebox *) +module mux8x0 ( + output Q, + input S0, S1, S2, A, B, C, D, E, F, G, H +); + specify + (S0 => Q) = 1593; // ('TSL', 'BSL') -> CZ + (S1 => Q) = 1437; // ('TAB', 'BAB') -> CZ + (S2 => Q) = 995; // TBS -> CZ + (A => Q) = 1887; // TA1 -> CZ + (B => Q) = 1873; // TA2 -> CZ + (C => Q) = 1856; // TB1 -> CZ + (D => Q) = 1860; // TB2 -> CZ + (E => Q) = 1714; // BA1 -> CZ + (F => Q) = 1773; // BA2 -> CZ + (G => Q) = 1749; // BB1 -> CZ + (H => Q) = 1723; // BB2 -> CZ + endspecify + + assign Q = S2 ? (S1 ? (S0 ? H : G) : (S0 ? F : E)) : (S1 ? (S0 ? D : C) : (S0 ? B : A)); +endmodule + +(* blackbox *) +(* keep *) +module qlal4s3b_cell_macro ( + input WB_CLK, + input WBs_ACK, + input [31:0] WBs_RD_DAT, + output [3:0] WBs_BYTE_STB, + output WBs_CYC, + output WBs_WE, + output WBs_RD, + output WBs_STB, + output [16:0] WBs_ADR, + input [3:0] SDMA_Req, + input [3:0] SDMA_Sreq, + output [3:0] SDMA_Done, + output [3:0] SDMA_Active, + input [3:0] FB_msg_out, + input [7:0] FB_Int_Clr, + output FB_Start, + input FB_Busy, + output WB_RST, + output Sys_PKfb_Rst, + output Clk16, + output Clk16_Rst, + output Clk21, + output Clk21_Rst, + output Sys_Pclk, + output Sys_Pclk_Rst, + input Sys_PKfb_Clk, + input [31:0] FB_PKfbData, + output [31:0] WBs_WR_DAT, + input [3:0] FB_PKfbPush, + input FB_PKfbSOF, + input FB_PKfbEOF, + output [7:0] Sensor_Int, + output FB_PKfbOverflow, + output [23:0] TimeStamp, + input Sys_PSel, + input [15:0] SPIm_Paddr, + input SPIm_PEnable, + input SPIm_PWrite, + input [31:0] SPIm_PWdata, + output SPIm_PReady, + output SPIm_PSlvErr, + output [31:0] SPIm_Prdata, + input [15:0] Device_ID, + input [13:0] FBIO_In_En, + input [13:0] FBIO_Out, + input [13:0] FBIO_Out_En, + output [13:0] FBIO_In, + inout [13:0] SFBIO, + input Device_ID_6S, + input Device_ID_4S, + input SPIm_PWdata_26S, + input SPIm_PWdata_24S, + input SPIm_PWdata_14S, + input SPIm_PWdata_11S, + input SPIm_PWdata_0S, + input SPIm_Paddr_8S, + input SPIm_Paddr_6S, + input FB_PKfbPush_1S, + input FB_PKfbData_31S, + input FB_PKfbData_21S, + input FB_PKfbData_19S, + input FB_PKfbData_9S, + input FB_PKfbData_6S, + input Sys_PKfb_ClkS, + input FB_BusyS, + input WB_CLKS +); + +endmodule diff --git a/techlibs/quicklogic/pp3_ffs_map.v b/techlibs/quicklogic/pp3_ffs_map.v new file mode 100644 index 000000000..73ba6c9c8 --- /dev/null +++ b/techlibs/quicklogic/pp3_ffs_map.v @@ -0,0 +1,4 @@ +module \$_DFFSRE_PPPP_ (input C, S, R, E, D, output Q); + wire _TECHMAP_REMOVEINIT_Q_ = 1; + dffepc #(.INIT(1'b0)) _TECHMAP_REPLACE_ (.CLK(C), .PRE(S), .CLR(R), .EN(E), .D(D), .Q(Q)); +endmodule diff --git a/techlibs/quicklogic/pp3_latches_map.v b/techlibs/quicklogic/pp3_latches_map.v new file mode 100644 index 000000000..240a3fb4e --- /dev/null +++ b/techlibs/quicklogic/pp3_latches_map.v @@ -0,0 +1,11 @@ +module \$_DLATCH_P_ (E, D, Q); + wire [1023:0] _TECHMAP_DO_ = "simplemap; opt"; + input E, D; + output Q = E ? D : Q; +endmodule + +module \$_DLATCH_N_ (E, D, Q); + wire [1023:0] _TECHMAP_DO_ = "simplemap; opt"; + input E, D; + output Q = !E ? D : Q; +endmodule diff --git a/techlibs/quicklogic/pp3_lut_map.v b/techlibs/quicklogic/pp3_lut_map.v new file mode 100644 index 000000000..4c375c9fd --- /dev/null +++ b/techlibs/quicklogic/pp3_lut_map.v @@ -0,0 +1,53 @@ +module \$lut ( + A, Y +); + parameter WIDTH = 0; + parameter LUT = 0; + + input [WIDTH-1:0] A; + output Y; + + generate + if (WIDTH == 1) begin + LUT1 #( + .EQN(""), + .INIT(LUT) + ) _TECHMAP_REPLACE_ ( + .O(Y), + .I0(A[0]) + ); + end else if (WIDTH == 2) begin + LUT2 #( + .EQN(""), + .INIT(LUT) + ) _TECHMAP_REPLACE_ ( + .O(Y), + .I0(A[0]), + .I1(A[1]) + ); + end else if (WIDTH == 3) begin + LUT3 #( + .EQN(""), + .INIT(LUT) + ) _TECHMAP_REPLACE_ ( + .O(Y), + .I0(A[0]), + .I1(A[1]), + .I2(A[2]) + ); + end else if (WIDTH == 4) begin + LUT4 #( + .EQN(""), + .INIT(LUT) + ) _TECHMAP_REPLACE_ ( + .O(Y), + .I0(A[0]), + .I1(A[1]), + .I2(A[2]), + .I3(A[3]) + ); + end else begin + wire _TECHMAP_FAIL_ = 1; + end + endgenerate +endmodule diff --git a/techlibs/quicklogic/synth_quicklogic.cc b/techlibs/quicklogic/synth_quicklogic.cc new file mode 100644 index 000000000..90eb0f78b --- /dev/null +++ b/techlibs/quicklogic/synth_quicklogic.cc @@ -0,0 +1,215 @@ +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2021 QuickLogic Corp. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ +#include "kernel/celltypes.h" +#include "kernel/log.h" +#include "kernel/register.h" +#include "kernel/rtlil.h" + +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + +struct SynthQuickLogicPass : public ScriptPass { + + SynthQuickLogicPass() : ScriptPass("synth_quicklogic", "Synthesis for QuickLogic FPGAs") {} + + void help() override + { + log("\n"); + log(" synth_quicklogic [options]\n"); + log("This command runs synthesis for QuickLogic FPGAs\n"); + log("\n"); + log(" -top <module>\n"); + log(" use the specified module as top module\n"); + log("\n"); + log(" -family <family>\n"); + log(" run synthesis for the specified QuickLogic architecture\n"); + log(" generate the synthesis netlist for the specified family.\n"); + log(" supported values:\n"); + log(" - pp3: PolarPro 3 \n"); + log("\n"); + log(" -blif <file>\n"); + log(" write the design to the specified BLIF file. writing of an output file\n"); + log(" is omitted if this parameter is not specified.\n"); + log("\n"); + log(" -verilog <file>\n"); + log(" write the design to the specified verilog file. writing of an output file\n"); + log(" is omitted if this parameter is not specified.\n"); + log("\n"); + log("The following commands are executed by this synthesis command:\n"); + help_script(); + log("\n"); + } + + string top_opt, blif_file, family, currmodule, verilog_file; + + void clear_flags() override + { + top_opt = "-auto-top"; + blif_file = ""; + verilog_file = ""; + currmodule = ""; + family = "pp3"; + } + + void execute(std::vector<std::string> args, RTLIL::Design *design) override + { + string run_from, run_to; + clear_flags(); + + size_t argidx; + for (argidx = 1; argidx < args.size(); argidx++) + { + if (args[argidx] == "-top" && argidx+1 < args.size()) { + top_opt = "-top " + args[++argidx]; + continue; + } + if (args[argidx] == "-family" && argidx+1 < args.size()) { + family = args[++argidx]; + continue; + } + if (args[argidx] == "-blif" && argidx+1 < args.size()) { + blif_file = args[++argidx]; + continue; + } + if (args[argidx] == "-verilog" && argidx+1 < args.size()) { + verilog_file = args[++argidx]; + continue; + } + break; + } + extra_args(args, argidx, design); + + if (!design->full_selection()) + log_cmd_error("This command only operates on fully selected designs!\n"); + + if (family != "pp3") + log_cmd_error("Invalid family specified: '%s'\n", family.c_str()); + + log_header(design, "Executing SYNTH_QUICKLOGIC pass.\n"); + log_push(); + + run_script(design, run_from, run_to); + + log_pop(); + } + + void script() override + { + if (check_label("begin")) { + run(stringf("read_verilog -lib -specify +/quicklogic/cells_sim.v +/quicklogic/%s_cells_sim.v", family.c_str())); + run("read_verilog -lib -specify +/quicklogic/lut_sim.v"); + run(stringf("hierarchy -check %s", help_mode ? "-top <top>" : top_opt.c_str())); + } + + if (check_label("coarse")) { + run("proc"); + run("flatten"); + run("tribuf -logic"); + run("deminout"); + run("opt_expr"); + run("opt_clean"); + run("check"); + run("opt -nodffe -nosdff"); + run("fsm"); + run("opt"); + run("wreduce"); + run("peepopt"); + run("opt_clean"); + run("share"); + run("techmap -map +/cmp2lut.v -D LUT_WIDTH=4"); + run("opt_expr"); + run("opt_clean"); + run("alumacc"); + run("pmuxtree"); + run("opt"); + run("memory -nomap"); + run("opt_clean"); + } + + if (check_label("map_ffram")) { + run("opt -fast -mux_undef -undriven -fine"); + run("memory_map -iattr -attr !ram_block -attr !rom_block -attr logic_block " + "-attr syn_ramstyle=auto -attr syn_ramstyle=registers " + "-attr syn_romstyle=auto -attr syn_romstyle=logic"); + run("opt -undriven -fine"); + } + + if (check_label("map_gates")) { + run("techmap"); + run("opt -fast"); + run("muxcover -mux8 -mux4"); + } + + if (check_label("map_ffs")) { + run("opt_expr"); + run("dfflegalize -cell $_DFFSRE_PPPP_ 0 -cell $_DLATCH_?_ x"); + + run(stringf("techmap -map +/quicklogic/%s_cells_map.v -map +/quicklogic/%s_ffs_map.v", family.c_str(), family.c_str())); + + run("opt_expr -mux_undef"); + } + + if (check_label("map_luts")) { + run(stringf("techmap -map +/quicklogic/%s_latches_map.v", family.c_str())); + run("abc -luts 1,2,2,4 -dress"); + + run("clean"); + } + + if (check_label("map_cells")) { + run(stringf("techmap -map +/quicklogic/%s_lut_map.v", family.c_str())); + run("clean"); + } + + if (check_label("check")) { + run("autoname"); + run("hierarchy -check"); + run("stat"); + run("check -noinit"); + } + + if (check_label("iomap")) { + run("clkbufmap -inpad ckpad Q:P"); + run("iopadmap -bits -outpad outpad A:P -inpad inpad Q:P -tinoutpad bipad EN:Q:A:P A:top"); + } + + if (check_label("finalize")) { + run("setundef -zero -params -undriven"); + run("hilomap -hicell logic_1 A -locell logic_0 A -singleton A:top"); + run("opt_clean -purge"); + run("check"); + run("blackbox =A:whitebox"); + } + + if (check_label("blif")) { + if (!blif_file.empty() || help_mode) { + run(stringf("write_blif -attr -param %s %s", top_opt.c_str(), blif_file.c_str())); + } + } + + if (check_label("verilog")) { + if (!verilog_file.empty()) { + run("write_verilog -noattr -nohex " + verilog_file); + } + } + } + +} SynthQuicklogicPass; + +PRIVATE_NAMESPACE_END diff --git a/tests/arch/quicklogic/add_sub.ys b/tests/arch/quicklogic/add_sub.ys new file mode 100644 index 000000000..168b3f8b3 --- /dev/null +++ b/tests/arch/quicklogic/add_sub.ys @@ -0,0 +1,11 @@ +read_verilog ../common/add_sub.v +hierarchy -top top +equiv_opt -assert -map +/quicklogic/lut_sim.v -map +/quicklogic/pp3_cells_sim.v synth_quicklogic -family pp3 # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd top # Constrain all select calls below inside the top module +select -assert-count 3 t:LUT2 +select -assert-count 4 t:LUT3 +select -assert-count 4 t:LUT4 +select -assert-count 8 t:inpad +select -assert-count 8 t:outpad +select -assert-none t:LUT2 t:LUT3 t:LUT4 t:inpad t:outpad %% t:* %D diff --git a/tests/arch/quicklogic/adffs.ys b/tests/arch/quicklogic/adffs.ys new file mode 100644 index 000000000..41a175844 --- /dev/null +++ b/tests/arch/quicklogic/adffs.ys @@ -0,0 +1,67 @@ +read_verilog ../common/adffs.v +design -save read + +hierarchy -top adff +proc +equiv_opt -async2sync -assert -map +/quicklogic/pp3_cells_sim.v -map +/quicklogic/cells_sim.v synth_quicklogic # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd adff # Constrain all select calls below inside the top module +select -assert-count 1 t:dffepc +select -assert-count 1 t:logic_0 +select -assert-count 1 t:logic_1 +select -assert-count 1 t:inpad +select -assert-count 1 t:outpad +select -assert-count 2 t:ckpad + +select -assert-none t:dffepc t:logic_0 t:logic_1 t:inpad t:outpad t:ckpad %% t:* %D + + +design -load read +hierarchy -top adffn +proc +equiv_opt -async2sync -assert -map +/quicklogic/pp3_cells_sim.v -map +/quicklogic/cells_sim.v -map +/quicklogic/lut_sim.v synth_quicklogic # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd adffn # Constrain all select calls below inside the top module +select -assert-count 1 t:LUT1 +select -assert-count 1 t:dffepc +select -assert-count 1 t:logic_0 +select -assert-count 1 t:logic_1 +select -assert-count 2 t:inpad +select -assert-count 1 t:outpad +select -assert-count 1 t:ckpad + +select -assert-none t:LUT1 t:dffepc t:logic_0 t:logic_1 t:inpad t:outpad t:ckpad %% t:* %D + + +design -load read +hierarchy -top dffs +proc +equiv_opt -async2sync -assert -map +/quicklogic/pp3_cells_sim.v -map +/quicklogic/cells_sim.v -map +/quicklogic/lut_sim.v synth_quicklogic # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd dffs # Constrain all select calls below inside the top module +select -assert-count 1 t:LUT2 +select -assert-count 1 t:dffepc +select -assert-count 1 t:logic_0 +select -assert-count 1 t:logic_1 +select -assert-count 3 t:inpad +select -assert-count 1 t:outpad +select -assert-count 1 t:ckpad + +select -assert-none t:LUT2 t:dffepc t:logic_0 t:logic_1 t:inpad t:outpad t:ckpad %% t:* %D + + +design -load read +hierarchy -top ndffnr +proc +equiv_opt -async2sync -assert -map +/quicklogic/pp3_cells_sim.v -map +/quicklogic/cells_sim.v -map +/quicklogic/lut_sim.v synth_quicklogic # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd ndffnr # Constrain all select calls below inside the top module +select -assert-count 1 t:LUT1 +select -assert-count 1 t:LUT2 +select -assert-count 1 t:dffepc +select -assert-count 1 t:logic_0 +select -assert-count 1 t:logic_1 +select -assert-count 4 t:inpad +select -assert-count 1 t:outpad + +select -assert-none t:LUT1 t:LUT2 t:dffepc t:logic_0 t:logic_1 t:inpad t:outpad %% t:* %D diff --git a/tests/arch/quicklogic/counter.ys b/tests/arch/quicklogic/counter.ys new file mode 100644 index 000000000..0c04b5742 --- /dev/null +++ b/tests/arch/quicklogic/counter.ys @@ -0,0 +1,18 @@ +read_verilog ../common/counter.v +hierarchy -top top +proc +flatten +equiv_opt -assert -multiclock -map +/quicklogic/pp3_cells_sim.v -map +/quicklogic/cells_sim.v -map +/quicklogic/lut_sim.v synth_quicklogic # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd top # Constrain all select calls below inside the top module +select -assert-count 1 t:LUT1 +select -assert-count 5 t:LUT2 +select -assert-count 2 t:LUT3 +select -assert-count 3 t:LUT4 +select -assert-count 8 t:dffepc +select -assert-count 1 t:logic_0 +select -assert-count 1 t:logic_1 +select -assert-count 8 t:outpad +select -assert-count 2 t:ckpad + +select -assert-none t:LUT1 t:LUT2 t:LUT3 t:LUT4 t:dffepc t:logic_0 t:logic_1 t:outpad t:ckpad %% t:* %D diff --git a/tests/arch/quicklogic/dffs.ys b/tests/arch/quicklogic/dffs.ys new file mode 100644 index 000000000..2e0a34540 --- /dev/null +++ b/tests/arch/quicklogic/dffs.ys @@ -0,0 +1,20 @@ +read_verilog ../common/dffs.v +rename dff my_dff # Work around conflicting module names between test and vendor cells +rename dffe my_dffe +design -save read + +hierarchy -top my_dff +proc +equiv_opt -async2sync -assert -map +/quicklogic/pp3_cells_sim.v -map +/quicklogic/cells_sim.v synth_quicklogic # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd dff # Constrain all select calls below inside the top module +select -assert-none t:* + +design -load read +hierarchy -top my_dffe +proc +equiv_opt -async2sync -assert -map +/quicklogic/pp3_cells_sim.v -map +/quicklogic/cells_sim.v synth_quicklogic # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd dffe # Constrain all select calls below inside the top module + +select -assert-none t:*
\ No newline at end of file diff --git a/tests/arch/quicklogic/fsm.ys b/tests/arch/quicklogic/fsm.ys new file mode 100644 index 000000000..7ed36b9e4 --- /dev/null +++ b/tests/arch/quicklogic/fsm.ys @@ -0,0 +1,24 @@ +read_verilog ../common/fsm.v +hierarchy -top fsm +proc +flatten + +equiv_opt -run :prove -map +/quicklogic/pp3_cells_sim.v -map +/quicklogic/cells_sim.v -map +/quicklogic/lut_sim.v synth_quicklogic +async2sync +miter -equiv -make_assert -flatten gold gate miter +sat -verify -prove-asserts -show-public -set-at 1 in_reset 1 -seq 20 -prove-skip 1 miter + +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd fsm # Constrain all select calls below inside the top module + +select -assert-count 3 t:LUT2 +select -assert-count 6 t:LUT3 +select -assert-count 7 t:LUT4 +select -assert-count 6 t:dffepc +select -assert-count 1 t:logic_0 +select -assert-count 1 t:logic_1 +select -assert-count 3 t:inpad +select -assert-count 2 t:outpad +select -assert-count 1 t:ckpad + +select -assert-none t:LUT2 t:LUT3 t:LUT4 t:dffepc t:logic_0 t:logic_1 t:inpad t:outpad t:ckpad %% t:* %D diff --git a/tests/arch/quicklogic/latches.ys b/tests/arch/quicklogic/latches.ys new file mode 100644 index 000000000..d7652f749 --- /dev/null +++ b/tests/arch/quicklogic/latches.ys @@ -0,0 +1,39 @@ +read_verilog ../common/latches.v +design -save read + +hierarchy -top latchp +proc +# Can't run any sort of equivalence check because latches are blown to LUTs +synth_quicklogic +cd latchp # Constrain all select calls below inside the top module +select -assert-count 1 t:LUT3 +select -assert-count 3 t:inpad +select -assert-count 1 t:outpad + +select -assert-none t:LUT3 t:inpad t:outpad %% t:* %D + + +design -load read +hierarchy -top latchn +proc +# Can't run any sort of equivalence check because latches are blown to LUTs +synth_quicklogic +cd latchn # Constrain all select calls below inside the top module +select -assert-count 1 t:LUT3 +select -assert-count 3 t:inpad +select -assert-count 1 t:outpad + +select -assert-none t:LUT3 t:inpad t:outpad %% t:* %D + + +design -load read +hierarchy -top latchsr +proc +# Can't run any sort of equivalence check because latches are blown to LUTs +synth_quicklogic +cd latchsr # Constrain all select calls below inside the top module +select -assert-count 2 t:LUT3 +select -assert-count 5 t:inpad +select -assert-count 1 t:outpad + +select -assert-none t:LUT3 t:inpad t:outpad %% t:* %D diff --git a/tests/arch/quicklogic/logic.ys b/tests/arch/quicklogic/logic.ys new file mode 100644 index 000000000..65f48a42b --- /dev/null +++ b/tests/arch/quicklogic/logic.ys @@ -0,0 +1,14 @@ +read_verilog ../common/logic.v +hierarchy -top top +proc +equiv_opt -assert -map +/quicklogic/pp3_cells_sim.v -map +/quicklogic/cells_sim.v -map +/quicklogic/lut_sim.v synth_quicklogic # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd top # Constrain all select calls below inside the top module + +select -assert-count 1 t:LUT1 +select -assert-count 6 t:LUT2 +select -assert-count 2 t:LUT4 +select -assert-count 8 t:inpad +select -assert-count 10 t:outpad + +select -assert-none t:LUT1 t:LUT2 t:LUT4 t:inpad t:outpad %% t:* %D diff --git a/tests/arch/quicklogic/mux.ys b/tests/arch/quicklogic/mux.ys new file mode 100644 index 000000000..632d14687 --- /dev/null +++ b/tests/arch/quicklogic/mux.ys @@ -0,0 +1,52 @@ +read_verilog ../common/mux.v +design -save read + +hierarchy -top mux2 +proc +equiv_opt -assert -map +/quicklogic/pp3_cells_sim.v -map +/quicklogic/cells_sim.v -map +/quicklogic/lut_sim.v synth_quicklogic # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd mux2 # Constrain all select calls below inside the top module +select -assert-count 1 t:LUT3 +select -assert-count 3 t:inpad +select -assert-count 1 t:outpad + +select -assert-none t:LUT3 t:inpad t:outpad %% t:* %D + +design -load read +hierarchy -top mux4 +proc +equiv_opt -assert -map +/quicklogic/pp3_cells_sim.v -map +/quicklogic/cells_sim.v -map +/quicklogic/lut_sim.v synth_quicklogic # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd mux4 # Constrain all select calls below inside the top module +select -assert-count 3 t:LUT3 +select -assert-count 6 t:inpad +select -assert-count 1 t:outpad + +select -assert-none t:LUT3 t:inpad t:outpad %% t:* %D + +design -load read +hierarchy -top mux8 +proc +equiv_opt -assert -map +/quicklogic/pp3_cells_sim.v -map +/quicklogic/cells_sim.v -map +/quicklogic/lut_sim.v synth_quicklogic # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd mux8 # Constrain all select calls below inside the top module +select -assert-count 4 t:LUT2 +select -assert-count 1 t:LUT3 +select -assert-count 2 t:mux4x0 +select -assert-count 11 t:inpad +select -assert-count 1 t:outpad + +select -assert-none t:LUT2 t:LUT3 t:mux4x0 t:inpad t:outpad %% t:* %D + +design -load read +hierarchy -top mux16 +proc +equiv_opt -assert -map +/quicklogic/pp3_cells_sim.v -map +/quicklogic/cells_sim.v -map +/quicklogic/lut_sim.v synth_quicklogic # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd mux16 # Constrain all select calls below inside the top module +select -assert-count 1 t:LUT3 +select -assert-count 2 t:mux8x0 +select -assert-count 20 t:inpad +select -assert-count 1 t:outpad + +select -assert-none t:LUT3 t:mux8x0 t:inpad t:outpad %% t:* %D diff --git a/tests/arch/quicklogic/run-test.sh b/tests/arch/quicklogic/run-test.sh new file mode 100755 index 000000000..4be4b70ae --- /dev/null +++ b/tests/arch/quicklogic/run-test.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash +set -eu +source ../../gen-tests-makefile.sh +run_tests --yosys-scripts --bash --yosys-args "-w 'Yosys has only limited support for tri-state logic at the moment.'" diff --git a/tests/arch/quicklogic/tribuf.ys b/tests/arch/quicklogic/tribuf.ys new file mode 100644 index 000000000..de763009e --- /dev/null +++ b/tests/arch/quicklogic/tribuf.ys @@ -0,0 +1,13 @@ +read_verilog ../common/tribuf.v +hierarchy -top tristate +proc +tribuf +flatten +synth +equiv_opt -assert -map +/quicklogic/pp3_cells_sim.v -map +/quicklogic/cells_sim.v -map +/simcells.v synth_quicklogic # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd tristate # Constrain all select calls below inside the top module +select -assert-count 2 t:inpad +select -assert-count 1 t:outpad +select -assert-count 1 t:$_TBUF_ +select -assert-none t:inpad t:outpad t:$_TBUF_ %% t:* %D diff --git a/tests/arch/xilinx/abc9_dff.ys b/tests/arch/xilinx/abc9_dff.ys index 210e87477..0ba3901f7 100644 --- a/tests/arch/xilinx/abc9_dff.ys +++ b/tests/arch/xilinx/abc9_dff.ys @@ -50,10 +50,10 @@ FDCE_1 /*#(.INIT(1))*/ fd7(.C(C), .CE(1'b0), .D(D), .CLR(1'b0), .Q(Q[6])); FDPE_1 #(.INIT(1)) fd8(.C(C), .CE(1'b0), .D(D), .PRE(1'b0), .Q(Q[7])); endmodule EOT -logger -expect warning "Whitebox '\$paramod\\FDRE\\INIT=1' with \(\* abc9_flop \*\) contains a \$dff cell with non-zero initial state -- this is not supported for ABC9 sequential synthesis. Treating as a blackbox\." 1 -logger -expect warning "Whitebox '\$paramod\\FDRE_1\\INIT=1' with \(\* abc9_flop \*\) contains a \$dff cell with non-zero initial state -- this is not supported for ABC9 sequential synthesis. Treating as a blackbox\." 1 +logger -expect warning "Whitebox '\$paramod\\FDRE\\INIT=.*1' with \(\* abc9_flop \*\) contains a \$dff cell with non-zero initial state -- this is not supported for ABC9 sequential synthesis. Treating as a blackbox\." 1 +logger -expect warning "Whitebox '\$paramod\\FDRE_1\\INIT=.*1' with \(\* abc9_flop \*\) contains a \$dff cell with non-zero initial state -- this is not supported for ABC9 sequential synthesis. Treating as a blackbox\." 1 logger -expect warning "Whitebox 'FDSE' with \(\* abc9_flop \*\) contains a \$dff cell with non-zero initial state -- this is not supported for ABC9 sequential synthesis. Treating as a blackbox\." 1 -logger -expect warning "Whitebox '\$paramod\\FDSE_1\\INIT=1' with \(\* abc9_flop \*\) contains a \$dff cell with non-zero initial state -- this is not supported for ABC9 sequential synthesis. Treating as a blackbox\." 1 +logger -expect warning "Whitebox '\$paramod\\FDSE_1\\INIT=.*1' with \(\* abc9_flop \*\) contains a \$dff cell with non-zero initial state -- this is not supported for ABC9 sequential synthesis. Treating as a blackbox\." 1 equiv_opt -assert -multiclock -map +/xilinx/cells_sim.v synth_xilinx -abc9 -dff -noiopad -noclkbuf design -load postopt select -assert-count 8 t:FD* |