From 01ea72f53a9707d741a1178d0ac4c4f69d6b65db Mon Sep 17 00:00:00 2001 From: David Shah Date: Mon, 21 Jan 2019 12:33:47 +0000 Subject: [PATCH 01/76] ecp5: Increase threshold for ALU mapping Signed-off-by: David Shah --- techlibs/ecp5/arith_map.v | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/techlibs/ecp5/arith_map.v b/techlibs/ecp5/arith_map.v index 1094c5f8a..eb7947601 100644 --- a/techlibs/ecp5/arith_map.v +++ b/techlibs/ecp5/arith_map.v @@ -33,7 +33,7 @@ module _80_ecp5_alu (A, B, CI, BI, X, Y, CO); input CI, BI; output [Y_WIDTH-1:0] CO; - wire _TECHMAP_FAIL_ = Y_WIDTH <= 2; + wire _TECHMAP_FAIL_ = Y_WIDTH <= 4; wire [Y_WIDTH-1:0] A_buf, B_buf; \$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(Y_WIDTH)) A_conv (.A(A), .Y(A_buf)); From d8003e87d1c5962e660ce84150239444b7fb037d Mon Sep 17 00:00:00 2001 From: David Shah Date: Mon, 21 Jan 2019 12:34:34 +0000 Subject: [PATCH 02/76] ecp5: More blackboxes Signed-off-by: David Shah --- techlibs/ecp5/cells_bb.v | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/techlibs/ecp5/cells_bb.v b/techlibs/ecp5/cells_bb.v index 425d62d24..32fb5c1ef 100644 --- a/techlibs/ecp5/cells_bb.v +++ b/techlibs/ecp5/cells_bb.v @@ -156,6 +156,23 @@ module OSCG( parameter DIV = 128; endmodule +(* blackbox *) (* keep *) +module USRMCLK( + input USRMCLKI, USRMCLKTS, + output USRMCLKO +); +endmodule + +(* blackbox *) (* keep *) +module JTAGG( + input TCK, TMS, TDI, JTDO2, JTDO1, + output TDO, JTDI, JTCK, JRTI2, JRTI1, + output JSHIFT, JUPDATE, JRSTN, JCE2, JCE1 +); +parameter ER1 = "ENABLED"; +parameter ER2 = "ENABLED"; +endmodule + (* blackbox *) module IDDRX1F( input D, SCLK, RST, From ee8c9e854f0b5f6500d030d4c700b29f042fb57f Mon Sep 17 00:00:00 2001 From: David Shah Date: Mon, 21 Jan 2019 12:35:22 +0000 Subject: [PATCH 03/76] ecp5: Add LSRMODE to flipflops for PRLD support Signed-off-by: David Shah --- techlibs/ecp5/cells_sim.v | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/techlibs/ecp5/cells_sim.v b/techlibs/ecp5/cells_sim.v index 507ab1beb..ca5d020f3 100644 --- a/techlibs/ecp5/cells_sim.v +++ b/techlibs/ecp5/cells_sim.v @@ -203,13 +203,14 @@ endmodule // --------------------------------------- -module TRELLIS_FF(input CLK, LSR, CE, DI, output reg Q); +module TRELLIS_FF(input CLK, LSR, CE, DI, M, output reg Q); parameter GSR = "ENABLED"; parameter [127:0] CEMUX = "1"; parameter CLKMUX = "CLK"; parameter LSRMUX = "LSR"; parameter SRMODE = "LSR_OVER_CE"; parameter REGSET = "RESET"; + parameter [127:0] LSRMODE = "LSR"; reg muxce; always @(*) @@ -222,8 +223,12 @@ module TRELLIS_FF(input CLK, LSR, CE, DI, output reg Q); wire muxlsr = (LSRMUX == "INV") ? ~LSR : LSR; wire muxclk = (CLKMUX == "INV") ? ~CLK : CLK; - - localparam srval = (REGSET == "SET") ? 1'b1 : 1'b0; + generate + if (LSRMODE == "PRLD") + wire srval = M; + else + localparam srval = (REGSET == "SET") ? 1'b1 : 1'b0; + endgenerate initial Q = srval; @@ -339,6 +344,8 @@ module TRELLIS_SLICE( parameter REG1_SD = "0"; parameter REG0_REGSET = "RESET"; parameter REG1_REGSET = "RESET"; + parameter REG0_LSRMODE = "LSR"; + parameter REG1_LSRMODE = "LSR"; parameter [127:0] CCU2_INJECT1_0 = "NO"; parameter [127:0] CCU2_INJECT1_1 = "NO"; parameter WREMUX = "WRE"; @@ -428,10 +435,11 @@ module TRELLIS_SLICE( .CLKMUX(CLKMUX), .LSRMUX(LSRMUX), .SRMODE(SRMODE), - .REGSET(REG0_REGSET) + .REGSET(REG0_REGSET), + .LSRMODE(REG0_LSRMODE) ) ff_0 ( .CLK(CLK), .LSR(LSR), .CE(CE), - .DI(muxdi0), + .DI(muxdi0), .M(M0), .Q(Q0) ); TRELLIS_FF #( @@ -440,10 +448,11 @@ module TRELLIS_SLICE( .CLKMUX(CLKMUX), .LSRMUX(LSRMUX), .SRMODE(SRMODE), - .REGSET(REG1_REGSET) + .REGSET(REG1_REGSET), + .LSRMODE(REG1_LSRMODE) ) ff_1 ( .CLK(CLK), .LSR(LSR), .CE(CE), - .DI(muxdi1), + .DI(muxdi1), .M(M1), .Q(Q1) ); endmodule From 549b8e74b2cef41a23e609bdb65c5b04b3141a61 Mon Sep 17 00:00:00 2001 From: David Shah Date: Fri, 30 Nov 2018 19:29:03 +0000 Subject: [PATCH 04/76] ecp5: Support for flipflop initialisation Signed-off-by: David Shah --- techlibs/ecp5/Makefile.inc | 2 +- techlibs/ecp5/ecp5_ffinit.cc | 198 +++++++++++++++++++++++++++++++++++ techlibs/ecp5/synth_ecp5.cc | 3 - 3 files changed, 199 insertions(+), 4 deletions(-) create mode 100644 techlibs/ecp5/ecp5_ffinit.cc diff --git a/techlibs/ecp5/Makefile.inc b/techlibs/ecp5/Makefile.inc index 8df02be5f..4db087e87 100644 --- a/techlibs/ecp5/Makefile.inc +++ b/techlibs/ecp5/Makefile.inc @@ -1,5 +1,5 @@ -OBJS += techlibs/ecp5/synth_ecp5.o +OBJS += techlibs/ecp5/synth_ecp5.o techlibs/ecp5/ecp5_ffinit.o $(eval $(call add_share_file,share/ecp5,techlibs/ecp5/cells_map.v)) $(eval $(call add_share_file,share/ecp5,techlibs/ecp5/cells_sim.v)) diff --git a/techlibs/ecp5/ecp5_ffinit.cc b/techlibs/ecp5/ecp5_ffinit.cc new file mode 100644 index 000000000..02945fff4 --- /dev/null +++ b/techlibs/ecp5/ecp5_ffinit.cc @@ -0,0 +1,198 @@ +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2012 Clifford Wolf + * Copyright (C) 2018-19 David Shah + * + * 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/yosys.h" +#include "kernel/sigtools.h" + +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + +struct Ecp5FfinitPass : public Pass { + Ecp5FfinitPass() : Pass("ecp5_ffinit", "ECP5: handle FF init values") { } + void help() YS_OVERRIDE + { + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| + log("\n"); + log(" ecp5_ffinit [options] [selection]\n"); + log("\n"); + log("Remove init values for FF output signals when equal to reset value.\n"); + log("If reset is not used, set the reset value to the init value, otherwise\n"); + log("unmap out the reset (if not an async reset).\n"); + } + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE + { + log_header(design, "Executing ECP5_FFINIT pass (implement FF init values).\n"); + + size_t argidx; + for (argidx = 1; argidx < args.size(); argidx++) + { + // if (args[argidx] == "-singleton") { + // singleton_mode = true; + // continue; + // } + break; + } + extra_args(args, argidx, design); + + for (auto module : design->selected_modules()) + { + log("Handling FF init values in %s.\n", log_id(module)); + + SigMap sigmap(module); + pool init_wires; + dict initbits; + dict initbit_to_wire; + pool handled_initbits; + + for (auto wire : module->selected_wires()) + { + if (wire->attributes.count("\\init") == 0) + continue; + + SigSpec wirebits = sigmap(wire); + Const initval = wire->attributes.at("\\init"); + init_wires.insert(wire); + + for (int i = 0; i < GetSize(wirebits) && i < GetSize(initval); i++) + { + SigBit bit = wirebits[i]; + State val = initval[i]; + + if (val != State::S0 && val != State::S1) + continue; + + if (initbits.count(bit)) { + if (initbits.at(bit) != val) + log_error("Conflicting init values for signal %s (%s = %s, %s = %s).\n", + log_signal(bit), log_signal(SigBit(wire, i)), log_signal(val), + log_signal(initbit_to_wire[bit]), log_signal(initbits.at(bit))); + continue; + } + + initbits[bit] = val; + initbit_to_wire[bit] = SigBit(wire, i); + } + } + for (auto cell : module->selected_cells()) + { + if (cell->type != "\\TRELLIS_FF") + continue; + SigSpec sig_d = cell->getPort("\\DI"); + SigSpec sig_q = cell->getPort("\\Q"); + SigSpec sig_lsr = cell->getPort("\\LSR"); + + if (GetSize(sig_d) < 1 || GetSize(sig_q) < 1) + continue; + + SigBit bit_d = sigmap(sig_d[0]); + SigBit bit_q = sigmap(sig_q[0]); + + std::string regset = "RESET"; + if (cell->hasParam("\\REGSET")) + regset = cell->getParam("\\REGSET").decode_string(); + State resetState; + if (regset == "SET") + resetState = State::S1; + else if (regset == "RESET") + resetState = State::S0; + else + log_error("FF cell %s has illegal REGSET value %s.\n", + log_id(cell), regset.c_str()); + + if (!initbits.count(bit_q)) + continue; + + State val = initbits.at(bit_q); + + log("FF init value for cell %s (%s): %s = %c\n", log_id(cell), log_id(cell->type), + log_signal(bit_q), val != State::S0 ? '1' : '0'); + // Initval is the same as the reset state. Matches hardware, nowt more to do + if (val == resetState) { + handled_initbits.insert(bit_q); + continue; + } + + if (GetSize(sig_lsr) >= 1 && sig_lsr[0] != State::S0) { + std::string srmode = "LSR_OVER_CE"; + if (cell->hasParam("\\SRMODE")) + srmode = cell->getParam("\\SRMODE").decode_string(); + if (srmode == "ASYNC") { + log("Async reset value %c for FF cell %s inconsistent with init value %c.\n", + resetState != State::S0 ? '1' : '0', log_id(cell), val != State::S0 ? '1' : '0'); + } else { + SigBit bit_lsr = sigmap(sig_lsr[0]); + Wire *new_bit_d = module->addWire(NEW_ID); + if (resetState == State::S0) { + module->addAndnotGate(NEW_ID, bit_d, bit_lsr, new_bit_d); + } else { + module->addOrGate(NEW_ID, bit_d, bit_lsr, new_bit_d); + } + + cell->setPort("\\DI", new_bit_d); + cell->setPort("\\LSR", State::S0); + + if(cell->hasPort("\\CE")) { + std::string cemux = "CE"; + if (cell->hasParam("\\CEMUX")) + cemux = cell->getParam("\\CEMUX").decode_string(); + SigSpec sig_ce = cell->getPort("\\CE"); + if (GetSize(sig_ce) >= 1) { + SigBit bit_ce = sigmap(sig_ce[0]); + Wire *new_bit_ce = module->addWire(NEW_ID); + if (cemux == "INV") + module->addAndnotGate(NEW_ID, bit_ce, bit_lsr, new_bit_ce); + else + module->addOrGate(NEW_ID, bit_ce, bit_lsr, new_bit_ce); + cell->setPort("\\CE", new_bit_ce); + } + } + cell->setParam("\\REGSET", val != State::S0 ? Const("SET") : Const("RESET")); + handled_initbits.insert(bit_q); + } + } else { + cell->setParam("\\REGSET", val != State::S0 ? Const("SET") : Const("RESET")); + handled_initbits.insert(bit_q); + } + } + + for (auto wire : init_wires) + { + if (wire->attributes.count("\\init") == 0) + continue; + + SigSpec wirebits = sigmap(wire); + Const &initval = wire->attributes.at("\\init"); + bool remove_attribute = true; + + for (int i = 0; i < GetSize(wirebits) && i < GetSize(initval); i++) { + if (handled_initbits.count(wirebits[i])) + initval[i] = State::Sx; + else if (initval[i] != State::Sx) + remove_attribute = false; + } + + if (remove_attribute) + wire->attributes.erase("\\init"); + } + } + } +} Ecp5FfinitPass; + +PRIVATE_NAMESPACE_END diff --git a/techlibs/ecp5/synth_ecp5.cc b/techlibs/ecp5/synth_ecp5.cc index 2e9176a84..835f10d8c 100644 --- a/techlibs/ecp5/synth_ecp5.cc +++ b/techlibs/ecp5/synth_ecp5.cc @@ -255,10 +255,7 @@ struct SynthEcp5Pass : public ScriptPass run("techmap -D NO_LUT -map +/ecp5/cells_map.v"); run("opt_expr -mux_undef"); run("simplemap"); - // TODO -#if 0 run("ecp5_ffinit"); -#endif } if (check_label("map_luts")) From 7913baedd8c776243cbcf5ce73549943d1fe83a2 Mon Sep 17 00:00:00 2001 From: David Shah Date: Tue, 12 Feb 2019 12:04:41 +0000 Subject: [PATCH 05/76] ecp5: Full set of IO-related blackboxes Signed-off-by: David Shah --- techlibs/ecp5/cells_bb.v | 102 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 102 insertions(+) diff --git a/techlibs/ecp5/cells_bb.v b/techlibs/ecp5/cells_bb.v index 32fb5c1ef..5b8d6bb4a 100644 --- a/techlibs/ecp5/cells_bb.v +++ b/techlibs/ecp5/cells_bb.v @@ -181,6 +181,31 @@ module IDDRX1F( parameter GSR = "ENABLED"; endmodule +(* blackbox *) +module IDDRX2F( + input D, SCLK, ECLK, RST, + output Q0, Q1, Q2, Q3 +); + parameter GSR = "ENABLED"; +endmodule + +(* blackbox *) +module IDDR71B( + input D, SCLK, ECLK, RST, ALIGNWD, + output Q0, Q1, Q2, Q3, Q4, Q5, Q6 +); + parameter GSR = "ENABLED"; +endmodule + +(* blackbox *) +module IDDRX2DQA( + input D, DQSR90, ECLK, SCLK, RST, + input RDPNTR2, RDPNTR1, RDPNTR0, WRPNTR2, WRPNTR1, WRPNTR0, + output Q0, Q1, Q2, Q3, QWL +); + parameter GSR = "ENABLED"; +endmodule + (* blackbox *) module ODDRX1F( input SCLK, RST, D0, D1, @@ -189,6 +214,83 @@ module ODDRX1F( parameter GSR = "ENABLED"; endmodule +(* blackbox *) +module ODDRX2F( + input SCLK, ECLK, RST, D0, D1, D2, D3, + output Q +); + parameter GSR = "ENABLED"; +endmodule + +(* blackbox *) +module ODDR71B( + input SCLK, ECLK, RST, D0, D1, D2, D3, D4, D5, D6, + output Q +); + parameter GSR = "ENABLED"; +endmodule + +(* blackbox *) +module OSHX2A( + input D0, D1, RST, ECLK, SCLK, + output Q +); + parameter GSR = "ENABLED"; +endmodule + +(* blackbox *) +module ODDRX2DQA( + input D0, D1, D2, D3, RST, ECLK, SCLK, DQSW270, + output Q +); + parameter GSR = "ENABLED"; +endmodule + +(* blackbox *) +module ODDRX2DQSB( + input D0, D1, D2, D3, RST, ECLK, SCLK, DQSW, + output Q +); + parameter GSR = "ENABLED"; +endmodule + +(* blackbox *) +module TSHX2DQA( + input T0, T1, SCLK, ECLK, DQSW270, RST, + output Q +); + parameter GSR = "ENABLED"; + parameter REGSET = "SET"; +endmodule + +(* blackbox *) +module TSHX2DQSA( + input T0, T1, SCLK, ECLK, DQSW, RST, + output Q +); + parameter GSR = "ENABLED"; + parameter REGSET = "SET"; +endmodule + + +(* blackbox *) +module DQSBUFM( + input DQSI, READ1, READ0, READCLKSEL2, READCLKSEL1, READCLKSEL0, DDRDEL, + input ECLK, SCLK, + input DYNDELAY7, DYNDELAY6, DYNDELAY5, DYNDELAY4, + input DYNDELAY3, DYNDELAY2, DYNDELAY1, DYNDELAY0, + input RST, RDLOADN, RDMOVE, RDDIRECTION, WRLOADN, WRMOVE, WRDIRECTION, PAUSE, + output DQSR90, DQSW, DQSW270, + output RDPNTR2, RDPNTR1, RDPNTR0, WRPNTR2, WRPNTR1, WRPNTR0, + output DATAVALID, BURSTDET, RDCFLAG, WRCFLAG +); + parameter DQS_LI_DEL_ADJ = "FACTORYONLY"; + parameter DQS_LI_DEL_VAL = 0; + parameter DQS_LO_DEL_ADJ = "FACTORYONLY"; + parameter DQS_LO_DEL_VAL = 0; + parameter GSR = "ENABLED"; +endmodule + (* blackbox *) module CLKDIVF( input CLKI, RST, ALIGNWD, From e0bc190879d1c722c267ae9370a16ce202345b76 Mon Sep 17 00:00:00 2001 From: David Shah Date: Wed, 13 Feb 2019 11:23:25 +0000 Subject: [PATCH 06/76] ecp5: Add ECLKSYNCB blackbox Signed-off-by: David Shah --- techlibs/ecp5/cells_bb.v | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/techlibs/ecp5/cells_bb.v b/techlibs/ecp5/cells_bb.v index 5b8d6bb4a..1de623fcd 100644 --- a/techlibs/ecp5/cells_bb.v +++ b/techlibs/ecp5/cells_bb.v @@ -272,7 +272,6 @@ module TSHX2DQSA( parameter REGSET = "SET"; endmodule - (* blackbox *) module DQSBUFM( input DQSI, READ1, READ0, READCLKSEL2, READCLKSEL1, READCLKSEL0, DDRDEL, @@ -300,6 +299,13 @@ module CLKDIVF( parameter DIV = "2.0"; endmodule +(* blackbox *) +module ECLKSYNCB( + input ECLKI, STOP, + output ECLKO +); +endmodule + (* blackbox *) module DCCA( input CLKI, CE, From c36f15b489c1d47e94901e9286c4f1c2afb815c4 Mon Sep 17 00:00:00 2001 From: David Shah Date: Tue, 19 Feb 2019 14:10:43 +0000 Subject: [PATCH 07/76] ecp5: Add DELAYF/DELAYG blackboxes Signed-off-by: David Shah --- techlibs/ecp5/cells_bb.v | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/techlibs/ecp5/cells_bb.v b/techlibs/ecp5/cells_bb.v index 1de623fcd..bac17260f 100644 --- a/techlibs/ecp5/cells_bb.v +++ b/techlibs/ecp5/cells_bb.v @@ -173,6 +173,24 @@ parameter ER1 = "ENABLED"; parameter ER2 = "ENABLED"; endmodule +(* blackbox *) +module DELAYF( + input A, LOADN, MOVE, DIRECTION, + output Z, CFLAG +); + parameter DEL_MODE = "USER_DEFINED"; + parameter DEL_VALUE = 0; +endmodule + +(* blackbox *) +module DELAYG( + input A, + output Z +); + parameter DEL_MODE = "USER_DEFINED"; + parameter DEL_VALUE = 0; +endmodule + (* blackbox *) module IDDRX1F( input D, SCLK, RST, From bb56cb738d6586059855cc3deefad12119673157 Mon Sep 17 00:00:00 2001 From: David Shah Date: Tue, 19 Feb 2019 19:34:37 +0000 Subject: [PATCH 08/76] ecp5: Add DDRDLLA Signed-off-by: David Shah --- techlibs/ecp5/cells_bb.v | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/techlibs/ecp5/cells_bb.v b/techlibs/ecp5/cells_bb.v index bac17260f..223e19b9e 100644 --- a/techlibs/ecp5/cells_bb.v +++ b/techlibs/ecp5/cells_bb.v @@ -308,6 +308,15 @@ module DQSBUFM( parameter GSR = "ENABLED"; endmodule +(* blackbox *) +module DDRDLLA( + input CLK, RST, UDDCNTLN, FREEZE, + output LOCK, DDRDEL, DCNTL7, DCNTL6, DCNTL5, DCNTL4, DCNTL3, DCNTL2, DCNTL1, DCNTL0 +); + parameter FORCE_MAX_DELAY = "NO"; + parameter GSR = "ENABLED"; +endmodule + (* blackbox *) module CLKDIVF( input CLKI, RST, ALIGNWD, From fa2f595cfa240b86edb26e859449c1c54eaf49ef Mon Sep 17 00:00:00 2001 From: David Shah Date: Tue, 19 Feb 2019 19:35:10 +0000 Subject: [PATCH 09/76] ecp5: Compatibility with Migen AsyncResetSynchronizer Signed-off-by: David Shah --- techlibs/ecp5/cells_map.v | 3 +++ techlibs/ecp5/cells_sim.v | 17 +++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/techlibs/ecp5/cells_map.v b/techlibs/ecp5/cells_map.v index 23182bdeb..6ab4b69f2 100644 --- a/techlibs/ecp5/cells_map.v +++ b/techlibs/ecp5/cells_map.v @@ -47,6 +47,9 @@ module \$__DFFSE_NP1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED" module \$__DFFSE_PP0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule module \$__DFFSE_PP1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule +// For Diamond compatibility, FIXME: add all Diamond flipflop mappings +module FD1S3BX(input PD, D, CK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(PD), .DI(D), .Q(Q)); endmodule + `ifndef NO_LUT module \$lut (A, Y); parameter WIDTH = 0; diff --git a/techlibs/ecp5/cells_sim.v b/techlibs/ecp5/cells_sim.v index ca5d020f3..d2d8b5793 100644 --- a/techlibs/ecp5/cells_sim.v +++ b/techlibs/ecp5/cells_sim.v @@ -556,3 +556,20 @@ module DP16KD( parameter INITVAL_3E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INITVAL_3F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; endmodule + +// For Diamond compatibility, FIXME: add all Diamond flipflop mappings +module FD1S3BX(input PD, D, CK, output Q); + TRELLIS_FF #( + .GSR("DISABLED"), + .CEMUX("1"), + .CLKMUX("CLK"), + .LSRMUX("LSR"), + .REGSET("SET"), + .SRMODE("ASYNC") + ) tff_i ( + .CLK(CK), + .LSR(PD), + .DI(D), + .Q(Q) + ); +endmodule From 171c425cf9addb61ef3f03596fd26355ed8af76d Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Mon, 25 Feb 2019 16:18:13 -0800 Subject: [PATCH 10/76] Fix FIRRTL to Verilog process instance subfield assignment. Don't emit subfield assignments: bits(x, y, z) <= ... - but instead, add them to the reverse-wire-map where they'll be treated at the end of the module. Enable tests which were disabled due to incorrect treatment of subfields. Assume the `$firrtl2verilog` variable contains any additional switches to control verilog generation (i.e. `--no-dedup -X mverilog`) --- backends/firrtl/firrtl.cc | 28 ++++++++++++++++++++-------- tests/asicworld/xfirrtl | 1 - tests/simple/xfirrtl | 1 - tests/tools/autotest.sh | 2 +- 4 files changed, 21 insertions(+), 11 deletions(-) diff --git a/backends/firrtl/firrtl.cc b/backends/firrtl/firrtl.cc index 0917ecba6..88c1038b7 100644 --- a/backends/firrtl/firrtl.cc +++ b/backends/firrtl/firrtl.cc @@ -169,7 +169,6 @@ struct FirrtlWorker return *str == '\\' ? str + 1 : str; } - std::string cellname(RTLIL::Cell *cell) { return fid(cell->name).c_str(); @@ -219,29 +218,42 @@ struct FirrtlWorker if (it->second.size() > 0) { const SigSpec &secondSig = it->second; const std::string firstName = cell_name + "." + make_id(it->first); - const std::string secondName = make_expr(secondSig); + const std::string secondExpr = make_expr(secondSig); // Find the direction for this port. FDirection dir = getPortFDirection(it->first, instModule); - std::string source, sink; + std::string sourceExpr, sinkExpr; + const SigSpec *sinkSig = nullptr; switch (dir) { case FD_INOUT: log_warning("Instance port connection %s.%s is INOUT; treating as OUT\n", cell_type.c_str(), log_signal(it->second)); case FD_OUT: - source = firstName; - sink = secondName; + sourceExpr = firstName; + sinkExpr = secondExpr; + sinkSig = &secondSig; break; case FD_NODIRECTION: log_warning("Instance port connection %s.%s is NODIRECTION; treating as IN\n", cell_type.c_str(), log_signal(it->second)); /* FALL_THROUGH */ case FD_IN: - source = secondName; - sink = firstName; + sourceExpr = secondExpr; + sinkExpr = firstName; break; default: log_error("Instance port %s.%s unrecognized connection direction 0x%x !\n", cell_type.c_str(), log_signal(it->second), dir); break; } - wire_exprs.push_back(stringf("\n%s%s <= %s", indent.c_str(), sink.c_str(), source.c_str())); + // Check for subfield assignment. + std::string bitsString = "bits("; + if (sinkExpr.substr(0, bitsString.length()) == bitsString ) { + if (sinkSig == nullptr) + log_error("Unknown subfield %s.%s\n", cell_type.c_str(), sinkExpr.c_str()); + // Don't generate the assignment here. + // Add the source and sink to the "reverse_wire_map" and we'll output the assignment + // as part of the coalesced subfield assignments for this wire. + register_reverse_wire_map(sourceExpr, *sinkSig); + } else { + wire_exprs.push_back(stringf("\n%s%s <= %s", indent.c_str(), sinkExpr.c_str(), sourceExpr.c_str())); + } } } wire_exprs.push_back(stringf("\n")); diff --git a/tests/asicworld/xfirrtl b/tests/asicworld/xfirrtl index c782a2bd6..08bf4ccd8 100644 --- a/tests/asicworld/xfirrtl +++ b/tests/asicworld/xfirrtl @@ -6,7 +6,6 @@ code_hdl_models_d_latch_gates.v combinational loop code_hdl_models_dff_async_reset.v $adff code_hdl_models_tff_async_reset.v $adff code_hdl_models_uart.v $adff -code_specman_switch_fabric.v subfield assignment (bits() <= ...) code_tidbits_asyn_reset.v $adff code_tidbits_reg_seq_example.v $adff code_verilog_tutorial_always_example.v empty module diff --git a/tests/simple/xfirrtl b/tests/simple/xfirrtl index 00e89b389..5bc75347b 100644 --- a/tests/simple/xfirrtl +++ b/tests/simple/xfirrtl @@ -12,7 +12,6 @@ multiplier.v inst id[0] of muxtree.v drops modules omsp_dbg_uart.v $adff operators.v $pow -paramods.v subfield assignment (bits() <= ...) partsel.v drops modules process.v drops modules realexpr.v drops modules diff --git a/tests/tools/autotest.sh b/tests/tools/autotest.sh index 218edf931..99ec3e7cd 100755 --- a/tests/tools/autotest.sh +++ b/tests/tools/autotest.sh @@ -175,7 +175,7 @@ do if [ -n "$firrtl2verilog" ]; then if test -z "$xfirrtl" || ! grep "$fn" "$xfirrtl" ; then "$toolsdir"/../../yosys -b "firrtl" -o ${bn}_ref.fir -f "$frontend $include_opts" -p "prep -nordff; proc; opt; memory; opt; fsm; opt -full -fine; pmuxtree" ${bn}_ref.v - $firrtl2verilog -i ${bn}_ref.fir -o ${bn}_ref.fir.v -X verilog + $firrtl2verilog -i ${bn}_ref.fir -o ${bn}_ref.fir.v test_passes -f "$frontend $include_opts" -p "hierarchy; proc; opt; memory; opt; fsm; opt -full -fine" ${bn}_ref.fir.v fi fi From 61fc411c5d7237e420ee6eb9f6eb093e70d1007d Mon Sep 17 00:00:00 2001 From: Larry Doolittle Date: Sun, 24 Feb 2019 22:08:52 -0800 Subject: [PATCH 11/76] Clean up some whitepsace outliers --- passes/techmap/dfflibmap.cc | 4 ++-- passes/techmap/flowmap.cc | 4 ++-- techlibs/ecp5/cells_sim.v | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/passes/techmap/dfflibmap.cc b/passes/techmap/dfflibmap.cc index b0528d473..274177a68 100644 --- a/passes/techmap/dfflibmap.cc +++ b/passes/techmap/dfflibmap.cc @@ -660,8 +660,8 @@ struct DfflibmapPass : public Pass { map_adff_to_dff("$_DFF_PP0_", "$_DFF_P_"); map_adff_to_dff("$_DFF_PP1_", "$_DFF_P_"); - log(" final dff cell mappings:\n"); - logmap_all(); + log(" final dff cell mappings:\n"); + logmap_all(); for (auto &it : design->modules_) if (design->selected(it.second) && !it.second->get_bool_attribute("\\blackbox")) diff --git a/passes/techmap/flowmap.cc b/passes/techmap/flowmap.cc index ddbd7bf5d..0b7931e48 100644 --- a/passes/techmap/flowmap.cc +++ b/passes/techmap/flowmap.cc @@ -132,9 +132,9 @@ static void dump_dot_graph(string filename, pool nodes, dict> edges, pool inputs, pool outputs, std::function node_style = - [](RTLIL::SigBit) { return GraphStyle{}; }, + [](RTLIL::SigBit) { return GraphStyle{}; }, std::function edge_style = - [](RTLIL::SigBit, RTLIL::SigBit) { return GraphStyle{}; }, + [](RTLIL::SigBit, RTLIL::SigBit) { return GraphStyle{}; }, string name = "") { FILE *f = fopen(filename.c_str(), "w"); diff --git a/techlibs/ecp5/cells_sim.v b/techlibs/ecp5/cells_sim.v index 507ab1beb..f27540bd7 100644 --- a/techlibs/ecp5/cells_sim.v +++ b/techlibs/ecp5/cells_sim.v @@ -57,7 +57,7 @@ module TRELLIS_RAM16X2 ( input RAD0, RAD1, RAD2, RAD3, output DO0, DO1 ); - parameter WCKMUX = "WCK"; + parameter WCKMUX = "WCK"; parameter WREMUX = "WRE"; parameter INITVAL_0 = 16'h0000; parameter INITVAL_1 = 16'h0000; @@ -104,7 +104,7 @@ module TRELLIS_DPR16X4 ( input [3:0] RAD, output [3:0] DO ); - parameter WCKMUX = "WCK"; + parameter WCKMUX = "WCK"; parameter WREMUX = "WRE"; parameter [63:0] INITVAL = 64'h0000000000000000; From 7a40294e93490fa462343244b1e2881c3c249c3f Mon Sep 17 00:00:00 2001 From: Larry Doolittle Date: Sun, 24 Feb 2019 22:09:54 -0800 Subject: [PATCH 12/76] techlibs/greenpak4/cells_map.v: Harmonize whitespace within lut module --- techlibs/greenpak4/cells_map.v | 44 +++++++++++++++++----------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/techlibs/greenpak4/cells_map.v b/techlibs/greenpak4/cells_map.v index b971a51fa..51c85183d 100644 --- a/techlibs/greenpak4/cells_map.v +++ b/techlibs/greenpak4/cells_map.v @@ -112,14 +112,14 @@ module GP_OBUFT(input IN, input OE, output OUT); endmodule module \$lut (A, Y); - parameter WIDTH = 0; - parameter LUT = 0; + parameter WIDTH = 0; + parameter LUT = 0; - input [WIDTH-1:0] A; - output Y; + input [WIDTH-1:0] A; + output Y; - generate - if (WIDTH == 1) begin + generate + if (WIDTH == 1) begin if(LUT == 2'b01) begin GP_INV _TECHMAP_REPLACE_ (.OUT(Y), .IN(A[0]) ); end @@ -127,22 +127,22 @@ module \$lut (A, Y); GP_2LUT #(.INIT({2'b00, LUT})) _TECHMAP_REPLACE_ (.OUT(Y), .IN0(A[0]), .IN1(1'b0)); end - end else - if (WIDTH == 2) begin - GP_2LUT #(.INIT(LUT)) _TECHMAP_REPLACE_ (.OUT(Y), - .IN0(A[0]), .IN1(A[1])); - end else - if (WIDTH == 3) begin - GP_3LUT #(.INIT(LUT)) _TECHMAP_REPLACE_ (.OUT(Y), - .IN0(A[0]), .IN1(A[1]), .IN2(A[2])); - end else - if (WIDTH == 4) begin - GP_4LUT #(.INIT(LUT)) _TECHMAP_REPLACE_ (.OUT(Y), - .IN0(A[0]), .IN1(A[1]), .IN2(A[2]), .IN3(A[3])); - end else begin - wire _TECHMAP_FAIL_ = 1; - end - endgenerate + end else + if (WIDTH == 2) begin + GP_2LUT #(.INIT(LUT)) _TECHMAP_REPLACE_ (.OUT(Y), + .IN0(A[0]), .IN1(A[1])); + end else + if (WIDTH == 3) begin + GP_3LUT #(.INIT(LUT)) _TECHMAP_REPLACE_ (.OUT(Y), + .IN0(A[0]), .IN1(A[1]), .IN2(A[2])); + end else + if (WIDTH == 4) begin + GP_4LUT #(.INIT(LUT)) _TECHMAP_REPLACE_ (.OUT(Y), + .IN0(A[0]), .IN1(A[1]), .IN2(A[2]), .IN3(A[3])); + end else begin + wire _TECHMAP_FAIL_ = 1; + end + endgenerate endmodule module \$__COUNT_ (CE, CLK, OUT, POUT, RST, UP); From a58dbcf2bae38835cdc2964718d4562ae4be4cc5 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 27 Feb 2019 11:37:08 -0800 Subject: [PATCH 13/76] Add "supercover" skeleton Signed-off-by: Clifford Wolf --- passes/sat/Makefile.inc | 1 + passes/sat/supercover.cc | 76 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+) create mode 100644 passes/sat/supercover.cc diff --git a/passes/sat/Makefile.inc b/passes/sat/Makefile.inc index 8ab0280c0..6cb1ea644 100644 --- a/passes/sat/Makefile.inc +++ b/passes/sat/Makefile.inc @@ -8,4 +8,5 @@ OBJS += passes/sat/expose.o OBJS += passes/sat/assertpmux.o OBJS += passes/sat/clk2fflogic.o OBJS += passes/sat/async2sync.o +OBJS += passes/sat/supercover.o diff --git a/passes/sat/supercover.cc b/passes/sat/supercover.cc new file mode 100644 index 000000000..9b208b0bf --- /dev/null +++ b/passes/sat/supercover.cc @@ -0,0 +1,76 @@ +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2012 Clifford Wolf + * + * 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/yosys.h" +#include "kernel/sigtools.h" + +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + +struct SupercoverPass : public Pass { + SupercoverPass() : Pass("supercover", "add hi/lo cover cells for each wire bit") { } + void help() YS_OVERRIDE + { + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| + log("\n"); + log(" supercover [options] [selection]\n"); + log("\n"); + log("This command adds two cover cells for each bit of each selected wire, one\n"); + log("checking for a hi signal level and one checking for lo level.\n"); + log("\n"); + } + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE + { + // bool flag_noinit = false; + + log_header(design, "Executing SUPERCOVER pass.\n"); + + size_t argidx; + for (argidx = 1; argidx < args.size(); argidx++) + { + // if (args[argidx] == "-noinit") { + // flag_noinit = true; + // continue; + // } + break; + } + extra_args(args, argidx, design); + + for (auto module : design->selected_modules()) + { + int cnt_wire = 0, cnt_bits = 0; + log("Adding cover cells to module %s.\n", log_id(module)); + for (auto wire : module->selected_wires()) + { + std::string src = wire->get_src_attribute(); + cnt_wire++; + for (auto bit : SigSpec(wire)) + { + SigSpec inv = module->Not(NEW_ID, bit); + module->addCover(NEW_ID, bit, State::S1, src); + module->addCover(NEW_ID, inv, State::S1, src); + cnt_bits++; + } + } + log(" added cover cells to %d wires, %d bits.\n", cnt_wire, cnt_bits); + } + } +} SupercoverPass; + +PRIVATE_NAMESPACE_END From 63be3f3bab9293cf5b8f7416fce13cdeaa030727 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 27 Feb 2019 11:45:13 -0800 Subject: [PATCH 14/76] Improvements in "supercover" pass Signed-off-by: Clifford Wolf --- passes/sat/supercover.cc | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/passes/sat/supercover.cc b/passes/sat/supercover.cc index 9b208b0bf..ba44f02d8 100644 --- a/passes/sat/supercover.cc +++ b/passes/sat/supercover.cc @@ -54,17 +54,33 @@ struct SupercoverPass : public Pass { for (auto module : design->selected_modules()) { + SigMap sigmap(module); + pool handled_bits; + int cnt_wire = 0, cnt_bits = 0; log("Adding cover cells to module %s.\n", log_id(module)); for (auto wire : module->selected_wires()) { + bool counted_wire = false; std::string src = wire->get_src_attribute(); - cnt_wire++; - for (auto bit : SigSpec(wire)) + + for (auto bit : sigmap(SigSpec(wire))) { + if (bit.wire == nullptr) + continue; + + if (handled_bits.count(bit)) + continue; + SigSpec inv = module->Not(NEW_ID, bit); module->addCover(NEW_ID, bit, State::S1, src); module->addCover(NEW_ID, inv, State::S1, src); + + handled_bits.insert(bit); + if (!counted_wire) { + counted_wire = false; + cnt_wire++; + } cnt_bits++; } } From f570aa5e1d3ac201089da2198f8e5084185fd92f Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 28 Feb 2019 12:15:58 -0800 Subject: [PATCH 15/76] Fix smt2 code generation for partially initialized memowy words, fixes #831 Signed-off-by: Clifford Wolf --- backends/smt2/smt2.cc | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/backends/smt2/smt2.cc b/backends/smt2/smt2.cc index 418f8d766..7f3cc94ca 100644 --- a/backends/smt2/smt2.cc +++ b/backends/smt2/smt2.cc @@ -1103,20 +1103,27 @@ struct Smt2Worker break; Const initword = init_data.extract(i*width, width, State::Sx); + Const initmask = initword; bool gen_init_constr = false; - for (auto bit : initword.bits) - if (bit == State::S0 || bit == State::S1) + for (int k = 0; k < GetSize(initword); k++) { + if (initword[k] == State::S0 || initword[k] == State::S1) { gen_init_constr = true; + initmask[k] = State::S1; + } else { + initmask[k] = State::S0; + initword[k] = State::S0; + } + } if (gen_init_constr) { if (statebv) /* FIXME */; else - init_list.push_back(stringf("(= (select (|%s#%d#0| state) #b%s) #b%s) ; %s[%d]", + init_list.push_back(stringf("(= (bvand (select (|%s#%d#0| state) #b%s) #b%s) #b%s) ; %s[%d]", get_id(module), arrayid, Const(i, abits).as_string().c_str(), - initword.as_string().c_str(), get_id(cell), i)); + initmask.as_string().c_str(), initword.as_string().c_str(), get_id(cell), i)); } } } From 64d91219b4e81366976a0e0a9b28efa4bd825022 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 28 Feb 2019 14:00:58 -0800 Subject: [PATCH 16/76] Fix pmgen for out-of-tree build Signed-off-by: Clifford Wolf --- passes/pmgen/Makefile.inc | 4 ++-- passes/pmgen/pmgen.py | 6 ++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/passes/pmgen/Makefile.inc b/passes/pmgen/Makefile.inc index 33baaca30..b9682612b 100644 --- a/passes/pmgen/Makefile.inc +++ b/passes/pmgen/Makefile.inc @@ -4,5 +4,5 @@ passes/pmgen/ice40_dsp.o: passes/pmgen/ice40_dsp_pm.h EXTRA_OBJS += passes/pmgen/ice40_dsp_pm.h .SECONDARY: passes/pmgen/ice40_dsp_pm.h -passes/pmgen/ice40_dsp_pm.h: passes/pmgen/ice40_dsp.pmg passes/pmgen/pmgen.py - $(P) cd passes/pmgen && python3 pmgen.py ice40_dsp +passes/pmgen/ice40_dsp_pm.h: passes/pmgen/pmgen.py passes/pmgen/ice40_dsp.pmg + $(P) mkdir -p passes/pmgen && cd passes/pmgen && python3 $^ diff --git a/passes/pmgen/pmgen.py b/passes/pmgen/pmgen.py index e688a4567..166d3963a 100644 --- a/passes/pmgen/pmgen.py +++ b/passes/pmgen/pmgen.py @@ -6,7 +6,9 @@ import pprint pp = pprint.PrettyPrinter(indent=4) -prefix = sys.argv[1] +pmgfile = sys.argv[1] +prefix = pmgfile.split("/")[-1] +prefix = prefix.split(".")[0] state_types = dict() udata_types = dict() @@ -73,7 +75,7 @@ def rewrite_cpp(s): return "".join(t) -with open("%s.pmg" % prefix, "r") as f: +with open(pmgfile, "r") as f: while True: line = f.readline() if line == "": break From 68a693717347cefc057cbf1a1c8d0f66500dec4f Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 28 Feb 2019 14:56:05 -0800 Subject: [PATCH 17/76] Fix pmgen for in-tree builds Signed-off-by: Clifford Wolf --- passes/pmgen/Makefile.inc | 2 +- passes/pmgen/pmgen.py | 15 ++++++++------- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/passes/pmgen/Makefile.inc b/passes/pmgen/Makefile.inc index b9682612b..e0dd0fc06 100644 --- a/passes/pmgen/Makefile.inc +++ b/passes/pmgen/Makefile.inc @@ -5,4 +5,4 @@ EXTRA_OBJS += passes/pmgen/ice40_dsp_pm.h .SECONDARY: passes/pmgen/ice40_dsp_pm.h passes/pmgen/ice40_dsp_pm.h: passes/pmgen/pmgen.py passes/pmgen/ice40_dsp.pmg - $(P) mkdir -p passes/pmgen && cd passes/pmgen && python3 $^ + $(P) mkdir -p passes/pmgen && python3 $^ diff --git a/passes/pmgen/pmgen.py b/passes/pmgen/pmgen.py index 166d3963a..034ac27aa 100644 --- a/passes/pmgen/pmgen.py +++ b/passes/pmgen/pmgen.py @@ -7,8 +7,9 @@ import pprint pp = pprint.PrettyPrinter(indent=4) pmgfile = sys.argv[1] -prefix = pmgfile.split("/")[-1] -prefix = prefix.split(".")[0] +assert pmgfile.endswith(".pmg") +prefix = pmgfile[0:-4] +pmname = prefix.split('/')[-1] state_types = dict() udata_types = dict() @@ -189,10 +190,10 @@ with open("%s_pm.h" % prefix, "w") as f: print("YOSYS_NAMESPACE_BEGIN", file=f) print("", file=f) - print("struct {}_pm {{".format(prefix), file=f) + print("struct {}_pm {{".format(pmname), file=f) print(" Module *module;", file=f) print(" SigMap sigmap;", file=f) - print(" std::function on_accept;".format(prefix), file=f) + print(" std::function on_accept;".format(pmname), file=f) print("", file=f) for index in range(len(blocks)): @@ -290,7 +291,7 @@ with open("%s_pm.h" % prefix, "w") as f: print(" }", file=f) print("", file=f) - print(" {}_pm(Module *module, const vector &cells) :".format(prefix), file=f) + print(" {}_pm(Module *module, const vector &cells) :".format(pmname), file=f) print(" module(module), sigmap(module) {", file=f) for s, t in sorted(udata_types.items()): if t.endswith("*"): @@ -320,7 +321,7 @@ with open("%s_pm.h" % prefix, "w") as f: print(" }", file=f) print("", file=f) - print(" ~{}_pm() {{".format(prefix), file=f) + print(" ~{}_pm() {{".format(pmname), file=f) print(" for (auto cell : autoremove_cells)", file=f) print(" module->remove(cell);", file=f) print(" }", file=f) @@ -339,7 +340,7 @@ with open("%s_pm.h" % prefix, "w") as f: print(" }", file=f) print("", file=f) - print(" void run(std::function on_accept_f) {{".format(prefix), file=f) + print(" void run(std::function on_accept_f) {{".format(pmname), file=f) print(" run([&](){on_accept_f(*this);});", file=f) print(" }", file=f) print("", file=f) From e2fc18f27b5e9f506724a486787c2106b9f7fb4f Mon Sep 17 00:00:00 2001 From: Larry Doolittle Date: Tue, 26 Feb 2019 10:28:42 -0800 Subject: [PATCH 18/76] Reduce amount of trailing whitespace in code base --- backends/protobuf/protobuf.cc | 6 +++--- misc/yosys.proto | 12 ++++++------ passes/pmgen/pmgen.py | 2 +- techlibs/achronix/speedster22i/cells_sim.v | 6 +++--- techlibs/anlogic/anlogic_eqn.cc | 4 ++-- techlibs/gowin/arith_map.v | 12 ++++++------ techlibs/gowin/synth_gowin.cc | 2 +- techlibs/intel/cycloneive/arith_map.v | 10 +++++----- techlibs/intel/cyclonev/cells_map.v | 4 ++-- 9 files changed, 29 insertions(+), 29 deletions(-) diff --git a/backends/protobuf/protobuf.cc b/backends/protobuf/protobuf.cc index f56147cef..549fc73ae 100644 --- a/backends/protobuf/protobuf.cc +++ b/backends/protobuf/protobuf.cc @@ -48,7 +48,7 @@ struct ProtobufDesignSerializer ProtobufDesignSerializer(bool use_selection, bool aig_mode) : aig_mode_(aig_mode), use_selection_(use_selection) { } - + string get_name(IdString name) { return RTLIL::unescape_id(name); @@ -60,7 +60,7 @@ struct ProtobufDesignSerializer { for (auto ¶m : parameters) { std::string key = get_name(param.first); - + yosys::pb::Parameter pb_param; @@ -207,7 +207,7 @@ struct ProtobufDesignSerializer (*models)[aig.name] = pb_model; } } - + void serialize_design(yosys::pb::Design *pb, Design *design) { GOOGLE_PROTOBUF_VERIFY_VERSION; diff --git a/misc/yosys.proto b/misc/yosys.proto index 2870176cb..a583e6265 100644 --- a/misc/yosys.proto +++ b/misc/yosys.proto @@ -1,12 +1,12 @@ // // yosys -- Yosys Open SYnthesis Suite -// +// // Copyright (C) 2018 Serge Bazanski -// +// // 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 @@ -73,7 +73,7 @@ message Module { BitVector bits = 2; } map port = 2; - + // Named cells in this module. message Cell { // Set to true when the name of this cell is automatically created and @@ -129,7 +129,7 @@ message Model { TYPE_FALSE = 6; }; Type type = 1; - + message Port { // Name of port. string portname = 1; @@ -148,7 +148,7 @@ message Model { // Set for AND, NAND. Gate gate = 3; } - + // Set when the node drives given output port(s). message OutPort { // Name of port. diff --git a/passes/pmgen/pmgen.py b/passes/pmgen/pmgen.py index 034ac27aa..762d8621f 100644 --- a/passes/pmgen/pmgen.py +++ b/passes/pmgen/pmgen.py @@ -85,7 +85,7 @@ with open(pmgfile, "r") as f: cmd = line.split() if len(cmd) == 0 or cmd[0].startswith("//"): continue cmd = cmd[0] - + if cmd == "state": m = re.match(r"^state\s+<(.*?)>\s+(([A-Za-z_][A-Za-z_0-9]*\s+)*[A-Za-z_][A-Za-z_0-9]*)\s*$", line) assert m diff --git a/techlibs/achronix/speedster22i/cells_sim.v b/techlibs/achronix/speedster22i/cells_sim.v index a94dce9b1..a0c60b4be 100755 --- a/techlibs/achronix/speedster22i/cells_sim.v +++ b/techlibs/achronix/speedster22i/cells_sim.v @@ -30,7 +30,7 @@ endmodule module PADOUT (output padout, input padin, input oe); assign padout = padin; assign oe = oe; -endmodule +endmodule module LUT4 (output dout, input din0, din1, din2, din3); @@ -66,14 +66,14 @@ always @(dataa_w or datab_w or datac_w or datad_w) begin datac_w, datad_w); end assign dout = combout_rt & 1'b1; -endmodule +endmodule module DFF (output q, input d, ck); reg q; always @(posedge ck) q <= d; - + endmodule diff --git a/techlibs/anlogic/anlogic_eqn.cc b/techlibs/anlogic/anlogic_eqn.cc index c025c65c4..741bf04cc 100644 --- a/techlibs/anlogic/anlogic_eqn.cc +++ b/techlibs/anlogic/anlogic_eqn.cc @@ -52,13 +52,13 @@ struct AnlogicEqnPass : public Pass { eqn += names[j]; else eqn += std::string("~") + names[j]; - + if (j!=(inputs-1)) eqn += "*"; } eqn += ")+"; } } - if (eqn.empty()) return Const("0"); + if (eqn.empty()) return Const("0"); eqn = eqn.substr(0, eqn.length()-1); return Const(eqn); } diff --git a/techlibs/gowin/arith_map.v b/techlibs/gowin/arith_map.v index 25e789e4a..e15de6423 100644 --- a/techlibs/gowin/arith_map.v +++ b/techlibs/gowin/arith_map.v @@ -25,24 +25,24 @@ module _80_gw1n_alu(A, B, CI, BI, X, Y, CO); parameter A_WIDTH = 1; parameter B_WIDTH = 1; parameter Y_WIDTH = 1; - + input [A_WIDTH-1:0] A; input [B_WIDTH-1:0] B; output [Y_WIDTH-1:0] X, Y; - + input CI, BI; output [Y_WIDTH-1:0] CO; - + wire _TECHMAP_FAIL_ = Y_WIDTH <= 2; - + wire [Y_WIDTH-1:0] A_buf, B_buf; \$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(Y_WIDTH)) A_conv (.A(A), .Y(A_buf)); \$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) B_conv (.A(B), .Y(B_buf)); - + wire [Y_WIDTH-1:0] AA = A_buf; wire [Y_WIDTH-1:0] BB = BI ? ~B_buf : B_buf; wire [Y_WIDTH-1:0] C = {CO, CI}; - + genvar i; generate for (i = 0; i < Y_WIDTH; i = i + 1) begin:slice ALU #(.ALU_MODE(32'b0)) diff --git a/techlibs/gowin/synth_gowin.cc b/techlibs/gowin/synth_gowin.cc index 96128a680..9a3fcdbb6 100644 --- a/techlibs/gowin/synth_gowin.cc +++ b/techlibs/gowin/synth_gowin.cc @@ -111,7 +111,7 @@ struct SynthGowinPass : public ScriptPass if (args[argidx] == "-noflatten") { flatten = false; continue; - } + } break; } extra_args(args, argidx, design); diff --git a/techlibs/intel/cycloneive/arith_map.v b/techlibs/intel/cycloneive/arith_map.v index b3a11272b..49e36aa25 100644 --- a/techlibs/intel/cycloneive/arith_map.v +++ b/techlibs/intel/cycloneive/arith_map.v @@ -32,7 +32,7 @@ module fa wire VCC; assign VCC = 1'b1; - + cycloneiv_lcell_comb gen_sum_0 (.combout(sum_x), .dataa(a_c), .datab(b_c), @@ -40,7 +40,7 @@ module fa .datad(VCC)); defparam syn__05_.lut_mask = 16'b1001011010010110; defparam syn__05_.sum_lutc_input = "datac"; - + cycloneiv_lcell_comb gen_cout_0 (.combout(cout_t), .dataa(cin_c), .datab(b_c), @@ -48,11 +48,11 @@ module fa .datad(VCC)); defparam syn__06_.lut_mask = 16'b1110000011100000; defparam syn__06_.sum_lutc_input = "datac"; - + endmodule // fa module f_stage(); - + endmodule // f_stage module f_end(); @@ -88,7 +88,7 @@ module _80_cycloneive_alu (A, B, CI, BI, X, Y, CO); .cin_c(C[0]), .cout_t(C0[1]), .sum_x(Y[0])); - + genvar i; generate for (i = 1; i < Y_WIDTH; i = i + 1) begin:slice cycloneive_lcell_comb #(.lut_mask(16'b0101_1010_0101_0000), .sum_lutc_input("cin")) arith_cell (.combout(Y[i]), .cout(CO[i]), .dataa(BB[i]), .datab(1'b1), .datac(1'b1), .datad(1'b1), .cin(C[i])); diff --git a/techlibs/intel/cyclonev/cells_map.v b/techlibs/intel/cyclonev/cells_map.v index bd60d4e17..f8d142bc9 100644 --- a/techlibs/intel/cyclonev/cells_map.v +++ b/techlibs/intel/cyclonev/cells_map.v @@ -76,7 +76,7 @@ module \$lut (A, Y); wire VCC; wire GND; assign {VCC,GND} = {1'b1,1'b0}; - + generate if (WIDTH == 1) begin assign Y = ~A[0]; // Not need to spend 1 logic cell for such an easy function @@ -151,7 +151,7 @@ module \$lut (A, Y); TODO: There's not a just 7-input function on Cyclone V, see the following note: **Extended LUT Mode** Use extended LUT mode to implement a specific set of 7-input functions. The set must - be a 2-to-1 multiplexer fed by two arbitrary 5-input functions sharing four inputs. + be a 2-to-1 multiplexer fed by two arbitrary 5-input functions sharing four inputs. [source](Device Interfaces and Integration Basics for Cyclone V Devices). end*/ else From 241901461ae02c6a41837e254088f277b8167476 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 28 Feb 2019 14:56:55 -0800 Subject: [PATCH 19/76] Add "write_verilog -siminit" Signed-off-by: Clifford Wolf --- backends/verilog/verilog_backend.cc | 13 +++++++++++-- tests/tools/autotest.sh | 2 +- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/backends/verilog/verilog_backend.cc b/backends/verilog/verilog_backend.cc index d351a6266..6818edb7a 100644 --- a/backends/verilog/verilog_backend.cc +++ b/backends/verilog/verilog_backend.cc @@ -33,7 +33,7 @@ USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN -bool verbose, norename, noattr, attr2comment, noexpr, nodec, nohex, nostr, defparam, decimal; +bool verbose, norename, noattr, attr2comment, noexpr, nodec, nohex, nostr, defparam, decimal, siminit; int auto_name_counter, auto_name_offset, auto_name_digits; std::map auto_name_map; std::set reg_wires, reg_ct; @@ -1310,7 +1310,7 @@ void dump_cell(std::ostream &f, std::string indent, RTLIL::Cell *cell) } } - if (reg_ct.count(cell->type) && cell->hasPort("\\Q")) { + if (siminit && reg_ct.count(cell->type) && cell->hasPort("\\Q")) { std::stringstream ss; dump_reg_init(ss, cell->getPort("\\Q")); if (!ss.str().empty()) { @@ -1607,6 +1607,10 @@ struct VerilogBackend : public Backend { log(" without this option all internal cells are converted to Verilog\n"); log(" expressions.\n"); log("\n"); + log(" -siminit\n"); + log(" add initial statements with hierarchical refs to initialize FFs when\n"); + log(" in -noexpr mode.\n"); + log("\n"); log(" -nodec\n"); log(" 32-bit constant values are by default dumped as decimal numbers,\n"); log(" not bit pattern. This option deactivates this feature and instead\n"); @@ -1663,6 +1667,7 @@ struct VerilogBackend : public Backend { nostr = false; defparam = false; decimal = false; + siminit = false; auto_prefix = ""; bool blackboxes = false; @@ -1739,6 +1744,10 @@ struct VerilogBackend : public Backend { decimal = true; continue; } + if (arg == "-siminit") { + siminit = true; + continue; + } if (arg == "-blackboxes") { blackboxes = true; continue; diff --git a/tests/tools/autotest.sh b/tests/tools/autotest.sh index 99ec3e7cd..0b9aceacc 100755 --- a/tests/tools/autotest.sh +++ b/tests/tools/autotest.sh @@ -8,7 +8,7 @@ verbose=false keeprunning=false makejmode=false frontend="verilog" -backend_opts="-noattr -noexpr" +backend_opts="-noattr -noexpr -siminit" autotb_opts="" include_opts="" xinclude_opts="" From cd2902ab1fec57503320e32ba5620c6487f9cb85 Mon Sep 17 00:00:00 2001 From: Elms Date: Thu, 28 Feb 2019 16:22:24 -0800 Subject: [PATCH 20/76] ice40: use 2 bits for READ/WRITE MODE for SB_RAM map EBLIF output .param will only use necessary 2 bits Signed-off-by: Elms --- techlibs/ice40/brams_map.v | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/techlibs/ice40/brams_map.v b/techlibs/ice40/brams_map.v index 19a61d73b..ad3bccd21 100644 --- a/techlibs/ice40/brams_map.v +++ b/techlibs/ice40/brams_map.v @@ -7,8 +7,8 @@ module \$__ICE40_RAM4K ( input [10:0] WADDR, input [15:0] MASK, WDATA ); - parameter integer READ_MODE = 0; - parameter integer WRITE_MODE = 0; + parameter [1:0] READ_MODE = 0; + parameter [1:0] WRITE_MODE = 0; parameter [0:0] NEGCLK_R = 0; parameter [0:0] NEGCLK_W = 0; From e847690bda520511735680bd4cb65b416edcdc3f Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 28 Feb 2019 17:24:46 -0800 Subject: [PATCH 21/76] Fix multiple issues in wreduce FF handling, fixes #835 Signed-off-by: Clifford Wolf --- passes/opt/wreduce.cc | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/passes/opt/wreduce.cc b/passes/opt/wreduce.cc index 09983bc67..1f7222e49 100644 --- a/passes/opt/wreduce.cc +++ b/passes/opt/wreduce.cc @@ -53,6 +53,7 @@ struct WreduceWorker std::set> work_queue_cells; std::set work_queue_bits; pool keep_bits; + dict init_bits; WreduceWorker(WreduceConfig *config, Module *module) : config(config), module(module), mi(module) { } @@ -141,6 +142,7 @@ struct WreduceWorker SigSpec sig_d = mi.sigmap(cell->getPort("\\D")); SigSpec sig_q = mi.sigmap(cell->getPort("\\Q")); + Const initval; int width_before = GetSize(sig_q); @@ -150,16 +152,24 @@ struct WreduceWorker bool zero_ext = sig_d[GetSize(sig_d)-1] == State::S0; bool sign_ext = !zero_ext; + for (int i = 0; i < GetSize(sig_q); i++) { + SigBit bit = sig_q[i]; + if (init_bits.count(bit)) + initval.bits.push_back(init_bits.at(bit)); + else + initval.bits.push_back(State::Sx); + } + for (int i = GetSize(sig_q)-1; i >= 0; i--) { - if (zero_ext && sig_d[i] == State::S0) { + if (zero_ext && sig_d[i] == State::S0 && (initval[i] == State::S0 || initval[i] == State::Sx)) { module->connect(sig_q[i], State::S0); sig_d.remove(i); sig_q.remove(i); continue; } - if (sign_ext && i > 0 && sig_d[i] == sig_d[i-1]) { + if (sign_ext && i > 0 && sig_d[i] == sig_d[i-1] && initval[i] == initval[i-1]) { module->connect(sig_q[i], sig_q[i-1]); sig_d.remove(i); sig_q.remove(i); @@ -167,7 +177,7 @@ struct WreduceWorker } auto info = mi.query(sig_q[i]); - if (!info->is_output && GetSize(info->ports) <= 1 && !keep_bits.count(mi.sigmap(sig_q[i]))) { + if (!info->is_output && GetSize(info->ports) == 1 && !keep_bits.count(mi.sigmap(sig_q[i]))) { sig_d.remove(i); sig_q.remove(i); zero_ext = false; @@ -183,10 +193,11 @@ struct WreduceWorker if (GetSize(sig_q) == 0) { log("Removed cell %s.%s (%s).\n", log_id(module), log_id(cell), log_id(cell->type)); + module->remove(cell); return; } - log("Removed top %d bits (of %d) from mux cell %s.%s (%s).\n", width_before - GetSize(sig_q), width_before, + log("Removed top %d bits (of %d) from FF cell %s.%s (%s).\n", width_before - GetSize(sig_q), width_before, log_id(module), log_id(cell), log_id(cell->type)); for (auto bit : sig_d) @@ -376,10 +387,18 @@ struct WreduceWorker void run() { - for (auto w : module->wires()) + for (auto w : module->wires()) { if (w->get_bool_attribute("\\keep")) for (auto bit : mi.sigmap(w)) keep_bits.insert(bit); + if (w->attributes.count("\\init")) { + Const initval = w->attributes.at("\\init"); + SigSpec initsig = mi.sigmap(w); + int width = std::min(GetSize(initval), GetSize(initsig)); + for (int i = 0; i < width; i++) + init_bits[initsig[i]] = initval[i]; + } + } for (auto c : module->selected_cells()) work_queue_cells.insert(c); From b84febafd75bc66d64cdc573265e086800b3e420 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 28 Feb 2019 20:26:54 -0800 Subject: [PATCH 22/76] Hotfix for "make test" Signed-off-by: Clifford Wolf --- tests/tools/autotest.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/tools/autotest.sh b/tests/tools/autotest.sh index 0b9aceacc..84e62e011 100755 --- a/tests/tools/autotest.sh +++ b/tests/tools/autotest.sh @@ -49,7 +49,7 @@ while getopts xmGl:wkjvref:s:p:n:S:I:-: opt; do r) backend_opts="$backend_opts -norename" ;; e) - backend_opts="$( echo " $backend_opts " | sed 's, -noexpr ,,; s,^ ,,; s, $,,;'; )" ;; + backend_opts="$( echo " $backend_opts " | sed 's, -noexpr , ,; s,^ ,,; s, $,,;'; )" ;; f) frontend="$OPTARG" ;; s) From 60e3c38054f10251021fa2f504ad2424da33aa1d Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 28 Feb 2019 20:34:42 -0800 Subject: [PATCH 23/76] Improve "read" error msg Signed-off-by: Clifford Wolf --- frontends/verific/verific.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontends/verific/verific.cc b/frontends/verific/verific.cc index 8ee951d20..9f52ffdc2 100644 --- a/frontends/verific/verific.cc +++ b/frontends/verific/verific.cc @@ -2316,7 +2316,7 @@ struct ReadPass : public Pass { } void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { - if (args.size() < 2) + if (args.size() < 2 || args[1][0] != '-') log_cmd_error("Missing mode parameter.\n"); if (args.size() < 3) From ca2b3feed82f923f06d0cf57787818f0f6793157 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Fri, 1 Mar 2019 19:25:23 +0100 Subject: [PATCH 24/76] Fix ECP5 cells_sim for iverilog --- techlibs/ecp5/cells_sim.v | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/techlibs/ecp5/cells_sim.v b/techlibs/ecp5/cells_sim.v index 8320ee70a..1e4002ee0 100644 --- a/techlibs/ecp5/cells_sim.v +++ b/techlibs/ecp5/cells_sim.v @@ -223,11 +223,12 @@ module TRELLIS_FF(input CLK, LSR, CE, DI, M, output reg Q); wire muxlsr = (LSRMUX == "INV") ? ~LSR : LSR; wire muxclk = (CLKMUX == "INV") ? ~CLK : CLK; + wire srval; generate if (LSRMODE == "PRLD") - wire srval = M; + assign srval = M; else - localparam srval = (REGSET == "SET") ? 1'b1 : 1'b0; + assign srval = (REGSET == "SET") ? 1'b1 : 1'b0; endgenerate initial Q = srval; From 3090951d54859c331d28232481361bb9c26b3d48 Mon Sep 17 00:00:00 2001 From: Keith Rothman <537074+litghost@users.noreply.github.com> Date: Fri, 1 Mar 2019 11:21:07 -0800 Subject: [PATCH 25/76] Changes required for VPR place and route synth_xilinx. Signed-off-by: Keith Rothman <537074+litghost@users.noreply.github.com> --- manual/command-reference-manual.tex | 19 +- techlibs/xilinx/Makefile.inc | 3 +- techlibs/xilinx/arith_map.v | 282 +++++++++++++++++++++++++++- techlibs/xilinx/brams_map.v | 24 +-- techlibs/xilinx/cells_map.v | 104 ++-------- techlibs/xilinx/cells_sim.v | 105 +++++++---- techlibs/xilinx/cells_xtra.sh | 4 +- techlibs/xilinx/cells_xtra.v | 19 ++ techlibs/xilinx/ff_map.v | 42 +++++ techlibs/xilinx/lut2lut.v | 65 ------- techlibs/xilinx/lut_map.v | 94 ++++++++++ techlibs/xilinx/synth_xilinx.cc | 68 +++++-- 12 files changed, 601 insertions(+), 228 deletions(-) create mode 100644 techlibs/xilinx/ff_map.v delete mode 100644 techlibs/xilinx/lut2lut.v create mode 100644 techlibs/xilinx/lut_map.v diff --git a/manual/command-reference-manual.tex b/manual/command-reference-manual.tex index bed6326e2..257bf7986 100644 --- a/manual/command-reference-manual.tex +++ b/manual/command-reference-manual.tex @@ -4244,9 +4244,15 @@ compatible with 7-Series Xilinx devices. is omitted if this parameter is not specified. -vpr - generate an output netlist (and BLIF file) suitable for VPR + generate an output netlist (and BLIF file) suitable for VPR. (this feature is experimental and incomplete) + -no-brams + disable infering of block rams + + -no-drams + disable infering of distributed rams + -run : only run the commands between the labels (see below). an empty from label is synonymous to 'begin', and empty to label is @@ -4274,11 +4280,11 @@ The following commands are executed by this synthesis command: coarse: synth -run coarse - bram: + bram: (only executed when '-no-brams' is not given) memory_bram -rules +/xilinx/brams.txt techmap -map +/xilinx/brams_map.v - dram: + dram: (only executed when '-no-drams' is not given) memory_bram -rules +/xilinx/drams.txt techmap -map +/xilinx/drams_map.v @@ -4288,16 +4294,17 @@ The following commands are executed by this synthesis command: dffsr2dff dff2dffe opt -full - techmap -map +/techmap.v -map +/xilinx/arith_map.v + techmap -map +/techmap.v -map +/xilinx/arith_map.v -map +/xilinx/ff_map.v opt -fast map_luts: - abc -luts 2:2,3,6:5,10,20 [-dff] + abc -luts 2:2,3,6:5,10,20 [-dff] (without '-vpr' only!) + abc -lut 5 [-dff] (with '-vpr' only!) clean map_cells: techmap -map +/xilinx/cells_map.v (with -D NO_LUT in vpr mode) - dffinit -ff FDRE Q INIT -ff FDCE Q INIT -ff FDPE Q INIT + dffinit -ff FDRE Q INIT -ff FDCE Q INIT -ff FDPE Q INIT -ff FDSE Q INIT clean check: diff --git a/techlibs/xilinx/Makefile.inc b/techlibs/xilinx/Makefile.inc index 887ea27d9..d68f03bb4 100644 --- a/techlibs/xilinx/Makefile.inc +++ b/techlibs/xilinx/Makefile.inc @@ -28,7 +28,8 @@ $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/brams_bb.v)) $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/drams.txt)) $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/drams_map.v)) $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/arith_map.v)) -$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/lut2lut.v)) +$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/ff_map.v)) +$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/lut_map.v)) $(eval $(call add_gen_share_file,share/xilinx,techlibs/xilinx/brams_init_36.vh)) $(eval $(call add_gen_share_file,share/xilinx,techlibs/xilinx/brams_init_32.vh)) diff --git a/techlibs/xilinx/arith_map.v b/techlibs/xilinx/arith_map.v index 03719659b..09a5f07e8 100644 --- a/techlibs/xilinx/arith_map.v +++ b/techlibs/xilinx/arith_map.v @@ -17,6 +17,9 @@ * */ +// ============================================================================ +// LCU + (* techmap_celltype = "$lcu" *) module _80_xilinx_lcu (P, G, CI, CO); parameter WIDTH = 2; @@ -28,10 +31,78 @@ module _80_xilinx_lcu (P, G, CI, CO); wire _TECHMAP_FAIL_ = WIDTH <= 2; + genvar i; + +`ifdef _CLB_CARRY + + localparam CARRY4_COUNT = (WIDTH + 3) / 4; + localparam MAX_WIDTH = CARRY4_COUNT * 4; + localparam PAD_WIDTH = MAX_WIDTH - WIDTH; + + wire [MAX_WIDTH-1:0] S = {{PAD_WIDTH{1'b0}}, P & ~G}; + wire [MAX_WIDTH-1:0] C = CO; + + generate for (i = 0; i < CARRY4_COUNT; i = i + 1) begin:slice + + // Partially occupied CARRY4 + if ((i+1)*4 > WIDTH) begin + + // First one + if (i == 0) begin + CARRY4 carry4_1st_part + ( + .CYINIT(CI), + .CI (1'd0), + .DI (G [(Y_WIDTH - 1):i*4]), + .S (S [(Y_WIDTH - 1):i*4]), + .CO (CO[(Y_WIDTH - 1):i*4]), + ); + // Another one + end else begin + CARRY4 carry4_part + ( + .CYINIT(1'd0), + .CI (C [i*4 - 1]), + .DI (G [(Y_WIDTH - 1):i*4]), + .S (S [(Y_WIDTH - 1):i*4]), + .CO (CO[(Y_WIDTH - 1):i*4]), + ); + end + + // Fully occupied CARRY4 + end else begin + + // First one + if (i == 0) begin + CARRY4 carry4_1st_full + ( + .CYINIT(CI), + .CI (1'd0), + .DI (G [((i+1)*4 - 1):i*4]), + .S (S [((i+1)*4 - 1):i*4]), + .CO (CO[((i+1)*4 - 1):i*4]), + ); + // Another one + end else begin + CARRY4 carry4_full + ( + .CYINIT(1'd0), + .CI (C [i*4 - 1]), + .DI (G [((i+1)*4 - 1):i*4]), + .S (S [((i+1)*4 - 1):i*4]), + .CO (CO[((i+1)*4 - 1):i*4]), + ); + end + + end + + end endgenerate + +`elsif _EXPLICIT_CARRY + wire [WIDTH-1:0] C = {CO, CI}; wire [WIDTH-1:0] S = P & ~G; - genvar i; generate for (i = 0; i < WIDTH; i = i + 1) begin:slice MUXCY muxcy ( .CI(C[i]), @@ -40,8 +111,28 @@ module _80_xilinx_lcu (P, G, CI, CO); .O(CO[i]) ); end endgenerate + +`else + + wire [WIDTH-1:0] C = {CO, CI}; + wire [WIDTH-1:0] S = P & ~G; + + generate for (i = 0; i < WIDTH; i = i + 1) begin:slice + MUXCY muxcy ( + .CI(C[i]), + .DI(G[i]), + .S(S[i]), + .O(CO[i]) + ); + end endgenerate +`endif + endmodule + +// ============================================================================ +// ALU + (* techmap_celltype = "$alu" *) module _80_xilinx_alu (A, B, CI, BI, X, Y, CO); parameter A_SIGNED = 0; @@ -49,6 +140,8 @@ module _80_xilinx_alu (A, B, CI, BI, X, Y, CO); parameter A_WIDTH = 1; parameter B_WIDTH = 1; parameter Y_WIDTH = 1; + parameter _TECHMAP_CONSTVAL_CI_ = 0; + parameter _TECHMAP_CONSTMSK_CI_ = 0; input [A_WIDTH-1:0] A; input [B_WIDTH-1:0] B; @@ -66,16 +159,189 @@ module _80_xilinx_alu (A, B, CI, BI, X, Y, CO); wire [Y_WIDTH-1:0] AA = A_buf; wire [Y_WIDTH-1:0] BB = BI ? ~B_buf : B_buf; - wire [Y_WIDTH-1:0] P = AA ^ BB; - wire [Y_WIDTH-1:0] G = AA & BB; - wire [Y_WIDTH-1:0] C = {CO, CI}; - wire [Y_WIDTH-1:0] S = P & ~G; + genvar i; + +`ifdef _CLB_CARRY + + localparam CARRY4_COUNT = (Y_WIDTH + 3) / 4; + localparam MAX_WIDTH = CARRY4_COUNT * 4; + localparam PAD_WIDTH = MAX_WIDTH - Y_WIDTH; + + wire [MAX_WIDTH-1:0] S = {{PAD_WIDTH{1'b0}}, AA ^ BB}; + wire [MAX_WIDTH-1:0] DI = {{PAD_WIDTH{1'b0}}, AA & BB}; + + wire [MAX_WIDTH-1:0] C = CO; genvar i; + generate for (i = 0; i < CARRY4_COUNT; i = i + 1) begin:slice + + // Partially occupied CARRY4 + if ((i+1)*4 > Y_WIDTH) begin + + // First one + if (i == 0) begin + CARRY4 #(.IS_INITIALIZED(1'd1)) carry4_1st_part + ( + .CYINIT(CI), + .CI (1'd0), + .DI (DI[(Y_WIDTH - 1):i*4]), + .S (S [(Y_WIDTH - 1):i*4]), + .O (Y [(Y_WIDTH - 1):i*4]), + .CO (CO[(Y_WIDTH - 1):i*4]) + ); + // Another one + end else begin + CARRY4 carry4_part + ( + .CYINIT(1'd0), + .CI (C [i*4 - 1]), + .DI (DI[(Y_WIDTH - 1):i*4]), + .S (S [(Y_WIDTH - 1):i*4]), + .O (Y [(Y_WIDTH - 1):i*4]), + .CO (CO[(Y_WIDTH - 1):i*4]) + ); + end + + // Fully occupied CARRY4 + end else begin + + // First one + if (i == 0) begin + CARRY4 #(.IS_INITIALIZED(1'd1)) carry4_1st_full + ( + .CYINIT(CI), + .CI (1'd0), + .DI (DI[((i+1)*4 - 1):i*4]), + .S (S [((i+1)*4 - 1):i*4]), + .O (Y [((i+1)*4 - 1):i*4]), + .CO (CO[((i+1)*4 - 1):i*4]) + ); + // Another one + end else begin + CARRY4 carry4_full + ( + .CYINIT(1'd0), + .CI (C [i*4 - 1]), + .DI (DI[((i+1)*4 - 1):i*4]), + .S (S [((i+1)*4 - 1):i*4]), + .O (Y [((i+1)*4 - 1):i*4]), + .CO (CO[((i+1)*4 - 1):i*4]) + ); + end + + end + + end endgenerate + +`elsif _EXPLICIT_CARRY + + wire [Y_WIDTH-1:0] S = AA ^ BB; + wire [Y_WIDTH-1:0] DI = AA & BB; + + wire CINIT; + // Carry chain. + // + // VPR requires that the carry chain never hit the fabric. The CO input + // to this techmap is the carry outputs for synthesis, e.g. might hit the + // fabric. + // + // So we maintain two wire sets, CO_CHAIN is the carry that is for VPR, + // e.g. off fabric dedicated chain. CO is the carry outputs that are + // available to the fabric. + wire [Y_WIDTH-1:0] CO_CHAIN; + wire [Y_WIDTH-1:0] C = {CO_CHAIN, CINIT}; + + // If carry chain is being initialized to a constant, techmap the constant + // source. Otherwise techmap the fabric source. + generate for (i = 0; i < 1; i = i + 1) begin:slice + CARRY0 #(.CYINIT_FABRIC(1)) carry( + .CI_INIT(CI), + .DI(DI[0]), + .S(S[0]), + .CO_CHAIN(CO_CHAIN[0]), + .CO_FABRIC(CO[0]), + .O(Y[0]) + ); + end endgenerate + + generate for (i = 1; i < Y_WIDTH-1; i = i + 1) begin:slice + if(i % 4 == 0) begin + CARRY0 carry ( + .CI(C[i]), + .DI(DI[i]), + .S(S[i]), + .CO_CHAIN(CO_CHAIN[i]), + .CO_FABRIC(CO[i]), + .O(Y[i]) + ); + end + else + begin + CARRY carry ( + .CI(C[i]), + .DI(DI[i]), + .S(S[i]), + .CO_CHAIN(CO_CHAIN[i]), + .CO_FABRIC(CO[i]), + .O(Y[i]) + ); + end + end endgenerate + + generate for (i = Y_WIDTH-1; i < Y_WIDTH; i = i + 1) begin:slice + if(i % 4 == 0) begin + CARRY0 top_of_carry ( + .CI(C[i]), + .DI(DI[i]), + .S(S[i]), + .CO_CHAIN(CO_CHAIN[i]), + .O(Y[i]) + ); + end + else + begin + CARRY top_of_carry ( + .CI(C[i]), + .DI(DI[i]), + .S(S[i]), + .CO_CHAIN(CO_CHAIN[i]), + .O(Y[i]) + ); + end + // Turns out CO_FABRIC and O both use [ABCD]MUX, so provide + // a non-congested path to output the top of the carry chain. + // Registering the output of the CARRY block would solve this, but not + // all designs do that. + if((i+1) % 4 == 0) begin + CARRY0 carry_output ( + .CI(CO_CHAIN[i]), + .DI(0), + .S(0), + .O(CO[i]) + ); + end + else + begin + CARRY carry_output ( + .CI(CO_CHAIN[i]), + .DI(0), + .S(0), + .O(CO[i]) + ); + end + end endgenerate + +`else + + wire [Y_WIDTH-1:0] S = AA ^ BB; + wire [Y_WIDTH-1:0] DI = AA & BB; + + wire [Y_WIDTH-1:0] C = {CO, CI}; + generate for (i = 0; i < Y_WIDTH; i = i + 1) begin:slice MUXCY muxcy ( .CI(C[i]), - .DI(G[i]), + .DI(DI[i]), .S(S[i]), .O(CO[i]) ); @@ -86,6 +352,8 @@ module _80_xilinx_alu (A, B, CI, BI, X, Y, CO); ); end endgenerate - assign X = P; +`endif + + assign X = S; endmodule diff --git a/techlibs/xilinx/brams_map.v b/techlibs/xilinx/brams_map.v index 7ea49158d..2a23b2553 100644 --- a/techlibs/xilinx/brams_map.v +++ b/techlibs/xilinx/brams_map.v @@ -30,8 +30,8 @@ module \$__XILINX_RAMB36_SDP (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, .RAM_MODE("SDP"), .READ_WIDTH_A(72), .WRITE_WIDTH_B(72), - .WRITE_MODE_A("READ_FIRST"), - .WRITE_MODE_B("READ_FIRST"), + .WRITE_MODE_A("WRITE_FIRST"), + .WRITE_MODE_B("WRITE_FIRST"), .IS_CLKARDCLK_INVERTED(!CLKPOL2), .IS_CLKBWRCLK_INVERTED(!CLKPOL3), `include "brams_init_36.vh" @@ -95,8 +95,8 @@ module \$__XILINX_RAMB18_SDP (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, .RAM_MODE("SDP"), .READ_WIDTH_A(36), .WRITE_WIDTH_B(36), - .WRITE_MODE_A("READ_FIRST"), - .WRITE_MODE_B("READ_FIRST"), + .WRITE_MODE_A("WRITE_FIRST"), + .WRITE_MODE_B("WRITE_FIRST"), .IS_CLKARDCLK_INVERTED(!CLKPOL2), .IS_CLKBWRCLK_INVERTED(!CLKPOL3), `include "brams_init_18.vh" @@ -171,8 +171,8 @@ module \$__XILINX_RAMB36_TDP (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, .READ_WIDTH_B(CFG_DBITS), .WRITE_WIDTH_A(CFG_DBITS), .WRITE_WIDTH_B(CFG_DBITS), - .WRITE_MODE_A("READ_FIRST"), - .WRITE_MODE_B("READ_FIRST"), + .WRITE_MODE_A("WRITE_FIRST"), + .WRITE_MODE_B("WRITE_FIRST"), .IS_CLKARDCLK_INVERTED(!CLKPOL2), .IS_CLKBWRCLK_INVERTED(!CLKPOL3), `include "brams_init_36.vh" @@ -209,8 +209,8 @@ module \$__XILINX_RAMB36_TDP (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, .READ_WIDTH_B(CFG_DBITS), .WRITE_WIDTH_A(CFG_DBITS), .WRITE_WIDTH_B(CFG_DBITS), - .WRITE_MODE_A("READ_FIRST"), - .WRITE_MODE_B("READ_FIRST"), + .WRITE_MODE_A("WRITE_FIRST"), + .WRITE_MODE_B("WRITE_FIRST"), .IS_CLKARDCLK_INVERTED(!CLKPOL2), .IS_CLKBWRCLK_INVERTED(!CLKPOL3), `include "brams_init_32.vh" @@ -285,8 +285,8 @@ module \$__XILINX_RAMB18_TDP (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, .READ_WIDTH_B(CFG_DBITS), .WRITE_WIDTH_A(CFG_DBITS), .WRITE_WIDTH_B(CFG_DBITS), - .WRITE_MODE_A("READ_FIRST"), - .WRITE_MODE_B("READ_FIRST"), + .WRITE_MODE_A("WRITE_FIRST"), + .WRITE_MODE_B("WRITE_FIRST"), .IS_CLKARDCLK_INVERTED(!CLKPOL2), .IS_CLKBWRCLK_INVERTED(!CLKPOL3), `include "brams_init_18.vh" @@ -323,8 +323,8 @@ module \$__XILINX_RAMB18_TDP (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, .READ_WIDTH_B(CFG_DBITS), .WRITE_WIDTH_A(CFG_DBITS), .WRITE_WIDTH_B(CFG_DBITS), - .WRITE_MODE_A("READ_FIRST"), - .WRITE_MODE_B("READ_FIRST"), + .WRITE_MODE_A("WRITE_FIRST"), + .WRITE_MODE_B("WRITE_FIRST"), .IS_CLKARDCLK_INVERTED(!CLKPOL2), .IS_CLKBWRCLK_INVERTED(!CLKPOL3), `include "brams_init_16.vh" diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index 0771be0b9..d5801c0fc 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -1,86 +1,20 @@ +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2012 Clifford Wolf + * + * 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. + * + */ -module \$_DFF_N_ (input D, C, output Q); FDRE #(.INIT(|0), .IS_C_INVERTED(|1), .IS_D_INVERTED(|0), .IS_R_INVERTED(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .R(1'b0)); endmodule -module \$_DFF_P_ (input D, C, output Q); FDRE #(.INIT(|0), .IS_C_INVERTED(|0), .IS_D_INVERTED(|0), .IS_R_INVERTED(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .R(1'b0)); endmodule - -module \$_DFFE_NP_ (input D, C, E, output Q); FDRE #(.INIT(|0), .IS_C_INVERTED(|1), .IS_D_INVERTED(|0), .IS_R_INVERTED(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .R(1'b0)); endmodule -module \$_DFFE_PP_ (input D, C, E, output Q); FDRE #(.INIT(|0), .IS_C_INVERTED(|0), .IS_D_INVERTED(|0), .IS_R_INVERTED(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .R(1'b0)); endmodule - -module \$_DFF_NN0_ (input D, C, R, output Q); FDCE #(.INIT(|0), .IS_C_INVERTED(|1), .IS_D_INVERTED(|0), .IS_CLR_INVERTED(|1)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .CLR(R)); endmodule -module \$_DFF_NP0_ (input D, C, R, output Q); FDCE #(.INIT(|0), .IS_C_INVERTED(|1), .IS_D_INVERTED(|0), .IS_CLR_INVERTED(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .CLR(R)); endmodule -module \$_DFF_PN0_ (input D, C, R, output Q); FDCE #(.INIT(|0), .IS_C_INVERTED(|0), .IS_D_INVERTED(|0), .IS_CLR_INVERTED(|1)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .CLR(R)); endmodule -module \$_DFF_PP0_ (input D, C, R, output Q); FDCE #(.INIT(|0), .IS_C_INVERTED(|0), .IS_D_INVERTED(|0), .IS_CLR_INVERTED(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .CLR(R)); endmodule - -module \$_DFF_NN1_ (input D, C, R, output Q); FDPE #(.INIT(|0), .IS_C_INVERTED(|1), .IS_D_INVERTED(|0), .IS_PRE_INVERTED(|1)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE(R)); endmodule -module \$_DFF_NP1_ (input D, C, R, output Q); FDPE #(.INIT(|0), .IS_C_INVERTED(|1), .IS_D_INVERTED(|0), .IS_PRE_INVERTED(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE(R)); endmodule -module \$_DFF_PN1_ (input D, C, R, output Q); FDPE #(.INIT(|0), .IS_C_INVERTED(|0), .IS_D_INVERTED(|0), .IS_PRE_INVERTED(|1)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE(R)); endmodule -module \$_DFF_PP1_ (input D, C, R, output Q); FDPE #(.INIT(|0), .IS_C_INVERTED(|0), .IS_D_INVERTED(|0), .IS_PRE_INVERTED(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE(R)); endmodule - -`ifndef NO_LUT -module \$lut (A, Y); - parameter WIDTH = 0; - parameter LUT = 0; - - input [WIDTH-1:0] A; - output Y; - - generate - if (WIDTH == 1) begin - LUT1 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y), - .I0(A[0])); - end else - if (WIDTH == 2) begin - LUT2 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y), - .I0(A[0]), .I1(A[1])); - end else - if (WIDTH == 3) begin - LUT3 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y), - .I0(A[0]), .I1(A[1]), .I2(A[2])); - end else - if (WIDTH == 4) begin - LUT4 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y), - .I0(A[0]), .I1(A[1]), .I2(A[2]), - .I3(A[3])); - end else - if (WIDTH == 5) begin - LUT5 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y), - .I0(A[0]), .I1(A[1]), .I2(A[2]), - .I3(A[3]), .I4(A[4])); - end else - if (WIDTH == 6) begin - LUT6 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y), - .I0(A[0]), .I1(A[1]), .I2(A[2]), - .I3(A[3]), .I4(A[4]), .I5(A[5])); - end else - if (WIDTH == 7) begin - wire T0, T1; - LUT6 #(.INIT(LUT[63:0])) fpga_lut_0 (.O(T0), - .I0(A[0]), .I1(A[1]), .I2(A[2]), - .I3(A[3]), .I4(A[4]), .I5(A[5])); - LUT6 #(.INIT(LUT[127:64])) fpga_lut_1 (.O(T1), - .I0(A[0]), .I1(A[1]), .I2(A[2]), - .I3(A[3]), .I4(A[4]), .I5(A[5])); - MUXF7 fpga_mux_0 (.O(Y), .I0(T0), .I1(T1), .S(A[6])); - end else - if (WIDTH == 8) begin - wire T0, T1, T2, T3, T4, T5; - LUT6 #(.INIT(LUT[63:0])) fpga_lut_0 (.O(T0), - .I0(A[0]), .I1(A[1]), .I2(A[2]), - .I3(A[3]), .I4(A[4]), .I5(A[5])); - LUT6 #(.INIT(LUT[127:64])) fpga_lut_1 (.O(T1), - .I0(A[0]), .I1(A[1]), .I2(A[2]), - .I3(A[3]), .I4(A[4]), .I5(A[5])); - LUT6 #(.INIT(LUT[191:128])) fpga_lut_2 (.O(T2), - .I0(A[0]), .I1(A[1]), .I2(A[2]), - .I3(A[3]), .I4(A[4]), .I5(A[5])); - LUT6 #(.INIT(LUT[255:192])) fpga_lut_3 (.O(T3), - .I0(A[0]), .I1(A[1]), .I2(A[2]), - .I3(A[3]), .I4(A[4]), .I5(A[5])); - MUXF7 fpga_mux_0 (.O(T4), .I0(T0), .I1(T1), .S(A[6])); - MUXF7 fpga_mux_1 (.O(T5), .I0(T2), .I1(T3), .S(A[6])); - MUXF8 fpga_mux_2 (.O(Y), .I0(T4), .I1(T5), .S(A[7])); - end else begin - wire _TECHMAP_FAIL_ = 1; - end - endgenerate -endmodule -`endif +// Empty for now diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v index eba17ac9c..787b37cc8 100644 --- a/techlibs/xilinx/cells_sim.v +++ b/techlibs/xilinx/cells_sim.v @@ -1,3 +1,21 @@ +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2012 Clifford Wolf + * + * 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. + * + */ // See Xilinx UG953 and UG474 for a description of the cell types below. // http://www.xilinx.com/support/documentation/user_guides/ug474_7Series_CLB.pdf @@ -104,56 +122,75 @@ module CARRY4(output [3:0] CO, O, input CI, CYINIT, input [3:0] DI, S); assign CO[3] = S[3] ? CO[2] : DI[3]; endmodule +`ifdef _EXPLICIT_CARRY + +module CARRY0(output CO_CHAIN, CO_FABRIC, O, input CI, CI_INIT, DI, S); + parameter CYINIT_FABRIC = 0; + wire CI_COMBINE; + if(CYINIT_FABRIC) begin + assign CI_COMBINE = CI_INIT; + end else begin + assign CI_COMBINE = CI; + end + assign CO_CHAIN = S ? CI_COMBINE : DI; + assign CO_FABRIC = S ? CI_COMBINE : DI; + assign O = S ^ CI_COMBINE; +endmodule + +module CARRY(output CO_CHAIN, CO_FABRIC, O, input CI, DI, S); + assign CO_CHAIN = S ? CI : DI; + assign CO_FABRIC = S ? CI : DI; + assign O = S ^ CI; +endmodule + +`endif + module FDRE (output reg Q, input C, CE, D, R); parameter [0:0] INIT = 1'b0; - parameter [0:0] IS_C_INVERTED = 1'b0; - parameter [0:0] IS_D_INVERTED = 1'b0; - parameter [0:0] IS_R_INVERTED = 1'b0; initial Q <= INIT; - generate case (|IS_C_INVERTED) - 1'b0: always @(posedge C) if (R == !IS_R_INVERTED) Q <= 1'b0; else if (CE) Q <= D ^ IS_D_INVERTED; - 1'b1: always @(negedge C) if (R == !IS_R_INVERTED) Q <= 1'b0; else if (CE) Q <= D ^ IS_D_INVERTED; - endcase endgenerate + always @(posedge C) if (R) Q <= 1'b0; else if(CE) Q <= D; endmodule module FDSE (output reg Q, input C, CE, D, S); - parameter [0:0] INIT = 1'b0; - parameter [0:0] IS_C_INVERTED = 1'b0; - parameter [0:0] IS_D_INVERTED = 1'b0; - parameter [0:0] IS_S_INVERTED = 1'b0; + parameter [0:0] INIT = 1'b1; initial Q <= INIT; - generate case (|IS_C_INVERTED) - 1'b0: always @(posedge C) if (S == !IS_S_INVERTED) Q <= 1'b1; else if (CE) Q <= D ^ IS_D_INVERTED; - 1'b1: always @(negedge C) if (S == !IS_S_INVERTED) Q <= 1'b1; else if (CE) Q <= D ^ IS_D_INVERTED; - endcase endgenerate + always @(posedge C) if (S) Q <= 1'b1; else if(CE) Q <= D; endmodule module FDCE (output reg Q, input C, CE, D, CLR); parameter [0:0] INIT = 1'b0; - parameter [0:0] IS_C_INVERTED = 1'b0; - parameter [0:0] IS_D_INVERTED = 1'b0; - parameter [0:0] IS_CLR_INVERTED = 1'b0; initial Q <= INIT; - generate case ({|IS_C_INVERTED, |IS_CLR_INVERTED}) - 2'b00: always @(posedge C, posedge CLR) if ( CLR) Q <= 1'b0; else if (CE) Q <= D ^ IS_D_INVERTED; - 2'b01: always @(posedge C, negedge CLR) if (!CLR) Q <= 1'b0; else if (CE) Q <= D ^ IS_D_INVERTED; - 2'b10: always @(negedge C, posedge CLR) if ( CLR) Q <= 1'b0; else if (CE) Q <= D ^ IS_D_INVERTED; - 2'b11: always @(negedge C, negedge CLR) if (!CLR) Q <= 1'b0; else if (CE) Q <= D ^ IS_D_INVERTED; - endcase endgenerate + always @(posedge C, posedge CLR) if (CLR) Q <= 1'b0; else if (CE) Q <= D; endmodule module FDPE (output reg Q, input C, CE, D, PRE); - parameter [0:0] INIT = 1'b0; - parameter [0:0] IS_C_INVERTED = 1'b0; - parameter [0:0] IS_D_INVERTED = 1'b0; - parameter [0:0] IS_PRE_INVERTED = 1'b0; + parameter [0:0] INIT = 1'b1; initial Q <= INIT; - generate case ({|IS_C_INVERTED, |IS_PRE_INVERTED}) - 2'b00: always @(posedge C, posedge PRE) if ( PRE) Q <= 1'b1; else if (CE) Q <= D ^ IS_D_INVERTED; - 2'b01: always @(posedge C, negedge PRE) if (!PRE) Q <= 1'b1; else if (CE) Q <= D ^ IS_D_INVERTED; - 2'b10: always @(negedge C, posedge PRE) if ( PRE) Q <= 1'b1; else if (CE) Q <= D ^ IS_D_INVERTED; - 2'b11: always @(negedge C, negedge PRE) if (!PRE) Q <= 1'b1; else if (CE) Q <= D ^ IS_D_INVERTED; - endcase endgenerate + always @(negedge C, posedge PRE) if (PRE) Q <= 1'b1; else if (CE) Q <= D; +endmodule + +module FDRE_1 (output reg Q, input C, CE, D, R); + parameter [0:0] INIT = 1'b0; + initial Q <= INIT; + always @(negedge C) if (R) Q <= 1'b0; else if(CE) Q <= D; +endmodule + +module FDSE_1 (output reg Q, input C, CE, D, S); + parameter [0:0] INIT = 1'b1; + initial Q <= INIT; + always @(negedge C) if (S) Q <= 1'b1; else if(CE) Q <= D; +endmodule + +module FDCE_1 (output reg Q, input C, CE, D, CLR); + parameter [0:0] INIT = 1'b0; + initial Q <= INIT; + always @(negedge C, posedge CLR) if (CLR) Q <= 1'b0; else if (CE) Q <= D; +endmodule + +module FDPE_1 (output reg Q, input C, CE, D, PRE); + parameter [0:0] INIT = 1'b1; + initial Q <= INIT; + always @(negedge C, posedge PRE) if (PRE) Q <= 1'b1; else if (CE) Q <= D; endmodule module RAM64X1D ( diff --git a/techlibs/xilinx/cells_xtra.sh b/techlibs/xilinx/cells_xtra.sh index 0480410f5..37c3e5480 100644 --- a/techlibs/xilinx/cells_xtra.sh +++ b/techlibs/xilinx/cells_xtra.sh @@ -115,7 +115,7 @@ function xtract_cell_decl() xtract_cell_decl PS7 xtract_cell_decl PULLDOWN xtract_cell_decl PULLUP - # xtract_cell_decl RAM128X1D + xtract_cell_decl RAM128X1D xtract_cell_decl RAM128X1S xtract_cell_decl RAM256X1S xtract_cell_decl RAM32M @@ -124,7 +124,7 @@ function xtract_cell_decl() xtract_cell_decl RAM32X1S_1 xtract_cell_decl RAM32X2S xtract_cell_decl RAM64M - # xtract_cell_decl RAM64X1D + xtract_cell_decl RAM64X1D xtract_cell_decl RAM64X1S xtract_cell_decl RAM64X1S_1 xtract_cell_decl RAM64X2S diff --git a/techlibs/xilinx/cells_xtra.v b/techlibs/xilinx/cells_xtra.v index 8d8b91ddc..995d62e18 100644 --- a/techlibs/xilinx/cells_xtra.v +++ b/techlibs/xilinx/cells_xtra.v @@ -3695,6 +3695,25 @@ module RAM128X1S (...); input A0, A1, A2, A3, A4, A5, A6, D, WCLK, WE; endmodule +module RAM128X1D ( + output DPO, SPO, + input D, WCLK, WE, + input [6:0] A, DPRA +); + parameter [127:0] INIT = 128'bx; + parameter IS_WCLK_INVERTED = 0; +endmodule + +module RAM64X1D ( + output DPO, SPO, + input D, WCLK, WE, + input A0, A1, A2, A3, A4, A5, + input DPRA0, DPRA1, DPRA2, DPRA3, DPRA4, DPRA5 +); + parameter [63:0] INIT = 64'bx; + parameter IS_WCLK_INVERTED = 0; +endmodule + module RAM256X1S (...); parameter [255:0] INIT = 256'h0; parameter [0:0] IS_WCLK_INVERTED = 1'b0; diff --git a/techlibs/xilinx/ff_map.v b/techlibs/xilinx/ff_map.v new file mode 100644 index 000000000..13beaa6ae --- /dev/null +++ b/techlibs/xilinx/ff_map.v @@ -0,0 +1,42 @@ +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2012 Clifford Wolf + * + * 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. + * + */ + +// ============================================================================ +// FF mapping + +`ifndef _NO_FFS + +module \$_DFF_N_ (input D, C, output Q); FDRE_1 #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .R(1'b0)); endmodule +module \$_DFF_P_ (input D, C, output Q); FDRE #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .R(1'b0)); endmodule + +module \$_DFFE_NP_ (input D, C, E, output Q); FDRE_1 #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .R(1'b0)); endmodule +module \$_DFFE_PP_ (input D, C, E, output Q); FDRE #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .R(1'b0)); endmodule + +module \$_DFF_NN0_ (input D, C, R, output Q); FDCE_1 #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .CLR(!R)); endmodule +module \$_DFF_NP0_ (input D, C, R, output Q); FDCE_1 #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .CLR( R)); endmodule +module \$_DFF_PN0_ (input D, C, R, output Q); FDCE #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .CLR(!R)); endmodule +module \$_DFF_PP0_ (input D, C, R, output Q); FDCE #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .CLR( R)); endmodule + +module \$_DFF_NN1_ (input D, C, R, output Q); FDPE_1 #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE(!R)); endmodule +module \$_DFF_NP1_ (input D, C, R, output Q); FDPE_1 #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE( R)); endmodule +module \$_DFF_PN1_ (input D, C, R, output Q); FDPE #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE(!R)); endmodule +module \$_DFF_PP1_ (input D, C, R, output Q); FDPE #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE( R)); endmodule + +`endif + diff --git a/techlibs/xilinx/lut2lut.v b/techlibs/xilinx/lut2lut.v deleted file mode 100644 index 061ad2041..000000000 --- a/techlibs/xilinx/lut2lut.v +++ /dev/null @@ -1,65 +0,0 @@ -module LUT1(output O, input I0); - parameter [1:0] INIT = 0; - \$lut #( - .WIDTH(1), - .LUT(INIT) - ) _TECHMAP_REPLACE_ ( - .A(I0), - .Y(O) - ); -endmodule - -module LUT2(output O, input I0, I1); - parameter [3:0] INIT = 0; - \$lut #( - .WIDTH(2), - .LUT(INIT) - ) _TECHMAP_REPLACE_ ( - .A({I1, I0}), - .Y(O) - ); -endmodule - -module LUT3(output O, input I0, I1, I2); - parameter [7:0] INIT = 0; - \$lut #( - .WIDTH(3), - .LUT(INIT) - ) _TECHMAP_REPLACE_ ( - .A({I2, I1, I0}), - .Y(O) - ); -endmodule - -module LUT4(output O, input I0, I1, I2, I3); - parameter [15:0] INIT = 0; - \$lut #( - .WIDTH(4), - .LUT(INIT) - ) _TECHMAP_REPLACE_ ( - .A({I3, I2, I1, I0}), - .Y(O) - ); -endmodule - -module LUT5(output O, input I0, I1, I2, I3, I4); - parameter [31:0] INIT = 0; - \$lut #( - .WIDTH(5), - .LUT(INIT) - ) _TECHMAP_REPLACE_ ( - .A({I4, I3, I2, I1, I0}), - .Y(O) - ); -endmodule - -module LUT6(output O, input I0, I1, I2, I3, I4, I5); - parameter [63:0] INIT = 0; - \$lut #( - .WIDTH(6), - .LUT(INIT) - ) _TECHMAP_REPLACE_ ( - .A({I5, I4, I3, I2, I1, I0}), - .Y(O) - ); -endmodule diff --git a/techlibs/xilinx/lut_map.v b/techlibs/xilinx/lut_map.v new file mode 100644 index 000000000..d07c59dee --- /dev/null +++ b/techlibs/xilinx/lut_map.v @@ -0,0 +1,94 @@ +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2012 Clifford Wolf + * + * 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. + * + */ + +// ============================================================================ +// LUT mapping + +`ifndef _NO_LUTS + +module \$lut (A, Y); + parameter WIDTH = 0; + parameter LUT = 0; + + input [WIDTH-1:0] A; + output Y; + + generate + if (WIDTH == 1) begin + LUT1 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y), + .I0(A[0])); + end else + if (WIDTH == 2) begin + LUT2 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y), + .I0(A[0]), .I1(A[1])); + end else + if (WIDTH == 3) begin + LUT3 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y), + .I0(A[0]), .I1(A[1]), .I2(A[2])); + end else + if (WIDTH == 4) begin + LUT4 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y), + .I0(A[0]), .I1(A[1]), .I2(A[2]), + .I3(A[3])); + end else + if (WIDTH == 5) begin + LUT5 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y), + .I0(A[0]), .I1(A[1]), .I2(A[2]), + .I3(A[3]), .I4(A[4])); + end else + if (WIDTH == 6) begin + LUT6 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y), + .I0(A[0]), .I1(A[1]), .I2(A[2]), + .I3(A[3]), .I4(A[4]), .I5(A[5])); + end else + if (WIDTH == 7) begin + wire T0, T1; + LUT6 #(.INIT(LUT[63:0])) fpga_lut_0 (.O(T0), + .I0(A[0]), .I1(A[1]), .I2(A[2]), + .I3(A[3]), .I4(A[4]), .I5(A[5])); + LUT6 #(.INIT(LUT[127:64])) fpga_lut_1 (.O(T1), + .I0(A[0]), .I1(A[1]), .I2(A[2]), + .I3(A[3]), .I4(A[4]), .I5(A[5])); + MUXF7 fpga_mux_0 (.O(Y), .I0(T0), .I1(T1), .S(A[6])); + end else + if (WIDTH == 8) begin + wire T0, T1, T2, T3, T4, T5; + LUT6 #(.INIT(LUT[63:0])) fpga_lut_0 (.O(T0), + .I0(A[0]), .I1(A[1]), .I2(A[2]), + .I3(A[3]), .I4(A[4]), .I5(A[5])); + LUT6 #(.INIT(LUT[127:64])) fpga_lut_1 (.O(T1), + .I0(A[0]), .I1(A[1]), .I2(A[2]), + .I3(A[3]), .I4(A[4]), .I5(A[5])); + LUT6 #(.INIT(LUT[191:128])) fpga_lut_2 (.O(T2), + .I0(A[0]), .I1(A[1]), .I2(A[2]), + .I3(A[3]), .I4(A[4]), .I5(A[5])); + LUT6 #(.INIT(LUT[255:192])) fpga_lut_3 (.O(T3), + .I0(A[0]), .I1(A[1]), .I2(A[2]), + .I3(A[3]), .I4(A[4]), .I5(A[5])); + MUXF7 fpga_mux_0 (.O(T4), .I0(T0), .I1(T1), .S(A[6])); + MUXF7 fpga_mux_1 (.O(T5), .I0(T2), .I1(T3), .S(A[6])); + MUXF8 fpga_mux_2 (.O(Y), .I0(T4), .I1(T5), .S(A[7])); + end else begin + wire _TECHMAP_FAIL_ = 1; + end + endgenerate +endmodule + +`endif + diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 6c11d885d..60cfde604 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -63,6 +63,12 @@ struct SynthXilinxPass : public Pass log(" generate an output netlist (and BLIF file) suitable for VPR\n"); log(" (this feature is experimental and incomplete)\n"); log("\n"); + log(" -no-brams\n"); + log(" disable infering of block rams\n"); + log("\n"); + log(" -no-drams\n"); + log(" disable infering of distributed rams\n"); + log("\n"); log(" -run :\n"); log(" only run the commands between the labels (see below). an empty\n"); log(" from label is synonymous to 'begin', and empty to label is\n"); @@ -90,11 +96,11 @@ struct SynthXilinxPass : public Pass log(" coarse:\n"); log(" synth -run coarse\n"); log("\n"); - log(" bram:\n"); + log(" bram: (only executed when '-no-brams' is not given)\n"); log(" memory_bram -rules +/xilinx/brams.txt\n"); log(" techmap -map +/xilinx/brams_map.v\n"); log("\n"); - log(" dram:\n"); + log(" dram: (only executed when '-no-drams' is not given)\n"); log(" memory_bram -rules +/xilinx/drams.txt\n"); log(" techmap -map +/xilinx/drams_map.v\n"); log("\n"); @@ -104,16 +110,17 @@ struct SynthXilinxPass : public Pass log(" dffsr2dff\n"); log(" dff2dffe\n"); log(" opt -full\n"); - log(" techmap -map +/techmap.v -map +/xilinx/arith_map.v\n"); + log(" techmap -map +/techmap.v -map +/xilinx/arith_map.v -map +/xilinx/ff_map.v\n"); log(" opt -fast\n"); log("\n"); log(" map_luts:\n"); - log(" abc -luts 2:2,3,6:5,10,20 [-dff]\n"); + log(" abc -luts 2:2,3,6:5,10,20 [-dff] (without '-vpr' only!)\n"); + log(" abc -lut 5 [-dff] (with '-vpr' only!)\n"); log(" clean\n"); log("\n"); log(" map_cells:\n"); - log(" techmap -map +/xilinx/cells_map.v (with -D NO_LUT in vpr mode)\n"); - log(" dffinit -ff FDRE Q INIT -ff FDCE Q INIT -ff FDPE Q INIT\n"); + log(" techmap -map +/xilinx/cells_map.v\n"); + log(" dffinit -ff FDRE Q INIT -ff FDCE Q INIT -ff FDPE Q INIT -ff FDSE Q INIT\n"); log(" clean\n"); log("\n"); log(" check:\n"); @@ -137,6 +144,8 @@ struct SynthXilinxPass : public Pass bool flatten = false; bool retime = false; bool vpr = false; + bool noBrams = false; + bool noDrams = false; size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) @@ -173,6 +182,14 @@ struct SynthXilinxPass : public Pass vpr = true; continue; } + if (args[argidx] == "-no-brams") { + noBrams = true; + continue; + } + if (args[argidx] == "-no-drams") { + noDrams = true; + continue; + } break; } extra_args(args, argidx, design); @@ -187,9 +204,18 @@ struct SynthXilinxPass : public Pass if (check_label(active, run_from, run_to, "begin")) { - Pass::call(design, "read_verilog -lib +/xilinx/cells_sim.v"); + if (vpr) { + Pass::call(design, "read_verilog -lib -D_EXPLICIT_CARRY +/xilinx/cells_sim.v"); + } else { + Pass::call(design, "read_verilog -lib +/xilinx/cells_sim.v"); + } + Pass::call(design, "read_verilog -lib +/xilinx/cells_xtra.v"); - Pass::call(design, "read_verilog -lib +/xilinx/brams_bb.v"); + + if (!noBrams) { + Pass::call(design, "read_verilog -lib +/xilinx/brams_bb.v"); + } + Pass::call(design, stringf("hierarchy -check %s", top_opt.c_str())); } @@ -206,14 +232,18 @@ struct SynthXilinxPass : public Pass if (check_label(active, run_from, run_to, "bram")) { - Pass::call(design, "memory_bram -rules +/xilinx/brams.txt"); - Pass::call(design, "techmap -map +/xilinx/brams_map.v"); + if (!noBrams) { + Pass::call(design, "memory_bram -rules +/xilinx/brams.txt"); + Pass::call(design, "techmap -map +/xilinx/brams_map.v"); + } } if (check_label(active, run_from, run_to, "dram")) { - Pass::call(design, "memory_bram -rules +/xilinx/drams.txt"); - Pass::call(design, "techmap -map +/xilinx/drams_map.v"); + if (!noDrams) { + Pass::call(design, "memory_bram -rules +/xilinx/drams.txt"); + Pass::call(design, "techmap -map +/xilinx/drams_map.v"); + } } if (check_label(active, run_from, run_to, "fine")) @@ -223,7 +253,14 @@ struct SynthXilinxPass : public Pass Pass::call(design, "dffsr2dff"); Pass::call(design, "dff2dffe"); Pass::call(design, "opt -full"); - Pass::call(design, "techmap -map +/techmap.v -map +/xilinx/arith_map.v"); + + if (vpr) { + Pass::call(design, "techmap -map +/techmap.v -map +/xilinx/arith_map.v -map +/xilinx/ff_map.v -D _EXPLICIT_CARRY"); + } else { + Pass::call(design, "techmap -map +/techmap.v -map +/xilinx/arith_map.v -map +/xilinx/ff_map.v"); + } + + Pass::call(design, "hierarchy -check"); Pass::call(design, "opt -fast"); } @@ -231,14 +268,13 @@ struct SynthXilinxPass : public Pass { Pass::call(design, "abc -luts 2:2,3,6:5,10,20" + string(retime ? " -dff" : "")); Pass::call(design, "clean"); + Pass::call(design, "techmap -map +/xilinx/lut_map.v"); } if (check_label(active, run_from, run_to, "map_cells")) { Pass::call(design, "techmap -map +/xilinx/cells_map.v"); - if (vpr) - Pass::call(design, "techmap -map +/xilinx/lut2lut.v"); - Pass::call(design, "dffinit -ff FDRE Q INIT -ff FDCE Q INIT -ff FDPE Q INIT"); + Pass::call(design, "dffinit -ff FDRE Q INIT -ff FDCE Q INIT -ff FDPE Q INIT -ff FDSE Q INIT"); Pass::call(design, "clean"); } From eccaf101d8324f518ed89134b4f21d2bdc636a8d Mon Sep 17 00:00:00 2001 From: Keith Rothman <537074+litghost@users.noreply.github.com> Date: Fri, 1 Mar 2019 12:14:27 -0800 Subject: [PATCH 26/76] Modify arguments to match existing style. Signed-off-by: Keith Rothman <537074+litghost@users.noreply.github.com> --- manual/command-reference-manual.tex | 10 +++++----- techlibs/xilinx/synth_xilinx.cc | 12 ++++++------ 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/manual/command-reference-manual.tex b/manual/command-reference-manual.tex index 257bf7986..bb9d7238c 100644 --- a/manual/command-reference-manual.tex +++ b/manual/command-reference-manual.tex @@ -4247,10 +4247,10 @@ compatible with 7-Series Xilinx devices. generate an output netlist (and BLIF file) suitable for VPR. (this feature is experimental and incomplete) - -no-brams - disable infering of block rams + -nobrams + disable infering of block rams - -no-drams + -nodrams disable infering of distributed rams -run : @@ -4280,11 +4280,11 @@ The following commands are executed by this synthesis command: coarse: synth -run coarse - bram: (only executed when '-no-brams' is not given) + bram: (only executed when '-nobrams' is not given) memory_bram -rules +/xilinx/brams.txt techmap -map +/xilinx/brams_map.v - dram: (only executed when '-no-drams' is not given) + dram: (only executed when '-nodrams' is not given) memory_bram -rules +/xilinx/drams.txt techmap -map +/xilinx/drams_map.v diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 60cfde604..12ad9fdaf 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -63,10 +63,10 @@ struct SynthXilinxPass : public Pass log(" generate an output netlist (and BLIF file) suitable for VPR\n"); log(" (this feature is experimental and incomplete)\n"); log("\n"); - log(" -no-brams\n"); + log(" -nobrams\n"); log(" disable infering of block rams\n"); log("\n"); - log(" -no-drams\n"); + log(" -nodrams\n"); log(" disable infering of distributed rams\n"); log("\n"); log(" -run :\n"); @@ -96,11 +96,11 @@ struct SynthXilinxPass : public Pass log(" coarse:\n"); log(" synth -run coarse\n"); log("\n"); - log(" bram: (only executed when '-no-brams' is not given)\n"); + log(" bram: (only executed when '-nobrams' is not given)\n"); log(" memory_bram -rules +/xilinx/brams.txt\n"); log(" techmap -map +/xilinx/brams_map.v\n"); log("\n"); - log(" dram: (only executed when '-no-drams' is not given)\n"); + log(" dram: (only executed when '-nodrams' is not given)\n"); log(" memory_bram -rules +/xilinx/drams.txt\n"); log(" techmap -map +/xilinx/drams_map.v\n"); log("\n"); @@ -182,11 +182,11 @@ struct SynthXilinxPass : public Pass vpr = true; continue; } - if (args[argidx] == "-no-brams") { + if (args[argidx] == "-nobrams") { noBrams = true; continue; } - if (args[argidx] == "-no-drams") { + if (args[argidx] == "-nodrams") { noDrams = true; continue; } From 03237de68605bb6eae73b96379faab0af6f8ce73 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 1 Mar 2019 12:59:07 -0800 Subject: [PATCH 27/76] Fix "write_edif -gndvccy" Signed-off-by: Clifford Wolf --- backends/edif/edif.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backends/edif/edif.cc b/backends/edif/edif.cc index 2d25f879d..7e30b67af 100644 --- a/backends/edif/edif.cc +++ b/backends/edif/edif.cc @@ -130,7 +130,7 @@ struct EdifBackend : public Backend { bool port_rename = false; bool attr_properties = false; std::map> lib_cell_ports; - bool nogndvcc = false, gndvccy = true; + bool nogndvcc = false, gndvccy = false; CellTypes ct(design); EdifNames edif_names; From 7cfae2c52fb8e210a68032a109646785e4353dcc Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 1 Mar 2019 13:35:09 -0800 Subject: [PATCH 28/76] Use mem2reg on memories that only have constant-index write ports Signed-off-by: Clifford Wolf --- frontends/ast/ast.h | 2 ++ frontends/ast/simplify.cc | 11 +++++++++++ 2 files changed, 13 insertions(+) diff --git a/frontends/ast/ast.h b/frontends/ast/ast.h index 08f91c9c3..89f7e6e4f 100644 --- a/frontends/ast/ast.h +++ b/frontends/ast/ast.h @@ -214,6 +214,8 @@ namespace AST MEM2REG_FL_SET_ASYNC = 0x00000800, MEM2REG_FL_EQ2 = 0x00001000, MEM2REG_FL_CMPLX_LHS = 0x00002000, + MEM2REG_FL_CONST_LHS = 0x00004000, + MEM2REG_FL_VAR_LHS = 0x00008000, /* proc flags */ MEM2REG_FL_EQ1 = 0x01000000, diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 46013544b..589c683f8 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -113,6 +113,9 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, if (memflags & AstNode::MEM2REG_FL_CMPLX_LHS) goto verbose_activate; + if ((memflags & AstNode::MEM2REG_FL_CONST_LHS) && !(memflags & AstNode::MEM2REG_FL_VAR_LHS)) + goto verbose_activate; + // log("Note: Not replacing memory %s with list of registers (flags=0x%08lx).\n", mem->str.c_str(), long(memflags)); continue; @@ -2936,6 +2939,14 @@ void AstNode::mem2reg_as_needed_pass1(dict> &mem2reg proc_flags[mem] |= AstNode::MEM2REG_FL_EQ1; } + // remember if this is a constant index or not + if (children[0]->children.size() && children[0]->children[0]->type == AST_RANGE && children[0]->children[0]->children.size()) { + if (children[0]->children[0]->children[0]->type == AST_CONSTANT) + mem2reg_candidates[mem] |= AstNode::MEM2REG_FL_CONST_LHS; + else + mem2reg_candidates[mem] |= AstNode::MEM2REG_FL_VAR_LHS; + } + // remember where this is if (flags & MEM2REG_FL_INIT) { if (!(mem2reg_candidates[mem] & AstNode::MEM2REG_FL_SET_INIT)) From a02d61576ec42931ed3a67c6900bcd5aeddaf8b8 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 1 Mar 2019 14:29:17 -0800 Subject: [PATCH 29/76] Minor improvements in README Signed-off-by: Clifford Wolf --- README.md | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 883f2b0a5..f17046488 100644 --- a/README.md +++ b/README.md @@ -34,11 +34,24 @@ compatible license that is similar in terms to the MIT license or the 2-clause BSD license). -Web Site -======== +Web Site and Other Resources +============================ More information and documentation can be found on the Yosys web site: -http://www.clifford.at/yosys/ +- http://www.clifford.at/yosys/ + +The "Documentation" page on the web site contains links to more resources, +including a manual that even describes some of the Yosys internals: +- http://www.clifford.at/yosys/documentation.html + +The file `CodingReadme` in this directory contains additional information +for people interested in using the Yosys C++ APIs. + +Users interested in formal verification might want to use the formal verification +front-end for Yosys, SymbiYosys: +- https://symbiyosys.readthedocs.io/en/latest/ +- https://github.com/YosysHQ/SymbiYosys + Setup ====== From 5ebeca12eb0bf9317acec3d619021ab337d445ba Mon Sep 17 00:00:00 2001 From: Keith Rothman <537074+litghost@users.noreply.github.com> Date: Fri, 1 Mar 2019 14:35:14 -0800 Subject: [PATCH 30/76] Use singular for disabling of DRAM or BRAM inference. Signed-off-by: Keith Rothman <537074+litghost@users.noreply.github.com> --- manual/command-reference-manual.tex | 19 ++++++------------- techlibs/xilinx/synth_xilinx.cc | 26 +++++++++++++------------- 2 files changed, 19 insertions(+), 26 deletions(-) diff --git a/manual/command-reference-manual.tex b/manual/command-reference-manual.tex index bb9d7238c..bed6326e2 100644 --- a/manual/command-reference-manual.tex +++ b/manual/command-reference-manual.tex @@ -4244,15 +4244,9 @@ compatible with 7-Series Xilinx devices. is omitted if this parameter is not specified. -vpr - generate an output netlist (and BLIF file) suitable for VPR. + generate an output netlist (and BLIF file) suitable for VPR (this feature is experimental and incomplete) - -nobrams - disable infering of block rams - - -nodrams - disable infering of distributed rams - -run : only run the commands between the labels (see below). an empty from label is synonymous to 'begin', and empty to label is @@ -4280,11 +4274,11 @@ The following commands are executed by this synthesis command: coarse: synth -run coarse - bram: (only executed when '-nobrams' is not given) + bram: memory_bram -rules +/xilinx/brams.txt techmap -map +/xilinx/brams_map.v - dram: (only executed when '-nodrams' is not given) + dram: memory_bram -rules +/xilinx/drams.txt techmap -map +/xilinx/drams_map.v @@ -4294,17 +4288,16 @@ The following commands are executed by this synthesis command: dffsr2dff dff2dffe opt -full - techmap -map +/techmap.v -map +/xilinx/arith_map.v -map +/xilinx/ff_map.v + techmap -map +/techmap.v -map +/xilinx/arith_map.v opt -fast map_luts: - abc -luts 2:2,3,6:5,10,20 [-dff] (without '-vpr' only!) - abc -lut 5 [-dff] (with '-vpr' only!) + abc -luts 2:2,3,6:5,10,20 [-dff] clean map_cells: techmap -map +/xilinx/cells_map.v (with -D NO_LUT in vpr mode) - dffinit -ff FDRE Q INIT -ff FDCE Q INIT -ff FDPE Q INIT -ff FDSE Q INIT + dffinit -ff FDRE Q INIT -ff FDCE Q INIT -ff FDPE Q INIT clean check: diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 12ad9fdaf..9e7559944 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -63,10 +63,10 @@ struct SynthXilinxPass : public Pass log(" generate an output netlist (and BLIF file) suitable for VPR\n"); log(" (this feature is experimental and incomplete)\n"); log("\n"); - log(" -nobrams\n"); + log(" -nobram\n"); log(" disable infering of block rams\n"); log("\n"); - log(" -nodrams\n"); + log(" -nodram\n"); log(" disable infering of distributed rams\n"); log("\n"); log(" -run :\n"); @@ -96,11 +96,11 @@ struct SynthXilinxPass : public Pass log(" coarse:\n"); log(" synth -run coarse\n"); log("\n"); - log(" bram: (only executed when '-nobrams' is not given)\n"); + log(" bram: (only executed when '-nobram' is not given)\n"); log(" memory_bram -rules +/xilinx/brams.txt\n"); log(" techmap -map +/xilinx/brams_map.v\n"); log("\n"); - log(" dram: (only executed when '-nodrams' is not given)\n"); + log(" dram: (only executed when '-nodram' is not given)\n"); log(" memory_bram -rules +/xilinx/drams.txt\n"); log(" techmap -map +/xilinx/drams_map.v\n"); log("\n"); @@ -144,8 +144,8 @@ struct SynthXilinxPass : public Pass bool flatten = false; bool retime = false; bool vpr = false; - bool noBrams = false; - bool noDrams = false; + bool nobram = false; + bool nodram = false; size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) @@ -182,12 +182,12 @@ struct SynthXilinxPass : public Pass vpr = true; continue; } - if (args[argidx] == "-nobrams") { - noBrams = true; + if (args[argidx] == "-nobram") { + nobram = true; continue; } - if (args[argidx] == "-nodrams") { - noDrams = true; + if (args[argidx] == "-nodram") { + nodram = true; continue; } break; @@ -212,7 +212,7 @@ struct SynthXilinxPass : public Pass Pass::call(design, "read_verilog -lib +/xilinx/cells_xtra.v"); - if (!noBrams) { + if (!nobram) { Pass::call(design, "read_verilog -lib +/xilinx/brams_bb.v"); } @@ -232,7 +232,7 @@ struct SynthXilinxPass : public Pass if (check_label(active, run_from, run_to, "bram")) { - if (!noBrams) { + if (!nobram) { Pass::call(design, "memory_bram -rules +/xilinx/brams.txt"); Pass::call(design, "techmap -map +/xilinx/brams_map.v"); } @@ -240,7 +240,7 @@ struct SynthXilinxPass : public Pass if (check_label(active, run_from, run_to, "dram")) { - if (!noDrams) { + if (!nodram) { Pass::call(design, "memory_bram -rules +/xilinx/drams.txt"); Pass::call(design, "techmap -map +/xilinx/drams_map.v"); } From 3e16f75bc6f490cada2b9c4e9b4962a66b1e8008 Mon Sep 17 00:00:00 2001 From: Keith Rothman <537074+litghost@users.noreply.github.com> Date: Fri, 1 Mar 2019 14:41:21 -0800 Subject: [PATCH 31/76] Revert FF models to include IS_x_INVERTED parameters. Signed-off-by: Keith Rothman <537074+litghost@users.noreply.github.com> --- techlibs/xilinx/cells_sim.v | 40 +++++++++++++++++++++++++++++++------ 1 file changed, 34 insertions(+), 6 deletions(-) diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v index 787b37cc8..ff5ff0726 100644 --- a/techlibs/xilinx/cells_sim.v +++ b/techlibs/xilinx/cells_sim.v @@ -147,26 +147,54 @@ endmodule module FDRE (output reg Q, input C, CE, D, R); parameter [0:0] INIT = 1'b0; + parameter [0:0] IS_C_INVERTED = 1'b0; + parameter [0:0] IS_D_INVERTED = 1'b0; + parameter [0:0] IS_R_INVERTED = 1'b0; initial Q <= INIT; - always @(posedge C) if (R) Q <= 1'b0; else if(CE) Q <= D; + generate case (|IS_C_INVERTED) + 1'b0: always @(posedge C) if (R == !IS_R_INVERTED) Q <= 1'b0; else if (CE) Q <= D ^ IS_D_INVERTED; + 1'b1: always @(negedge C) if (R == !IS_R_INVERTED) Q <= 1'b0; else if (CE) Q <= D ^ IS_D_INVERTED; + endcase endgenerate endmodule module FDSE (output reg Q, input C, CE, D, S); - parameter [0:0] INIT = 1'b1; + parameter [0:0] INIT = 1'b0; + parameter [0:0] IS_C_INVERTED = 1'b0; + parameter [0:0] IS_D_INVERTED = 1'b0; + parameter [0:0] IS_S_INVERTED = 1'b0; initial Q <= INIT; - always @(posedge C) if (S) Q <= 1'b1; else if(CE) Q <= D; + generate case (|IS_C_INVERTED) + 1'b0: always @(posedge C) if (S == !IS_S_INVERTED) Q <= 1'b1; else if (CE) Q <= D ^ IS_D_INVERTED; + 1'b1: always @(negedge C) if (S == !IS_S_INVERTED) Q <= 1'b1; else if (CE) Q <= D ^ IS_D_INVERTED; + endcase endgenerate endmodule module FDCE (output reg Q, input C, CE, D, CLR); parameter [0:0] INIT = 1'b0; + parameter [0:0] IS_C_INVERTED = 1'b0; + parameter [0:0] IS_D_INVERTED = 1'b0; + parameter [0:0] IS_CLR_INVERTED = 1'b0; initial Q <= INIT; - always @(posedge C, posedge CLR) if (CLR) Q <= 1'b0; else if (CE) Q <= D; + generate case ({|IS_C_INVERTED, |IS_CLR_INVERTED}) + 2'b00: always @(posedge C, posedge CLR) if ( CLR) Q <= 1'b0; else if (CE) Q <= D ^ IS_D_INVERTED; + 2'b01: always @(posedge C, negedge CLR) if (!CLR) Q <= 1'b0; else if (CE) Q <= D ^ IS_D_INVERTED; + 2'b10: always @(negedge C, posedge CLR) if ( CLR) Q <= 1'b0; else if (CE) Q <= D ^ IS_D_INVERTED; + 2'b11: always @(negedge C, negedge CLR) if (!CLR) Q <= 1'b0; else if (CE) Q <= D ^ IS_D_INVERTED; + endcase endgenerate endmodule module FDPE (output reg Q, input C, CE, D, PRE); - parameter [0:0] INIT = 1'b1; + parameter [0:0] INIT = 1'b0; + parameter [0:0] IS_C_INVERTED = 1'b0; + parameter [0:0] IS_D_INVERTED = 1'b0; + parameter [0:0] IS_PRE_INVERTED = 1'b0; initial Q <= INIT; - always @(negedge C, posedge PRE) if (PRE) Q <= 1'b1; else if (CE) Q <= D; + generate case ({|IS_C_INVERTED, |IS_PRE_INVERTED}) + 2'b00: always @(posedge C, posedge PRE) if ( PRE) Q <= 1'b1; else if (CE) Q <= D ^ IS_D_INVERTED; + 2'b01: always @(posedge C, negedge PRE) if (!PRE) Q <= 1'b1; else if (CE) Q <= D ^ IS_D_INVERTED; + 2'b10: always @(negedge C, posedge PRE) if ( PRE) Q <= 1'b1; else if (CE) Q <= D ^ IS_D_INVERTED; + 2'b11: always @(negedge C, negedge PRE) if (!PRE) Q <= 1'b1; else if (CE) Q <= D ^ IS_D_INVERTED; + endcase endgenerate endmodule module FDRE_1 (output reg Q, input C, CE, D, R); From 57f8bb471feecafad9d9e0bae77ea937b6b03a83 Mon Sep 17 00:00:00 2001 From: Larry Doolittle Date: Fri, 1 Mar 2019 20:15:20 -0800 Subject: [PATCH 32/76] Try again for passes/pmgen/ice40_dsp_pm.h rule Tested on both in-tree and out-of-tree builds --- passes/pmgen/Makefile.inc | 2 +- passes/pmgen/pmgen.py | 15 ++++++++------- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/passes/pmgen/Makefile.inc b/passes/pmgen/Makefile.inc index e0dd0fc06..e0609d9ba 100644 --- a/passes/pmgen/Makefile.inc +++ b/passes/pmgen/Makefile.inc @@ -5,4 +5,4 @@ EXTRA_OBJS += passes/pmgen/ice40_dsp_pm.h .SECONDARY: passes/pmgen/ice40_dsp_pm.h passes/pmgen/ice40_dsp_pm.h: passes/pmgen/pmgen.py passes/pmgen/ice40_dsp.pmg - $(P) mkdir -p passes/pmgen && python3 $^ + $(P) mkdir -p passes/pmgen && python3 $^ $@ diff --git a/passes/pmgen/pmgen.py b/passes/pmgen/pmgen.py index 762d8621f..d9747b065 100644 --- a/passes/pmgen/pmgen.py +++ b/passes/pmgen/pmgen.py @@ -9,7 +9,8 @@ pp = pprint.PrettyPrinter(indent=4) pmgfile = sys.argv[1] assert pmgfile.endswith(".pmg") prefix = pmgfile[0:-4] -pmname = prefix.split('/')[-1] +prefix = prefix.split('/')[-1] +outfile = sys.argv[2] state_types = dict() udata_types = dict() @@ -179,7 +180,7 @@ with open(pmgfile, "r") as f: blocks.append(block) -with open("%s_pm.h" % prefix, "w") as f: +with open(outfile, "w") as f: print("// Generated by pmgen.py from {}.pgm".format(prefix), file=f) print("", file=f) @@ -190,10 +191,10 @@ with open("%s_pm.h" % prefix, "w") as f: print("YOSYS_NAMESPACE_BEGIN", file=f) print("", file=f) - print("struct {}_pm {{".format(pmname), file=f) + print("struct {}_pm {{".format(prefix), file=f) print(" Module *module;", file=f) print(" SigMap sigmap;", file=f) - print(" std::function on_accept;".format(pmname), file=f) + print(" std::function on_accept;".format(prefix), file=f) print("", file=f) for index in range(len(blocks)): @@ -291,7 +292,7 @@ with open("%s_pm.h" % prefix, "w") as f: print(" }", file=f) print("", file=f) - print(" {}_pm(Module *module, const vector &cells) :".format(pmname), file=f) + print(" {}_pm(Module *module, const vector &cells) :".format(prefix), file=f) print(" module(module), sigmap(module) {", file=f) for s, t in sorted(udata_types.items()): if t.endswith("*"): @@ -321,7 +322,7 @@ with open("%s_pm.h" % prefix, "w") as f: print(" }", file=f) print("", file=f) - print(" ~{}_pm() {{".format(pmname), file=f) + print(" ~{}_pm() {{".format(prefix), file=f) print(" for (auto cell : autoremove_cells)", file=f) print(" module->remove(cell);", file=f) print(" }", file=f) @@ -340,7 +341,7 @@ with open("%s_pm.h" % prefix, "w") as f: print(" }", file=f) print("", file=f) - print(" void run(std::function on_accept_f) {{".format(pmname), file=f) + print(" void run(std::function on_accept_f) {{".format(prefix), file=f) print(" run([&](){on_accept_f(*this);});", file=f) print(" }", file=f) print("", file=f) From f75aee87e3038f663dc61f9d3098d5056ccdced7 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 2 Mar 2019 08:29:28 -0800 Subject: [PATCH 33/76] Disable macOS builds in Travis Signed-off-by: Clifford Wolf --- .travis.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index 8aacbb8b1..7c6e4e43c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -132,11 +132,11 @@ matrix: env: - MATRIX_EVAL="CONFIG=clang && CC=clang-5.0 && CXX=clang++-5.0" - # Latest clang on Mac OS X - - os: osx - osx_image: xcode9.4 - env: - - MATRIX_EVAL="CONFIG=clang && CC=clang && CXX=clang++" +# # Latest clang on Mac OS X +# - os: osx +# osx_image: xcode9.4 +# env: +# - MATRIX_EVAL="CONFIG=clang && CC=clang && CXX=clang++" before_install: - ./.travis/setup.sh From 5d93dcce862d281f0df495eeee755cd4bfca342d Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 2 Mar 2019 09:58:20 -0800 Subject: [PATCH 34/76] Fix $readmem[hb] for mem2reg memories, fixes #785 Signed-off-by: Clifford Wolf --- frontends/ast/simplify.cc | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 589c683f8..1c35516d4 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -2172,6 +2172,8 @@ skip_dynamic_range_lvalue_expansion:; } newNode = readmem(str == "\\$readmemh", node_filename->bitsAsConst().decode_string(), node_memory->id2ast, start_addr, finish_addr, unconditional_init); + delete node_filename; + delete node_memory; goto apply_newNode; } @@ -3059,6 +3061,39 @@ bool AstNode::mem2reg_as_needed_pass2(pool &mem2reg_set, AstNode *mod, if (type == AST_FUNCTION || type == AST_TASK) return false; + if (type == AST_MEMINIT && id2ast && mem2reg_set.count(id2ast)) + { + log_assert(children[0]->type == AST_CONSTANT); + log_assert(children[1]->type == AST_CONSTANT); + log_assert(children[2]->type == AST_CONSTANT); + + int cursor = children[0]->asInt(false); + Const data = children[1]->bitsAsConst(); + int length = children[2]->asInt(false); + + if (length != 0) + { + AstNode *block = new AstNode(AST_INITIAL, new AstNode(AST_BLOCK)); + mod->children.push_back(block); + block = block->children[0]; + + int wordsz = GetSize(data) / length; + + for (int i = 0; i < length; i++) { + block->children.push_back(new AstNode(AST_ASSIGN_EQ, new AstNode(AST_IDENTIFIER, new AstNode(AST_RANGE, AstNode::mkconst_int(cursor+i, false))), mkconst_bits(data.extract(i*wordsz, wordsz).bits, false))); + block->children.back()->children[0]->str = str; + block->children.back()->children[0]->id2ast = id2ast; + block->children.back()->children[0]->was_checked = true; + } + } + + AstNode *newNode = new AstNode(AST_NONE); + newNode->cloneInto(this); + delete newNode; + + did_something = true; + } + if (type == AST_ASSIGN && block == NULL && children[0]->mem2reg_check(mem2reg_set)) { if (async_block == NULL) { From ce6695e22c7d2b8856ec5bb93a94264555aa55b5 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 2 Mar 2019 10:38:13 -0800 Subject: [PATCH 35/76] Fix $global_clock handling vs autowire Signed-off-by: Clifford Wolf --- frontends/ast/simplify.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 1c35516d4..d0b31078a 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -941,7 +941,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, } } if (current_scope.count(str) == 0) { - if (flag_autowire) { + if (flag_autowire || str == "\\$global_clock") { AstNode *auto_wire = new AstNode(AST_AUTOWIRE); auto_wire->str = str; current_ast_mod->children.push_back(auto_wire); From 3a51714451dbd5a0aec5d5167429f899950f2c4e Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 2 Mar 2019 11:40:57 -0800 Subject: [PATCH 36/76] Fix error for wire decl in always block, fixes #763 Signed-off-by: Clifford Wolf --- frontends/ast/genrtlil.cc | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc index 2d591b29d..13383845a 100644 --- a/frontends/ast/genrtlil.cc +++ b/frontends/ast/genrtlil.cc @@ -544,7 +544,11 @@ struct AST_INTERNAL::ProcessGenerator break; case AST_WIRE: - log_file_error(ast->filename, ast->linenum, "Found wire declaration in block without label!\n"); + log_file_error(ast->filename, ast->linenum, "Found reg declaration in block without label!\n"); + break; + + case AST_ASSIGN: + log_file_error(ast->filename, ast->linenum, "Found continous assignment in always/initial block!\n"); break; case AST_PARAMETER: From ae9286386de117991f887f919f5af3fac40173cc Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 2 Mar 2019 12:36:46 -0800 Subject: [PATCH 37/76] Only run derive on blackbox modules when ports have dynamic size Signed-off-by: Clifford Wolf --- README.md | 3 +++ frontends/ast/ast.h | 1 + frontends/ast/simplify.cc | 19 +++++++++++++++++++ passes/hierarchy/hierarchy.cc | 2 +- 4 files changed, 24 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index f17046488..9bac468a7 100644 --- a/README.md +++ b/README.md @@ -309,6 +309,9 @@ Verilog Attributes and non-standard features passes to identify input and output ports of cells. The Verilog backend also does not output blackbox modules on default. +- The ``dynports'' attribute is used by the Verilog front-end to mark modules + that have ports with a width that depends on a parameter. + - The ``keep`` attribute on cells and wires is used to mark objects that should never be removed by the optimizer. This is used for example for cells that have hidden connections that are not part of the netlist, such as IO pads. diff --git a/frontends/ast/ast.h b/frontends/ast/ast.h index 89f7e6e4f..8b185ff51 100644 --- a/frontends/ast/ast.h +++ b/frontends/ast/ast.h @@ -239,6 +239,7 @@ namespace AST bool has_const_only_constructs(bool &recommend_const_eval); void replace_variables(std::map &variables, AstNode *fcall); AstNode *eval_const_function(AstNode *fcall); + bool is_simple_const_expr(); // create a human-readable text representation of the AST (for debugging) void dumpAst(FILE *f, std::string indent) const; diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index d0b31078a..7160c6c0f 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -328,6 +328,15 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, for (size_t i = 0; i < children.size(); i++) { AstNode *node = children[i]; if (node->type == AST_WIRE) { + if (node->children.size() == 1 && node->children[0]->type == AST_RANGE) { + for (auto c : node->children[0]->children) { + if (!c->is_simple_const_expr()) { + if (attributes.count("\\dynports")) + delete attributes.at("\\dynports"); + attributes["\\dynports"] = AstNode::mkconst_int(1, true); + } + } + } if (this_wire_scope.count(node->str) > 0) { AstNode *first_node = this_wire_scope[node->str]; if (first_node->is_input && node->is_reg) @@ -3323,6 +3332,16 @@ bool AstNode::has_const_only_constructs(bool &recommend_const_eval) return false; } +bool AstNode::is_simple_const_expr() +{ + if (type == AST_IDENTIFIER) + return false; + for (auto child : children) + if (!child->is_simple_const_expr()) + return false; + return true; +} + // helper function for AstNode::eval_const_function() void AstNode::replace_variables(std::map &variables, AstNode *fcall) { diff --git a/passes/hierarchy/hierarchy.cc b/passes/hierarchy/hierarchy.cc index 2d8edebb5..88c339e8c 100644 --- a/passes/hierarchy/hierarchy.cc +++ b/passes/hierarchy/hierarchy.cc @@ -910,7 +910,7 @@ struct HierarchyPass : public Pass { if (m == nullptr) continue; - if (m->get_bool_attribute("\\blackbox") && !cell->parameters.empty()) { + if (m->get_bool_attribute("\\blackbox") && !cell->parameters.empty() && m->get_bool_attribute("\\dynports")) { IdString new_m_name = m->derive(design, cell->parameters, true); if (new_m_name.empty()) continue; From a176ac95ded8b5aa9efb98b7a8e6981c90827d0e Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 3 Mar 2019 21:35:57 -0800 Subject: [PATCH 38/76] Update igloo2 example to Libero v12.0 Signed-off-by: Clifford Wolf --- examples/igloo2/libero.tcl | 9 ++++----- examples/igloo2/runme.sh | 2 +- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/examples/igloo2/libero.tcl b/examples/igloo2/libero.tcl index 1f3476316..82e614cd4 100644 --- a/examples/igloo2/libero.tcl +++ b/examples/igloo2/libero.tcl @@ -15,6 +15,7 @@ new_project \ import_files -hdl_source {netlist.vm} import_files -sdc {example.sdc} import_files -io_pdc {example.pdc} +build_design_hierarchy set_option -synth 0 organize_tool_files -tool PLACEROUTE \ @@ -44,10 +45,8 @@ puts "**> VERIFYTIMING" run_tool -name {VERIFYTIMING} puts "<** VERIFYTIMING" -save_project - -# puts "**> export_bitstream" -# export_bitstream_file -trusted_facility_file 1 -trusted_facility_file_components {FABRIC} -# puts "<** export_bitstream" +puts "**> export_bitstream" +export_bitstream_file -trusted_facility_file 1 -trusted_facility_file_components {FABRIC} +puts "<** export_bitstream" exit 0 diff --git a/examples/igloo2/runme.sh b/examples/igloo2/runme.sh index 54247759f..95f2282ba 100644 --- a/examples/igloo2/runme.sh +++ b/examples/igloo2/runme.sh @@ -1,4 +1,4 @@ #!/bin/bash set -ex yosys -p 'synth_sf2 -top example -edif netlist.edn -vlog netlist.vm' example.v -LM_LICENSE_FILE=1702@`hostname` /opt/microsemi/Libero_SoC_v11.9/Libero/bin/libero SCRIPT:libero.tcl +LM_LICENSE_FILE=1702@`hostname` /opt/microsemi/Libero_SoC_v12.0/Libero/bin/libero SCRIPT:libero.tcl From 107d8848041289bdf3ed85f2ca6c7e02fa9ec774 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 3 Mar 2019 23:54:35 -0800 Subject: [PATCH 39/76] Improve igloo2 example Signed-off-by: Clifford Wolf --- examples/igloo2/libero.tcl | 9 +++++++-- examples/igloo2/runme.sh | 4 +++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/examples/igloo2/libero.tcl b/examples/igloo2/libero.tcl index 82e614cd4..6f7d4e24b 100644 --- a/examples/igloo2/libero.tcl +++ b/examples/igloo2/libero.tcl @@ -33,20 +33,25 @@ configure_tool -name PLACEROUTE \ -params EFFORT_LEVEL:false \ -params REPAIR_MIN_DELAY:false +puts "" puts "**> COMPILE" run_tool -name {COMPILE} puts "<** COMPILE" +puts "" puts "**> PLACEROUTE" run_tool -name {PLACEROUTE} puts "<** PLACEROUTE" +puts "" puts "**> VERIFYTIMING" run_tool -name {VERIFYTIMING} puts "<** VERIFYTIMING" -puts "**> export_bitstream" +puts "" +puts "**> BITSTREAM" export_bitstream_file -trusted_facility_file 1 -trusted_facility_file_components {FABRIC} -puts "<** export_bitstream" +puts "<** BITSTREAM" +puts "" exit 0 diff --git a/examples/igloo2/runme.sh b/examples/igloo2/runme.sh index 95f2282ba..a08894e0a 100644 --- a/examples/igloo2/runme.sh +++ b/examples/igloo2/runme.sh @@ -1,4 +1,6 @@ #!/bin/bash set -ex yosys -p 'synth_sf2 -top example -edif netlist.edn -vlog netlist.vm' example.v -LM_LICENSE_FILE=1702@`hostname` /opt/microsemi/Libero_SoC_v12.0/Libero/bin/libero SCRIPT:libero.tcl +export LM_LICENSE_FILE=${LM_LICENSE_FILE:-1702@localhost} +/opt/microsemi/Libero_SoC_v12.0/Libero/bin/libero SCRIPT:libero.tcl +cp proj/designer/example/export/example.stp . From 777864d02ea3382c822a764e928e06b6142da6ec Mon Sep 17 00:00:00 2001 From: David Shah Date: Mon, 4 Mar 2019 11:18:53 +0000 Subject: [PATCH 40/76] ecp5: Demote conflicting FF init values to a warning Signed-off-by: David Shah --- techlibs/ecp5/ecp5_ffinit.cc | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/techlibs/ecp5/ecp5_ffinit.cc b/techlibs/ecp5/ecp5_ffinit.cc index 02945fff4..dbd16cac9 100644 --- a/techlibs/ecp5/ecp5_ffinit.cc +++ b/techlibs/ecp5/ecp5_ffinit.cc @@ -79,10 +79,12 @@ struct Ecp5FfinitPass : public Pass { continue; if (initbits.count(bit)) { - if (initbits.at(bit) != val) - log_error("Conflicting init values for signal %s (%s = %s, %s = %s).\n", + if (initbits.at(bit) != val) { + log_warning("Conflicting init values for signal %s (%s = %s, %s = %s).\n", log_signal(bit), log_signal(SigBit(wire, i)), log_signal(val), log_signal(initbit_to_wire[bit]), log_signal(initbits.at(bit))); + initbits.at(bit) = State::Sx; + } continue; } @@ -121,6 +123,9 @@ struct Ecp5FfinitPass : public Pass { State val = initbits.at(bit_q); + if (val == State::Sx) + continue; + log("FF init value for cell %s (%s): %s = %c\n", log_id(cell), log_id(cell->type), log_signal(bit_q), val != State::S0 ? '1' : '0'); // Initval is the same as the reset state. Matches hardware, nowt more to do From 228f132ec388fd8d0791ed3f0944b850de054370 Mon Sep 17 00:00:00 2001 From: Keith Rothman <537074+litghost@users.noreply.github.com> Date: Mon, 4 Mar 2019 09:22:22 -0800 Subject: [PATCH 41/76] Revert BRAM WRITE_MODE changes. Signed-off-by: Keith Rothman <537074+litghost@users.noreply.github.com> --- techlibs/xilinx/brams_map.v | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/techlibs/xilinx/brams_map.v b/techlibs/xilinx/brams_map.v index 2a23b2553..7ea49158d 100644 --- a/techlibs/xilinx/brams_map.v +++ b/techlibs/xilinx/brams_map.v @@ -30,8 +30,8 @@ module \$__XILINX_RAMB36_SDP (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, .RAM_MODE("SDP"), .READ_WIDTH_A(72), .WRITE_WIDTH_B(72), - .WRITE_MODE_A("WRITE_FIRST"), - .WRITE_MODE_B("WRITE_FIRST"), + .WRITE_MODE_A("READ_FIRST"), + .WRITE_MODE_B("READ_FIRST"), .IS_CLKARDCLK_INVERTED(!CLKPOL2), .IS_CLKBWRCLK_INVERTED(!CLKPOL3), `include "brams_init_36.vh" @@ -95,8 +95,8 @@ module \$__XILINX_RAMB18_SDP (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, .RAM_MODE("SDP"), .READ_WIDTH_A(36), .WRITE_WIDTH_B(36), - .WRITE_MODE_A("WRITE_FIRST"), - .WRITE_MODE_B("WRITE_FIRST"), + .WRITE_MODE_A("READ_FIRST"), + .WRITE_MODE_B("READ_FIRST"), .IS_CLKARDCLK_INVERTED(!CLKPOL2), .IS_CLKBWRCLK_INVERTED(!CLKPOL3), `include "brams_init_18.vh" @@ -171,8 +171,8 @@ module \$__XILINX_RAMB36_TDP (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, .READ_WIDTH_B(CFG_DBITS), .WRITE_WIDTH_A(CFG_DBITS), .WRITE_WIDTH_B(CFG_DBITS), - .WRITE_MODE_A("WRITE_FIRST"), - .WRITE_MODE_B("WRITE_FIRST"), + .WRITE_MODE_A("READ_FIRST"), + .WRITE_MODE_B("READ_FIRST"), .IS_CLKARDCLK_INVERTED(!CLKPOL2), .IS_CLKBWRCLK_INVERTED(!CLKPOL3), `include "brams_init_36.vh" @@ -209,8 +209,8 @@ module \$__XILINX_RAMB36_TDP (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, .READ_WIDTH_B(CFG_DBITS), .WRITE_WIDTH_A(CFG_DBITS), .WRITE_WIDTH_B(CFG_DBITS), - .WRITE_MODE_A("WRITE_FIRST"), - .WRITE_MODE_B("WRITE_FIRST"), + .WRITE_MODE_A("READ_FIRST"), + .WRITE_MODE_B("READ_FIRST"), .IS_CLKARDCLK_INVERTED(!CLKPOL2), .IS_CLKBWRCLK_INVERTED(!CLKPOL3), `include "brams_init_32.vh" @@ -285,8 +285,8 @@ module \$__XILINX_RAMB18_TDP (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, .READ_WIDTH_B(CFG_DBITS), .WRITE_WIDTH_A(CFG_DBITS), .WRITE_WIDTH_B(CFG_DBITS), - .WRITE_MODE_A("WRITE_FIRST"), - .WRITE_MODE_B("WRITE_FIRST"), + .WRITE_MODE_A("READ_FIRST"), + .WRITE_MODE_B("READ_FIRST"), .IS_CLKARDCLK_INVERTED(!CLKPOL2), .IS_CLKBWRCLK_INVERTED(!CLKPOL3), `include "brams_init_18.vh" @@ -323,8 +323,8 @@ module \$__XILINX_RAMB18_TDP (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, .READ_WIDTH_B(CFG_DBITS), .WRITE_WIDTH_A(CFG_DBITS), .WRITE_WIDTH_B(CFG_DBITS), - .WRITE_MODE_A("WRITE_FIRST"), - .WRITE_MODE_B("WRITE_FIRST"), + .WRITE_MODE_A("READ_FIRST"), + .WRITE_MODE_B("READ_FIRST"), .IS_CLKARDCLK_INVERTED(!CLKPOL2), .IS_CLKBWRCLK_INVERTED(!CLKPOL3), `include "brams_init_16.vh" From 32a901ddf21711e2b2fe2a0a8719ff7f69fd9489 Mon Sep 17 00:00:00 2001 From: Kali Prasad Date: Mon, 4 Mar 2019 23:26:56 +0530 Subject: [PATCH 42/76] Added examples/anlogic/ --- examples/anlogic/.gitignore | 4 ++++ examples/anlogic/README | 13 +++++++++++++ examples/anlogic/build.sh | 4 ++++ examples/anlogic/build.tcl | 11 +++++++++++ examples/anlogic/demo.adc | 2 ++ examples/anlogic/demo.v | 18 ++++++++++++++++++ examples/anlogic/demo.ys | 3 +++ 7 files changed, 55 insertions(+) create mode 100644 examples/anlogic/.gitignore create mode 100644 examples/anlogic/README create mode 100755 examples/anlogic/build.sh create mode 100644 examples/anlogic/build.tcl create mode 100644 examples/anlogic/demo.adc create mode 100644 examples/anlogic/demo.v create mode 100644 examples/anlogic/demo.ys diff --git a/examples/anlogic/.gitignore b/examples/anlogic/.gitignore new file mode 100644 index 000000000..fa9424cd8 --- /dev/null +++ b/examples/anlogic/.gitignore @@ -0,0 +1,4 @@ +demo.bit +demo_phy.area +full.v +*.log \ No newline at end of file diff --git a/examples/anlogic/README b/examples/anlogic/README new file mode 100644 index 000000000..99143cce0 --- /dev/null +++ b/examples/anlogic/README @@ -0,0 +1,13 @@ +LED Blink project for Anlogic Lichee Tang board. + +Follow the install instructions for the Tang Dynasty IDE from given link below. + +https://tang.sipeed.com/en/getting-started/installing-td-ide/linux/ + + +set TD_HOME env variable to the full path to the TD as follow. + +export TD_HOME= + +then run "bash build.sh" in this directory. + diff --git a/examples/anlogic/build.sh b/examples/anlogic/build.sh new file mode 100755 index 000000000..8b77a32d6 --- /dev/null +++ b/examples/anlogic/build.sh @@ -0,0 +1,4 @@ +#!/bin/bash +set -ex +yosys demo.ys +$TD_HOME/bin/td build.tcl \ No newline at end of file diff --git a/examples/anlogic/build.tcl b/examples/anlogic/build.tcl new file mode 100644 index 000000000..db8c3b347 --- /dev/null +++ b/examples/anlogic/build.tcl @@ -0,0 +1,11 @@ +import_device eagle_s20.db -package BG256 +read_verilog full.v -top demo +read_adc demo.adc +optimize_rtl +map_macro +map +pack +place +route +report_area -io_info -file demo_phy.area +bitgen -bit demo.bit -version 0X00 -g ucode:00000000000000000000000000000000 diff --git a/examples/anlogic/demo.adc b/examples/anlogic/demo.adc new file mode 100644 index 000000000..c8fbaed3e --- /dev/null +++ b/examples/anlogic/demo.adc @@ -0,0 +1,2 @@ +set_pin_assignment {CLK_IN} { LOCATION = K14; } ##24MHZ +set_pin_assignment {R_LED} { LOCATION = R3; } ##R_LED \ No newline at end of file diff --git a/examples/anlogic/demo.v b/examples/anlogic/demo.v new file mode 100644 index 000000000..a7edf4e37 --- /dev/null +++ b/examples/anlogic/demo.v @@ -0,0 +1,18 @@ +module demo ( + input wire CLK_IN, + output wire R_LED +); + parameter time1 = 30'd12_000_000; + reg led_state; + reg [29:0] count; + + always @(posedge CLK_IN)begin + if(count == time1)begin + count<= 30'd0; + led_state <= ~led_state; + end + else + count <= count + 1'b1; + end + assign R_LED = led_state; +endmodule \ No newline at end of file diff --git a/examples/anlogic/demo.ys b/examples/anlogic/demo.ys new file mode 100644 index 000000000..5687bcd31 --- /dev/null +++ b/examples/anlogic/demo.ys @@ -0,0 +1,3 @@ +read_verilog demo.v +synth_anlogic -top demo +write_verilog full.v \ No newline at end of file From d6c4dfb9020ee19eebe3adadca89b65627184d81 Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Mon, 4 Mar 2019 13:23:58 -0800 Subject: [PATCH 43/76] Ensure fid() calls make_id() for consistency; tests/simple/dff_init.v fails Mark dff_init.v as expected to fail since it uses "initial value". --- backends/firrtl/firrtl.cc | 3 +-- tests/simple/xfirrtl | 1 + 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/backends/firrtl/firrtl.cc b/backends/firrtl/firrtl.cc index 88c1038b7..eef6401b2 100644 --- a/backends/firrtl/firrtl.cc +++ b/backends/firrtl/firrtl.cc @@ -165,8 +165,7 @@ struct FirrtlWorker std::string fid(RTLIL::IdString internal_id) { - const char *str = internal_id.c_str(); - return *str == '\\' ? str + 1 : str; + return make_id(internal_id); } std::string cellname(RTLIL::Cell *cell) diff --git a/tests/simple/xfirrtl b/tests/simple/xfirrtl index 5bc75347b..50d693513 100644 --- a/tests/simple/xfirrtl +++ b/tests/simple/xfirrtl @@ -1,6 +1,7 @@ # This file contains the names of verilog files to exclude from verilog to FIRRTL regression tests due to known failures. arraycells.v inst id[0] of dff_different_styles.v +dff_init.v Initial value not supported generate.v combinational loop hierdefparam.v inst id[0] of i2c_master_tests.v $adff From 13844c765818b5d8c0d16d62dcc530f688d2c28a Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 5 Mar 2019 15:16:13 -0800 Subject: [PATCH 44/76] Use "write_edif -pvector bra" for Xilinx EDIF files Signed-off-by: Clifford Wolf --- techlibs/xilinx/synth_xilinx.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 6c11d885d..3632f348f 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -252,7 +252,7 @@ struct SynthXilinxPass : public Pass if (check_label(active, run_from, run_to, "edif")) { if (!edif_file.empty()) - Pass::call(design, stringf("write_edif %s", edif_file.c_str())); + Pass::call(design, stringf("write_edif -pvector bra %s", edif_file.c_str())); } if (check_label(active, run_from, run_to, "blif")) { From 3ef427f4a96ac8f890cf94079315e172db409526 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 5 Mar 2019 15:21:04 -0800 Subject: [PATCH 45/76] Add missing newline Signed-off-by: Clifford Wolf --- examples/anlogic/build.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/anlogic/build.sh b/examples/anlogic/build.sh index 8b77a32d6..e0f6b4cfe 100755 --- a/examples/anlogic/build.sh +++ b/examples/anlogic/build.sh @@ -1,4 +1,4 @@ #!/bin/bash set -ex yosys demo.ys -$TD_HOME/bin/td build.tcl \ No newline at end of file +$TD_HOME/bin/td build.tcl From 24d1b92eda20269da7ee7ae713f3ab92b8865349 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 5 Mar 2019 17:27:58 -0800 Subject: [PATCH 46/76] Improve igloo2 exmaple Signed-off-by: Clifford Wolf --- examples/igloo2/example.pdc | 7 +++++++ examples/igloo2/example.sdc | 1 + examples/igloo2/example.v | 12 ++++++------ examples/igloo2/libero.tcl | 4 ++-- 4 files changed, 16 insertions(+), 8 deletions(-) diff --git a/examples/igloo2/example.pdc b/examples/igloo2/example.pdc index e6ffd53db..0cf34adb3 100644 --- a/examples/igloo2/example.pdc +++ b/examples/igloo2/example.pdc @@ -1 +1,8 @@ # Add placement constraints here +set_io clk -pinname H16 -fixed yes -DIRECTION INPUT +set_io SW1 -pinname H12 -fixed yes -DIRECTION INPUT +set_io SW2 -pinname H13 -fixed yes -DIRECTION INPUT +set_io LED1 -pinname J16 -fixed yes -DIRECTION OUTPUT +set_io LED2 -pinname M16 -fixed yes -DIRECTION OUTPUT +set_io LED3 -pinname K16 -fixed yes -DIRECTION OUTPUT +set_io LED4 -pinname N16 -fixed yes -DIRECTION OUTPUT diff --git a/examples/igloo2/example.sdc b/examples/igloo2/example.sdc index c6ff94161..f8b487316 100644 --- a/examples/igloo2/example.sdc +++ b/examples/igloo2/example.sdc @@ -1 +1,2 @@ # Add timing constraints here +create_clock -period 10.000 -waveform {0.000 5.000} [get_ports {clk}] diff --git a/examples/igloo2/example.v b/examples/igloo2/example.v index 1a1967d5a..b701c707d 100644 --- a/examples/igloo2/example.v +++ b/examples/igloo2/example.v @@ -1,23 +1,23 @@ module example ( input clk, - input EN, + input SW1, + input SW2, output LED1, output LED2, output LED3, - output LED4, - output LED5 + output LED4 ); - localparam BITS = 5; + localparam BITS = 4; localparam LOG2DELAY = 22; reg [BITS+LOG2DELAY-1:0] counter = 0; reg [BITS-1:0] outcnt; always @(posedge clk) begin - counter <= counter + EN; + counter <= counter + SW1 + SW2 + 1; outcnt <= counter >> LOG2DELAY; end - assign {LED1, LED2, LED3, LED4, LED5} = outcnt ^ (outcnt >> 1); + assign {LED1, LED2, LED3, LED4} = outcnt ^ (outcnt >> 1); endmodule diff --git a/examples/igloo2/libero.tcl b/examples/igloo2/libero.tcl index 6f7d4e24b..abc94e479 100644 --- a/examples/igloo2/libero.tcl +++ b/examples/igloo2/libero.tcl @@ -8,8 +8,8 @@ new_project \ -block_mode 0 \ -hdl "VERILOG" \ -family IGLOO2 \ - -die PA4MGL500 \ - -package tq144 \ + -die PA4MGL2500 \ + -package vf256 \ -speed -1 import_files -hdl_source {netlist.vm} From d03780c3f463bb8ac2c5d300ba7a591f1bc90a8f Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 5 Mar 2019 17:55:29 -0800 Subject: [PATCH 47/76] Fix spelling in pmgen/README.md --- passes/pmgen/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/passes/pmgen/README.md b/passes/pmgen/README.md index a1007dc62..223b43059 100644 --- a/passes/pmgen/README.md +++ b/passes/pmgen/README.md @@ -16,7 +16,7 @@ API of Generated Matcher ======================== When `pmgen.py` reads a `foobar.pmg` file, it writes `foobar_pm.h` containing -a class `foobar_pm`. That class is instanciated with an RTLIL module and a +a class `foobar_pm`. That class is instantiated with an RTLIL module and a list of cells from that module: foobar_pm pm(module, module->selected_cells()); @@ -142,7 +142,7 @@ The `select` lines are evaluated once for each cell when the matcher is initialized. A `match` block will only consider cells for which all `select` expressions evaluated to `true`. Note that the state variable corresponding to the match (in the example `mul`) is the only state variable that may be used -`select` lines. +in `select` lines. Index lines are using the `index expr1 === expr2` syntax. `expr1` is evaluated during matcher initialization and the same restrictions apply as for From 7c03b0b08209c7e1b3972a05db63b23c0b1d7a5e Mon Sep 17 00:00:00 2001 From: Kali Prasad Date: Wed, 6 Mar 2019 09:51:11 +0530 Subject: [PATCH 48/76] examples/anlogic/ now also output the SVF file. --- examples/anlogic/.gitignore | 5 ++++- examples/anlogic/README | 1 - examples/anlogic/build.tcl | 2 +- examples/anlogic/demo.adc | 2 +- examples/anlogic/demo.v | 10 +++++----- examples/anlogic/demo.ys | 2 +- 6 files changed, 12 insertions(+), 10 deletions(-) diff --git a/examples/anlogic/.gitignore b/examples/anlogic/.gitignore index fa9424cd8..97c978a15 100644 --- a/examples/anlogic/.gitignore +++ b/examples/anlogic/.gitignore @@ -1,4 +1,7 @@ demo.bit demo_phy.area full.v -*.log \ No newline at end of file +*.log +*.h +*.tde +*.svf diff --git a/examples/anlogic/README b/examples/anlogic/README index 99143cce0..35d8e9cb1 100644 --- a/examples/anlogic/README +++ b/examples/anlogic/README @@ -10,4 +10,3 @@ set TD_HOME env variable to the full path to the TD as fo export TD_HOME= then run "bash build.sh" in this directory. - diff --git a/examples/anlogic/build.tcl b/examples/anlogic/build.tcl index db8c3b347..06db525c9 100644 --- a/examples/anlogic/build.tcl +++ b/examples/anlogic/build.tcl @@ -8,4 +8,4 @@ pack place route report_area -io_info -file demo_phy.area -bitgen -bit demo.bit -version 0X00 -g ucode:00000000000000000000000000000000 +bitgen -bit demo.bit -version 0X0000 -svf demo.svf -svf_comment_on -g ucode:00000000000000000000000000000000 diff --git a/examples/anlogic/demo.adc b/examples/anlogic/demo.adc index c8fbaed3e..ec802502e 100644 --- a/examples/anlogic/demo.adc +++ b/examples/anlogic/demo.adc @@ -1,2 +1,2 @@ set_pin_assignment {CLK_IN} { LOCATION = K14; } ##24MHZ -set_pin_assignment {R_LED} { LOCATION = R3; } ##R_LED \ No newline at end of file +set_pin_assignment {R_LED} { LOCATION = R3; } ##R_LED diff --git a/examples/anlogic/demo.v b/examples/anlogic/demo.v index a7edf4e37..e17db771e 100644 --- a/examples/anlogic/demo.v +++ b/examples/anlogic/demo.v @@ -1,18 +1,18 @@ module demo ( - input wire CLK_IN, - output wire R_LED + input wire CLK_IN, + output wire R_LED ); parameter time1 = 30'd12_000_000; reg led_state; reg [29:0] count; - + always @(posedge CLK_IN)begin if(count == time1)begin - count<= 30'd0; + count<= 30'd0; led_state <= ~led_state; end else count <= count + 1'b1; end assign R_LED = led_state; -endmodule \ No newline at end of file +endmodule diff --git a/examples/anlogic/demo.ys b/examples/anlogic/demo.ys index 5687bcd31..cb396cc2b 100644 --- a/examples/anlogic/demo.ys +++ b/examples/anlogic/demo.ys @@ -1,3 +1,3 @@ read_verilog demo.v synth_anlogic -top demo -write_verilog full.v \ No newline at end of file +write_verilog full.v From da5181a3df6ceed96f1762e4cdaec5cbe3ea23db Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 5 Mar 2019 19:49:39 -0800 Subject: [PATCH 49/76] Improvements in SF2 flow and demo Signed-off-by: Clifford Wolf --- examples/igloo2/.gitignore | 1 + examples/igloo2/runme.sh | 2 +- techlibs/sf2/sf2_iobs.cc | 15 ++++++++++----- techlibs/sf2/synth_sf2.cc | 16 +++++++++++++--- 4 files changed, 25 insertions(+), 9 deletions(-) diff --git a/examples/igloo2/.gitignore b/examples/igloo2/.gitignore index ea58efc9f..33b7182d3 100644 --- a/examples/igloo2/.gitignore +++ b/examples/igloo2/.gitignore @@ -1,3 +1,4 @@ /netlist.edn /netlist.vm +/example.stp /proj diff --git a/examples/igloo2/runme.sh b/examples/igloo2/runme.sh index a08894e0a..838f027db 100644 --- a/examples/igloo2/runme.sh +++ b/examples/igloo2/runme.sh @@ -1,6 +1,6 @@ #!/bin/bash set -ex -yosys -p 'synth_sf2 -top example -edif netlist.edn -vlog netlist.vm' example.v +yosys -p 'synth_sf2 -noclkbuf -top example -edif netlist.edn -vlog netlist.vm' example.v export LM_LICENSE_FILE=${LM_LICENSE_FILE:-1702@localhost} /opt/microsemi/Libero_SoC_v12.0/Libero/bin/libero SCRIPT:libero.tcl cp proj/designer/example/export/example.stp . diff --git a/techlibs/sf2/sf2_iobs.cc b/techlibs/sf2/sf2_iobs.cc index 27141430c..a85552575 100644 --- a/techlibs/sf2/sf2_iobs.cc +++ b/techlibs/sf2/sf2_iobs.cc @@ -33,18 +33,23 @@ struct Sf2IobsPass : public Pass { log("\n"); log("Add SF2 I/O buffers to top module IOs as needed.\n"); log("\n"); + log(" -noclkbuf\n"); + log(" Do not insert clock buffers\n"); + log("\n"); } void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { + bool noclkbuf_mode = false; + log_header(design, "Executing sf2_iobs pass (insert IO buffers).\n"); size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) { - // if (args[argidx] == "-singleton") { - // singleton_mode = true; - // continue; - // } + if (args[argidx] == "-noclkbuf") { + noclkbuf_mode = true; + continue; + } break; } extra_args(args, argidx, design); @@ -94,7 +99,7 @@ struct Sf2IobsPass : public Pass { if (wire->port_output) { buf_type = "\\OUTBUF"; buf_port = "\\D"; - } else if (clk_bits.count(canonical_bit)) { + } else if (clk_bits.count(canonical_bit) && !noclkbuf_mode) { buf_type = "\\CLKBUF"; buf_port = "\\Y"; } else { diff --git a/techlibs/sf2/synth_sf2.cc b/techlibs/sf2/synth_sf2.cc index bdc20456d..b834af07d 100644 --- a/techlibs/sf2/synth_sf2.cc +++ b/techlibs/sf2/synth_sf2.cc @@ -63,6 +63,9 @@ struct SynthSf2Pass : public ScriptPass log(" -noiobs\n"); log(" run synthesis in \"block mode\", i.e. do not insert IO buffers\n"); log("\n"); + log(" -noclkbuf\n"); + log(" do not inser clock buffers, only simpe IO buffers\n"); + log("\n"); log(" -retime\n"); log(" run 'abc' with -dff option\n"); log("\n"); @@ -73,7 +76,7 @@ struct SynthSf2Pass : public ScriptPass } string top_opt, edif_file, vlog_file, json_file; - bool flatten, retime, iobs; + bool flatten, retime, iobs, clkbuf; void clear_flags() YS_OVERRIDE { @@ -84,6 +87,7 @@ struct SynthSf2Pass : public ScriptPass flatten = true; retime = false; iobs = true; + clkbuf = true; } void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE @@ -130,6 +134,10 @@ struct SynthSf2Pass : public ScriptPass iobs = false; continue; } + if (args[argidx] == "-noclkbuf") { + clkbuf = false; + continue; + } break; } extra_args(args, argidx, design); @@ -201,8 +209,10 @@ struct SynthSf2Pass : public ScriptPass if (check_label("map_iobs")) { - if (iobs || help_mode) - run("sf2_iobs", "(unless -noiobs)"); + if (help_mode) + run("sf2_iobs [-noclkbuf]", "(unless -noiobs)"); + else if (iobs) + run(clkbuf ? "sf2_iobs" : "sf2_iobs -noclkbuf"); run("clean"); } From e22afeae907e6340aac7797f60c309916fd72097 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 5 Mar 2019 20:35:48 -0800 Subject: [PATCH 50/76] Improve igloo2 example Signed-off-by: Clifford Wolf --- examples/igloo2/example.pdc | 12 ++++++++++ examples/igloo2/example.v | 44 +++++++++++++++++++++++++++++++++++-- 2 files changed, 54 insertions(+), 2 deletions(-) diff --git a/examples/igloo2/example.pdc b/examples/igloo2/example.pdc index 0cf34adb3..298d9e934 100644 --- a/examples/igloo2/example.pdc +++ b/examples/igloo2/example.pdc @@ -1,8 +1,20 @@ # Add placement constraints here + set_io clk -pinname H16 -fixed yes -DIRECTION INPUT + set_io SW1 -pinname H12 -fixed yes -DIRECTION INPUT set_io SW2 -pinname H13 -fixed yes -DIRECTION INPUT + set_io LED1 -pinname J16 -fixed yes -DIRECTION OUTPUT set_io LED2 -pinname M16 -fixed yes -DIRECTION OUTPUT set_io LED3 -pinname K16 -fixed yes -DIRECTION OUTPUT set_io LED4 -pinname N16 -fixed yes -DIRECTION OUTPUT + +set_io AA -pinname L12 -fixed yes -DIRECTION OUTPUT +set_io AB -pinname L13 -fixed yes -DIRECTION OUTPUT +set_io AC -pinname M13 -fixed yes -DIRECTION OUTPUT +set_io AD -pinname N15 -fixed yes -DIRECTION OUTPUT +set_io AE -pinname L11 -fixed yes -DIRECTION OUTPUT +set_io AF -pinname L14 -fixed yes -DIRECTION OUTPUT +set_io AG -pinname N14 -fixed yes -DIRECTION OUTPUT +set_io CA -pinname M15 -fixed yes -DIRECTION OUTPUT diff --git a/examples/igloo2/example.v b/examples/igloo2/example.v index b701c707d..05b6ced5e 100644 --- a/examples/igloo2/example.v +++ b/examples/igloo2/example.v @@ -5,10 +5,13 @@ module example ( output LED1, output LED2, output LED3, - output LED4 + output LED4, + + output AA, AB, AC, AD, + output AE, AF, AG, CA ); - localparam BITS = 4; + localparam BITS = 8; localparam LOG2DELAY = 22; reg [BITS+LOG2DELAY-1:0] counter = 0; @@ -20,4 +23,41 @@ module example ( end assign {LED1, LED2, LED3, LED4} = outcnt ^ (outcnt >> 1); + + // seg7enc seg7encinst ( + // .seg({AA, AB, AC, AD, AE, AF, AG}), + // .dat(CA ? outcnt[3:0] : outcnt[7:4]) + // ); + + assign {AA, AB, AC, AD, AE, AF, AG} = ~(7'b 100_0000 >> outcnt[7:4]); + assign CA = counter[10]; +endmodule + +module seg7enc ( + input [3:0] dat, + output [6:0] seg +); + reg [6:0] seg_inv; + always @* begin + seg_inv = 0; + case (dat) + 4'h0: seg_inv = 7'b 0111111; + 4'h1: seg_inv = 7'b 0000110; + 4'h2: seg_inv = 7'b 1011011; + 4'h3: seg_inv = 7'b 1001111; + 4'h4: seg_inv = 7'b 1100110; + 4'h5: seg_inv = 7'b 1101101; + 4'h6: seg_inv = 7'b 1111101; + 4'h7: seg_inv = 7'b 0000111; + 4'h8: seg_inv = 7'b 1111111; + 4'h9: seg_inv = 7'b 1101111; + 4'hA: seg_inv = 7'b 1110111; + 4'hB: seg_inv = 7'b 1111100; + 4'hC: seg_inv = 7'b 0111001; + 4'hD: seg_inv = 7'b 1011110; + 4'hE: seg_inv = 7'b 1111001; + 4'hF: seg_inv = 7'b 1110001; + endcase + end + assign seg = ~seg_inv; endmodule From b1b9edf5cc9e280346ffa0132d570a8ff656eb22 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 5 Mar 2019 20:47:07 -0800 Subject: [PATCH 51/76] Improve igloo2 example Signed-off-by: Clifford Wolf --- examples/igloo2/example.v | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/examples/igloo2/example.v b/examples/igloo2/example.v index 05b6ced5e..4a9486e50 100644 --- a/examples/igloo2/example.v +++ b/examples/igloo2/example.v @@ -24,13 +24,14 @@ module example ( assign {LED1, LED2, LED3, LED4} = outcnt ^ (outcnt >> 1); + // assign CA = counter[10]; // seg7enc seg7encinst ( // .seg({AA, AB, AC, AD, AE, AF, AG}), // .dat(CA ? outcnt[3:0] : outcnt[7:4]) // ); - assign {AA, AB, AC, AD, AE, AF, AG} = ~(7'b 100_0000 >> outcnt[7:4]); - assign CA = counter[10]; + assign {AA, AB, AC, AD, AE, AF, AG} = ~(7'b 100_0000 >> outcnt[6:4]); + assign CA = outcnt[7]; endmodule module seg7enc ( From 78762316aabf6d6fb55cfd4ab5b5a161a69ba203 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 6 Mar 2019 00:41:02 -0800 Subject: [PATCH 52/76] Refactor SF2 iobuf insertion, Add clkint insertion Signed-off-by: Clifford Wolf --- examples/igloo2/runme.sh | 2 +- techlibs/sf2/cells_sim.v | 7 ++ techlibs/sf2/sf2_iobs.cc | 214 ++++++++++++++++++++++++-------------- techlibs/sf2/synth_sf2.cc | 14 +-- 4 files changed, 153 insertions(+), 84 deletions(-) diff --git a/examples/igloo2/runme.sh b/examples/igloo2/runme.sh index 838f027db..a08894e0a 100644 --- a/examples/igloo2/runme.sh +++ b/examples/igloo2/runme.sh @@ -1,6 +1,6 @@ #!/bin/bash set -ex -yosys -p 'synth_sf2 -noclkbuf -top example -edif netlist.edn -vlog netlist.vm' example.v +yosys -p 'synth_sf2 -top example -edif netlist.edn -vlog netlist.vm' example.v export LM_LICENSE_FILE=${LM_LICENSE_FILE:-1702@localhost} /opt/microsemi/Libero_SoC_v12.0/Libero/bin/libero SCRIPT:libero.tcl cp proj/designer/example/export/example.stp . diff --git a/techlibs/sf2/cells_sim.v b/techlibs/sf2/cells_sim.v index f967068af..b49101616 100644 --- a/techlibs/sf2/cells_sim.v +++ b/techlibs/sf2/cells_sim.v @@ -74,6 +74,13 @@ module CFG4 ( assign Y = INIT >> {D, C, B, A}; endmodule +module CLKINT ( + input A, + output Y +); + assign Y = A; +endmodule + module CLKBUF ( input PAD, output Y diff --git a/techlibs/sf2/sf2_iobs.cc b/techlibs/sf2/sf2_iobs.cc index a85552575..dea8e353b 100644 --- a/techlibs/sf2/sf2_iobs.cc +++ b/techlibs/sf2/sf2_iobs.cc @@ -23,6 +23,136 @@ USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN +static void handle_iobufs(Module *module, bool clkbuf_mode) +{ + SigMap sigmap(module); + + pool clk_bits; + pool handled_io_bits; + dict rewrite_bits; + vector> pad_bits; + + for (auto cell : module->cells()) + { + if (clkbuf_mode && cell->type == "\\SLE") { + for (auto bit : sigmap(cell->getPort("\\CLK"))) + clk_bits.insert(bit); + } + if (cell->type.in("\\INBUF", "\\OUTBUF", "\\TRIBUF", "\\BIBUF", "\\CLKBUF", "\\CLKBIBUF", + "\\INBUF_DIFF", "\\OUTBUF_DIFF", "\\BIBUFF_DIFF", "\\TRIBUF_DIFF", "\\CLKBUF_DIFF", + "\\GCLKBUF", "\\GCLKBUF_DIFF", "\\GCLKBIBUF")) { + for (auto bit : sigmap(cell->getPort("\\PAD"))) + handled_io_bits.insert(bit); + } + } + + for (auto wire : vector(module->wires())) + { + if (!wire->port_input && !wire->port_output) + continue; + + for (int index = 0; index < GetSize(wire); index++) + { + SigBit bit(wire, index); + SigBit canonical_bit = sigmap(bit); + + if (handled_io_bits.count(canonical_bit)) + continue; + + if (wire->port_input && wire->port_output) + log_error("Failed to add buffer for inout port bit %s.\n", log_signal(bit)); + + IdString buf_type, buf_port; + + if (wire->port_output) { + buf_type = "\\OUTBUF"; + buf_port = "\\D"; + } else if (clkbuf_mode && clk_bits.count(canonical_bit)) { + buf_type = "\\CLKBUF"; + buf_port = "\\Y"; + } else { + buf_type = "\\INBUF"; + buf_port = "\\Y"; + } + + Cell *c = module->addCell(NEW_ID, buf_type); + SigBit new_bit = module->addWire(NEW_ID); + c->setPort(buf_port, new_bit); + pad_bits.push_back(make_pair(c, bit)); + rewrite_bits[canonical_bit] = new_bit; + + log("Added %s cell %s for port bit %s.\n", log_id(c->type), log_id(c), log_signal(bit)); + } + } + + auto rewrite_function = [&](SigSpec &s) { + for (auto &bit : s) { + SigBit canonical_bit = sigmap(bit); + if (rewrite_bits.count(canonical_bit)) + bit = rewrite_bits.at(canonical_bit); + } + }; + + module->rewrite_sigspecs(rewrite_function); + + for (auto &it : pad_bits) + it.first->setPort("\\PAD", it.second); +} + +static void handle_clkint(Module *module) +{ + SigMap sigmap(module); + + pool clk_bits; + vector handled_clk_bits; + + for (auto cell : module->cells()) + { + if (cell->type == "\\SLE") { + for (auto bit : sigmap(cell->getPort("\\CLK"))) + clk_bits.insert(bit); + } + if (cell->type.in("\\CLKBUF", "\\CLKBIBUF", "\\CLKBUF_DIFF", "\\GCLKBUF", "\\GCLKBUF_DIFF", "\\GCLKBIBUF", + "\\CLKINT", "\\CLKINT_PRESERVE", "\\GCLKINT", "\\RCLKINT", "\\RGCLKINT")) { + for (auto bit : sigmap(cell->getPort("\\Y"))) + handled_clk_bits.push_back(bit); + } + } + + for (auto bit : handled_clk_bits) + clk_bits.erase(bit); + + for (auto cell : vector(module->cells())) + for (auto &conn : cell->connections()) + { + if (!cell->output(conn.first)) + continue; + + SigSpec sig = conn.second; + bool did_something = false; + + for (auto &bit : sig) { + SigBit canonical_bit = sigmap(bit); + if (clk_bits.count(canonical_bit)) { + Cell *c = module->addCell(NEW_ID, "\\CLKINT"); + SigBit new_bit = module->addWire(NEW_ID); + c->setPort("\\A", new_bit); + c->setPort("\\Y", bit); + log("Added %s cell %s for clock signal %s.\n", log_id(c->type), log_id(c), log_signal(bit)); + clk_bits.erase(canonical_bit); + did_something = true; + bit = new_bit; + } + } + + if (did_something) + cell->setPort(conn.first, sig); + } + + for (auto bit : clk_bits) + log_error("Failed to insert CLKINT for clock signal %s.\n", log_signal(bit)); +} + struct Sf2IobsPass : public Pass { Sf2IobsPass() : Pass("sf2_iobs", "SF2: insert IO buffers") { } void help() YS_OVERRIDE @@ -31,23 +161,23 @@ struct Sf2IobsPass : public Pass { log("\n"); log(" sf2_iobs [options] [selection]\n"); log("\n"); - log("Add SF2 I/O buffers to top module IOs as needed.\n"); + log("Add SF2 I/O buffers and global buffers to top module as needed.\n"); log("\n"); - log(" -noclkbuf\n"); - log(" Do not insert clock buffers\n"); + log(" -clkbuf\n"); + log(" Insert PAD->global_net clock buffers\n"); log("\n"); } void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { - bool noclkbuf_mode = false; + bool clkbuf_mode = false; log_header(design, "Executing sf2_iobs pass (insert IO buffers).\n"); size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) { - if (args[argidx] == "-noclkbuf") { - noclkbuf_mode = true; + if (args[argidx] == "-clkbuf") { + clkbuf_mode = true; continue; } break; @@ -59,76 +189,8 @@ struct Sf2IobsPass : public Pass { if (module == nullptr) log_cmd_error("No top module found.\n"); - SigMap sigmap(module); - - pool clk_bits; - pool handled_io_bits; - dict rewrite_bits; - vector> pad_bits; - - for (auto cell : module->cells()) - { - if (cell->type == "\\SLE") { - for (auto bit : sigmap(cell->getPort("\\CLK"))) - clk_bits.insert(bit); - } - if (cell->type.in("\\INBUF", "\\OUTBUF", "\\CLKBUF")) { - for (auto bit : sigmap(cell->getPort("\\PAD"))) - handled_io_bits.insert(bit); - } - } - - for (auto wire : vector(module->wires())) - { - if (!wire->port_input && !wire->port_output) - continue; - - for (int index = 0; index < GetSize(wire); index++) - { - SigBit bit(wire, index); - SigBit canonical_bit = sigmap(bit); - - if (handled_io_bits.count(canonical_bit)) - continue; - - if (wire->port_input && wire->port_output) - log_error("Failed to add buffer for inout port bit %s.\n", log_signal(bit)); - - IdString buf_type, buf_port; - - if (wire->port_output) { - buf_type = "\\OUTBUF"; - buf_port = "\\D"; - } else if (clk_bits.count(canonical_bit) && !noclkbuf_mode) { - buf_type = "\\CLKBUF"; - buf_port = "\\Y"; - } else { - buf_type = "\\INBUF"; - buf_port = "\\Y"; - } - - Cell *c = module->addCell(NEW_ID, buf_type); - SigBit new_bit = module->addWire(NEW_ID); - c->setPort(buf_port, new_bit); - pad_bits.push_back(make_pair(c, bit)); - rewrite_bits[canonical_bit] = new_bit; - - log("Added %s cell %s for port bit %s.\n", log_id(c->type), log_id(c), log_signal(bit)); - } - } - - auto rewrite_function = [&](SigSpec &s) { - for (auto &bit : s) { - SigBit canonical_bit = sigmap(bit); - if (rewrite_bits.count(canonical_bit)) - bit = rewrite_bits.at(canonical_bit); - } - }; - - module->rewrite_sigspecs(rewrite_function); - - for (auto &it : pad_bits) - it.first->setPort("\\PAD", it.second); + handle_iobufs(module, clkbuf_mode); + handle_clkint(module); } } Sf2IobsPass; diff --git a/techlibs/sf2/synth_sf2.cc b/techlibs/sf2/synth_sf2.cc index b834af07d..0924df7a6 100644 --- a/techlibs/sf2/synth_sf2.cc +++ b/techlibs/sf2/synth_sf2.cc @@ -63,8 +63,8 @@ struct SynthSf2Pass : public ScriptPass log(" -noiobs\n"); log(" run synthesis in \"block mode\", i.e. do not insert IO buffers\n"); log("\n"); - log(" -noclkbuf\n"); - log(" do not inser clock buffers, only simpe IO buffers\n"); + log(" -clkbuf\n"); + log(" insert direct PAD->global_net buffers\n"); log("\n"); log(" -retime\n"); log(" run 'abc' with -dff option\n"); @@ -87,7 +87,7 @@ struct SynthSf2Pass : public ScriptPass flatten = true; retime = false; iobs = true; - clkbuf = true; + clkbuf = false; } void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE @@ -134,8 +134,8 @@ struct SynthSf2Pass : public ScriptPass iobs = false; continue; } - if (args[argidx] == "-noclkbuf") { - clkbuf = false; + if (args[argidx] == "-clkbuf") { + clkbuf = true; continue; } break; @@ -210,9 +210,9 @@ struct SynthSf2Pass : public ScriptPass if (check_label("map_iobs")) { if (help_mode) - run("sf2_iobs [-noclkbuf]", "(unless -noiobs)"); + run("sf2_iobs [-clkbuf]", "(unless -noiobs)"); else if (iobs) - run(clkbuf ? "sf2_iobs" : "sf2_iobs -noclkbuf"); + run(clkbuf ? "sf2_iobs -clkbuf" : "sf2_iobs"); run("clean"); } From 2d2c1617ee3015368336ceb014a9cd98c60181ed Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 6 Mar 2019 15:47:54 -0800 Subject: [PATCH 53/76] Add sf2 techmap rules for more FF types Signed-off-by: Clifford Wolf --- techlibs/sf2/cells_map.v | 64 ++++++++++++++++++++++++---------------- 1 file changed, 39 insertions(+), 25 deletions(-) diff --git a/techlibs/sf2/cells_map.v b/techlibs/sf2/cells_map.v index 5b8888294..6ad7807d2 100644 --- a/techlibs/sf2/cells_map.v +++ b/techlibs/sf2/cells_map.v @@ -1,40 +1,54 @@ -// module \$_DFF_N_ (input D, C, output Q); SB_DFFN _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C)); endmodule +module \$_DFF_N_ (input D, C, output Q); + SLE _TECHMAP_REPLACE_ (.D(D), .CLK(!C), .EN(1'b1), .ALn(1'b1), .ADn(1'b1), .SLn(1'b1), .SD(1'b0), .LAT(1'b0), .Q(Q)); +endmodule module \$_DFF_P_ (input D, C, output Q); - SLE _TECHMAP_REPLACE_ ( - .D(D), - .CLK(C), - .EN(1'b1), - .ALn(1'b1), - .ADn(1'b1), - .SLn(1'b1), - .SD(1'b0), - .LAT(1'b0), - .Q(Q) - ); + SLE _TECHMAP_REPLACE_ (.D(D), .CLK(C), .EN(1'b1), .ALn(1'b1), .ADn(1'b1), .SLn(1'b1), .SD(1'b0), .LAT(1'b0), .Q(Q)); +endmodule + +module \$_DFF_NN0_ (input D, C, R, output Q); + SLE _TECHMAP_REPLACE_ (.D(D), .CLK(!C), .EN(1'b1), .ALn(R), .ADn(1'b1), .SLn(1'b1), .SD(1'b0), .LAT(1'b0), .Q(Q)); +endmodule + +module \$_DFF_NN1_ (input D, C, R, output Q); + SLE _TECHMAP_REPLACE_ (.D(D), .CLK(!C), .EN(1'b1), .ALn(R), .ADn(1'b0), .SLn(1'b1), .SD(1'b0), .LAT(1'b0), .Q(Q)); +endmodule + +module \$_DFF_NP0_ (input D, C, R, output Q); + SLE _TECHMAP_REPLACE_ (.D(D), .CLK(!C), .EN(1'b1), .ALn(!R), .ADn(1'b1), .SLn(1'b1), .SD(1'b0), .LAT(1'b0), .Q(Q)); +endmodule + +module \$_DFF_NP1_ (input D, C, R, output Q); + SLE _TECHMAP_REPLACE_ (.D(D), .CLK(!C), .EN(1'b1), .ALn(!R), .ADn(1'b0), .SLn(1'b1), .SD(1'b0), .LAT(1'b0), .Q(Q)); +endmodule + +module \$_DFF_PN0_ (input D, C, R, output Q); + SLE _TECHMAP_REPLACE_ (.D(D), .CLK(C), .EN(1'b1), .ALn(R), .ADn(1'b1), .SLn(1'b1), .SD(1'b0), .LAT(1'b0), .Q(Q)); +endmodule + +module \$_DFF_PN1_ (input D, C, R, output Q); + SLE _TECHMAP_REPLACE_ (.D(D), .CLK(C), .EN(1'b1), .ALn(R), .ADn(1'b0), .SLn(1'b1), .SD(1'b0), .LAT(1'b0), .Q(Q)); +endmodule + +module \$_DFF_PP0_ (input D, C, R, output Q); + SLE _TECHMAP_REPLACE_ (.D(D), .CLK(C), .EN(1'b1), .ALn(!R), .ADn(1'b1), .SLn(1'b1), .SD(1'b0), .LAT(1'b0), .Q(Q)); +endmodule + +module \$_DFF_PP1_ (input D, C, R, output Q); + SLE _TECHMAP_REPLACE_ (.D(D), .CLK(C), .EN(1'b1), .ALn(!R), .ADn(1'b0), .SLn(1'b1), .SD(1'b0), .LAT(1'b0), .Q(Q)); endmodule // module \$_DFFE_NN_ (input D, C, E, output Q); SB_DFFNE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(!E)); endmodule // module \$_DFFE_PN_ (input D, C, E, output Q); SB_DFFE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(!E)); endmodule -// +// // module \$_DFFE_NP_ (input D, C, E, output Q); SB_DFFNE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E)); endmodule // module \$_DFFE_PP_ (input D, C, E, output Q); SB_DFFE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E)); endmodule -// -// module \$_DFF_NN0_ (input D, C, R, output Q); SB_DFFNR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(!R)); endmodule -// module \$_DFF_NN1_ (input D, C, R, output Q); SB_DFFNS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .S(!R)); endmodule -// module \$_DFF_PN0_ (input D, C, R, output Q); SB_DFFR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(!R)); endmodule -// module \$_DFF_PN1_ (input D, C, R, output Q); SB_DFFS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .S(!R)); endmodule -// -// module \$_DFF_NP0_ (input D, C, R, output Q); SB_DFFNR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(R)); endmodule -// module \$_DFF_NP1_ (input D, C, R, output Q); SB_DFFNS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .S(R)); endmodule -// module \$_DFF_PP0_ (input D, C, R, output Q); SB_DFFR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(R)); endmodule -// module \$_DFF_PP1_ (input D, C, R, output Q); SB_DFFS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .S(R)); endmodule -// +// // module \$__DFFE_NN0 (input D, C, E, R, output Q); SB_DFFNER _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .R(!R)); endmodule // module \$__DFFE_NN1 (input D, C, E, R, output Q); SB_DFFNES _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .S(!R)); endmodule // module \$__DFFE_PN0 (input D, C, E, R, output Q); SB_DFFER _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .R(!R)); endmodule // module \$__DFFE_PN1 (input D, C, E, R, output Q); SB_DFFES _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .S(!R)); endmodule -// +// // module \$__DFFE_NP0 (input D, C, E, R, output Q); SB_DFFNER _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .R(R)); endmodule // module \$__DFFE_NP1 (input D, C, E, R, output Q); SB_DFFNES _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .S(R)); endmodule // module \$__DFFE_PP0 (input D, C, E, R, output Q); SB_DFFER _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .R(R)); endmodule From 8b0719d1e328751a50c0c07ec1fc65884fd119fc Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 6 Mar 2019 16:18:49 -0800 Subject: [PATCH 54/76] Improvements in sf2 cells_sim.v Signed-off-by: Clifford Wolf --- techlibs/sf2/cells_sim.v | 297 ++++++++++++++++++++++++++++++++++----- techlibs/sf2/sf2_iobs.cc | 4 +- 2 files changed, 261 insertions(+), 40 deletions(-) diff --git a/techlibs/sf2/cells_sim.v b/techlibs/sf2/cells_sim.v index b49101616..f3f7695cf 100644 --- a/techlibs/sf2/cells_sim.v +++ b/techlibs/sf2/cells_sim.v @@ -1,41 +1,3 @@ -module SLE ( - output Q, - input ADn, - input ALn, - input CLK, - input D, - input LAT, - input SD, - input EN, - input SLn -); - reg q_latch, q_ff; - - always @(posedge CLK, negedge ALn) begin - if (!ALn) begin - q_ff <= !ADn; - end else if (EN) begin - if (!SLn) - q_ff <= SD; - else - q_ff <= D; - end - end - - always @* begin - if (!ALn) begin - q_latch <= !ADn; - end else if (CLK && EN) begin - if (!SLn) - q_ff <= SD; - else - q_ff <= D; - end - end - - assign Q = LAT ? q_latch : q_ff; -endmodule - module CFG1 ( output Y, input A @@ -74,6 +36,41 @@ module CFG4 ( assign Y = INIT >> {D, C, B, A}; endmodule +module ADD2 ( + input A, B, + output Y +); + assign Y = A & B; +endmodule + +module ADD3 ( + input A, B, C, + output Y +); + assign Y = A & B & C; +endmodule + +module ADD4 ( + input A, B, C, D, + output Y +); + assign Y = A & B & C & D; +endmodule + +module BUFF ( + input A, + output Y +); + assign Y = A; +endmodule + +module BUFD ( + input A, + output Y +); + assign Y = A; +endmodule + module CLKINT ( input A, output Y @@ -81,6 +78,217 @@ module CLKINT ( assign Y = A; endmodule +module CLKINT_PRESERVE ( + input A, + output Y +); + assign Y = A; +endmodule + +module GCLKINT ( + input A, EN, + output Y +); + assign Y = A & EN; +endmodule + +module RCLKINT ( + input A, + output Y +); + assign Y = A; +endmodule + +module RGCLKINT ( + input A, EN, + output Y +); + assign Y = A & EN; +endmodule + +module SLE ( + output Q, + input ADn, + input ALn, + input CLK, + input D, + input LAT, + input SD, + input EN, + input SLn +); + reg q_latch, q_ff; + + always @(posedge CLK, negedge ALn) begin + if (!ALn) begin + q_ff <= !ADn; + end else if (EN) begin + if (!SLn) + q_ff <= SD; + else + q_ff <= D; + end + end + + always @* begin + if (!ALn) begin + q_latch <= !ADn; + end else if (CLK && EN) begin + if (!SLn) + q_ff <= SD; + else + q_ff <= D; + end + end + + assign Q = LAT ? q_latch : q_ff; +endmodule + +// module AR1 +// module FCEND_BUFF +// module FCINIT_BUFF +// module FLASH_FREEZE +// module OSCILLATOR +// module SYSRESET +// module SYSCTRL_RESET_STATUS +// module LIVE_PROBE_FB +// module GCLKBUF +// module GCLKBUF_DIFF +// module GCLKBIBUF +// module DFN1 +// module DFN1C0 +// module DFN1E1 +// module DFN1E1C0 +// module DFN1E1P0 +// module DFN1P0 +// module DLN1 +// module DLN1C0 +// module DLN1P0 + +module INV ( + input A, + output Y +); + assign Y = !A; +endmodule + +module INVD ( + input A, + output Y +); + assign Y = !A; +endmodule + +module MX2 ( + input A, B, S, + output Y +); + assign Y = S ? B : A; +endmodule + +module MX4 ( + input D0, D1, D2, D3, S0, S1, + output Y +); + assign Y = S1 ? (S0 ? D3 : D2) : (S0 ? D1 : D0); +endmodule + +module NAND2 ( + input A, B, + output Y +); + assign Y = !(A & B); +endmodule + +module NAND3 ( + input A, B, C, + output Y +); + assign Y = !(A & B & C); +endmodule + +module NAND4 ( + input A, B, C, D, + output Y +); + assign Y = !(A & B & C & D); +endmodule + +module NOR2 ( + input A, B, + output Y +); + assign Y = !(A | B); +endmodule + +module NOR3 ( + input A, B, C, + output Y +); + assign Y = !(A | B | C); +endmodule + +module NOR4 ( + input A, B, C, D, + output Y +); + assign Y = !(A | B | C | D); +endmodule + +module OR2 ( + input A, B, + output Y +); + assign Y = A | B; +endmodule + +module OR3 ( + input A, B, C, + output Y +); + assign Y = A | B | C; +endmodule + +module OR4 ( + input A, B, C, D, + output Y +); + assign Y = A | B | C | D; +endmodule + +module XOR2 ( + input A, B, + output Y +); + assign Y = A ^ B; +endmodule + +module XOR3 ( + input A, B, C, + output Y +); + assign Y = A ^ B ^ C; +endmodule + +module XOR4 ( + input A, B, C, D, + output Y +); + assign Y = A ^ B ^ C ^ D; +endmodule + +module XOR8 ( + input A, B, C, D, E, F, G, H, + output Y +); + assign Y = A ^ B ^ C ^ D ^ E ^ F ^ G ^ H; +endmodule + +// module UJTAG +// module BIBUF +// module BIBUF_DIFF +// module CLKBIBUF + module CLKBUF ( input PAD, output Y @@ -88,6 +296,8 @@ module CLKBUF ( assign Y = PAD; endmodule +// module CLKBUF_DIFF + module INBUF ( input PAD, output Y @@ -95,9 +305,20 @@ module INBUF ( assign Y = PAD; endmodule +// module INBUF_DIFF + module OUTBUF ( input D, output PAD ); assign PAD = D; endmodule + +// module OUTBUF_DIFF +// module TRIBUFF +// module TRIBUFF_DIFF +// module DDR_IN +// module DDR_OUT +// module RAM1K18 +// module RAM64x18 +// module MACC diff --git a/techlibs/sf2/sf2_iobs.cc b/techlibs/sf2/sf2_iobs.cc index dea8e353b..3d43332e2 100644 --- a/techlibs/sf2/sf2_iobs.cc +++ b/techlibs/sf2/sf2_iobs.cc @@ -38,8 +38,8 @@ static void handle_iobufs(Module *module, bool clkbuf_mode) for (auto bit : sigmap(cell->getPort("\\CLK"))) clk_bits.insert(bit); } - if (cell->type.in("\\INBUF", "\\OUTBUF", "\\TRIBUF", "\\BIBUF", "\\CLKBUF", "\\CLKBIBUF", - "\\INBUF_DIFF", "\\OUTBUF_DIFF", "\\BIBUFF_DIFF", "\\TRIBUF_DIFF", "\\CLKBUF_DIFF", + if (cell->type.in("\\INBUF", "\\OUTBUF", "\\TRIBUFF", "\\BIBUF", "\\CLKBUF", "\\CLKBIBUF", + "\\INBUF_DIFF", "\\OUTBUF_DIFF", "\\BIBUFF_DIFF", "\\TRIBUFF_DIFF", "\\CLKBUF_DIFF", "\\GCLKBUF", "\\GCLKBUF_DIFF", "\\GCLKBIBUF")) { for (auto bit : sigmap(cell->getPort("\\PAD"))) handled_io_bits.insert(bit); From 350dfd3745ec2efa92a601d3bab7712fd9bec07c Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 7 Mar 2019 09:08:26 -0800 Subject: [PATCH 55/76] Add link to SF2 / igloo2 macro library guide Signed-off-by: Clifford Wolf --- techlibs/sf2/cells_sim.v | 45 +++++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/techlibs/sf2/cells_sim.v b/techlibs/sf2/cells_sim.v index f3f7695cf..c62748b11 100644 --- a/techlibs/sf2/cells_sim.v +++ b/techlibs/sf2/cells_sim.v @@ -1,3 +1,27 @@ +// https://coredocs.s3.amazonaws.com/Libero/12_0_0/Tool/sf2_mlg.pdf + +module ADD2 ( + + input A, B, + output Y +); + assign Y = A & B; +endmodule + +module ADD3 ( + input A, B, C, + output Y +); + assign Y = A & B & C; +endmodule + +module ADD4 ( + input A, B, C, D, + output Y +); + assign Y = A & B & C & D; +endmodule + module CFG1 ( output Y, input A @@ -36,27 +60,6 @@ module CFG4 ( assign Y = INIT >> {D, C, B, A}; endmodule -module ADD2 ( - input A, B, - output Y -); - assign Y = A & B; -endmodule - -module ADD3 ( - input A, B, C, - output Y -); - assign Y = A & B & C; -endmodule - -module ADD4 ( - input A, B, C, D, - output Y -); - assign Y = A & B & C & D; -endmodule - module BUFF ( input A, output Y From cda37830b060fd46834d8eb7af1171a1ffaee8ca Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 7 Mar 2019 10:52:44 -0800 Subject: [PATCH 56/76] Add hack for handling SVA labels via Verific Signed-off-by: Clifford Wolf --- frontends/verific/verificsva.cc | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/frontends/verific/verificsva.cc b/frontends/verific/verificsva.cc index 6681115df..8ea8372d3 100644 --- a/frontends/verific/verificsva.cc +++ b/frontends/verific/verificsva.cc @@ -1666,7 +1666,20 @@ struct VerificSvaImporter log(" importing SVA property at root cell %s (%s) at %s:%d.\n", root->Name(), root->View()->Owner()->Name(), LineFile::GetFileName(root->Linefile()), LineFile::GetLineNo(root->Linefile())); - RTLIL::IdString root_name = module->uniquify(importer->mode_names || root->IsUserDeclared() ? RTLIL::escape_id(root->Name()) : NEW_ID); + bool is_user_declared = root->IsUserDeclared(); + + // FIXME + if (!is_user_declared) { + const char *name = root->Name(); + for (int i = 0; name[i]; i++) { + if (i ? (name[i] < '0' || name[i] > '9') : (name[i] != 'i')) { + is_user_declared = true; + break; + } + } + } + + RTLIL::IdString root_name = module->uniquify(importer->mode_names || is_user_declared ? RTLIL::escape_id(root->Name()) : NEW_ID); // parse SVA sequence into trigger signal From 22ff60850e68b5e98d4693a9a06ec688dac6d5ee Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 7 Mar 2019 11:17:32 -0800 Subject: [PATCH 57/76] Add support for SVA labels in read_verilog Signed-off-by: Clifford Wolf --- frontends/ast/genrtlil.cc | 12 +++- frontends/ast/simplify.cc | 1 + frontends/verilog/verilog_parser.y | 102 ++++++++++++++++++++++------- 3 files changed, 89 insertions(+), 26 deletions(-) diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc index 13383845a..d7da6fb40 100644 --- a/frontends/ast/genrtlil.cc +++ b/frontends/ast/genrtlil.cc @@ -1413,10 +1413,16 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) if (GetSize(en) != 1) en = current_module->ReduceBool(NEW_ID, en); - std::stringstream sstr; - sstr << celltype << "$" << filename << ":" << linenum << "$" << (autoidx++); + IdString cellname; + if (str.empty()) { + std::stringstream sstr; + sstr << celltype << "$" << filename << ":" << linenum << "$" << (autoidx++); + cellname = sstr.str(); + } else { + cellname = str; + } - RTLIL::Cell *cell = current_module->addCell(sstr.str(), celltype); + RTLIL::Cell *cell = current_module->addCell(cellname, celltype); cell->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum); for (auto &attr : attributes) { diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 7160c6c0f..bdd8ccb17 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -1511,6 +1511,7 @@ skip_dynamic_range_lvalue_expansion:; newNode->children.push_back(assign_en); AstNode *assertnode = new AstNode(type); + assertnode->str = str; assertnode->children.push_back(new AstNode(AST_IDENTIFIER)); assertnode->children.push_back(new AstNode(AST_IDENTIFIER)); assertnode->children[0]->str = id_check; diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index a6718b020..2258f3f6f 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -126,7 +126,7 @@ static void free_attr(std::map *al) %type range range_or_multirange non_opt_range non_opt_multirange range_or_signed_int %type wire_type expr basic_expr concat_list rvalue lvalue lvalue_concat_list -%type opt_label tok_prim_wrapper hierarchical_id +%type opt_label opt_stmt_label tok_prim_wrapper hierarchical_id %type opt_signed opt_property unique_case_attr %type attr case_attr @@ -1338,7 +1338,12 @@ opt_property: }; opt_stmt_label: - TOK_ID ':' | /* empty */; + TOK_ID ':' { + $$ = $1; + } | + /* empty */ { + $$ = NULL; + }; modport_stmt: TOK_MODPORT TOK_ID { @@ -1377,53 +1382,104 @@ modport_type_token: assert: opt_stmt_label TOK_ASSERT opt_property '(' expr ')' ';' { - if (noassert_mode) + if (noassert_mode) { delete $5; - else - ast_stack.back()->children.push_back(new AstNode(assume_asserts_mode ? AST_ASSUME : AST_ASSERT, $5)); + } else { + AstNode *node = new AstNode(assume_asserts_mode ? AST_ASSUME : AST_ASSERT, $5); + if ($1 != nullptr) + node->str = *$1; + ast_stack.back()->children.push_back(node); + } + if ($1 != nullptr) + delete $1; } | opt_stmt_label TOK_ASSUME opt_property '(' expr ')' ';' { - if (noassume_mode) + if (noassume_mode) { delete $5; - else - ast_stack.back()->children.push_back(new AstNode(assert_assumes_mode ? AST_ASSERT : AST_ASSUME, $5)); + } else { + AstNode *node = new AstNode(assert_assumes_mode ? AST_ASSERT : AST_ASSUME, $5); + if ($1 != nullptr) + node->str = *$1; + ast_stack.back()->children.push_back(node); + } + if ($1 != nullptr) + delete $1; } | opt_stmt_label TOK_ASSERT opt_property '(' TOK_EVENTUALLY expr ')' ';' { - if (noassert_mode) + if (noassert_mode) { delete $6; - else - ast_stack.back()->children.push_back(new AstNode(assume_asserts_mode ? AST_FAIR : AST_LIVE, $6)); + } else { + AstNode *node = new AstNode(assume_asserts_mode ? AST_FAIR : AST_LIVE, $6); + if ($1 != nullptr) + node->str = *$1; + ast_stack.back()->children.push_back(node); + } + if ($1 != nullptr) + delete $1; } | opt_stmt_label TOK_ASSUME opt_property '(' TOK_EVENTUALLY expr ')' ';' { - if (noassume_mode) + if (noassume_mode) { delete $6; - else - ast_stack.back()->children.push_back(new AstNode(assert_assumes_mode ? AST_LIVE : AST_FAIR, $6)); + } else { + AstNode *node = new AstNode(assert_assumes_mode ? AST_LIVE : AST_FAIR, $6); + if ($1 != nullptr) + node->str = *$1; + ast_stack.back()->children.push_back(node); + } + if ($1 != nullptr) + delete $1; } | opt_stmt_label TOK_COVER opt_property '(' expr ')' ';' { - ast_stack.back()->children.push_back(new AstNode(AST_COVER, $5)); + AstNode *node = new AstNode(AST_COVER, $5); + if ($1 != nullptr) { + node->str = *$1; + delete $1; + } + ast_stack.back()->children.push_back(node); } | opt_stmt_label TOK_COVER opt_property '(' ')' ';' { - ast_stack.back()->children.push_back(new AstNode(AST_COVER, AstNode::mkconst_int(1, false))); + AstNode *node = new AstNode(AST_COVER, AstNode::mkconst_int(1, false)); + if ($1 != nullptr) { + node->str = *$1; + delete $1; + } + ast_stack.back()->children.push_back(node); } | opt_stmt_label TOK_COVER ';' { - ast_stack.back()->children.push_back(new AstNode(AST_COVER, AstNode::mkconst_int(1, false))); + AstNode *node = new AstNode(AST_COVER, AstNode::mkconst_int(1, false)); + if ($1 != nullptr) { + node->str = *$1; + delete $1; + } + ast_stack.back()->children.push_back(node); } | opt_stmt_label TOK_RESTRICT opt_property '(' expr ')' ';' { - if (norestrict_mode) + if (norestrict_mode) { delete $5; - else - ast_stack.back()->children.push_back(new AstNode(AST_ASSUME, $5)); + } else { + AstNode *node = new AstNode(AST_ASSUME, $5); + if ($1 != nullptr) + node->str = *$1; + ast_stack.back()->children.push_back(node); + } if (!$3) log_file_warning(current_filename, get_line_num(), "SystemVerilog does not allow \"restrict\" without \"property\".\n"); + if ($1 != nullptr) + delete $1; } | opt_stmt_label TOK_RESTRICT opt_property '(' TOK_EVENTUALLY expr ')' ';' { - if (norestrict_mode) + if (norestrict_mode) { delete $6; - else - ast_stack.back()->children.push_back(new AstNode(AST_FAIR, $6)); + } else { + AstNode *node = new AstNode(AST_FAIR, $6); + if ($1 != nullptr) + node->str = *$1; + ast_stack.back()->children.push_back(node); + } if (!$3) log_file_warning(current_filename, get_line_num(), "SystemVerilog does not allow \"restrict\" without \"property\".\n"); + if ($1 != nullptr) + delete $1; }; assert_property: From 5dfc7becca1f1faf6e77fb3b5d07d97171613d90 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 7 Mar 2019 11:31:46 -0800 Subject: [PATCH 58/76] Use SVA label in smt export if available Signed-off-by: Clifford Wolf --- backends/smt2/smt2.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backends/smt2/smt2.cc b/backends/smt2/smt2.cc index 7f3cc94ca..a26bff57b 100644 --- a/backends/smt2/smt2.cc +++ b/backends/smt2/smt2.cc @@ -887,8 +887,8 @@ struct Smt2Worker string name_a = get_bool(cell->getPort("\\A")); string name_en = get_bool(cell->getPort("\\EN")); - decls.push_back(stringf("; yosys-smt2-%s %d %s\n", cell->type.c_str() + 1, id, - cell->attributes.count("\\src") ? cell->attributes.at("\\src").decode_string().c_str() : get_id(cell))); + string infostr = (cell->name[0] == '$' && cell->attributes.count("\\src")) ? cell->attributes.at("\\src").decode_string() : get_id(cell); + decls.push_back(stringf("; yosys-smt2-%s %d %s\n", cell->type.c_str() + 1, id, infostr.c_str())); if (cell->type == "$cover") decls.push_back(stringf("(define-fun |%s_%c %d| ((state |%s_s|)) Bool (and %s %s)) ; %s\n", From e71055cfe8f3d90e157174b1fd83a06487a0a6a2 Mon Sep 17 00:00:00 2001 From: Sylvain Munaut Date: Thu, 7 Mar 2019 23:48:10 +0100 Subject: [PATCH 59/76] ice40: Add ice40_braminit pass to allow initialization of BRAM from file This adds a INIT_FILE attribute to the SB_RAM40_4K blocks that will initialize content from a hex file. Same behavior is imlemented in the simulation model and in a new pass for actual synthesis Signed-off-by: Sylvain Munaut --- techlibs/ice40/Makefile.inc | 1 + techlibs/ice40/cells_sim.v | 88 ++++++++++------- techlibs/ice40/ice40_braminit.cc | 159 +++++++++++++++++++++++++++++++ 3 files changed, 211 insertions(+), 37 deletions(-) create mode 100644 techlibs/ice40/ice40_braminit.cc diff --git a/techlibs/ice40/Makefile.inc b/techlibs/ice40/Makefile.inc index 2750901c8..723b59d6f 100644 --- a/techlibs/ice40/Makefile.inc +++ b/techlibs/ice40/Makefile.inc @@ -1,5 +1,6 @@ OBJS += techlibs/ice40/synth_ice40.o +OBJS += techlibs/ice40/ice40_braminit.o OBJS += techlibs/ice40/ice40_ffssr.o OBJS += techlibs/ice40/ice40_ffinit.o OBJS += techlibs/ice40/ice40_opt.o diff --git a/techlibs/ice40/cells_sim.v b/techlibs/ice40/cells_sim.v index 2041693cc..bc36cdd14 100644 --- a/techlibs/ice40/cells_sim.v +++ b/techlibs/ice40/cells_sim.v @@ -326,6 +326,8 @@ module SB_RAM40_4K ( parameter INIT_E = 256'h0000000000000000000000000000000000000000000000000000000000000000; parameter INIT_F = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_FILE = ""; + `ifndef BLACKBOX wire [15:0] WMASK_I; wire [15:0] RMASK_I; @@ -408,43 +410,46 @@ module SB_RAM40_4K ( reg [15:0] memory [0:255]; initial begin - for (i=0; i<16; i=i+1) begin + if (INIT_FILE != "") + $readmemh(INIT_FILE, memory); + else + for (i=0; i<16; i=i+1) begin `ifdef YOSYS - memory[ 0*16 + i] <= INIT_0[16*i +: 16]; - memory[ 1*16 + i] <= INIT_1[16*i +: 16]; - memory[ 2*16 + i] <= INIT_2[16*i +: 16]; - memory[ 3*16 + i] <= INIT_3[16*i +: 16]; - memory[ 4*16 + i] <= INIT_4[16*i +: 16]; - memory[ 5*16 + i] <= INIT_5[16*i +: 16]; - memory[ 6*16 + i] <= INIT_6[16*i +: 16]; - memory[ 7*16 + i] <= INIT_7[16*i +: 16]; - memory[ 8*16 + i] <= INIT_8[16*i +: 16]; - memory[ 9*16 + i] <= INIT_9[16*i +: 16]; - memory[10*16 + i] <= INIT_A[16*i +: 16]; - memory[11*16 + i] <= INIT_B[16*i +: 16]; - memory[12*16 + i] <= INIT_C[16*i +: 16]; - memory[13*16 + i] <= INIT_D[16*i +: 16]; - memory[14*16 + i] <= INIT_E[16*i +: 16]; - memory[15*16 + i] <= INIT_F[16*i +: 16]; + memory[ 0*16 + i] <= INIT_0[16*i +: 16]; + memory[ 1*16 + i] <= INIT_1[16*i +: 16]; + memory[ 2*16 + i] <= INIT_2[16*i +: 16]; + memory[ 3*16 + i] <= INIT_3[16*i +: 16]; + memory[ 4*16 + i] <= INIT_4[16*i +: 16]; + memory[ 5*16 + i] <= INIT_5[16*i +: 16]; + memory[ 6*16 + i] <= INIT_6[16*i +: 16]; + memory[ 7*16 + i] <= INIT_7[16*i +: 16]; + memory[ 8*16 + i] <= INIT_8[16*i +: 16]; + memory[ 9*16 + i] <= INIT_9[16*i +: 16]; + memory[10*16 + i] <= INIT_A[16*i +: 16]; + memory[11*16 + i] <= INIT_B[16*i +: 16]; + memory[12*16 + i] <= INIT_C[16*i +: 16]; + memory[13*16 + i] <= INIT_D[16*i +: 16]; + memory[14*16 + i] <= INIT_E[16*i +: 16]; + memory[15*16 + i] <= INIT_F[16*i +: 16]; `else - memory[ 0*16 + i] = INIT_0[16*i +: 16]; - memory[ 1*16 + i] = INIT_1[16*i +: 16]; - memory[ 2*16 + i] = INIT_2[16*i +: 16]; - memory[ 3*16 + i] = INIT_3[16*i +: 16]; - memory[ 4*16 + i] = INIT_4[16*i +: 16]; - memory[ 5*16 + i] = INIT_5[16*i +: 16]; - memory[ 6*16 + i] = INIT_6[16*i +: 16]; - memory[ 7*16 + i] = INIT_7[16*i +: 16]; - memory[ 8*16 + i] = INIT_8[16*i +: 16]; - memory[ 9*16 + i] = INIT_9[16*i +: 16]; - memory[10*16 + i] = INIT_A[16*i +: 16]; - memory[11*16 + i] = INIT_B[16*i +: 16]; - memory[12*16 + i] = INIT_C[16*i +: 16]; - memory[13*16 + i] = INIT_D[16*i +: 16]; - memory[14*16 + i] = INIT_E[16*i +: 16]; - memory[15*16 + i] = INIT_F[16*i +: 16]; + memory[ 0*16 + i] = INIT_0[16*i +: 16]; + memory[ 1*16 + i] = INIT_1[16*i +: 16]; + memory[ 2*16 + i] = INIT_2[16*i +: 16]; + memory[ 3*16 + i] = INIT_3[16*i +: 16]; + memory[ 4*16 + i] = INIT_4[16*i +: 16]; + memory[ 5*16 + i] = INIT_5[16*i +: 16]; + memory[ 6*16 + i] = INIT_6[16*i +: 16]; + memory[ 7*16 + i] = INIT_7[16*i +: 16]; + memory[ 8*16 + i] = INIT_8[16*i +: 16]; + memory[ 9*16 + i] = INIT_9[16*i +: 16]; + memory[10*16 + i] = INIT_A[16*i +: 16]; + memory[11*16 + i] = INIT_B[16*i +: 16]; + memory[12*16 + i] = INIT_C[16*i +: 16]; + memory[13*16 + i] = INIT_D[16*i +: 16]; + memory[14*16 + i] = INIT_E[16*i +: 16]; + memory[15*16 + i] = INIT_F[16*i +: 16]; `endif - end + end end always @(posedge WCLK) begin @@ -504,6 +509,8 @@ module SB_RAM40_4KNR ( parameter INIT_E = 256'h0000000000000000000000000000000000000000000000000000000000000000; parameter INIT_F = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_FILE = ""; + SB_RAM40_4K #( .WRITE_MODE(WRITE_MODE), .READ_MODE (READ_MODE ), @@ -522,7 +529,8 @@ module SB_RAM40_4KNR ( .INIT_C (INIT_C ), .INIT_D (INIT_D ), .INIT_E (INIT_E ), - .INIT_F (INIT_F ) + .INIT_F (INIT_F ), + .INIT_FILE (INIT_FILE ) ) RAM ( .RDATA(RDATA), .RCLK (~RCLKN), @@ -566,6 +574,8 @@ module SB_RAM40_4KNW ( parameter INIT_E = 256'h0000000000000000000000000000000000000000000000000000000000000000; parameter INIT_F = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_FILE = ""; + SB_RAM40_4K #( .WRITE_MODE(WRITE_MODE), .READ_MODE (READ_MODE ), @@ -584,7 +594,8 @@ module SB_RAM40_4KNW ( .INIT_C (INIT_C ), .INIT_D (INIT_D ), .INIT_E (INIT_E ), - .INIT_F (INIT_F ) + .INIT_F (INIT_F ), + .INIT_FILE (INIT_FILE ) ) RAM ( .RDATA(RDATA), .RCLK (RCLK ), @@ -628,6 +639,8 @@ module SB_RAM40_4KNRNW ( parameter INIT_E = 256'h0000000000000000000000000000000000000000000000000000000000000000; parameter INIT_F = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_FILE = ""; + SB_RAM40_4K #( .WRITE_MODE(WRITE_MODE), .READ_MODE (READ_MODE ), @@ -646,7 +659,8 @@ module SB_RAM40_4KNRNW ( .INIT_C (INIT_C ), .INIT_D (INIT_D ), .INIT_E (INIT_E ), - .INIT_F (INIT_F ) + .INIT_F (INIT_F ), + .INIT_FILE (INIT_FILE ) ) RAM ( .RDATA(RDATA), .RCLK (~RCLKN), diff --git a/techlibs/ice40/ice40_braminit.cc b/techlibs/ice40/ice40_braminit.cc new file mode 100644 index 000000000..bf12f9148 --- /dev/null +++ b/techlibs/ice40/ice40_braminit.cc @@ -0,0 +1,159 @@ +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2012 Clifford Wolf + * + * 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/yosys.h" +#include "kernel/sigtools.h" +#include +#include +#include + +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + +static void run_ice40_braminit(Module *module) +{ + for (auto cell : module->selected_cells()) + { + uint16_t mem[256]; + + /* Only consider cells we're interested in */ + if (cell->type != "\\SB_RAM40_4K" && + cell->type != "\\SB_RAM40_4KNR" && + cell->type != "\\SB_RAM40_4KNW" && + cell->type != "\\SB_RAM40_4KNRNW") + continue; + if (!cell->hasParam("\\INIT_FILE")) + continue; + std::string init_file = cell->getParam("\\INIT_FILE").decode_string(); + cell->unsetParam("\\INIT_FILE"); + if (init_file == "") + continue; + + /* Open file */ + log("Processing %s : %s\n", RTLIL::id2cstr(cell->name), init_file.c_str()); + + std::ifstream f; + f.open(init_file.c_str()); + if (f.fail()) { + log("Can not open file `%s`.\n", init_file.c_str()); + continue; + } + + /* Defaults to 0 */ + memset(mem, 0x00, sizeof(mem)); + + /* Process each line */ + bool in_comment = false; + int cursor = 0; + + while (!f.eof()) + { + std::string line, token; + std::getline(f, line); + + for (int i = 0; i < GetSize(line); i++) + { + if (in_comment && line.substr(i, 2) == "*/") { + line[i] = ' '; + line[i+1] = ' '; + in_comment = false; + continue; + } + if (!in_comment && line.substr(i, 2) == "/*") + in_comment = true; + if (in_comment) + line[i] = ' '; + } + + while (1) + { + bool set_cursor = false; + long value; + + token = next_token(line, " \t\r\n"); + if (token.empty() || token.substr(0, 2) == "//") + break; + + if (token[0] == '@') { + token = token.substr(1); + set_cursor = true; + } + + const char *nptr = token.c_str(); + char *endptr; + value = strtol(nptr, &endptr, 16); + if (!*nptr || *endptr) { + log("Can not parse %s `%s` for %s.\n", + set_cursor ? "address" : "value", + nptr, token.c_str() + ); + continue; + } + + if (set_cursor) + cursor = value; + else if (cursor >= 0 && cursor < 256) + mem[cursor++] = value; + else + log("Attempt to initialize non existent address %d\n", cursor); + } + } + + /* Set attributes */ + const char *hex = "0123456789ABCDEF"; + for (int i=0; i<16; i++) { + std::string val = ""; + for (int j=15; j>=0; j--) + val += std::bitset<16>(mem[i*16+j]).to_string(); + cell->setParam("\\INIT_" + std::string(1, hex[i]), RTLIL::Const::from_string(val)); + } + } +} + +struct Ice40BRAMInitPass : public Pass { + Ice40BRAMInitPass() : Pass("ice40_braminit", "iCE40: perform SB_RAM40_4K initialization from file") { } + void help() YS_OVERRIDE + { + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| + log("\n"); + log(" ice40_braminit\n"); + log("\n"); + log("This command processes all SB_RAM40_4K blocks with a non-empty INIT_FILE\n"); + log("parameter and converts it inti the required INIT_x attributes\n"); + log("\n"); + } + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE + { + log_header(design, "Executing ICE40_BRAMINIT pass.\n"); + + size_t argidx; + for (argidx = 1; argidx < args.size(); argidx++) { + // if (args[argidx] == "-???") { + // continue; + // } + break; + } + extra_args(args, argidx, design); + + for (auto module : design->selected_modules()) + run_ice40_braminit(module); + } +} Ice40BRAMInitPass; + +PRIVATE_NAMESPACE_END From 5b6f59103374413e9c64c4f228853ce06b03ce29 Mon Sep 17 00:00:00 2001 From: Sylvain Munaut Date: Fri, 8 Mar 2019 00:11:17 +0100 Subject: [PATCH 60/76] ice40: Run ice40_braminit pass by default Signed-off-by: Sylvain Munaut --- techlibs/ice40/synth_ice40.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/techlibs/ice40/synth_ice40.cc b/techlibs/ice40/synth_ice40.cc index 34501b335..8899bfcc4 100644 --- a/techlibs/ice40/synth_ice40.cc +++ b/techlibs/ice40/synth_ice40.cc @@ -257,6 +257,7 @@ struct SynthIce40Pass : public ScriptPass { run("memory_bram -rules +/ice40/brams.txt"); run("techmap -map +/ice40/brams_map.v"); + run("ice40_braminit"); } if (check_label("map")) From a330c6836318d43d52cda68959f2b86c2b2ede9c Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 7 Mar 2019 22:44:37 -0800 Subject: [PATCH 61/76] Fix handling of task output ports in clocked always blocks, fixes #857 Signed-off-by: Clifford Wolf --- frontends/ast/simplify.cc | 35 +++++++++++++++++++---------------- tests/simple/task_func.v | 19 +++++++++++++++++++ 2 files changed, 38 insertions(+), 16 deletions(-) diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 7160c6c0f..d0274cf78 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -2224,6 +2224,8 @@ skip_dynamic_range_lvalue_expansion:; std::map replace_rules; vector added_mod_children; dict wire_cache; + vector new_stmts; + vector output_assignments; if (current_block == NULL) { @@ -2348,8 +2350,8 @@ skip_dynamic_range_lvalue_expansion:; wire->port_id = 0; wire->is_input = false; wire->is_output = false; - if (!child->is_output) - wire->attributes["\\nosync"] = AstNode::mkconst_int(1, false); + wire->is_reg = true; + wire->attributes["\\nosync"] = AstNode::mkconst_int(1, false); wire_cache[child->str] = wire; current_ast_mod->children.push_back(wire); @@ -2371,13 +2373,10 @@ skip_dynamic_range_lvalue_expansion:; new AstNode(AST_ASSIGN_EQ, wire_id, arg) : new AstNode(AST_ASSIGN_EQ, arg, wire_id); assign->children[0]->was_checked = true; - - for (auto it = current_block->children.begin(); it != current_block->children.end(); it++) { - if (*it != current_block_child) - continue; - current_block->children.insert(it, assign); - break; - } + if (child->is_input) + new_stmts.push_back(assign); + else + output_assignments.push_back(assign); } } @@ -2391,15 +2390,19 @@ skip_dynamic_range_lvalue_expansion:; { AstNode *stmt = child->clone(); stmt->replace_ids(prefix, replace_rules); - - for (auto it = current_block->children.begin(); it != current_block->children.end(); it++) { - if (*it != current_block_child) - continue; - current_block->children.insert(it, stmt); - break; - } + new_stmts.push_back(stmt); } + new_stmts.insert(new_stmts.end(), output_assignments.begin(), output_assignments.end()); + + for (auto it = current_block->children.begin(); ; it++) { + log_assert(it != current_block->children.end()); + if (*it == current_block_child) { + current_block->children.insert(it, new_stmts.begin(), new_stmts.end()); + break; + } + } + replace_fcall_with_id: if (type == AST_FCALL) { delete_children(); diff --git a/tests/simple/task_func.v b/tests/simple/task_func.v index fa50c1d5c..f6e902f63 100644 --- a/tests/simple/task_func.v +++ b/tests/simple/task_func.v @@ -120,3 +120,22 @@ module task_func_test04(input [7:0] in, output [7:0] out1, out2, out3, out4); assign out3 = test3(in); assign out4 = test4(in); endmodule + +// ------------------------------------------------------------------- + +// https://github.com/YosysHQ/yosys/issues/857 +module task_func_test05(data_in,data_out,clk); + output reg data_out; + input data_in; + input clk; + + task myTask; + output out; + input in; + out = in; + endtask + + always @(posedge clk) begin + myTask(data_out,data_in); + end +endmodule From 1dc060f32eea0df2ba45770365060251163b2857 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sat, 9 Mar 2019 00:43:50 +0000 Subject: [PATCH 62/76] Fix spelling --- frontends/verific/README | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontends/verific/README b/frontends/verific/README index c76cdd637..89584f2e8 100644 --- a/frontends/verific/README +++ b/frontends/verific/README @@ -21,7 +21,7 @@ Then run in the following command in this directory: sby -f example.sby -This will generate approximately one page of text outpout. The last lines +This will generate approximately one page of text output. The last lines should be something like this: SBY [example] summary: Elapsed clock time [H:MM:SS (secs)]: 0:00:00 (0) From 2aa3903757642616f38d1069e1b706fcbf3168c4 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sat, 9 Mar 2019 01:54:01 +0000 Subject: [PATCH 63/76] Add -chparam option to verific command --- frontends/verific/verific.cc | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/frontends/verific/verific.cc b/frontends/verific/verific.cc index 9f52ffdc2..4ba96d251 100644 --- a/frontends/verific/verific.cc +++ b/frontends/verific/verific.cc @@ -1855,6 +1855,12 @@ struct VerificPass : public Pass { log(" -autocover\n"); log(" Generate automatic cover statements for all asserts\n"); log("\n"); + log(" -chparam name value \n"); + log(" Elaborate the specified top modules (all modules when -all given) using\n"); + log(" this parameter value, for modules where this parameter exists. This option\n"); + log(" can be specified multiple times to override multiple parameters.\n"); + log(" String values must be passed in double quotes (\").\n"); + log("\n"); log(" -v, -vv\n"); log(" Verbose log messages. (-vv is even more verbose than -v.)\n"); log("\n"); @@ -2109,6 +2115,7 @@ struct VerificPass : public Pass { bool mode_autocover = false; bool flatten = false, extnets = false; string dumpfile; + Map parameters(STRING_HASH); for (argidx++; argidx < GetSize(args); argidx++) { if (args[argidx] == "-all") { @@ -2147,6 +2154,15 @@ struct VerificPass : public Pass { mode_autocover = true; continue; } + if (args[argidx] == "-chparam" && argidx+2 < GetSize(args)) { + const std::string &key = args[++argidx]; + const std::string &value = args[++argidx]; + unsigned new_insertion = parameters.Insert(key.c_str(), value.c_str(), + 1 /* force_overwrite */); + if (!new_insertion) + log_warning_noprefix("-chparam %s already specified: overwriting.\n", key.c_str()); + continue; + } if (args[argidx] == "-V") { mode_verific = true; continue; @@ -2180,7 +2196,7 @@ struct VerificPass : public Pass { if (vhdl_lib) vhdl_libs.InsertLast(vhdl_lib); if (veri_lib) veri_libs.InsertLast(veri_lib); - Array *netlists = hier_tree::ElaborateAll(&veri_libs, &vhdl_libs); + Array *netlists = hier_tree::ElaborateAll(&veri_libs, &vhdl_libs, ¶meters); Netlist *nl; int i; @@ -2217,7 +2233,7 @@ struct VerificPass : public Pass { } log("Running hier_tree::Elaborate().\n"); - Array *netlists = hier_tree::Elaborate(&veri_modules, &vhdl_units); + Array *netlists = hier_tree::Elaborate(&veri_modules, &vhdl_units, ¶meters); Netlist *nl; int i; From ee013fba54f8bca0940143f655f5b4ad3d7b7b96 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sat, 9 Mar 2019 01:56:16 +0000 Subject: [PATCH 64/76] Update help message for -chparam --- frontends/verific/verific.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/frontends/verific/verific.cc b/frontends/verific/verific.cc index 4ba96d251..c412cd3a3 100644 --- a/frontends/verific/verific.cc +++ b/frontends/verific/verific.cc @@ -1857,7 +1857,8 @@ struct VerificPass : public Pass { log("\n"); log(" -chparam name value \n"); log(" Elaborate the specified top modules (all modules when -all given) using\n"); - log(" this parameter value, for modules where this parameter exists. This option\n"); + log(" this parameter value. Modules on which this parameter does not exist will\n"); + log(" cause Verific to produce a VERI-1928 or VHDL-1676 message. This option\n"); log(" can be specified multiple times to override multiple parameters.\n"); log(" String values must be passed in double quotes (\").\n"); log("\n"); From e7a34d342ed1dd01074acdafca4f8f5557f8150f Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 8 Mar 2019 22:53:58 -0800 Subject: [PATCH 65/76] Also add support for labels on sva module items, fixes #699 Signed-off-by: Clifford Wolf --- frontends/verilog/verilog_lexer.l | 57 +++++++++++-- frontends/verilog/verilog_parser.y | 132 +++++++++++++++++------------ 2 files changed, 129 insertions(+), 60 deletions(-) diff --git a/frontends/verilog/verilog_lexer.l b/frontends/verilog/verilog_lexer.l index 1b1873e24..e51a12f76 100644 --- a/frontends/verilog/verilog_lexer.l +++ b/frontends/verilog/verilog_lexer.l @@ -189,10 +189,57 @@ YOSYS_NAMESPACE_END "always_ff" { SV_KEYWORD(TOK_ALWAYS); } "always_latch" { SV_KEYWORD(TOK_ALWAYS); } -"assert" { if (formal_mode) return TOK_ASSERT; SV_KEYWORD(TOK_ASSERT); } -"assume" { if (formal_mode) return TOK_ASSUME; SV_KEYWORD(TOK_ASSUME); } -"cover" { if (formal_mode) return TOK_COVER; SV_KEYWORD(TOK_COVER); } -"restrict" { if (formal_mode) return TOK_RESTRICT; SV_KEYWORD(TOK_RESTRICT); } + /* parse labels on assert, assume, cover, and restrict right here because it's insanley complex + to do it in the parser (because we force the parser too early to reduce when parsing cells..) */ +([a-zA-Z_$][a-zA-Z0-9_$]*[ \t\r\n]*:[ \t\r\n]*)?(assert|assume|cover|restrict)/[^a-zA-Z0-9_$\.] { + frontend_verilog_yylval.string = new std::string(yytext); + auto &str = *frontend_verilog_yylval.string; + std::string keyword; + int cursor = 0; + + while (1) { + if (cursor == GetSize(str)) { + keyword = str; + delete frontend_verilog_yylval.string; + frontend_verilog_yylval.string = nullptr; + goto sva_without_label; + } + char c = str[cursor]; + if (c != ' ' && c != '\t' && c != '\r' && c != '\n' && c != ':') { + cursor++; + continue; + } + + keyword = str.substr(cursor); + str = "\\" + str.substr(0, cursor); + break; + } + + cursor = 0; + while (1) { + log_assert(cursor < GetSize(keyword)); + char c = keyword[cursor]; + if (c != ' ' && c != '\t' && c != '\r' && c != '\n' && c != ':') { + keyword = keyword.substr(cursor); + break; + } + cursor++; + } + + if (keyword == "assert") { return TOK_ASSERT; } + else if (keyword == "assume") { return TOK_ASSUME; } + else if (keyword == "cover") { return TOK_COVER; } + else if (keyword == "restrict") { return TOK_RESTRICT; } + else log_abort(); + +sva_without_label: + if (keyword == "assert") { if (formal_mode) return TOK_ASSERT; SV_KEYWORD(TOK_ASSERT); } + else if (keyword == "assume") { if (formal_mode) return TOK_ASSUME; SV_KEYWORD(TOK_ASSUME); } + else if (keyword == "cover") { if (formal_mode) return TOK_COVER; SV_KEYWORD(TOK_COVER); } + else if (keyword == "restrict") { if (formal_mode) return TOK_RESTRICT; SV_KEYWORD(TOK_RESTRICT); } + else log_abort(); +} + "property" { if (formal_mode) return TOK_PROPERTY; SV_KEYWORD(TOK_PROPERTY); } "rand" { if (formal_mode) return TOK_RAND; SV_KEYWORD(TOK_RAND); } "const" { if (formal_mode) return TOK_CONST; SV_KEYWORD(TOK_CONST); } @@ -303,7 +350,7 @@ supply1 { return TOK_SUPPLY1; } [a-zA-Z_$][a-zA-Z0-9_$\.]* { frontend_verilog_yylval.string = new std::string(std::string("\\") + yytext); - return TOK_ID; + return TOK_ID; } "/*"[ \t]*(synopsys|synthesis)[ \t]*translate_off[ \t]*"*/" { diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index 2258f3f6f..649dd384f 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -106,6 +106,7 @@ static void free_attr(std::map *al) } %token TOK_STRING TOK_ID TOK_CONSTVAL TOK_REALVAL TOK_PRIMITIVE +%token TOK_ASSERT TOK_ASSUME TOK_RESTRICT TOK_COVER %token ATTR_BEGIN ATTR_END DEFATTR_BEGIN DEFATTR_END %token TOK_MODULE TOK_ENDMODULE TOK_PARAMETER TOK_LOCALPARAM TOK_DEFPARAM %token TOK_PACKAGE TOK_ENDPACKAGE TOK_PACKAGESEP @@ -119,14 +120,13 @@ static void free_attr(std::map *al) %token TOK_GENERATE TOK_ENDGENERATE TOK_GENVAR TOK_REAL %token TOK_SYNOPSYS_FULL_CASE TOK_SYNOPSYS_PARALLEL_CASE %token TOK_SUPPLY0 TOK_SUPPLY1 TOK_TO_SIGNED TOK_TO_UNSIGNED -%token TOK_POS_INDEXED TOK_NEG_INDEXED TOK_ASSERT TOK_ASSUME -%token TOK_RESTRICT TOK_COVER TOK_PROPERTY TOK_ENUM TOK_TYPEDEF +%token TOK_POS_INDEXED TOK_NEG_INDEXED TOK_PROPERTY TOK_ENUM TOK_TYPEDEF %token TOK_RAND TOK_CONST TOK_CHECKER TOK_ENDCHECKER TOK_EVENTUALLY %token TOK_INCREMENT TOK_DECREMENT TOK_UNIQUE TOK_PRIORITY %type range range_or_multirange non_opt_range non_opt_multirange range_or_signed_int %type wire_type expr basic_expr concat_list rvalue lvalue lvalue_concat_list -%type opt_label opt_stmt_label tok_prim_wrapper hierarchical_id +%type opt_label tok_prim_wrapper hierarchical_id %type opt_signed opt_property unique_case_attr %type attr case_attr @@ -1337,14 +1337,6 @@ opt_property: $$ = false; }; -opt_stmt_label: - TOK_ID ':' { - $$ = $1; - } | - /* empty */ { - $$ = NULL; - }; - modport_stmt: TOK_MODPORT TOK_ID { AstNode *modport = new AstNode(AST_MODPORT); @@ -1381,11 +1373,35 @@ modport_type_token: TOK_INPUT {current_modport_input = 1; current_modport_output = 0;} | TOK_OUTPUT {current_modport_input = 0; current_modport_output = 1;} assert: - opt_stmt_label TOK_ASSERT opt_property '(' expr ')' ';' { + TOK_ASSERT opt_property '(' expr ')' ';' { + if (noassert_mode) { + delete $4; + } else { + AstNode *node = new AstNode(assume_asserts_mode ? AST_ASSUME : AST_ASSERT, $4); + if ($1 != nullptr) + node->str = *$1; + ast_stack.back()->children.push_back(node); + } + if ($1 != nullptr) + delete $1; + } | + TOK_ASSUME opt_property '(' expr ')' ';' { + if (noassume_mode) { + delete $4; + } else { + AstNode *node = new AstNode(assert_assumes_mode ? AST_ASSERT : AST_ASSUME, $4); + if ($1 != nullptr) + node->str = *$1; + ast_stack.back()->children.push_back(node); + } + if ($1 != nullptr) + delete $1; + } | + TOK_ASSERT opt_property '(' TOK_EVENTUALLY expr ')' ';' { if (noassert_mode) { delete $5; } else { - AstNode *node = new AstNode(assume_asserts_mode ? AST_ASSUME : AST_ASSERT, $5); + AstNode *node = new AstNode(assume_asserts_mode ? AST_FAIR : AST_LIVE, $5); if ($1 != nullptr) node->str = *$1; ast_stack.back()->children.push_back(node); @@ -1393,11 +1409,11 @@ assert: if ($1 != nullptr) delete $1; } | - opt_stmt_label TOK_ASSUME opt_property '(' expr ')' ';' { + TOK_ASSUME opt_property '(' TOK_EVENTUALLY expr ')' ';' { if (noassume_mode) { delete $5; } else { - AstNode *node = new AstNode(assert_assumes_mode ? AST_ASSERT : AST_ASSUME, $5); + AstNode *node = new AstNode(assert_assumes_mode ? AST_LIVE : AST_FAIR, $5); if ($1 != nullptr) node->str = *$1; ast_stack.back()->children.push_back(node); @@ -1405,39 +1421,15 @@ assert: if ($1 != nullptr) delete $1; } | - opt_stmt_label TOK_ASSERT opt_property '(' TOK_EVENTUALLY expr ')' ';' { - if (noassert_mode) { - delete $6; - } else { - AstNode *node = new AstNode(assume_asserts_mode ? AST_FAIR : AST_LIVE, $6); - if ($1 != nullptr) - node->str = *$1; - ast_stack.back()->children.push_back(node); - } - if ($1 != nullptr) - delete $1; - } | - opt_stmt_label TOK_ASSUME opt_property '(' TOK_EVENTUALLY expr ')' ';' { - if (noassume_mode) { - delete $6; - } else { - AstNode *node = new AstNode(assert_assumes_mode ? AST_LIVE : AST_FAIR, $6); - if ($1 != nullptr) - node->str = *$1; - ast_stack.back()->children.push_back(node); - } - if ($1 != nullptr) - delete $1; - } | - opt_stmt_label TOK_COVER opt_property '(' expr ')' ';' { - AstNode *node = new AstNode(AST_COVER, $5); + TOK_COVER opt_property '(' expr ')' ';' { + AstNode *node = new AstNode(AST_COVER, $4); if ($1 != nullptr) { node->str = *$1; delete $1; } ast_stack.back()->children.push_back(node); } | - opt_stmt_label TOK_COVER opt_property '(' ')' ';' { + TOK_COVER opt_property '(' ')' ';' { AstNode *node = new AstNode(AST_COVER, AstNode::mkconst_int(1, false)); if ($1 != nullptr) { node->str = *$1; @@ -1445,7 +1437,7 @@ assert: } ast_stack.back()->children.push_back(node); } | - opt_stmt_label TOK_COVER ';' { + TOK_COVER ';' { AstNode *node = new AstNode(AST_COVER, AstNode::mkconst_int(1, false)); if ($1 != nullptr) { node->str = *$1; @@ -1453,30 +1445,30 @@ assert: } ast_stack.back()->children.push_back(node); } | - opt_stmt_label TOK_RESTRICT opt_property '(' expr ')' ';' { + TOK_RESTRICT opt_property '(' expr ')' ';' { if (norestrict_mode) { - delete $5; + delete $4; } else { - AstNode *node = new AstNode(AST_ASSUME, $5); + AstNode *node = new AstNode(AST_ASSUME, $4); if ($1 != nullptr) node->str = *$1; ast_stack.back()->children.push_back(node); } - if (!$3) + if (!$2) log_file_warning(current_filename, get_line_num(), "SystemVerilog does not allow \"restrict\" without \"property\".\n"); if ($1 != nullptr) delete $1; } | - opt_stmt_label TOK_RESTRICT opt_property '(' TOK_EVENTUALLY expr ')' ';' { + TOK_RESTRICT opt_property '(' TOK_EVENTUALLY expr ')' ';' { if (norestrict_mode) { - delete $6; + delete $5; } else { - AstNode *node = new AstNode(AST_FAIR, $6); + AstNode *node = new AstNode(AST_FAIR, $5); if ($1 != nullptr) node->str = *$1; ast_stack.back()->children.push_back(node); } - if (!$3) + if (!$2) log_file_warning(current_filename, get_line_num(), "SystemVerilog does not allow \"restrict\" without \"property\".\n"); if ($1 != nullptr) delete $1; @@ -1485,30 +1477,60 @@ assert: assert_property: TOK_ASSERT TOK_PROPERTY '(' expr ')' ';' { ast_stack.back()->children.push_back(new AstNode(assume_asserts_mode ? AST_ASSUME : AST_ASSERT, $4)); + if ($1 != nullptr) { + ast_stack.back()->children.back()->str = *$1; + delete $1; + } } | TOK_ASSUME TOK_PROPERTY '(' expr ')' ';' { ast_stack.back()->children.push_back(new AstNode(AST_ASSUME, $4)); + if ($1 != nullptr) { + ast_stack.back()->children.back()->str = *$1; + delete $1; + } } | TOK_ASSERT TOK_PROPERTY '(' TOK_EVENTUALLY expr ')' ';' { ast_stack.back()->children.push_back(new AstNode(assume_asserts_mode ? AST_FAIR : AST_LIVE, $5)); + if ($1 != nullptr) { + ast_stack.back()->children.back()->str = *$1; + delete $1; + } } | TOK_ASSUME TOK_PROPERTY '(' TOK_EVENTUALLY expr ')' ';' { ast_stack.back()->children.push_back(new AstNode(AST_FAIR, $5)); + if ($1 != nullptr) { + ast_stack.back()->children.back()->str = *$1; + delete $1; + } } | TOK_COVER TOK_PROPERTY '(' expr ')' ';' { ast_stack.back()->children.push_back(new AstNode(AST_COVER, $4)); + if ($1 != nullptr) { + ast_stack.back()->children.back()->str = *$1; + delete $1; + } } | TOK_RESTRICT TOK_PROPERTY '(' expr ')' ';' { - if (norestrict_mode) + if (norestrict_mode) { delete $4; - else + } else { ast_stack.back()->children.push_back(new AstNode(AST_ASSUME, $4)); + if ($1 != nullptr) { + ast_stack.back()->children.back()->str = *$1; + delete $1; + } + } } | TOK_RESTRICT TOK_PROPERTY '(' TOK_EVENTUALLY expr ')' ';' { - if (norestrict_mode) + if (norestrict_mode) { delete $5; - else + } else { ast_stack.back()->children.push_back(new AstNode(AST_FAIR, $5)); + if ($1 != nullptr) { + ast_stack.back()->children.back()->str = *$1; + delete $1; + } + } }; simple_behavioral_stmt: From 399ab16315468df95fc8a180d384d2ce8eed8049 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 9 Mar 2019 11:52:00 -0800 Subject: [PATCH 66/76] Add $dffsr support to async2sync Signed-off-by: Clifford Wolf --- passes/sat/async2sync.cc | 53 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 51 insertions(+), 2 deletions(-) diff --git a/passes/sat/async2sync.cc b/passes/sat/async2sync.cc index c92db7118..d045d0dcb 100644 --- a/passes/sat/async2sync.cc +++ b/passes/sat/async2sync.cc @@ -39,7 +39,7 @@ struct Async2syncPass : public Pass { log("reset value in the next cycle regardless of the data-in value at the time of\n"); log("the clock edge.\n"); log("\n"); - log("Currently only $adff cells are supported by this pass.\n"); + log("Currently only $adff and $dffsr cells are supported by this pass.\n"); log("\n"); } void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE @@ -84,7 +84,7 @@ struct Async2syncPass : public Pass { bool arst_pol = cell->parameters["\\ARST_POLARITY"].as_bool(); Const arst_val = cell->parameters["\\ARST_VALUE"]; - SigSpec sig_clk = cell->getPort("\\CLK"); + // SigSpec sig_clk = cell->getPort("\\CLK"); SigSpec sig_arst = cell->getPort("\\ARST"); SigSpec sig_d = cell->getPort("\\D"); SigSpec sig_q = cell->getPort("\\Q"); @@ -120,6 +120,55 @@ struct Async2syncPass : public Pass { cell->type = "$dff"; continue; } + + if (cell->type.in("$dffsr")) + { + // bool clk_pol = cell->parameters["\\CLK_POLARITY"].as_bool(); + bool set_pol = cell->parameters["\\SET_POLARITY"].as_bool(); + bool clr_pol = cell->parameters["\\CLR_POLARITY"].as_bool(); + + // SigSpec sig_clk = cell->getPort("\\CLK"); + SigSpec sig_set = cell->getPort("\\SET"); + SigSpec sig_clr = cell->getPort("\\CLR"); + SigSpec sig_d = cell->getPort("\\D"); + SigSpec sig_q = cell->getPort("\\Q"); + + log("Replacing %s.%s (%s): SET=%s, CLR=%s, D=%s, Q=%s\n", + log_id(module), log_id(cell), log_id(cell->type), + log_signal(sig_set), log_signal(sig_clr), log_signal(sig_d), log_signal(sig_q)); + + Const init_val; + for (int i = 0; i < GetSize(sig_q); i++) { + SigBit bit = sigmap(sig_q[i]); + init_val.bits.push_back(initbits.count(bit) ? initbits.at(bit) : State::Sx); + del_initbits.insert(bit); + } + + Wire *new_d = module->addWire(NEW_ID, GetSize(sig_d)); + Wire *new_q = module->addWire(NEW_ID, GetSize(sig_q)); + new_q->attributes["\\init"] = init_val; + + if (!set_pol) + sig_set = module->Not(NEW_ID, sig_set); + + if (clr_pol) + sig_clr = module->Not(NEW_ID, sig_clr); + + SigSpec tmp = module->Or(NEW_ID, sig_d, sig_set); + module->addAnd(NEW_ID, tmp, sig_clr, new_d); + + tmp = module->Or(NEW_ID, new_q, sig_set); + module->addAnd(NEW_ID, tmp, sig_clr, sig_q); + + cell->setPort("\\D", new_d); + cell->setPort("\\Q", new_q); + cell->unsetPort("\\SET"); + cell->unsetPort("\\CLR"); + cell->unsetParam("\\SET_POLARITY"); + cell->unsetParam("\\CLR_POLARITY"); + cell->type = "$dff"; + continue; + } } for (auto wire : module->wires()) From 94f995ee3784e1a94a484fd399be2be4793d4e41 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 9 Mar 2019 13:19:41 -0800 Subject: [PATCH 67/76] Fix signed $shift/$shiftx handling in write_smt2 Signed-off-by: Clifford Wolf --- backends/smt2/smt2.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/backends/smt2/smt2.cc b/backends/smt2/smt2.cc index a26bff57b..688535f33 100644 --- a/backends/smt2/smt2.cc +++ b/backends/smt2/smt2.cc @@ -416,6 +416,7 @@ struct Smt2Worker for (char ch : expr) { if (ch == 'A') processed_expr += get_bv(sig_a); else if (ch == 'B') processed_expr += get_bv(sig_b); + else if (ch == 'P') processed_expr += get_bv(cell->getPort("\\B")); else if (ch == 'L') processed_expr += is_signed ? "a" : "l"; else if (ch == 'U') processed_expr += is_signed ? "s" : "u"; else processed_expr += ch; @@ -554,7 +555,7 @@ struct Smt2Worker if (cell->type.in("$shift", "$shiftx")) { if (cell->getParam("\\B_SIGNED").as_bool()) { - return export_bvop(cell, stringf("(ite (bvsge B #b%0*d) " + return export_bvop(cell, stringf("(ite (bvsge P #b%0*d) " "(bvlshr A B) (bvlshr A (bvneg B)))", GetSize(cell->getPort("\\B")), 0), 's'); } else { From ff4c2a14ae34eeb899c3cf0ca1109f0106b41679 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 9 Mar 2019 13:24:55 -0800 Subject: [PATCH 68/76] Fix typo in ice40_braminit help msg Signed-off-by: Clifford Wolf --- techlibs/ice40/ice40_braminit.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/techlibs/ice40/ice40_braminit.cc b/techlibs/ice40/ice40_braminit.cc index bf12f9148..4fa6b0792 100644 --- a/techlibs/ice40/ice40_braminit.cc +++ b/techlibs/ice40/ice40_braminit.cc @@ -135,7 +135,7 @@ struct Ice40BRAMInitPass : public Pass { log(" ice40_braminit\n"); log("\n"); log("This command processes all SB_RAM40_4K blocks with a non-empty INIT_FILE\n"); - log("parameter and converts it inti the required INIT_x attributes\n"); + log("parameter and converts it into the required INIT_x attributes\n"); log("\n"); } void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE From b02d9c2634de0898b2c483c438ba56540e0f3f69 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 10 Mar 2019 16:27:18 -0700 Subject: [PATCH 69/76] Fix handling of cases that look like sva labels, fixes #862 Signed-off-by: Clifford Wolf --- frontends/verilog/verilog_lexer.l | 59 +++---------- frontends/verilog/verilog_parser.y | 131 ++++++++++++++++------------- 2 files changed, 82 insertions(+), 108 deletions(-) diff --git a/frontends/verilog/verilog_lexer.l b/frontends/verilog/verilog_lexer.l index e51a12f76..6ef38252a 100644 --- a/frontends/verilog/verilog_lexer.l +++ b/frontends/verilog/verilog_lexer.l @@ -189,57 +189,18 @@ YOSYS_NAMESPACE_END "always_ff" { SV_KEYWORD(TOK_ALWAYS); } "always_latch" { SV_KEYWORD(TOK_ALWAYS); } - /* parse labels on assert, assume, cover, and restrict right here because it's insanley complex - to do it in the parser (because we force the parser too early to reduce when parsing cells..) */ -([a-zA-Z_$][a-zA-Z0-9_$]*[ \t\r\n]*:[ \t\r\n]*)?(assert|assume|cover|restrict)/[^a-zA-Z0-9_$\.] { - frontend_verilog_yylval.string = new std::string(yytext); - auto &str = *frontend_verilog_yylval.string; - std::string keyword; - int cursor = 0; - - while (1) { - if (cursor == GetSize(str)) { - keyword = str; - delete frontend_verilog_yylval.string; - frontend_verilog_yylval.string = nullptr; - goto sva_without_label; - } - char c = str[cursor]; - if (c != ' ' && c != '\t' && c != '\r' && c != '\n' && c != ':') { - cursor++; - continue; - } - - keyword = str.substr(cursor); - str = "\\" + str.substr(0, cursor); - break; - } - - cursor = 0; - while (1) { - log_assert(cursor < GetSize(keyword)); - char c = keyword[cursor]; - if (c != ' ' && c != '\t' && c != '\r' && c != '\n' && c != ':') { - keyword = keyword.substr(cursor); - break; - } - cursor++; - } - - if (keyword == "assert") { return TOK_ASSERT; } - else if (keyword == "assume") { return TOK_ASSUME; } - else if (keyword == "cover") { return TOK_COVER; } - else if (keyword == "restrict") { return TOK_RESTRICT; } - else log_abort(); - -sva_without_label: - if (keyword == "assert") { if (formal_mode) return TOK_ASSERT; SV_KEYWORD(TOK_ASSERT); } - else if (keyword == "assume") { if (formal_mode) return TOK_ASSUME; SV_KEYWORD(TOK_ASSUME); } - else if (keyword == "cover") { if (formal_mode) return TOK_COVER; SV_KEYWORD(TOK_COVER); } - else if (keyword == "restrict") { if (formal_mode) return TOK_RESTRICT; SV_KEYWORD(TOK_RESTRICT); } - else log_abort(); + /* use special token for labels on assert, assume, cover, and restrict because it's insanley complex + to fix parsing of cells otherwise. (the current cell parser forces a reduce very early to update some + global state.. its a mess) */ +[a-zA-Z_$][a-zA-Z0-9_$]*/[ \t\r\n]*:[ \t\r\n]*(assert|assume|cover|restrict)[^a-zA-Z0-9_$\.] { + frontend_verilog_yylval.string = new std::string(std::string("\\") + yytext); + return TOK_SVA_LABEL; } +"assert" { if (formal_mode) return TOK_ASSERT; SV_KEYWORD(TOK_ASSERT); } +"assume" { if (formal_mode) return TOK_ASSUME; SV_KEYWORD(TOK_ASSUME); } +"cover" { if (formal_mode) return TOK_COVER; SV_KEYWORD(TOK_COVER); } +"restrict" { if (formal_mode) return TOK_RESTRICT; SV_KEYWORD(TOK_RESTRICT); } "property" { if (formal_mode) return TOK_PROPERTY; SV_KEYWORD(TOK_PROPERTY); } "rand" { if (formal_mode) return TOK_RAND; SV_KEYWORD(TOK_RAND); } "const" { if (formal_mode) return TOK_CONST; SV_KEYWORD(TOK_CONST); } diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index 649dd384f..52685f637 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -105,8 +105,8 @@ static void free_attr(std::map *al) bool boolean; } -%token TOK_STRING TOK_ID TOK_CONSTVAL TOK_REALVAL TOK_PRIMITIVE -%token TOK_ASSERT TOK_ASSUME TOK_RESTRICT TOK_COVER +%token TOK_STRING TOK_ID TOK_CONSTVAL TOK_REALVAL TOK_PRIMITIVE TOK_SVA_LABEL +%token TOK_ASSERT TOK_ASSUME TOK_RESTRICT TOK_COVER %token ATTR_BEGIN ATTR_END DEFATTR_BEGIN DEFATTR_END %token TOK_MODULE TOK_ENDMODULE TOK_PARAMETER TOK_LOCALPARAM TOK_DEFPARAM %token TOK_PACKAGE TOK_ENDPACKAGE TOK_PACKAGESEP @@ -126,7 +126,7 @@ static void free_attr(std::map *al) %type range range_or_multirange non_opt_range non_opt_multirange range_or_signed_int %type wire_type expr basic_expr concat_list rvalue lvalue lvalue_concat_list -%type opt_label tok_prim_wrapper hierarchical_id +%type opt_label opt_sva_label tok_prim_wrapper hierarchical_id %type opt_signed opt_property unique_case_attr %type attr case_attr @@ -1329,6 +1329,14 @@ opt_label: $$ = NULL; }; +opt_sva_label: + TOK_SVA_LABEL ':' { + $$ = $1; + } | + /* empty */ { + $$ = NULL; + }; + opt_property: TOK_PROPERTY { $$ = true; @@ -1373,35 +1381,11 @@ modport_type_token: TOK_INPUT {current_modport_input = 1; current_modport_output = 0;} | TOK_OUTPUT {current_modport_input = 0; current_modport_output = 1;} assert: - TOK_ASSERT opt_property '(' expr ')' ';' { - if (noassert_mode) { - delete $4; - } else { - AstNode *node = new AstNode(assume_asserts_mode ? AST_ASSUME : AST_ASSERT, $4); - if ($1 != nullptr) - node->str = *$1; - ast_stack.back()->children.push_back(node); - } - if ($1 != nullptr) - delete $1; - } | - TOK_ASSUME opt_property '(' expr ')' ';' { - if (noassume_mode) { - delete $4; - } else { - AstNode *node = new AstNode(assert_assumes_mode ? AST_ASSERT : AST_ASSUME, $4); - if ($1 != nullptr) - node->str = *$1; - ast_stack.back()->children.push_back(node); - } - if ($1 != nullptr) - delete $1; - } | - TOK_ASSERT opt_property '(' TOK_EVENTUALLY expr ')' ';' { + opt_sva_label TOK_ASSERT opt_property '(' expr ')' ';' { if (noassert_mode) { delete $5; } else { - AstNode *node = new AstNode(assume_asserts_mode ? AST_FAIR : AST_LIVE, $5); + AstNode *node = new AstNode(assume_asserts_mode ? AST_ASSUME : AST_ASSERT, $5); if ($1 != nullptr) node->str = *$1; ast_stack.back()->children.push_back(node); @@ -1409,11 +1393,11 @@ assert: if ($1 != nullptr) delete $1; } | - TOK_ASSUME opt_property '(' TOK_EVENTUALLY expr ')' ';' { + opt_sva_label TOK_ASSUME opt_property '(' expr ')' ';' { if (noassume_mode) { delete $5; } else { - AstNode *node = new AstNode(assert_assumes_mode ? AST_LIVE : AST_FAIR, $5); + AstNode *node = new AstNode(assert_assumes_mode ? AST_ASSERT : AST_ASSUME, $5); if ($1 != nullptr) node->str = *$1; ast_stack.back()->children.push_back(node); @@ -1421,15 +1405,39 @@ assert: if ($1 != nullptr) delete $1; } | - TOK_COVER opt_property '(' expr ')' ';' { - AstNode *node = new AstNode(AST_COVER, $4); + opt_sva_label TOK_ASSERT opt_property '(' TOK_EVENTUALLY expr ')' ';' { + if (noassert_mode) { + delete $6; + } else { + AstNode *node = new AstNode(assume_asserts_mode ? AST_FAIR : AST_LIVE, $6); + if ($1 != nullptr) + node->str = *$1; + ast_stack.back()->children.push_back(node); + } + if ($1 != nullptr) + delete $1; + } | + opt_sva_label TOK_ASSUME opt_property '(' TOK_EVENTUALLY expr ')' ';' { + if (noassume_mode) { + delete $6; + } else { + AstNode *node = new AstNode(assert_assumes_mode ? AST_LIVE : AST_FAIR, $6); + if ($1 != nullptr) + node->str = *$1; + ast_stack.back()->children.push_back(node); + } + if ($1 != nullptr) + delete $1; + } | + opt_sva_label TOK_COVER opt_property '(' expr ')' ';' { + AstNode *node = new AstNode(AST_COVER, $5); if ($1 != nullptr) { node->str = *$1; delete $1; } ast_stack.back()->children.push_back(node); } | - TOK_COVER opt_property '(' ')' ';' { + opt_sva_label TOK_COVER opt_property '(' ')' ';' { AstNode *node = new AstNode(AST_COVER, AstNode::mkconst_int(1, false)); if ($1 != nullptr) { node->str = *$1; @@ -1437,7 +1445,7 @@ assert: } ast_stack.back()->children.push_back(node); } | - TOK_COVER ';' { + opt_sva_label TOK_COVER ';' { AstNode *node = new AstNode(AST_COVER, AstNode::mkconst_int(1, false)); if ($1 != nullptr) { node->str = *$1; @@ -1445,87 +1453,87 @@ assert: } ast_stack.back()->children.push_back(node); } | - TOK_RESTRICT opt_property '(' expr ')' ';' { + opt_sva_label TOK_RESTRICT opt_property '(' expr ')' ';' { if (norestrict_mode) { - delete $4; + delete $5; } else { - AstNode *node = new AstNode(AST_ASSUME, $4); + AstNode *node = new AstNode(AST_ASSUME, $5); if ($1 != nullptr) node->str = *$1; ast_stack.back()->children.push_back(node); } - if (!$2) + if (!$3) log_file_warning(current_filename, get_line_num(), "SystemVerilog does not allow \"restrict\" without \"property\".\n"); if ($1 != nullptr) delete $1; } | - TOK_RESTRICT opt_property '(' TOK_EVENTUALLY expr ')' ';' { + opt_sva_label TOK_RESTRICT opt_property '(' TOK_EVENTUALLY expr ')' ';' { if (norestrict_mode) { - delete $5; + delete $6; } else { - AstNode *node = new AstNode(AST_FAIR, $5); + AstNode *node = new AstNode(AST_FAIR, $6); if ($1 != nullptr) node->str = *$1; ast_stack.back()->children.push_back(node); } - if (!$2) + if (!$3) log_file_warning(current_filename, get_line_num(), "SystemVerilog does not allow \"restrict\" without \"property\".\n"); if ($1 != nullptr) delete $1; }; assert_property: - TOK_ASSERT TOK_PROPERTY '(' expr ')' ';' { - ast_stack.back()->children.push_back(new AstNode(assume_asserts_mode ? AST_ASSUME : AST_ASSERT, $4)); + opt_sva_label TOK_ASSERT TOK_PROPERTY '(' expr ')' ';' { + ast_stack.back()->children.push_back(new AstNode(assume_asserts_mode ? AST_ASSUME : AST_ASSERT, $5)); if ($1 != nullptr) { ast_stack.back()->children.back()->str = *$1; delete $1; } } | - TOK_ASSUME TOK_PROPERTY '(' expr ')' ';' { - ast_stack.back()->children.push_back(new AstNode(AST_ASSUME, $4)); + opt_sva_label TOK_ASSUME TOK_PROPERTY '(' expr ')' ';' { + ast_stack.back()->children.push_back(new AstNode(AST_ASSUME, $5)); if ($1 != nullptr) { ast_stack.back()->children.back()->str = *$1; delete $1; } } | - TOK_ASSERT TOK_PROPERTY '(' TOK_EVENTUALLY expr ')' ';' { - ast_stack.back()->children.push_back(new AstNode(assume_asserts_mode ? AST_FAIR : AST_LIVE, $5)); + opt_sva_label TOK_ASSERT TOK_PROPERTY '(' TOK_EVENTUALLY expr ')' ';' { + ast_stack.back()->children.push_back(new AstNode(assume_asserts_mode ? AST_FAIR : AST_LIVE, $6)); if ($1 != nullptr) { ast_stack.back()->children.back()->str = *$1; delete $1; } } | - TOK_ASSUME TOK_PROPERTY '(' TOK_EVENTUALLY expr ')' ';' { - ast_stack.back()->children.push_back(new AstNode(AST_FAIR, $5)); + opt_sva_label TOK_ASSUME TOK_PROPERTY '(' TOK_EVENTUALLY expr ')' ';' { + ast_stack.back()->children.push_back(new AstNode(AST_FAIR, $6)); if ($1 != nullptr) { ast_stack.back()->children.back()->str = *$1; delete $1; } } | - TOK_COVER TOK_PROPERTY '(' expr ')' ';' { - ast_stack.back()->children.push_back(new AstNode(AST_COVER, $4)); + opt_sva_label TOK_COVER TOK_PROPERTY '(' expr ')' ';' { + ast_stack.back()->children.push_back(new AstNode(AST_COVER, $5)); if ($1 != nullptr) { ast_stack.back()->children.back()->str = *$1; delete $1; } } | - TOK_RESTRICT TOK_PROPERTY '(' expr ')' ';' { + opt_sva_label TOK_RESTRICT TOK_PROPERTY '(' expr ')' ';' { if (norestrict_mode) { - delete $4; + delete $5; } else { - ast_stack.back()->children.push_back(new AstNode(AST_ASSUME, $4)); + ast_stack.back()->children.push_back(new AstNode(AST_ASSUME, $5)); if ($1 != nullptr) { ast_stack.back()->children.back()->str = *$1; delete $1; } } } | - TOK_RESTRICT TOK_PROPERTY '(' TOK_EVENTUALLY expr ')' ';' { + opt_sva_label TOK_RESTRICT TOK_PROPERTY '(' TOK_EVENTUALLY expr ')' ';' { if (norestrict_mode) { - delete $5; + delete $6; } else { - ast_stack.back()->children.push_back(new AstNode(AST_FAIR, $5)); + ast_stack.back()->children.push_back(new AstNode(AST_FAIR, $6)); if ($1 != nullptr) { ast_stack.back()->children.back()->str = *$1; delete $1; @@ -1748,6 +1756,11 @@ case_expr_list: TOK_DEFAULT { ast_stack.back()->children.push_back(new AstNode(AST_DEFAULT)); } | + TOK_SVA_LABEL { + ast_stack.back()->children.push_back(new AstNode(AST_IDENTIFIER)); + ast_stack.back()->children.back()->str = *$1; + delete $1; + } | expr { ast_stack.back()->children.push_back($1); } | From d9bb5f3637634ea214194b612aee4bb0c62d7a5c Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Mon, 11 Mar 2019 01:08:36 -0700 Subject: [PATCH 70/76] Add ENABLE_GLOB Makefile switch Signed-off-by: Clifford Wolf --- Makefile | 5 +++++ kernel/yosys.cc | 8 +++++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 8e93cd285..b8fbcc040 100644 --- a/Makefile +++ b/Makefile @@ -10,6 +10,7 @@ CONFIG := clang # features (the more the better) ENABLE_TCL := 1 ENABLE_ABC := 1 +ENABLE_GLOB := 1 ENABLE_PLUGINS := 1 ENABLE_READLINE := 1 ENABLE_EDITLINE := 0 @@ -298,6 +299,10 @@ LDLIBS += -ldl endif endif +ifeq ($(ENABLE_GLOB),1) +CXXFLAGS += -DYOSYS_ENABLE_GLOB +endif + ifeq ($(ENABLE_TCL),1) TCL_VERSION ?= tcl$(shell bash -c "tclsh <(echo 'puts [info tclversion]')") ifeq ($(OS), FreeBSD) diff --git a/kernel/yosys.cc b/kernel/yosys.cc index 2ed0f4db4..6fd53f85e 100644 --- a/kernel/yosys.cc +++ b/kernel/yosys.cc @@ -33,7 +33,7 @@ # include #endif -#ifdef _WIN32 +#if defined(_WIN32) # include # include #elif defined(__APPLE__) @@ -41,13 +41,15 @@ # include # include # include -# include #else # include # include # include # include # include +#endif + +#if !defined(_WIN32) && defined(YOSYS_ENABLE_GLOB) # include #endif @@ -564,7 +566,7 @@ std::vector glob_filename(const std::string &filename_pattern) { std::vector results; -#ifdef _WIN32 +#if defined(_WIN32) || !defined(YOSYS_ENABLE_GLOB) results.push_back(filename_pattern); #else glob_t globbuf; From 20c6a8c9b0abb384517c4cc6f58cd29a90bda6ff Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Mon, 11 Mar 2019 20:12:28 +0100 Subject: [PATCH 71/76] Improve determinism of IdString DB for similar scripts Signed-off-by: Clifford Wolf --- backends/verilog/verilog_backend.cc | 4 ++ kernel/log.cc | 4 ++ kernel/register.cc | 2 + kernel/rtlil.cc | 2 + kernel/rtlil.h | 64 ++++++++++++++++++++++++++--- 5 files changed, 71 insertions(+), 5 deletions(-) diff --git a/backends/verilog/verilog_backend.cc b/backends/verilog/verilog_backend.cc index 6818edb7a..83d83f488 100644 --- a/backends/verilog/verilog_backend.cc +++ b/backends/verilog/verilog_backend.cc @@ -1673,6 +1673,8 @@ struct VerilogBackend : public Backend { bool blackboxes = false; bool selected = false; + auto_name_map.clear(); + reg_wires.clear(); reg_ct.clear(); reg_ct.insert("$dff"); @@ -1779,6 +1781,8 @@ struct VerilogBackend : public Backend { dump_module(*f, "", it->second); } + auto_name_map.clear(); + reg_wires.clear(); reg_ct.clear(); } } VerilogBackend; diff --git a/kernel/log.cc b/kernel/log.cc index 0ee2170a0..400a549dd 100644 --- a/kernel/log.cc +++ b/kernel/log.cc @@ -196,7 +196,11 @@ void logv_header(RTLIL::Design *design, const char *format, va_list ap) if (log_hdump.count(header_id) && design != nullptr) for (auto &filename : log_hdump.at(header_id)) { log("Dumping current design to '%s'.\n", filename.c_str()); + if (yosys_xtrace) + IdString::xtrace_db_dump(); Pass::call(design, {"dump", "-o", filename}); + if (yosys_xtrace) + log("#X# -- end of dump --\n"); } if (pop_errfile) diff --git a/kernel/register.cc b/kernel/register.cc index 402a5b3ea..64956401f 100644 --- a/kernel/register.cc +++ b/kernel/register.cc @@ -86,6 +86,8 @@ Pass::pre_post_exec_state_t Pass::pre_execute() void Pass::post_execute(Pass::pre_post_exec_state_t state) { + IdString::checkpoint(); + int64_t time_ns = PerformanceTimer::query() - state.begin_ns; runtime_ns += time_ns; current_pass = state.parent_pass; diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index d4aebcda9..7f1816190 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -33,6 +33,8 @@ std::vector RTLIL::IdString::global_refcount_storage_; std::vector RTLIL::IdString::global_id_storage_; dict RTLIL::IdString::global_id_index_; std::vector RTLIL::IdString::global_free_idx_list_; +int RTLIL::IdString::last_created_idx_[8]; +int RTLIL::IdString::last_created_idx_ptr_; RTLIL::Const::Const() { diff --git a/kernel/rtlil.h b/kernel/rtlil.h index f877622aa..01323d112 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -76,6 +76,9 @@ namespace RTLIL struct IdString { + #undef YOSYS_XTRACE_GET_PUT + #undef YOSYS_SORT_ID_FREE_LIST + // the global id string cache static struct destruct_guard_t { @@ -89,9 +92,43 @@ namespace RTLIL static dict global_id_index_; static std::vector global_free_idx_list_; + static int last_created_idx_ptr_; + static int last_created_idx_[8]; + + static inline void xtrace_db_dump() + { + #ifdef YOSYS_XTRACE_GET_PUT + for (int idx = 0; idx < GetSize(global_id_storage_); idx++) + { + if (global_id_storage_.at(idx) == nullptr) + log("#X# DB-DUMP index %d: FREE\n", idx); + else + log("#X# DB-DUMP index %d: '%s' (ref %d)\n", idx, global_id_storage_.at(idx), global_refcount_storage_.at(idx)); + } + #endif + } + + static inline void checkpoint() + { + last_created_idx_ptr_ = 0; + for (int i = 0; i < 8; i++) { + if (last_created_idx_[i]) + put_reference(last_created_idx_[i]); + last_created_idx_[i] = 0; + } + #ifdef YOSYS_SORT_ID_FREE_LIST + std::sort(global_free_idx_list_.begin(), global_free_idx_list_.end(), std::greater()); + #endif + } + static inline int get_reference(int idx) { global_refcount_storage_.at(idx)++; + #ifdef YOSYS_XTRACE_GET_PUT + if (yosys_xtrace) { + log("#X# GET-BY-INDEX '%s' (index %d, refcount %d)\n", global_id_storage_.at(idx), idx, global_refcount_storage_.at(idx)); + } + #endif return idx; } @@ -107,6 +144,11 @@ namespace RTLIL auto it = global_id_index_.find((char*)p); if (it != global_id_index_.end()) { global_refcount_storage_.at(it->second)++; + #ifdef YOSYS_XTRACE_GET_PUT + if (yosys_xtrace) { + log("#X# GET-BY-NAME '%s' (index %d, refcount %d)\n", global_id_storage_.at(it->second), it->second, global_refcount_storage_.at(it->second)); + } + #endif return it->second; } @@ -124,16 +166,22 @@ namespace RTLIL global_refcount_storage_.at(idx)++; // Avoid Create->Delete->Create pattern - static IdString last_created_id; - put_reference(last_created_id.index_); - last_created_id.index_ = idx; - get_reference(last_created_id.index_); + if (last_created_idx_[last_created_idx_ptr_]) + put_reference(last_created_idx_[last_created_idx_ptr_]); + last_created_idx_[last_created_idx_ptr_] = idx; + get_reference(last_created_idx_[last_created_idx_ptr_]); + last_created_idx_ptr_ = (last_created_idx_ptr_ + 1) & 7; if (yosys_xtrace) { log("#X# New IdString '%s' with index %d.\n", p, idx); log_backtrace("-X- ", yosys_xtrace-1); } + #ifdef YOSYS_XTRACE_GET_PUT + if (yosys_xtrace) { + log("#X# GET-BY-NAME '%s' (index %d, refcount %d)\n", global_id_storage_.at(idx), idx, global_refcount_storage_.at(idx)); + } + #endif return idx; } @@ -144,6 +192,12 @@ namespace RTLIL if (!destruct_guard.ok) return; + #ifdef YOSYS_XTRACE_GET_PUT + if (yosys_xtrace) { + log("#X# PUT '%s' (index %d, refcount %d)\n", global_id_storage_.at(idx), idx, global_refcount_storage_.at(idx)); + } + #endif + log_assert(global_refcount_storage_.at(idx) > 0); if (--global_refcount_storage_.at(idx) != 0) @@ -1282,7 +1336,7 @@ inline bool RTLIL::SigBit::operator<(const RTLIL::SigBit &other) const { return wire ? (offset < other.offset) : (data < other.data); if (wire != nullptr && other.wire != nullptr) return wire->name < other.wire->name; - return wire < other.wire; + return (wire != nullptr) < (other.wire != nullptr); } inline bool RTLIL::SigBit::operator==(const RTLIL::SigBit &other) const { From ab5b50ae3c9e63fe3da3ae0451500c1cb5be1743 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 12 Mar 2019 20:09:47 +0100 Subject: [PATCH 72/76] Only set MEM2REG_FL_CONST_LHS/MEM2REG_FL_VAR_LHS for non-init writes, fixes #867 Signed-off-by: Clifford Wolf --- frontends/ast/simplify.cc | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index ae7dec88d..f747a07cd 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -2954,12 +2954,14 @@ void AstNode::mem2reg_as_needed_pass1(dict> &mem2reg proc_flags[mem] |= AstNode::MEM2REG_FL_EQ1; } - // remember if this is a constant index or not - if (children[0]->children.size() && children[0]->children[0]->type == AST_RANGE && children[0]->children[0]->children.size()) { - if (children[0]->children[0]->children[0]->type == AST_CONSTANT) - mem2reg_candidates[mem] |= AstNode::MEM2REG_FL_CONST_LHS; - else - mem2reg_candidates[mem] |= AstNode::MEM2REG_FL_VAR_LHS; + // for proper (non-init) writes: remember if this is a constant index or not + if ((flags & MEM2REG_FL_INIT) == 0) { + if (children[0]->children.size() && children[0]->children[0]->type == AST_RANGE && children[0]->children[0]->children.size()) { + if (children[0]->children[0]->children[0]->type == AST_CONSTANT) + mem2reg_candidates[mem] |= AstNode::MEM2REG_FL_CONST_LHS; + else + mem2reg_candidates[mem] |= AstNode::MEM2REG_FL_VAR_LHS; + } } // remember where this is From a4ddc569b4c0e51e89317ade8c4183f41acc1cb5 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 12 Mar 2019 20:10:55 +0100 Subject: [PATCH 73/76] Remove outdated "blocking assignment to memory" warning Signed-off-by: Clifford Wolf --- frontends/ast/simplify.cc | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index f747a07cd..de300bbce 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -50,7 +50,6 @@ using namespace AST_INTERNAL; bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, int width_hint, bool sign_hint, bool in_param) { static int recursion_counter = 0; - static pair last_blocking_assignment_warn; static bool deep_recursion_warning = false; if (recursion_counter++ == 1000 && deep_recursion_warning) { @@ -72,7 +71,6 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, if (stage == 0) { log_assert(type == AST_MODULE || type == AST_INTERFACE); - last_blocking_assignment_warn = pair(); deep_recursion_warning = true; while (simplify(const_fold, at_zero, in_lvalue, 1, width_hint, sign_hint, in_param)) { } @@ -1592,14 +1590,6 @@ skip_dynamic_range_lvalue_expansion:; sstr << "$memwr$" << children[0]->str << "$" << filename << ":" << linenum << "$" << (autoidx++); std::string id_addr = sstr.str() + "_ADDR", id_data = sstr.str() + "_DATA", id_en = sstr.str() + "_EN"; - if (type == AST_ASSIGN_EQ) { - pair this_blocking_assignment_warn(filename, linenum); - if (this_blocking_assignment_warn != last_blocking_assignment_warn) - log_warning("Blocking assignment to memory in line %s:%d is handled like a non-blocking assignment.\n", - filename.c_str(), linenum); - last_blocking_assignment_warn = this_blocking_assignment_warn; - } - int mem_width, mem_size, addr_bits; bool mem_signed = children[0]->id2ast->is_signed; children[0]->id2ast->meminfo(mem_width, mem_size, addr_bits); From d25a0c8adeb421246732539b19738a8e68fc1315 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 12 Mar 2019 20:12:02 +0100 Subject: [PATCH 74/76] Improve handling of memories used in mem index expressions on LHS of an assignment Signed-off-by: Clifford Wolf --- frontends/ast/simplify.cc | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index de300bbce..1c9932ee0 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -2918,7 +2918,7 @@ void AstNode::mem2reg_as_needed_pass1(dict> &mem2reg dict &mem2reg_candidates, dict &proc_flags, uint32_t &flags) { uint32_t children_flags = 0; - int ignore_children_counter = 0; + int lhs_children_counter = 0; if (type == AST_ASSIGN || type == AST_ASSIGN_LE || type == AST_ASSIGN_EQ) { @@ -2966,7 +2966,7 @@ void AstNode::mem2reg_as_needed_pass1(dict> &mem2reg } } - ignore_children_counter = 1; + lhs_children_counter = 1; } if (type == AST_IDENTIFIER && id2ast && id2ast->type == AST_MEMORY) @@ -3009,12 +3009,23 @@ void AstNode::mem2reg_as_needed_pass1(dict> &mem2reg log_assert((flags & ~0x000000ff) == 0); for (auto child : children) - if (ignore_children_counter > 0) - ignore_children_counter--; - else if (proc_flags_p) + { + if (lhs_children_counter > 0) { + lhs_children_counter--; + if (child->children.size() && child->children[0]->type == AST_RANGE && child->children[0]->children.size()) { + for (auto c : child->children[0]->children) { + if (proc_flags_p) + c->mem2reg_as_needed_pass1(mem2reg_places, mem2reg_candidates, *proc_flags_p, flags); + else + c->mem2reg_as_needed_pass1(mem2reg_places, mem2reg_candidates, proc_flags, flags); + } + } + } else + if (proc_flags_p) child->mem2reg_as_needed_pass1(mem2reg_places, mem2reg_candidates, *proc_flags_p, flags); else child->mem2reg_as_needed_pass1(mem2reg_places, mem2reg_candidates, proc_flags, flags); + } flags &= ~children_flags | backup_flags; From 9284cf92b8dcb510a2a9511965e587e42944c543 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 12 Mar 2019 20:14:18 +0100 Subject: [PATCH 75/76] Remove ice40/cells_sim.v hack to avoid warning for blocking memory writes Signed-off-by: Clifford Wolf --- techlibs/ice40/cells_sim.v | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/techlibs/ice40/cells_sim.v b/techlibs/ice40/cells_sim.v index bc36cdd14..62a28364b 100644 --- a/techlibs/ice40/cells_sim.v +++ b/techlibs/ice40/cells_sim.v @@ -414,24 +414,6 @@ module SB_RAM40_4K ( $readmemh(INIT_FILE, memory); else for (i=0; i<16; i=i+1) begin -`ifdef YOSYS - memory[ 0*16 + i] <= INIT_0[16*i +: 16]; - memory[ 1*16 + i] <= INIT_1[16*i +: 16]; - memory[ 2*16 + i] <= INIT_2[16*i +: 16]; - memory[ 3*16 + i] <= INIT_3[16*i +: 16]; - memory[ 4*16 + i] <= INIT_4[16*i +: 16]; - memory[ 5*16 + i] <= INIT_5[16*i +: 16]; - memory[ 6*16 + i] <= INIT_6[16*i +: 16]; - memory[ 7*16 + i] <= INIT_7[16*i +: 16]; - memory[ 8*16 + i] <= INIT_8[16*i +: 16]; - memory[ 9*16 + i] <= INIT_9[16*i +: 16]; - memory[10*16 + i] <= INIT_A[16*i +: 16]; - memory[11*16 + i] <= INIT_B[16*i +: 16]; - memory[12*16 + i] <= INIT_C[16*i +: 16]; - memory[13*16 + i] <= INIT_D[16*i +: 16]; - memory[14*16 + i] <= INIT_E[16*i +: 16]; - memory[15*16 + i] <= INIT_F[16*i +: 16]; -`else memory[ 0*16 + i] = INIT_0[16*i +: 16]; memory[ 1*16 + i] = INIT_1[16*i +: 16]; memory[ 2*16 + i] = INIT_2[16*i +: 16]; @@ -448,7 +430,6 @@ module SB_RAM40_4K ( memory[13*16 + i] = INIT_D[16*i +: 16]; memory[14*16 + i] = INIT_E[16*i +: 16]; memory[15*16 + i] = INIT_F[16*i +: 16]; -`endif end end From 1cd04a68389671c91dddb56cc3d2f9032f9b44e3 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 12 Mar 2019 21:14:50 +0100 Subject: [PATCH 76/76] Fix a bug in handling quotes in multi-cmd lines in Yosys scripts Signed-off-by: Clifford Wolf --- kernel/yosys.cc | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/kernel/yosys.cc b/kernel/yosys.cc index 6fd53f85e..450e4e4cf 100644 --- a/kernel/yosys.cc +++ b/kernel/yosys.cc @@ -218,12 +218,18 @@ std::string next_token(std::string &text, const char *sep, bool long_strings) if (long_strings && pos_begin != text.size() && text[pos_begin] == '"') { string sep_string = sep; - for (size_t i = pos_begin+1; i < text.size(); i++) + for (size_t i = pos_begin+1; i < text.size(); i++) { if (text[i] == '"' && (i+1 == text.size() || sep_string.find(text[i+1]) != std::string::npos)) { std::string token = text.substr(pos_begin, i-pos_begin+1); text = text.substr(i+1); return token; } + if (i+1 < text.size() && text[i] == '"' && text[i+1] == ';' && (i+2 == text.size() || sep_string.find(text[i+2]) != std::string::npos)) { + std::string token = text.substr(pos_begin, i-pos_begin+1); + text = text.substr(i+2); + return token + ";"; + } + } } size_t pos_end = text.find_first_of(sep, pos_begin);