diff --git a/abc.script b/abc.script new file mode 100644 index 0000000..3896c15 --- /dev/null +++ b/abc.script @@ -0,0 +1 @@ +strash; collapse; diff --git a/cells_sim.v b/cells_sim.v new file mode 100644 index 0000000..47a8762 --- /dev/null +++ b/cells_sim.v @@ -0,0 +1,76 @@ +module GAL_SOP (A, Y); + +parameter WIDTH = 0; +parameter DEPTH = 0; +parameter TABLE = 0; + +input [WIDTH-1:0] A; +output reg Y; + +integer i, j; +reg match; + +always @* begin + Y = 0; + for (i = 0; i < DEPTH; i=i+1) begin + match = 1; + for (j = 0; j < WIDTH; j=j+1) begin + if (TABLE[2*WIDTH*i + 2*j + 0] && A[j]) match = 0; + if (TABLE[2*WIDTH*i + 2*j + 1] && !A[j]) match = 0; + end + if (match) Y = 1; + end +end + +endmodule + +/*module DFF_P (C, D, Q); + +input C, D; +output reg Q; + +always @ (posedge C) + Q <= D; + +endmodule + +module NDFF_P (C, D, Q); + +input C, D; +output reg Q; + +always @ (posedge C) + Q <= !D; + +endmodule*/ + +module GAL_INPUT (A, Y); + +input A; +output Y; + +assign Y = A; + +endmodule + +module GAL_OLMC (C, A, Y); + +parameter REGISTERED = 0; +parameter INVERTED = 0; + +input C, A; +inout reg Y; + +generate + if (REGISTERED == 1) begin + always @ (posedge C) begin + Y <= (INVERTED == 0) ? A : !A; + end + end else begin + always @ (*) begin + Y <= (INVERTED == 0) ? A : !A; + end + end +endgenerate + +endmodule diff --git a/extractions/olmc.v b/extractions/olmc.v new file mode 100644 index 0000000..e852393 --- /dev/null +++ b/extractions/olmc.v @@ -0,0 +1,20 @@ +module REG_OUT_P ( + input C, A, + output Y +); + + +DFF_P dff_p_inst (.C(C), .D(A), .Q(Y)); +GAL_OUTPUT gal_output_inst (.A(Y)); + +endmodule + +module REG_OUT_N ( + input C, A, + output Y +); + +NDFF_P dff_p_inst (.C(C), .D(A), .Q(Y)); +GAL_OUTPUT gal_output_inst (.A(X)); + +endmodule diff --git a/synth_gal.tcl b/synth_gal.tcl index 414899c..a5312e0 100755 --- a/synth_gal.tcl +++ b/synth_gal.tcl @@ -6,42 +6,76 @@ if { $argc != 1 } { exit } +set fbasename [file rootname [file tail [lindex $argv 0]]] +puts $fbasename + exec rm -rf output exec mkdir output -## Read Verilog +## Read Verilog/Liberty file read_verilog [lindex $argv 0] hierarchy -auto-top +read_verilog -lib cells_sim.v +read_liberty -lib techmaps/gal_dff.lib ## First pass synthesis +tribuf synth design -save preop +# Map IO pins (and undo port removal for the output) +iopadmap -bits -inpad GAL_INPUT Y:A -toutpad GAL_OUTPUT E:A:Y -outpad GAL_OUTPUT A +expose */t:GAL_OUTPUT "%x:+\[A\]" */t:GAL_OUTPUT %d + ## DFF/SOP mapping dfflibmap -liberty techmaps/gal_dff.lib -# Get count of non-clock inputs and registers (TODO make finding clk more robust) -set num_inputs_regs [regexp -inline {\d+} [tee -s result.string select -count t:DFF_P i:* */clk %d]] +# Get count of non-clock inputs and registers +set num_inputs [regexp -inline {\d+} [tee -s result.string select -count t:GAL_INPUT]] +set num_regs [regexp -inline {\d+} [tee -s result.string select -count t:DFF_P]] +set num_inputs_regs [expr $num_inputs + $num_regs] +if {$num_regs > 0} { set num_inputs_regs [expr $num_inputs_regs - 1] } + +#abc -sop -I $num_inputs_regs -P 256 +#abc -sop -I 8 -P 8 +#abc -script "+strash;,dretime;,collapse;,write_pla,test.pla" -sop +# Force one-level SOP +abc -script "abc.script" -sop + +# Resynth all too big SOPs together in multi-level SOP +#select "t:\$sop" r:DEPTH>8 %i +#techmap -autoproc -map sop.v +#yosys proc +#techmap +#select * +#abc -sop -I $num_inputs_regs -P 8 -abc -sop -I $num_inputs_regs -P 256 -#abc -sop -I 8 -P 256 opt clean -purge +show -width + ## Tech mapping -techmap -map techmaps/pla.v -D PLA_MAX_PRODUCTS=8 +# Logic +techmap -map techmaps/pla.v -D PLA_MAX_PRODUCTS=10000 + +# Sequential OLMC extract -map extractions/ndff.v +extract -constports -map extractions/olmc.v +techmap -map techmaps/olmc.v o:* %x o:* %d + +# Combinational OLMC +iopadmap -bits -outpad GAL_COMB_OUTPUT_P A:Y */t:GAL_SOP "%x:+\[Y\]" */t:GAL_SOP %d o:* %i +techmap -map techmaps/olmc_comb.v o:* %x o:* %d clean -purge ## Write output files and graph -write_verilog output/synth.v -write_json output/synth.json -write_table output/synth.txt -write_blif output/synth.blif -write_rtlil output/synth.rtlil - -show -width -signed -enum +write_verilog "output/synth_${fbasename}.v" +write_json "output/synth_${fbasename}.json" +write_table "output/synth_${fbasename}.txt" +write_blif "output/synth_${fbasename}.blif" +write_rtlil "output/synth_${fbasename}.rtlil" ## Verify equivalence # Backup and make gold and gate modules @@ -49,21 +83,25 @@ design -stash postop design -copy-from preop -as gold A:top design -copy-from postop -as gate A:top -# Reverse tech map into primatives -#chtype -map GAL_SOP $sop gate -#chtype -map DFF_P $_DFF_P_ -techmap -map techmaps/inv_techmap.v +# Inverse tech map into primatives +techmap -autoproc -map cells_sim.v -autoproc +clean -purge # Verify equiv_make gold gate equiv +tribuf -formal equiv equiv_induct equiv -equiv_simple equiv +equiv_status -assert equiv + +# Get LTP from inverse tech map so FF cells are recognized +ltp -noff # Restore backup design -load postop ## Print final stats -ltp -noff +show -width -signed -enum + stat shell diff --git a/techmaps/inv_techmap.v b/techmaps/inv_techmap.v deleted file mode 100644 index 2497e82..0000000 --- a/techmaps/inv_techmap.v +++ /dev/null @@ -1,40 +0,0 @@ -module GAL_SOP (A, Y); - -parameter WIDTH = 0; -parameter DEPTH = 0; -parameter TABLE = 0; - -input [WIDTH-1:0] A; -output reg Y; - -\$sop #( - .WIDTH(WIDTH), - .DEPTH(DEPTH), - .TABLE(TABLE) -) sop_partial ( - .A(A), - .Y(Y) -); - -endmodule - -module DFF_P (C, D, Q); - -input C, D; -output Q; - -\$_DFF_P_ dff_inst (.C(C), .D(D), .Q(Q)); - -endmodule - -module NDFF_P (C, D, Q); - -input C, D; -output Q; - -wire Y; - -\$_NOT_ not_inst (.A(D), .Y(Y)); -\$_DFF_P_ dff_inst (.C(C), .D(Y), .Q(Q)); - -endmodule diff --git a/techmaps/olmc.v b/techmaps/olmc.v new file mode 100644 index 0000000..a1dc41b --- /dev/null +++ b/techmaps/olmc.v @@ -0,0 +1,56 @@ +(* techmap_celltype = "REG_OUT_P" *) +module _80_REG_OUT_P (C, A, Y); + input C, A; + output Y; + + generate + GAL_OLMC #( + .REGISTERED(1'b1), + .INVERTED(1'b0) + ) _TECHMAP_REPLACE_ ( + .C(C), + .A(A), + .Y(Y) + ); + endgenerate +endmodule + +(* techmap_celltype = "REG_OUT_N" *) +module _81_REG_OUT_N (C, A, Y); + input C, A; + output Y; + + generate + GAL_OLMC #( + .REGISTERED(1'b1), + .INVERTED(1'b1) + ) _TECHMAP_REPLACE_ ( + .C(C), + .A(A), + .Y(Y) + ); + endgenerate +endmodule + +(* techmap_celltype = "GAL_OUTPUT" *) +module _82_GAL_OUTPUT (A); + input A; + + // Delete +endmodule + +(* techmap_celltype = "GAL_COMB_OUTPUT_P" *) +module _82_GAL_COMB_OUTPUT_P (A, Y); + input A, Y; + + generate + GAL_OLMC #( + .REGISTERED(1'b0), + .INVERTED(1'b0) + ) _TECHMAP_REPLACE_ ( + .C(1'bX), + .A(A), + .Y(Y) + ); + endgenerate +endmodule diff --git a/techmaps/olmc_comb.v b/techmaps/olmc_comb.v new file mode 100644 index 0000000..9e0bcc8 --- /dev/null +++ b/techmaps/olmc_comb.v @@ -0,0 +1,31 @@ +(* techmap_celltype = "GAL_COMB_OUTPUT_P" *) +module _80_GAL_COMB_OUTPUT_P (A, Y); + input A, Y; + + generate + GAL_OLMC #( + .REGISTERED(1'b0), + .INVERTED(1'b0) + ) _TECHMAP_REPLACE_ ( + .C(1'bX), + .A(A), + .Y(Y) + ); + endgenerate +endmodule + +(* techmap_celltype = "$_NOT_" *) +module _80_NOT (A, Y); + input A, Y; + + generate + GAL_OLMC #( + .REGISTERED(1'b0), + .INVERTED(1'b1) + ) _TECHMAP_REPLACE_ ( + .C(1'bX), + .A(A), + .Y(Y) + ); + endgenerate +endmodule diff --git a/testcases/adder_downto_upto.v b/testcases/adder_downto_upto.v new file mode 100644 index 0000000..7f1de7e --- /dev/null +++ b/testcases/adder_downto_upto.v @@ -0,0 +1,9 @@ +module adder_downto_upto (A, B, C); + +input [2:0] A; +input [0:2] B; +output [3:0] C; + +assign C = A + B; + +endmodule diff --git a/testcases/and_gate.v b/testcases/and_gate.v new file mode 100644 index 0000000..2f39b89 --- /dev/null +++ b/testcases/and_gate.v @@ -0,0 +1,8 @@ +module and_gate (A, B, Y); + +input A, B; +output Y; + +assign Y = A && B; + +endmodule diff --git a/testcases/big_xor.v b/testcases/big_xor.v new file mode 100644 index 0000000..cb8ee79 --- /dev/null +++ b/testcases/big_xor.v @@ -0,0 +1,8 @@ +module big_xor (A, Y); + +input [7:0] A; +output Y; + +assign Y = ^A; + +endmodule diff --git a/testcases/nand_gate.v b/testcases/nand_gate.v new file mode 100644 index 0000000..ebab144 --- /dev/null +++ b/testcases/nand_gate.v @@ -0,0 +1,8 @@ +module nand_gate (A, B, Y); + +input A, B; +output Y; + +assign Y = !(A && B); + +endmodule diff --git a/test.v b/testcases/test.v similarity index 100% rename from test.v rename to testcases/test.v diff --git a/testcases/tristate.v b/testcases/tristate.v new file mode 100644 index 0000000..c44985d --- /dev/null +++ b/testcases/tristate.v @@ -0,0 +1,8 @@ +module tristate ( + input a, b, c, + output y +); + +assign y = c ? a && b : 1'bz; + +endmodule diff --git a/testcases/up_counter_downto.v b/testcases/up_counter_downto.v new file mode 100644 index 0000000..750310d --- /dev/null +++ b/testcases/up_counter_downto.v @@ -0,0 +1,11 @@ +module test ( + input clk, + + output reg [7:0] counter +); + +always @ (posedge clk) begin + counter <= counter + 1; +end + +endmodule diff --git a/testcases/up_counter_upto.v b/testcases/up_counter_upto.v new file mode 100644 index 0000000..7b9c821 --- /dev/null +++ b/testcases/up_counter_upto.v @@ -0,0 +1,11 @@ +module test ( + input clk, + + output reg [0:7] counter +); + +always @ (posedge clk) begin + counter <= counter + 1; +end + +endmodule