diff --git a/techlibs/sf2/NOTES.txt b/techlibs/sf2/NOTES.txt new file mode 100644 index 000000000..67784b546 --- /dev/null +++ b/techlibs/sf2/NOTES.txt @@ -0,0 +1,84 @@ +Using yosys with Libero Soc +=========================== + +Yosys does synthesis and therefore could be used instead of Synplify in +the Libero workflow. You still have to use LiberoSoc for place, route, +bitsteam generation, timing analysis... + +This is unfortunately not trivial, but this is also not too difficult. +When you run the Synthesize step, three tools are executed one after the other. + +You'd better to write a simple script, like this one (assuming the top module +is top): + +----------- run_yosys.sh -------------- +#!/bin/sh + +set -e + +yosys -p 'read_verilog hdl/top.v; synth_sf2; write_verilog -defparam synthesis/top_yosys.v' + +rwnetlist64 --script yosys/rwnetlist.tcl + +echo "##### run g4compile" + +g4compile --script yosys/run_compile.tcl + +libero SCRIPT:run_yosys.tcl +------------------------------------ + +Yosys will do the synthesis and write a netlist in verilog. Then you have +to call microsemi tools to build the netlist for the P&R tools. + +The first one do a file format conversion. During the normal workflow, the +tcl file is created in a temporary file. You can use this one: + +------------- tcl/rwnetlist.tcl --------- +set_device -fam SmartFusion2 +read_verilog \ + -file {../synthesis/top_yosys.v} +write_adl -file {../designer/top/top.adl} +---------------------------------------- + +Probably, you will have to change the family for Igloo2. + +The second command link the netlists. The tcl script is generated by +liberoSoc in designer/top/run_compile.tcl. You can use it as it. +The "Source Files" value could be changed but it looks to have no effect. +This commands create the .afl file. + +Then you can use the normal flow. This is done by the run_yosys.tcl: + +----------- run_yosys.tcl -------------- +open_project -file {./top.prjx} +run_tool -name {PLACEROUTE} +run_tool -name {PROGRAMDEVICE} +----------------------------------------- + + +Using MSS, HPMS or other IPs +============================ + +This works. You'd better to configure CCC (~ the PLL) and the MSS using +liberoSoc as the configuration bits are not documented. +Then you have to manually gather the HDL sources generated for the IPs. +They are in the component subdirectory. Sometimes there are both a _syn and +a _pre version of the same file. They are for symplify and precision. +Use only once, the symplify version should be OK. For the MSS, these are the +blackboxes, so you don't need them. + +SYSRESET and XTLOSC have one fake port. This is handled, provided you use +the blackbox module declared by Yosys in cell_sim.v. This is OK by default +too. + + +What is missing +=============== + +Always flatten your design (this is the default). Hierarchical designs +don't work. + +Constraints (SDC files) are not supported by Yosys. Furthermore, due to +flattening and optimization, nets name may change. + +More testing... diff --git a/techlibs/sf2/arith_map.v b/techlibs/sf2/arith_map.v index f16b1abb8..eb367799b 100644 --- a/techlibs/sf2/arith_map.v +++ b/techlibs/sf2/arith_map.v @@ -17,5 +17,53 @@ * */ +(* techmap_celltype = "$alu" *) +module \$__SF2_ALU (A, B, CI, BI, X, Y, CO); + parameter A_SIGNED = 0; + parameter B_SIGNED = 0; + parameter A_WIDTH = 1; + parameter B_WIDTH = 1; + parameter Y_WIDTH = 1; + + (* force_downto *) + input [A_WIDTH-1:0] A; + (* force_downto *) + input [B_WIDTH-1:0] B; + (* force_downto *) + output [Y_WIDTH-1:0] X, Y; + + input CI, BI; + (* force_downto *) + output [Y_WIDTH-1:0] CO; + + wire _TECHMAP_FAIL_ = Y_WIDTH <= 2; + + (* force_downto *) + wire [Y_WIDTH-1:0] AA, BB; + \$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(Y_WIDTH)) A_conv (.A(A), .Y(AA)); + \$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) B_conv (.A(B), .Y(BB)); + + (* force_downto *) + wire [Y_WIDTH-1:0] C = {CO, CI}; + + genvar i; + generate for (i = 0; i < Y_WIDTH; i = i + 1) begin:slice + ARI1 #( + // G = F1 = A[i] & (B[i]^BI) + // Y = F0 = A[i]^B[i]^BI + // P = Y + // ADCB + .INIT(20'b 01_11_0010_1000_1001_0110) + ) carry ( + .A(1'b0), + .B(AA[i]), + .C(BB[i]), + .D(BI), + .FCI(C[i]), + .Y(X[i]), + .S(Y[i]), + .FCO(CO[i]) + ); + end endgenerate +endmodule -// nothing here yet diff --git a/techlibs/sf2/cells_sim.v b/techlibs/sf2/cells_sim.v index 4b57bad7b..02335404b 100644 --- a/techlibs/sf2/cells_sim.v +++ b/techlibs/sf2/cells_sim.v @@ -152,12 +152,26 @@ module SLE ( assign Q = LAT ? q_latch : q_ff; endmodule -// module AR1 +module ARI1 ( + input A, B, C, D, FCI, + output Y, S, FCO +); + parameter [19:0] INIT = 20'h0; + wire [2:0] Fsel = {D, C, B}; + wire F0 = INIT[Fsel]; + wire F1 = INIT[8 + Fsel]; + wire Yout = A ? F1 : F0; + assign Y = Yout; + wire S = FCI ^ Yout; + wire G = INIT[16] ? (INIT[17] ? F1 : F0) : INIT[17]; + wire P = INIT[19] ? 1'b1 : (INIT[18] ? Yout : 1'b0); + assign FCO = P ? FCI : G; +endmodule + // module FCEND_BUFF // module FCINIT_BUFF // module FLASH_FREEZE // module OSCILLATOR -// module SYSRESET // module SYSCTRL_RESET_STATUS // module LIVE_PROBE_FB @@ -333,6 +347,7 @@ module BIBUF ( inout PAD, output Y ); + parameter IOSTD = ""; assign PAD = E ? D : 1'bz; assign Y = PAD; endmodule @@ -347,6 +362,7 @@ module BIBUF_DIFF ( inout PADN, output Y ); + parameter IOSTD = ""; endmodule module CLKBIBUF ( @@ -357,6 +373,7 @@ module CLKBIBUF ( (* clkbuf_driver *) output Y ); + parameter IOSTD = ""; assign PAD = E ? D : 1'bz; assign Y = PAD; endmodule @@ -367,6 +384,7 @@ module CLKBUF ( (* clkbuf_driver *) output Y ); + parameter IOSTD = ""; assign Y = PAD; endmodule @@ -379,6 +397,7 @@ module CLKBUF_DIFF ( (* clkbuf_driver *) output Y ); + parameter IOSTD = ""; endmodule module INBUF ( @@ -386,6 +405,7 @@ module INBUF ( input PAD, output Y ); + parameter IOSTD = ""; assign Y = PAD; endmodule @@ -397,6 +417,7 @@ module INBUF_DIFF ( input PADN, output Y ); + parameter IOSTD = ""; endmodule module OUTBUF ( @@ -404,6 +425,7 @@ module OUTBUF ( (* iopad_external_pin *) output PAD ); + parameter IOSTD = ""; assign PAD = D; endmodule @@ -415,6 +437,7 @@ module OUTBUF_DIFF ( (* iopad_external_pin *) output PADN ); + parameter IOSTD = ""; endmodule module TRIBUFF ( @@ -423,6 +446,7 @@ module TRIBUFF ( (* iopad_external_pin *) output PAD ); + parameter IOSTD = ""; assign PAD = E ? D : 1'bz; endmodule @@ -435,6 +459,7 @@ module TRIBUFF_DIFF ( (* iopad_external_pin *) output PADN ); + parameter IOSTD = ""; endmodule // module DDR_IN @@ -442,3 +467,113 @@ endmodule // module RAM1K18 // module RAM64x18 // module MACC + +(* blackbox *) +module SYSRESET ( + (* iopad_external_pin *) + input DEVRST_N, + output POWER_ON_RESET_N); +endmodule + + +(* blackbox *) +module XTLOSC ( + (* iopad_external_pin *) + input XTL, + output CLKOUT); + parameter [1:0] MODE = 2'h3; + parameter real FREQUENCY = 20.0; +endmodule + +(* blackbox *) +module RAM1K18 ( + input [13:0] A_ADDR, + input [2:0] A_BLK, + (* clkbuf_sink *) + input A_CLK, + input [17:0] A_DIN, + output [17:0] A_DOUT, + input [1:0] A_WEN, + input [2:0] A_WIDTH, + input A_WMODE, + input A_ARST_N, + input A_DOUT_LAT, + input A_DOUT_ARST_N, + (* clkbuf_sink *) + input A_DOUT_CLK, + input A_DOUT_EN, + input A_DOUT_SRST_N, + + input [13:0] B_ADDR, + input [2:0] B_BLK, + (* clkbuf_sink *) + input B_CLK, + input [17:0] B_DIN, + output [17:0] B_DOUT, + input [1:0] B_WEN, + input [2:0] B_WIDTH, + input B_WMODE, + input B_ARST_N, + input B_DOUT_LAT, + input B_DOUT_ARST_N, + (* clkbuf_sink *) + input B_DOUT_CLK, + input B_DOUT_EN, + input B_DOUT_SRST_N, + + input A_EN, + input B_EN, + input SII_LOCK, + output BUSY); +endmodule + +(* blackbox *) +module RAM64x18 ( + input [9:0] A_ADDR, + input [1:0] A_BLK, + input [2:0] A_WIDTH, + output [17:0] A_DOUT, + input A_DOUT_ARST_N, + (* clkbuf_sink *) + input A_DOUT_CLK, + input A_DOUT_EN, + input A_DOUT_LAT, + input A_DOUT_SRST_N, + (* clkbuf_sink *) + input A_ADDR_CLK, + input A_ADDR_EN, + input A_ADDR_LAT, + input A_ADDR_SRST_N, + input A_ADDR_ARST_N, + + input [9:0] B_ADDR, + input [1:0] B_BLK, + input [2:0] B_WIDTH, + output [17:0] B_DOUT, + input B_DOUT_ARST_N, + (* clkbuf_sink *) + input B_DOUT_CLK, + input B_DOUT_EN, + input B_DOUT_LAT, + input B_DOUT_SRST_N, + (* clkbuf_sink *) + input B_ADDR_CLK, + input B_ADDR_EN, + input B_ADDR_LAT, + input B_ADDR_SRST_N, + input B_ADDR_ARST_N, + + input [9:0] C_ADDR, + (* clkbuf_sink *) + input C_CLK, + input [17:0] C_DIN, + input C_WEN, + input [1:0] C_BLK, + input [2:0] C_WIDTH, + + input A_EN, + input B_EN, + input C_EN, + input SII_LOCK, + output BUSY); +endmodule diff --git a/techlibs/sf2/synth_sf2.cc b/techlibs/sf2/synth_sf2.cc index f78b4f012..bf4a6e031 100644 --- a/techlibs/sf2/synth_sf2.cc +++ b/techlibs/sf2/synth_sf2.cc @@ -66,6 +66,9 @@ struct SynthSf2Pass : public ScriptPass log(" -clkbuf\n"); log(" insert direct PAD->global_net buffers\n"); log("\n"); + log(" -discard-ffinit\n"); + log(" discard FF init value instead of emitting an error\n"); + log("\n"); log(" -retime\n"); log(" run 'abc' with '-dff -D 1' options\n"); log("\n"); @@ -76,7 +79,7 @@ struct SynthSf2Pass : public ScriptPass } string top_opt, edif_file, vlog_file, json_file; - bool flatten, retime, iobs, clkbuf; + bool flatten, retime, iobs, clkbuf, discard_ffinit; void clear_flags() override { @@ -88,6 +91,7 @@ struct SynthSf2Pass : public ScriptPass retime = false; iobs = true; clkbuf = false; + discard_ffinit = false; } void execute(std::vector args, RTLIL::Design *design) override @@ -138,6 +142,10 @@ struct SynthSf2Pass : public ScriptPass clkbuf = true; continue; } + if (args[argidx] == "-discard-ffinit") { + discard_ffinit = true; + continue; + } break; } extra_args(args, argidx, design); @@ -171,6 +179,8 @@ struct SynthSf2Pass : public ScriptPass if (check_label("coarse")) { + if (discard_ffinit || help_mode) + run("attrmap -remove init", "(only if -discard-ffinit)"); run("synth -run coarse"); } @@ -218,9 +228,9 @@ struct SynthSf2Pass : public ScriptPass } else { run("clkbufmap -buf CLKINT Y:A"); } - run("iopadmap -bits -inpad INBUF Y:PAD -outpad OUTBUF D:PAD -toutpad TRIBUFF E:D:PAD -tinoutpad BIBUF E:Y:D:PAD", "(unless -noiobs"); + run("iopadmap -bits -inpad INBUF Y:PAD -outpad OUTBUF D:PAD -toutpad TRIBUFF E:D:PAD -tinoutpad BIBUF E:Y:D:PAD", "(unless -noiobs)"); } - run("clean"); + run("clean -purge"); } if (check_label("check")) diff --git a/techlibs/sf2/tests/test_arith.ys b/techlibs/sf2/tests/test_arith.ys new file mode 100644 index 000000000..da7b96602 --- /dev/null +++ b/techlibs/sf2/tests/test_arith.ys @@ -0,0 +1,22 @@ +# Our implementation +read_verilog ../arith_map.v +read_verilog ../cells_sim.v +read_verilog -DSIMLIB_NOCHECKS ../../common/simlib.v +rename \$__SF2_ALU gate +hierarchy -top gate -chparam A_WIDTH 4 -chparam B_WIDTH 5 -chparam Y_WIDTH 5 +flatten +opt +write_verilog gate.v + +# The reference +read_verilog -DSIMLIB_NOCHECKS ../../common/simlib.v +rename \$alu gold +hierarchy -top gold -chparam A_WIDTH 4 -chparam B_WIDTH 5 -chparam Y_WIDTH 5 +flatten +proc +clean +write_verilog gold.v + +read_verilog gate.v +miter -equiv -flatten -make_outputs gold gate miter +sat -verify -prove trigger 0 -show-ports miter