3
0
Fork 0
mirror of https://github.com/YosysHQ/yosys synced 2025-04-24 01:25:33 +00:00

Merge branch 'master' into xaig

This commit is contained in:
Eddie Hung 2019-04-08 16:31:59 -07:00
commit bca3cf6843
115 changed files with 5852 additions and 720 deletions

View file

@ -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

View file

@ -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);
}

View file

@ -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))

View file

@ -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));

View file

@ -156,6 +156,41 @@ 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 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,
@ -164,6 +199,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,
@ -172,6 +232,91 @@ 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 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,
@ -181,6 +326,13 @@ module CLKDIVF(
parameter DIV = "2.0";
endmodule
(* blackbox *)
module ECLKSYNCB(
input ECLKI, STOP,
output ECLKO
);
endmodule
(* blackbox *)
module DCCA(
input CLKI, CE,

View file

@ -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;

View file

@ -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,13 @@ 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;
wire srval;
generate
if (LSRMODE == "PRLD")
assign srval = M;
else
assign srval = (REGSET == "SET") ? 1'b1 : 1'b0;
endgenerate
initial Q = srval;
@ -339,6 +345,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 +436,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 +449,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
@ -547,3 +557,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

View file

@ -0,0 +1,203 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
* Copyright (C) 2018-19 David Shah <david@symbioticeda.com>
*
* 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<std::string> 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<Wire*> init_wires;
dict<SigBit, State> initbits;
dict<SigBit, SigBit> initbit_to_wire;
pool<SigBit> 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_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;
}
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);
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
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

View file

@ -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"))

View file

@ -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))

View file

@ -111,7 +111,7 @@ struct SynthGowinPass : public ScriptPass
if (args[argidx] == "-noflatten") {
flatten = false;
continue;
}
}
break;
}
extra_args(args, argidx, design);

View file

@ -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

View file

@ -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;

View file

@ -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,27 @@ module SB_RAM40_4K (
reg [15:0] memory [0:255];
initial begin
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];
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
if (INIT_FILE != "")
$readmemh(INIT_FILE, memory);
else
for (i=0; i<16; i=i+1) begin
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];
end
end
always @(posedge WCLK) begin
@ -504,6 +490,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 +510,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 +555,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 +575,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 +620,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 +640,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),

View file

@ -0,0 +1,159 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
*
* 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 <stdlib.h>
#include <stdio.h>
#include <bitset>
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 into the required INIT_x attributes\n");
log("\n");
}
void execute(std::vector<std::string> 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

View file

@ -266,6 +266,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"))

View file

@ -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]));

View file

@ -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

View file

@ -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

View file

@ -1,39 +1,25 @@
module SLE (
output Q,
input ADn,
input ALn,
input CLK,
input D,
input LAT,
input SD,
input EN,
input SLn
// https://coredocs.s3.amazonaws.com/Libero/12_0_0/Tool/sf2_mlg.pdf
module ADD2 (
input A, B,
output Y
);
reg q_latch, q_ff;
assign Y = A & B;
endmodule
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
module ADD3 (
input A, B, C,
output Y
);
assign Y = A & B & C;
endmodule
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;
module ADD4 (
input A, B, C, D,
output Y
);
assign Y = A & B & C & D;
endmodule
module CFG1 (
@ -74,6 +60,238 @@ module CFG4 (
assign Y = INIT >> {D, C, B, A};
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
);
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
@ -81,6 +299,8 @@ module CLKBUF (
assign Y = PAD;
endmodule
// module CLKBUF_DIFF
module INBUF (
input PAD,
output Y
@ -88,9 +308,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

View file

@ -23,6 +23,136 @@
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
static void handle_iobufs(Module *module, bool clkbuf_mode)
{
SigMap sigmap(module);
pool<SigBit> clk_bits;
pool<SigBit> handled_io_bits;
dict<SigBit, SigBit> rewrite_bits;
vector<pair<Cell*, SigBit>> 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", "\\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);
}
}
for (auto wire : vector<Wire*>(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<SigBit> clk_bits;
vector<SigBit> 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<Cell*>(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,20 +161,25 @@ 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(" -clkbuf\n");
log(" Insert PAD->global_net clock buffers\n");
log("\n");
}
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
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] == "-singleton") {
// singleton_mode = true;
// continue;
// }
if (args[argidx] == "-clkbuf") {
clkbuf_mode = true;
continue;
}
break;
}
extra_args(args, argidx, design);
@ -54,76 +189,8 @@ struct Sf2IobsPass : public Pass {
if (module == nullptr)
log_cmd_error("No top module found.\n");
SigMap sigmap(module);
pool<SigBit> clk_bits;
pool<SigBit> handled_io_bits;
dict<SigBit, SigBit> rewrite_bits;
vector<pair<Cell*, SigBit>> 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<Wire*>(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)) {
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;

View file

@ -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(" -clkbuf\n");
log(" insert direct PAD->global_net 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 = false;
}
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
@ -130,6 +134,10 @@ struct SynthSf2Pass : public ScriptPass
iobs = false;
continue;
}
if (args[argidx] == "-clkbuf") {
clkbuf = true;
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 [-clkbuf]", "(unless -noiobs)");
else if (iobs)
run(clkbuf ? "sf2_iobs -clkbuf" : "sf2_iobs");
run("clean");
}

View file

@ -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))

View file

@ -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

View file

@ -1,86 +1,20 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
*
* 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

View file

@ -1,3 +1,21 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
*
* 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,6 +122,29 @@ 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;
@ -156,6 +197,30 @@ module FDPE (output reg Q, input C, CE, D, PRE);
endcase endgenerate
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 (
output DPO, SPO,
input D, WCLK, WE,

View file

@ -7,6 +7,7 @@ function xtract_cell_decl()
{
for dir in $libdir/xeclib $libdir/retarget; do
[ -f $dir/$1.v ] || continue
[ -z "$2" ] || echo $2
egrep '^\s*((end)?module|parameter|input|inout|output|(end)?function|(end)?task)' $dir/$1.v |
sed -re '/UNPLACED/ d; /^\s*function/,/endfunction/ d; /^\s*task/,/endtask/ d;
s,//.*,,; s/#?\(.*/(...);/; s/^(input|output|parameter)/ \1/;
@ -37,10 +38,10 @@ function xtract_cell_decl()
xtract_cell_decl BUFMR
xtract_cell_decl BUFMRCE
xtract_cell_decl BUFR
xtract_cell_decl CAPTUREE2
xtract_cell_decl CAPTUREE2 "(* keep *)"
# xtract_cell_decl CARRY4
xtract_cell_decl CFGLUT5
xtract_cell_decl DCIRESET
xtract_cell_decl DCIRESET "(* keep *)"
xtract_cell_decl DNA_PORT
xtract_cell_decl DSP48E1
xtract_cell_decl EFUSE_USR
@ -67,10 +68,10 @@ function xtract_cell_decl()
xtract_cell_decl IBUFDS_GTE2
xtract_cell_decl IBUFDS_IBUFDISABLE
xtract_cell_decl IBUFDS_INTERMDISABLE
xtract_cell_decl ICAPE2
xtract_cell_decl ICAPE2 "(* keep *)"
xtract_cell_decl IDDR
xtract_cell_decl IDDR_2CLK
xtract_cell_decl IDELAYCTRL
xtract_cell_decl IDELAYCTRL "(* keep *)"
xtract_cell_decl IDELAYE2
xtract_cell_decl IN_FIFO
xtract_cell_decl IOBUF
@ -112,10 +113,10 @@ function xtract_cell_decl()
xtract_cell_decl PHY_CONTROL
xtract_cell_decl PLLE2_ADV
xtract_cell_decl PLLE2_BASE
xtract_cell_decl PS7
xtract_cell_decl PS7 "(* keep *)"
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 +125,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
@ -136,7 +137,7 @@ function xtract_cell_decl()
xtract_cell_decl ROM64X1
xtract_cell_decl SRL16E
xtract_cell_decl SRLC32E
xtract_cell_decl STARTUPE2
xtract_cell_decl STARTUPE2 "(* keep *)"
xtract_cell_decl USR_ACCESSE2
xtract_cell_decl XADC
} > cells_xtra.new

View file

@ -114,6 +114,7 @@ module BUFR (...);
parameter SIM_DEVICE = "7SERIES";
endmodule
(* keep *)
module CAPTUREE2 (...);
parameter ONESHOT = "TRUE";
input CAP;
@ -130,6 +131,7 @@ module CFGLUT5 (...);
input CDI, CE, CLK;
endmodule
(* keep *)
module DCIRESET (...);
output LOCKED;
input RST;
@ -2102,6 +2104,7 @@ module IBUFDS_INTERMDISABLE (...);
input INTERMDISABLE;
endmodule
(* keep *)
module ICAPE2 (...);
parameter [31:0] DEVICE_ID = 32'h04244093;
parameter ICAP_WIDTH = "X32";
@ -2149,6 +2152,7 @@ module IDDR_2CLK (...);
input S;
endmodule
(* keep *)
module IDELAYCTRL (...);
parameter SIM_DEVICE = "7SERIES";
output RDY;
@ -3057,6 +3061,7 @@ module PLLE2_BASE (...);
input RST;
endmodule
(* keep *)
module PS7 (...);
output DMA0DAVALID;
output DMA0DRREADY;
@ -3688,6 +3693,17 @@ module PULLUP (...);
output O;
endmodule
module RAM128X1D (...);
parameter [127:0] INIT = 128'h00000000000000000000000000000000;
parameter [0:0] IS_WCLK_INVERTED = 1'b0;
output DPO, SPO;
input [6:0] A;
input [6:0] DPRA;
input D;
input WCLK;
input WE;
endmodule
module RAM128X1S (...);
parameter [127:0] INIT = 128'h00000000000000000000000000000000;
parameter [0:0] IS_WCLK_INVERTED = 1'b0;
@ -3778,6 +3794,13 @@ module RAM64M (...);
input WE;
endmodule
module RAM64X1D (...);
parameter [63:0] INIT = 64'h0000000000000000;
parameter [0:0] IS_WCLK_INVERTED = 1'b0;
output DPO, SPO;
input A0, A1, A2, A3, A4, A5, D, DPRA0, DPRA1, DPRA2, DPRA3, DPRA4, DPRA5, WCLK, WE;
endmodule
module RAM64X1S (...);
parameter [63:0] INIT = 64'h0000000000000000;
parameter [0:0] IS_WCLK_INVERTED = 1'b0;
@ -3840,6 +3863,7 @@ module SRLC32E (...);
input CE, CLK, D;
endmodule
(* keep *)
module STARTUPE2 (...);
parameter PROG_USR = "FALSE";
parameter real SIM_CCLK_FREQ = 0.0;

42
techlibs/xilinx/ff_map.v Normal file
View file

@ -0,0 +1,42 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
*
* 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

View file

@ -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

94
techlibs/xilinx/lut_map.v Normal file
View file

@ -0,0 +1,94 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
*
* 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

View file

@ -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(" -nobram\n");
log(" disable infering of block rams\n");
log("\n");
log(" -nodram\n");
log(" disable infering of distributed rams\n");
log("\n");
log(" -run <from_label>:<to_label>\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 '-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:\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");
@ -104,16 +110,18 @@ 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(" -ff FDRE_1 Q INIT -ff FDCE_1 Q INIT -ff FDPE_1 Q INIT -ff FDSE_1 Q INIT\n");
log(" clean\n");
log("\n");
log(" check:\n");
@ -137,6 +145,8 @@ struct SynthXilinxPass : public Pass
bool flatten = false;
bool retime = false;
bool vpr = false;
bool nobram = false;
bool nodram = false;
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++)
@ -173,6 +183,14 @@ struct SynthXilinxPass : public Pass
vpr = true;
continue;
}
if (args[argidx] == "-nobram") {
nobram = true;
continue;
}
if (args[argidx] == "-nodram") {
nodram = true;
continue;
}
break;
}
extra_args(args, argidx, design);
@ -187,9 +205,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 (!nobram) {
Pass::call(design, "read_verilog -lib +/xilinx/brams_bb.v");
}
Pass::call(design, stringf("hierarchy -check %s", top_opt.c_str()));
}
@ -206,14 +233,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 (!nobram) {
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 (!nodram) {
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 +254,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 +269,14 @@ 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 "
"-ff FDRE_1 Q INIT -ff FDCE_1 Q INIT -ff FDPE_1 Q INIT -ff FDSE_1 Q INIT");
Pass::call(design, "clean");
}
@ -252,7 +290,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"))
{