From 004999218f52cd5a1308023a474ee608b842a5b7 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 5 May 2020 08:01:27 -0700 Subject: techlibs/common: more robustness when *_WIDTH = 0 --- techlibs/common/cmp2lcu.v | 8 ++++++-- techlibs/common/techmap.v | 29 ++++++++++++++++++++++++----- 2 files changed, 30 insertions(+), 7 deletions(-) (limited to 'techlibs/common') diff --git a/techlibs/common/cmp2lcu.v b/techlibs/common/cmp2lcu.v index b6f4aeed6..e42f346d1 100644 --- a/techlibs/common/cmp2lcu.v +++ b/techlibs/common/cmp2lcu.v @@ -108,8 +108,12 @@ generate // Generate if any comparisons call for it wire [LCU_WIDTH-1:0] G_ = {G[LCU_WIDTH-1:1], G[0] | GG}; end - $__CMP2LCU #(.AB_WIDTH(AB_WIDTH-1), .AB_SIGNED(1'b0), .LCU_WIDTH(LCU_WIDTH), .BUDGET(BUDGET-COST), .CI(CI)) - _TECHMAP_REPLACE_ (.A(A[AB_WIDTH-2:0]), .B(B[AB_WIDTH-2:0]), .P(P_), .G(G_), .Y(Y)); + if (AB_WIDTH == 1) + $__CMP2LCU #(.AB_WIDTH(AB_WIDTH-1), .AB_SIGNED(1'b0), .LCU_WIDTH(LCU_WIDTH), .BUDGET(BUDGET-COST), .CI(CI)) + _TECHMAP_REPLACE_ (.A(), .B(), .P(P_), .G(G_), .Y(Y)); + else + $__CMP2LCU #(.AB_WIDTH(AB_WIDTH-1), .AB_SIGNED(1'b0), .LCU_WIDTH(LCU_WIDTH), .BUDGET(BUDGET-COST), .CI(CI)) + _TECHMAP_REPLACE_ (.A(A[AB_WIDTH-2:0]), .B(B[AB_WIDTH-2:0]), .P(P_), .G(G_), .Y(Y)); end end endgenerate diff --git a/techlibs/common/techmap.v b/techlibs/common/techmap.v index ecf4d5dc5..225cff449 100644 --- a/techlibs/common/techmap.v +++ b/techlibs/common/techmap.v @@ -285,13 +285,32 @@ module _90_alu (A, B, CI, BI, X, Y, CO); input CI, BI; output [Y_WIDTH-1:0] CO; - 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] AA, BB; wire [Y_WIDTH-1:0] BB = BI ? ~B_buf : B_buf; + if (A_WIDTH == 0) begin + wire [Y_WIDTH-1:0] B_buf; + \$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) B_conv (.A(B), .Y(B_buf)); + + assign AA = {Y_WIDTH{1'b0}}; + assign BB = BI ? ~B_buf : B_buf; + end + else if (B_WIDTH == 0) begin + wire [Y_WIDTH-1:0] A_buf; + \$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(Y_WIDTH)) A_conv (.A(A), .Y(A_buf)); + + assign AA = A_buf; + assign BB = {Y_WIDTH{BI ? 1'b0 : 1'b1}}; + end + else begin + 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)); + + assign AA = A_buf; + assign BB = BI ? ~B_buf : B_buf; + end + \$lcu #(.WIDTH(Y_WIDTH)) lcu (.P(X), .G(AA & BB), .CI(CI), .CO(CO)); assign X = AA ^ BB; -- cgit v1.2.3 From 95763c8d18eec49de3acff5d38a82f54cc25cb1b Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 13 Apr 2020 09:38:07 -0700 Subject: abc9_ops: add 'dff' label for auto handling of (* abc9_flop *) boxes --- techlibs/common/abc9_model.v | 3 --- 1 file changed, 3 deletions(-) (limited to 'techlibs/common') diff --git a/techlibs/common/abc9_model.v b/techlibs/common/abc9_model.v index c0c5dc2fd..9e8048faf 100644 --- a/techlibs/common/abc9_model.v +++ b/techlibs/common/abc9_model.v @@ -1,6 +1,3 @@ -module \$__ABC9_FF_ (input D, output Q); -endmodule - (* abc9_box *) module \$__ABC9_DELAY (input I, output O); parameter DELAY = 0; -- cgit v1.2.3 From 48052ad813db3561a959a1921466d571bafa354c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 16 Apr 2020 10:24:02 -0700 Subject: abc9: add flop boxes to basic $_DFF_P_ and $_DFF_N_ too --- techlibs/common/Makefile.inc | 2 ++ techlibs/common/abc9_map.v | 21 +++++++++++++++++++++ techlibs/common/abc9_model.v | 20 ++++++++++++++++++++ techlibs/common/abc9_unmap.v | 12 ++++++++++++ 4 files changed, 55 insertions(+) create mode 100644 techlibs/common/abc9_map.v create mode 100644 techlibs/common/abc9_unmap.v (limited to 'techlibs/common') diff --git a/techlibs/common/Makefile.inc b/techlibs/common/Makefile.inc index 7b1e4b430..607e772a2 100644 --- a/techlibs/common/Makefile.inc +++ b/techlibs/common/Makefile.inc @@ -30,4 +30,6 @@ $(eval $(call add_share_file,share,techlibs/common/cmp2lut.v)) $(eval $(call add_share_file,share,techlibs/common/cells.lib)) $(eval $(call add_share_file,share,techlibs/common/mul2dsp.v)) $(eval $(call add_share_file,share,techlibs/common/abc9_model.v)) +$(eval $(call add_share_file,share,techlibs/common/abc9_map.v)) +$(eval $(call add_share_file,share,techlibs/common/abc9_unmap.v)) $(eval $(call add_share_file,share,techlibs/common/cmp2lcu.v)) diff --git a/techlibs/common/abc9_map.v b/techlibs/common/abc9_map.v new file mode 100644 index 000000000..b04a5b64f --- /dev/null +++ b/techlibs/common/abc9_map.v @@ -0,0 +1,21 @@ +(* techmap_celltype = "$_DFF_N_ $_DFF_P_" *) +module $_DFF_x_(input C, D, output Q); + parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx; + parameter _TECHMAP_CELLTYPE_ = ""; + generate if (_TECHMAP_WIREINIT_Q_ === 1'b1) + wire _TECHMAP_FAIL_ = 1; + else if (_TECHMAP_CELLTYPE_ == "$_DFF_N_") begin + wire D_; + $__DFF_N__$abc9_flop #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.C(C), .D(D), .Q(Q), .n1(D_)); + $_DFF_N_ ff (.C(C), .D(D_), .Q(Q)); + end + else if (_TECHMAP_CELLTYPE_ == "$_DFF_P_") begin + wire D_; + $__DFF_P__$abc9_flop #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.C(C), .D(D), .Q(Q), .n1(D_)); + $_DFF_P_ ff (.C(C), .D(D_), .Q(Q)); + end + else if (_TECHMAP_CELLTYPE_ != "") + $error("Unrecognised _TECHMAP_CELLTYPE_"); + endgenerate + wire _TECHMAP_REMOVEINIT_Q_ = 1; +endmodule diff --git a/techlibs/common/abc9_model.v b/techlibs/common/abc9_model.v index 9e8048faf..41acf4d97 100644 --- a/techlibs/common/abc9_model.v +++ b/techlibs/common/abc9_model.v @@ -5,3 +5,23 @@ module \$__ABC9_DELAY (input I, output O); (I => O) = DELAY; endspecify endmodule + +(* abc9_flop, abc9_box, lib_whitebox *) +module $__DFF_N__$abc9_flop(input C, D, Q, (* init=INIT *) output n1); + parameter [0:0] INIT = 1'bx; + assign n1 = D; + specify + $setup(D, posedge C, 0); + (posedge C => (n1:D)) = 0; + endspecify +endmodule + +(* abc9_flop, abc9_box, lib_whitebox *) +module $__DFF_P__$abc9_flop(input C, D, Q, (* init=INIT *) output n1); + parameter [0:0] INIT = 1'bx; + assign n1 = D; + specify + $setup(D, posedge C, 0); + (posedge C => (n1:D)) = 0; + endspecify +endmodule diff --git a/techlibs/common/abc9_unmap.v b/techlibs/common/abc9_unmap.v new file mode 100644 index 000000000..0fd07207d --- /dev/null +++ b/techlibs/common/abc9_unmap.v @@ -0,0 +1,12 @@ +(* techmap_celltype = "$__DFF_N__$abc9_flop $__DFF_P__$abc9_flop" *) +module $__DFF_x__$abc9_flop (input C, D, Q, (* init = INIT *) output n1); + parameter [0:0] INIT = 1'bx; + parameter _TECHMAP_CELLTYPE_ = ""; + generate if (_TECHMAP_CELLTYPE_ == "$__DFF_N__$abc9_flop") + $_DFF_N_ _TECHMAP_REPLACE_ (.C(C), .D(D), .Q(Q)); + else if (_TECHMAP_CELLTYPE_ == "$__DFF_P__$abc9_flop") + $_DFF_P_ _TECHMAP_REPLACE_ (.C(C), .D(D), .Q(Q)); + else if (_TECHMAP_CELLTYPE_ != "") + $error("Unrecognised _TECHMAP_CELLTYPE_"); + endgenerate +endmodule -- cgit v1.2.3 From 722540dbf942d2b8acbaf7372001c7d982eb2845 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 16 Apr 2020 12:08:59 -0700 Subject: abc9: not enough to techmap_fail on (* init=1 *), hide them using $__ --- techlibs/common/abc9_map.v | 24 ++++++++++++++---------- techlibs/common/abc9_unmap.v | 12 ++++++++++++ 2 files changed, 26 insertions(+), 10 deletions(-) (limited to 'techlibs/common') diff --git a/techlibs/common/abc9_map.v b/techlibs/common/abc9_map.v index b04a5b64f..5f1822485 100644 --- a/techlibs/common/abc9_map.v +++ b/techlibs/common/abc9_map.v @@ -2,20 +2,24 @@ module $_DFF_x_(input C, D, output Q); parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx; parameter _TECHMAP_CELLTYPE_ = ""; - generate if (_TECHMAP_WIREINIT_Q_ === 1'b1) - wire _TECHMAP_FAIL_ = 1; - else if (_TECHMAP_CELLTYPE_ == "$_DFF_N_") begin - wire D_; - $__DFF_N__$abc9_flop #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.C(C), .D(D), .Q(Q), .n1(D_)); - $_DFF_N_ ff (.C(C), .D(D_), .Q(Q)); + wire D_; + generate if (_TECHMAP_CELLTYPE_ == "$_DFF_N_") begin + if (_TECHMAP_WIREINIT_Q_ === 1'b0) begin + $__DFF_N__$abc9_flop #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.C(C), .D(D), .Q(Q), .n1(D_)); + $_DFF_N_ ff (.C(C), .D(D_), .Q(Q)); + end + else + $__DFF_N_ _TECHMAP_REPLACE_ (.C(C), .D(D), .Q(Q));// hide from abc9 using $__ prefix end else if (_TECHMAP_CELLTYPE_ == "$_DFF_P_") begin - wire D_; - $__DFF_P__$abc9_flop #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.C(C), .D(D), .Q(Q), .n1(D_)); - $_DFF_P_ ff (.C(C), .D(D_), .Q(Q)); + if (_TECHMAP_WIREINIT_Q_ === 1'b0) begin + $__DFF_P__$abc9_flop #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.C(C), .D(D), .Q(Q), .n1(D_)); + $_DFF_P_ ff (.C(C), .D(D_), .Q(Q)); + end + else + $__DFF_P_ _TECHMAP_REPLACE_ (.C(C), .D(D), .Q(Q)); // hide from abc9 using $__ prefix end else if (_TECHMAP_CELLTYPE_ != "") $error("Unrecognised _TECHMAP_CELLTYPE_"); endgenerate - wire _TECHMAP_REMOVEINIT_Q_ = 1; endmodule diff --git a/techlibs/common/abc9_unmap.v b/techlibs/common/abc9_unmap.v index 0fd07207d..4dfac0cbb 100644 --- a/techlibs/common/abc9_unmap.v +++ b/techlibs/common/abc9_unmap.v @@ -10,3 +10,15 @@ module $__DFF_x__$abc9_flop (input C, D, Q, (* init = INIT *) output n1); $error("Unrecognised _TECHMAP_CELLTYPE_"); endgenerate endmodule + +(* techmap_celltype = "$__DFF_N_ $__DFF_P_" *) +module $__DFF_N__$abc9_flop(input C, D, output Q); + parameter _TECHMAP_CELLTYPE_ = ""; + generate if (_TECHMAP_CELLTYPE_ == "$__DFF_N_") + $_DFF_N_ _TECHMAP_REPLACE_ (.C(C), .D(D), .Q(Q)); + else if (_TECHMAP_CELLTYPE_ == "$__DFF_P_") + $_DFF_P_ _TECHMAP_REPLACE_ (.C(C), .D(D), .Q(Q)); + else if (_TECHMAP_CELLTYPE_ != "") + $error("Unrecognised _TECHMAP_CELLTYPE_"); + endgenerate +endmodule -- cgit v1.2.3 From 57c478c537ef23c05ca34ecdf4c4334fd82c104e Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 21 Apr 2020 17:54:24 -0700 Subject: abc9: only do +/abc9_map if `DFF --- techlibs/common/abc9_map.v | 2 ++ 1 file changed, 2 insertions(+) (limited to 'techlibs/common') diff --git a/techlibs/common/abc9_map.v b/techlibs/common/abc9_map.v index 5f1822485..57b3831d8 100644 --- a/techlibs/common/abc9_map.v +++ b/techlibs/common/abc9_map.v @@ -1,3 +1,4 @@ +`ifdef DFF (* techmap_celltype = "$_DFF_N_ $_DFF_P_" *) module $_DFF_x_(input C, D, output Q); parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx; @@ -23,3 +24,4 @@ module $_DFF_x_(input C, D, output Q); $error("Unrecognised _TECHMAP_CELLTYPE_"); endgenerate endmodule +`endif -- cgit v1.2.3 From e79127fcebf9c5aed47f6f56fcfc8a4c4f98705c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 13 May 2020 18:02:05 -0700 Subject: Cleanup; reduce Module::derive() calls --- techlibs/common/abc9_model.v | 6 +++--- techlibs/common/abc9_unmap.v | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'techlibs/common') diff --git a/techlibs/common/abc9_model.v b/techlibs/common/abc9_model.v index 41acf4d97..a86f6a436 100644 --- a/techlibs/common/abc9_model.v +++ b/techlibs/common/abc9_model.v @@ -1,5 +1,5 @@ (* abc9_box *) -module \$__ABC9_DELAY (input I, output O); +module $__ABC9_DELAY (input I, output O); parameter DELAY = 0; specify (I => O) = DELAY; @@ -7,7 +7,7 @@ module \$__ABC9_DELAY (input I, output O); endmodule (* abc9_flop, abc9_box, lib_whitebox *) -module $__DFF_N__$abc9_flop(input C, D, Q, (* init=INIT *) output n1); +module $__DFF_N__$abc9_flop (input C, D, Q, (* init=INIT *) output n1); parameter [0:0] INIT = 1'bx; assign n1 = D; specify @@ -17,7 +17,7 @@ module $__DFF_N__$abc9_flop(input C, D, Q, (* init=INIT *) output n1); endmodule (* abc9_flop, abc9_box, lib_whitebox *) -module $__DFF_P__$abc9_flop(input C, D, Q, (* init=INIT *) output n1); +module $__DFF_P__$abc9_flop (input C, D, Q, (* init=INIT *) output n1); parameter [0:0] INIT = 1'bx; assign n1 = D; specify diff --git a/techlibs/common/abc9_unmap.v b/techlibs/common/abc9_unmap.v index 4dfac0cbb..d628a73ac 100644 --- a/techlibs/common/abc9_unmap.v +++ b/techlibs/common/abc9_unmap.v @@ -12,7 +12,7 @@ module $__DFF_x__$abc9_flop (input C, D, Q, (* init = INIT *) output n1); endmodule (* techmap_celltype = "$__DFF_N_ $__DFF_P_" *) -module $__DFF_N__$abc9_flop(input C, D, output Q); +module $__DFF_N__$abc9_flop (input C, D, output Q); parameter _TECHMAP_CELLTYPE_ = ""; generate if (_TECHMAP_CELLTYPE_ == "$__DFF_N_") $_DFF_N_ _TECHMAP_REPLACE_ (.C(C), .D(D), .Q(Q)); -- cgit v1.2.3 From 97a0a0431489568300b40c1d376af7b5d8cb7027 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 13 May 2020 21:56:06 -0700 Subject: abc9_ops/xaiger: further reducing Module::derive() calls by ... replacing _all_ (* abc9_box *) instantiations with their derived types --- techlibs/common/abc9_map.v | 6 +++--- techlibs/common/abc9_model.v | 6 ++---- 2 files changed, 5 insertions(+), 7 deletions(-) (limited to 'techlibs/common') diff --git a/techlibs/common/abc9_map.v b/techlibs/common/abc9_map.v index 57b3831d8..182915842 100644 --- a/techlibs/common/abc9_map.v +++ b/techlibs/common/abc9_map.v @@ -3,10 +3,10 @@ module $_DFF_x_(input C, D, output Q); parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx; parameter _TECHMAP_CELLTYPE_ = ""; - wire D_; + (* init=_TECHMAP_WIREINIT_Q_ *) wire D_; generate if (_TECHMAP_CELLTYPE_ == "$_DFF_N_") begin if (_TECHMAP_WIREINIT_Q_ === 1'b0) begin - $__DFF_N__$abc9_flop #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.C(C), .D(D), .Q(Q), .n1(D_)); + $__DFF_N__$abc9_flop _TECHMAP_REPLACE_ (.C(C), .D(D), .Q(Q), .n1(D_)); $_DFF_N_ ff (.C(C), .D(D_), .Q(Q)); end else @@ -14,7 +14,7 @@ module $_DFF_x_(input C, D, output Q); end else if (_TECHMAP_CELLTYPE_ == "$_DFF_P_") begin if (_TECHMAP_WIREINIT_Q_ === 1'b0) begin - $__DFF_P__$abc9_flop #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.C(C), .D(D), .Q(Q), .n1(D_)); + $__DFF_P__$abc9_flop _TECHMAP_REPLACE_ (.C(C), .D(D), .Q(Q), .n1(D_)); $_DFF_P_ ff (.C(C), .D(D_), .Q(Q)); end else diff --git a/techlibs/common/abc9_model.v b/techlibs/common/abc9_model.v index a86f6a436..4fee60f75 100644 --- a/techlibs/common/abc9_model.v +++ b/techlibs/common/abc9_model.v @@ -7,8 +7,7 @@ module $__ABC9_DELAY (input I, output O); endmodule (* abc9_flop, abc9_box, lib_whitebox *) -module $__DFF_N__$abc9_flop (input C, D, Q, (* init=INIT *) output n1); - parameter [0:0] INIT = 1'bx; +module $__DFF_N__$abc9_flop (input C, D, Q, output n1); assign n1 = D; specify $setup(D, posedge C, 0); @@ -17,8 +16,7 @@ module $__DFF_N__$abc9_flop (input C, D, Q, (* init=INIT *) output n1); endmodule (* abc9_flop, abc9_box, lib_whitebox *) -module $__DFF_P__$abc9_flop (input C, D, Q, (* init=INIT *) output n1); - parameter [0:0] INIT = 1'bx; +module $__DFF_P__$abc9_flop (input C, D, Q, output n1); assign n1 = D; specify $setup(D, posedge C, 0); -- cgit v1.2.3 From 13f9d65b6fc09af76330c02ab420324b50db61da Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 14 May 2020 00:29:45 -0700 Subject: abc9: preserve $_DFF_?_.Q's (* init *); rely on clean to remove it --- techlibs/common/abc9_map.v | 4 ++-- techlibs/common/abc9_unmap.v | 5 ++--- 2 files changed, 4 insertions(+), 5 deletions(-) (limited to 'techlibs/common') diff --git a/techlibs/common/abc9_map.v b/techlibs/common/abc9_map.v index 182915842..bb2b4a4b1 100644 --- a/techlibs/common/abc9_map.v +++ b/techlibs/common/abc9_map.v @@ -3,14 +3,14 @@ module $_DFF_x_(input C, D, output Q); parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx; parameter _TECHMAP_CELLTYPE_ = ""; - (* init=_TECHMAP_WIREINIT_Q_ *) wire D_; + wire D_; generate if (_TECHMAP_CELLTYPE_ == "$_DFF_N_") begin if (_TECHMAP_WIREINIT_Q_ === 1'b0) begin $__DFF_N__$abc9_flop _TECHMAP_REPLACE_ (.C(C), .D(D), .Q(Q), .n1(D_)); $_DFF_N_ ff (.C(C), .D(D_), .Q(Q)); end else - $__DFF_N_ _TECHMAP_REPLACE_ (.C(C), .D(D), .Q(Q));// hide from abc9 using $__ prefix + $__DFF_N_ _TECHMAP_REPLACE_ (.C(C), .D(D), .Q(Q)); // hide from abc9 using $__ prefix end else if (_TECHMAP_CELLTYPE_ == "$_DFF_P_") begin if (_TECHMAP_WIREINIT_Q_ === 1'b0) begin diff --git a/techlibs/common/abc9_unmap.v b/techlibs/common/abc9_unmap.v index d628a73ac..b765356d8 100644 --- a/techlibs/common/abc9_unmap.v +++ b/techlibs/common/abc9_unmap.v @@ -1,6 +1,5 @@ (* techmap_celltype = "$__DFF_N__$abc9_flop $__DFF_P__$abc9_flop" *) -module $__DFF_x__$abc9_flop (input C, D, Q, (* init = INIT *) output n1); - parameter [0:0] INIT = 1'bx; +module $__DFF_x__$abc9_flop (input C, D, Q, output n1); parameter _TECHMAP_CELLTYPE_ = ""; generate if (_TECHMAP_CELLTYPE_ == "$__DFF_N__$abc9_flop") $_DFF_N_ _TECHMAP_REPLACE_ (.C(C), .D(D), .Q(Q)); @@ -12,7 +11,7 @@ module $__DFF_x__$abc9_flop (input C, D, Q, (* init = INIT *) output n1); endmodule (* techmap_celltype = "$__DFF_N_ $__DFF_P_" *) -module $__DFF_N__$abc9_flop (input C, D, output Q); +module $__DFF_x_ (input C, D, output Q); parameter _TECHMAP_CELLTYPE_ = ""; generate if (_TECHMAP_CELLTYPE_ == "$__DFF_N_") $_DFF_N_ _TECHMAP_REPLACE_ (.C(C), .D(D), .Q(Q)); -- cgit v1.2.3 From 67fc0c3698693f049e805211c49d6219f17d7c7d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 14 May 2020 16:44:35 -0700 Subject: abc9: use (* abc9_keep *) instead of (* abc9_scc *); apply to $_DFF_?_ instead of moving them to $__ prefix --- techlibs/common/abc9_map.v | 4 ++-- techlibs/common/abc9_unmap.v | 12 ------------ 2 files changed, 2 insertions(+), 14 deletions(-) (limited to 'techlibs/common') diff --git a/techlibs/common/abc9_map.v b/techlibs/common/abc9_map.v index bb2b4a4b1..6ed90b5f5 100644 --- a/techlibs/common/abc9_map.v +++ b/techlibs/common/abc9_map.v @@ -10,7 +10,7 @@ module $_DFF_x_(input C, D, output Q); $_DFF_N_ ff (.C(C), .D(D_), .Q(Q)); end else - $__DFF_N_ _TECHMAP_REPLACE_ (.C(C), .D(D), .Q(Q)); // hide from abc9 using $__ prefix + (* abc9_keep *) $_DFF_N_ _TECHMAP_REPLACE_ (.C(C), .D(D), .Q(Q)); end else if (_TECHMAP_CELLTYPE_ == "$_DFF_P_") begin if (_TECHMAP_WIREINIT_Q_ === 1'b0) begin @@ -18,7 +18,7 @@ module $_DFF_x_(input C, D, output Q); $_DFF_P_ ff (.C(C), .D(D_), .Q(Q)); end else - $__DFF_P_ _TECHMAP_REPLACE_ (.C(C), .D(D), .Q(Q)); // hide from abc9 using $__ prefix + (* abc9_keep *) $_DFF_P_ _TECHMAP_REPLACE_ (.C(C), .D(D), .Q(Q)); end else if (_TECHMAP_CELLTYPE_ != "") $error("Unrecognised _TECHMAP_CELLTYPE_"); diff --git a/techlibs/common/abc9_unmap.v b/techlibs/common/abc9_unmap.v index b765356d8..bcbe91477 100644 --- a/techlibs/common/abc9_unmap.v +++ b/techlibs/common/abc9_unmap.v @@ -9,15 +9,3 @@ module $__DFF_x__$abc9_flop (input C, D, Q, output n1); $error("Unrecognised _TECHMAP_CELLTYPE_"); endgenerate endmodule - -(* techmap_celltype = "$__DFF_N_ $__DFF_P_" *) -module $__DFF_x_ (input C, D, output Q); - parameter _TECHMAP_CELLTYPE_ = ""; - generate if (_TECHMAP_CELLTYPE_ == "$__DFF_N_") - $_DFF_N_ _TECHMAP_REPLACE_ (.C(C), .D(D), .Q(Q)); - else if (_TECHMAP_CELLTYPE_ == "$__DFF_P_") - $_DFF_P_ _TECHMAP_REPLACE_ (.C(C), .D(D), .Q(Q)); - else if (_TECHMAP_CELLTYPE_ != "") - $error("Unrecognised _TECHMAP_CELLTYPE_"); - endgenerate -endmodule -- cgit v1.2.3 From aee439360bba642dcbffe5b803aa9a994b11d183 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcelina=20Ko=C5=9Bcielnicka?= Date: Mon, 18 May 2020 18:15:03 +0200 Subject: Add force_downto and force_upto wire attributes. Fixes #2058. --- techlibs/common/adff2dff.v | 3 ++ techlibs/common/cmp2lcu.v | 12 ++++++++ techlibs/common/cmp2lut.v | 3 ++ techlibs/common/dff2ff.v | 2 ++ techlibs/common/mul2dsp.v | 18 ++++++++++++ techlibs/common/techmap.v | 73 +++++++++++++++++++++++++++++++--------------- 6 files changed, 88 insertions(+), 23 deletions(-) (limited to 'techlibs/common') diff --git a/techlibs/common/adff2dff.v b/techlibs/common/adff2dff.v index 86744d415..eca0110eb 100644 --- a/techlibs/common/adff2dff.v +++ b/techlibs/common/adff2dff.v @@ -6,8 +6,11 @@ module adff2dff (CLK, ARST, D, Q); parameter ARST_VALUE = 0; input CLK, ARST; + (* force_downto *) input [WIDTH-1:0] D; + (* force_downto *) output reg [WIDTH-1:0] Q; + (* force_downto *) wire reg [WIDTH-1:0] NEXT_Q; wire [1023:0] _TECHMAP_DO_ = "proc;;"; diff --git a/techlibs/common/cmp2lcu.v b/techlibs/common/cmp2lcu.v index e42f346d1..a221727e7 100644 --- a/techlibs/common/cmp2lcu.v +++ b/techlibs/common/cmp2lcu.v @@ -12,8 +12,11 @@ parameter A_WIDTH = 0; parameter B_WIDTH = 0; parameter Y_WIDTH = 0; +(* force_downto *) input [A_WIDTH-1:0] A; +(* force_downto *) input [B_WIDTH-1:0] B; +(* force_downto *) output [Y_WIDTH-1:0] Y; parameter _TECHMAP_CELLTYPE_ = ""; @@ -32,7 +35,9 @@ generate else begin // Perform sign extension on A and B localparam WIDTH = A_WIDTH > B_WIDTH ? A_WIDTH : B_WIDTH; + (* force_downto *) wire [WIDTH-1:0] AA = {{(WIDTH-A_WIDTH){A_SIGNED ? A[A_WIDTH-1] : 1'b0}}, A}; + (* force_downto *) wire [WIDTH-1:0] BB = {{(WIDTH-B_WIDTH){B_SIGNED ? B[B_WIDTH-1] : 1'b0}}, B}; // For $ge operation, start with the assumption that A and B are // equal (propagating this equality if A and B turn out to be so) @@ -54,9 +59,13 @@ parameter LCU_WIDTH = 1; parameter BUDGET = 0; parameter CI = 0; +(* force_downto *) input [AB_WIDTH-1:0] A; // A from original $gt/$ge +(* force_downto *) input [AB_WIDTH-1:0] B; // B from original $gt/$ge +(* force_downto *) input [LCU_WIDTH-1:0] P; // P of $lcu +(* force_downto *) input [LCU_WIDTH-1:0] G; // G of $lcu output Y; @@ -66,6 +75,7 @@ parameter [LCU_WIDTH-1:0] _TECHMAP_CONSTMSK_P_ = 0; generate if (AB_WIDTH == 0) begin + (* force_downto *) wire [LCU_WIDTH-1:0] CO; $lcu #(.WIDTH(LCU_WIDTH)) _TECHMAP_REPLACE_ (.P(P), .G(G), .CI(CI), .CO(CO)); assign Y = CO[LCU_WIDTH-1]; @@ -104,8 +114,10 @@ generate else begin // Propagate only if all pairs are equal // (inconclusive evidence to say A >= B) + (* force_downto *) wire [LCU_WIDTH-1:0] P_ = {P[LCU_WIDTH-1:1], P[0] & PP}; // Generate if any comparisons call for it + (* force_downto *) wire [LCU_WIDTH-1:0] G_ = {G[LCU_WIDTH-1:1], G[0] | GG}; end if (AB_WIDTH == 1) diff --git a/techlibs/common/cmp2lut.v b/techlibs/common/cmp2lut.v index 8ecd356cc..ec8f98e8d 100644 --- a/techlibs/common/cmp2lut.v +++ b/techlibs/common/cmp2lut.v @@ -16,8 +16,11 @@ parameter A_WIDTH = 0; parameter B_WIDTH = 0; parameter Y_WIDTH = 0; +(* force_downto *) input [A_WIDTH-1:0] A; +(* force_downto *) input [B_WIDTH-1:0] B; +(* force_downto *) output [Y_WIDTH-1:0] Y; parameter _TECHMAP_CELLTYPE_ = ""; diff --git a/techlibs/common/dff2ff.v b/techlibs/common/dff2ff.v index 2dc4d20d3..33a79ffff 100644 --- a/techlibs/common/dff2ff.v +++ b/techlibs/common/dff2ff.v @@ -4,7 +4,9 @@ module dff2ff (CLK, D, Q); parameter CLK_POLARITY = 1; input CLK; + (* force_downto *) input [WIDTH-1:0] D; + (* force_downto *) output reg [WIDTH-1:0] Q; wire [1023:0] _TECHMAP_DO_ = "proc;;"; diff --git a/techlibs/common/mul2dsp.v b/techlibs/common/mul2dsp.v index 4cabb4453..bec47d01f 100644 --- a/techlibs/common/mul2dsp.v +++ b/techlibs/common/mul2dsp.v @@ -57,8 +57,11 @@ module _80_mul (A, B, Y); 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] Y; parameter _TECHMAP_CELLTYPE_ = ""; @@ -119,13 +122,19 @@ module _80_mul (A, B, Y); localparam last_A_WIDTH = A_WIDTH-n*(`DSP_A_MAXWIDTH_PARTIAL-sign_headroom); localparam last_Y_WIDTH = B_WIDTH+last_A_WIDTH; if (A_SIGNED && B_SIGNED) begin + (* force_downto *) wire signed [partial_Y_WIDTH-1:0] partial [n-1:0]; + (* force_downto *) wire signed [last_Y_WIDTH-1:0] last_partial; + (* force_downto *) wire signed [Y_WIDTH-1:0] partial_sum [n:0]; end else begin + (* force_downto *) wire [partial_Y_WIDTH-1:0] partial [n-1:0]; + (* force_downto *) wire [last_Y_WIDTH-1:0] last_partial; + (* force_downto *) wire [Y_WIDTH-1:0] partial_sum [n:0]; end @@ -170,13 +179,19 @@ module _80_mul (A, B, Y); localparam last_B_WIDTH = B_WIDTH-n*(`DSP_B_MAXWIDTH_PARTIAL-sign_headroom); localparam last_Y_WIDTH = A_WIDTH+last_B_WIDTH; if (A_SIGNED && B_SIGNED) begin + (* force_downto *) wire signed [partial_Y_WIDTH-1:0] partial [n-1:0]; + (* force_downto *) wire signed [last_Y_WIDTH-1:0] last_partial; + (* force_downto *) wire signed [Y_WIDTH-1:0] partial_sum [n:0]; end else begin + (* force_downto *) wire [partial_Y_WIDTH-1:0] partial [n-1:0]; + (* force_downto *) wire [last_Y_WIDTH-1:0] last_partial; + (* force_downto *) wire [Y_WIDTH-1:0] partial_sum [n:0]; end @@ -249,8 +264,11 @@ module _90_soft_mul (A, B, Y); 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] Y; // Indirection necessary since mapping diff --git a/techlibs/common/techmap.v b/techlibs/common/techmap.v index 225cff449..c1efc378b 100644 --- a/techlibs/common/techmap.v +++ b/techlibs/common/techmap.v @@ -85,8 +85,11 @@ module _90_shift_ops_shr_shl_sshl_sshr (A, B, Y); localparam shift_left = _TECHMAP_CELLTYPE_ == "$shl" || _TECHMAP_CELLTYPE_ == "$sshl"; localparam sign_extend = A_SIGNED && _TECHMAP_CELLTYPE_ == "$sshr"; + (* force_downto *) input [A_WIDTH-1:0] A; + (* force_downto *) input [B_WIDTH-1:0] B; + (* force_downto *) output [Y_WIDTH-1:0] Y; localparam WIDTH = `MAX(A_WIDTH, Y_WIDTH); @@ -96,6 +99,7 @@ module _90_shift_ops_shr_shl_sshl_sshr (A, B, Y); wire [1023:0] _TECHMAP_DO_01_ = "RECURSION; CONSTMAP; opt_muxtree; opt_expr -mux_undef -mux_bool -fine;;;"; integer i; + (* force_downto *) reg [WIDTH-1:0] buffer; reg overflow; @@ -125,8 +129,11 @@ module _90_shift_shiftx (A, B, Y); 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] Y; parameter _TECHMAP_CELLTYPE_ = ""; @@ -173,6 +180,7 @@ module _90_shift_shiftx (A, B, Y); wire [1023:0] _TECHMAP_DO_01_ = "CONSTMAP; opt_muxtree; opt_expr -mux_undef -mux_bool -fine;;;"; integer i; + (* force_downto *) reg [WIDTH-1:0] buffer; reg overflow; @@ -216,9 +224,12 @@ endmodule module _90_fa (A, B, C, X, Y); parameter WIDTH = 1; + (* force_downto *) input [WIDTH-1:0] A, B, C; + (* force_downto *) output [WIDTH-1:0] X, Y; + (* force_downto *) wire [WIDTH-1:0] t1, t2, t3; assign t1 = A ^ B, t2 = A & B, t3 = C & t1; @@ -229,12 +240,15 @@ endmodule module _90_lcu (P, G, CI, CO); parameter WIDTH = 2; + (* force_downto *) input [WIDTH-1:0] P, G; input CI; + (* force_downto *) output [WIDTH-1:0] CO; integer i, j; + (* force_downto *) reg [WIDTH-1:0] p, g; wire [1023:0] _TECHMAP_DO_ = "proc; opt -fast"; @@ -278,38 +292,26 @@ module _90_alu (A, B, CI, BI, X, Y, CO); 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 [Y_WIDTH-1:0] AA, BB; + (* force_downto *) + wire [Y_WIDTH-1:0] AA = A_buf; + (* force_downto *) wire [Y_WIDTH-1:0] BB = BI ? ~B_buf : B_buf; - if (A_WIDTH == 0) begin - wire [Y_WIDTH-1:0] B_buf; - \$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) B_conv (.A(B), .Y(B_buf)); - - assign AA = {Y_WIDTH{1'b0}}; - assign BB = BI ? ~B_buf : B_buf; - end - else if (B_WIDTH == 0) begin - wire [Y_WIDTH-1:0] A_buf; - \$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(Y_WIDTH)) A_conv (.A(A), .Y(A_buf)); - - assign AA = A_buf; - assign BB = {Y_WIDTH{BI ? 1'b0 : 1'b1}}; - end - else begin - 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)); - - assign AA = A_buf; - assign BB = BI ? ~B_buf : B_buf; - end + (* force_downto *) + 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)); \$lcu #(.WIDTH(Y_WIDTH)) lcu (.P(X), .G(AA & BB), .CI(CI), .CO(CO)); @@ -335,15 +337,19 @@ endmodule module \$__div_mod_u (A, B, Y, R); parameter WIDTH = 1; + (* force_downto *) input [WIDTH-1:0] A, B; + (* force_downto *) output [WIDTH-1:0] Y, R; + (* force_downto *) wire [WIDTH*WIDTH-1:0] chaindata; assign R = chaindata[WIDTH*WIDTH-1:WIDTH*(WIDTH-1)]; genvar i; generate begin for (i = 0; i < WIDTH; i=i+1) begin:stage + (* force_downto *) wire [WIDTH-1:0] stage_in; if (i == 0) begin:cp @@ -369,14 +375,19 @@ module \$__div_mod (A, B, Y, R); A_WIDTH >= B_WIDTH && A_WIDTH >= Y_WIDTH ? A_WIDTH : B_WIDTH >= A_WIDTH && B_WIDTH >= Y_WIDTH ? B_WIDTH : Y_WIDTH; + (* force_downto *) input [A_WIDTH-1:0] A; + (* force_downto *) input [B_WIDTH-1:0] B; + (* force_downto *) output [Y_WIDTH-1:0] Y, R; + (* force_downto *) wire [WIDTH-1:0] A_buf, B_buf; \$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(WIDTH)) A_conv (.A(A), .Y(A_buf)); \$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(WIDTH)) B_conv (.A(B), .Y(B_buf)); + (* force_downto *) wire [WIDTH-1:0] A_buf_u, B_buf_u, Y_u, R_u; assign A_buf_u = A_SIGNED && A_buf[WIDTH-1] ? -A_buf : A_buf; assign B_buf_u = B_SIGNED && B_buf[WIDTH-1] ? -B_buf : B_buf; @@ -402,8 +413,11 @@ module _90_div (A, B, Y); 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] Y; \$__div_mod #( @@ -427,8 +441,11 @@ module _90_mod (A, B, Y); 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] Y; \$__div_mod #( @@ -457,8 +474,11 @@ module _90_pow (A, B, Y); 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] Y; wire _TECHMAP_FAIL_ = 1; @@ -474,20 +494,27 @@ module _90_pmux (A, B, S, Y); parameter WIDTH = 1; parameter S_WIDTH = 1; + (* force_downto *) input [WIDTH-1:0] A; + (* force_downto *) input [WIDTH*S_WIDTH-1:0] B; + (* force_downto *) input [S_WIDTH-1:0] S; + (* force_downto *) output [WIDTH-1:0] Y; + (* force_downto *) wire [WIDTH-1:0] Y_B; genvar i, j; generate + (* force_downto *) wire [WIDTH*S_WIDTH-1:0] B_AND_S; for (i = 0; i < S_WIDTH; i = i + 1) begin:B_AND assign B_AND_S[WIDTH*(i+1)-1:WIDTH*i] = B[WIDTH*(i+1)-1:WIDTH*i] & {WIDTH{S[i]}}; end:B_AND for (i = 0; i < WIDTH; i = i + 1) begin:B_OR + (* force_downto *) wire [S_WIDTH-1:0] B_AND_BITS; for (j = 0; j < S_WIDTH; j = j + 1) begin:B_AND_BITS_COLLECT assign B_AND_BITS[j] = B_AND_S[WIDTH*j+i]; -- cgit v1.2.3 From 17163cf43a6b6eec9aac44f6a4463dda54b8ed68 Mon Sep 17 00:00:00 2001 From: Xiretza Date: Wed, 8 Apr 2020 19:30:47 +0200 Subject: Add flooring modulo operator The $div and $mod cells use truncating division semantics (rounding towards 0), as defined by e.g. Verilog. Another rounding mode, flooring (rounding towards negative infinity), can be used in e.g. VHDL. The new $modfloor cell provides this flooring modulo (also known as "remainder" in several languages, but this name is ambiguous). This commit also fixes the handling of $mod in opt_expr, which was previously optimized as if it was $modfloor. --- techlibs/common/simlib.v | 48 ++++++++++++++++++++++++++++ techlibs/common/techmap.v | 79 +++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 124 insertions(+), 3 deletions(-) (limited to 'techlibs/common') diff --git a/techlibs/common/simlib.v b/techlibs/common/simlib.v index 2cdddeabb..57fc07caa 100644 --- a/techlibs/common/simlib.v +++ b/techlibs/common/simlib.v @@ -1021,6 +1021,14 @@ endmodule // -------------------------------------------------------- +// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| +//- +//- $mod (A, B, Y) +//- +//- Modulo/remainder of division with truncated result (rounded towards 0). +//- +//- Invariant: $div(A, B) * B + $mod(A, B) == A +//- module \$mod (A, B, Y); parameter A_SIGNED = 0; @@ -1043,6 +1051,46 @@ endgenerate endmodule +// -------------------------------------------------------- + +// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| +//- +//- $modfloor (A, B, Y) +//- +//- Modulo/remainder of division with floored result (rounded towards negative infinity). +//- +//- Invariant: $divfloor(A, B) * B + $modfloor(A, B) == A +//- +module \$modfloor (A, B, Y); + +parameter A_SIGNED = 0; +parameter B_SIGNED = 0; +parameter A_WIDTH = 0; +parameter B_WIDTH = 0; +parameter Y_WIDTH = 0; + +input [A_WIDTH-1:0] A; +input [B_WIDTH-1:0] B; +output [Y_WIDTH-1:0] Y; + +generate + if (A_SIGNED && B_SIGNED) begin:BLOCK1 + localparam WIDTH = B_WIDTH >= Y_WIDTH ? B_WIDTH : Y_WIDTH; + wire [WIDTH-1:0] B_buf, Y_trunc; + assign B_buf = $signed(B); + assign Y_trunc = $signed(A) % $signed(B); + // flooring mod is the same as truncating mod for positive division results (A and B have + // the same sign), as well as when there's no remainder. + // For all other cases, they behave as `floor - trunc = B` + assign Y = (A[A_WIDTH-1] == B[B_WIDTH-1]) || Y_trunc == 0 ? Y_trunc : $signed(B_buf) + $signed(Y_trunc); + end else begin:BLOCK2 + // no difference between truncating and flooring for unsigned + assign Y = A % B; + end +endgenerate + +endmodule + // -------------------------------------------------------- `ifndef SIMLIB_NOPOW diff --git a/techlibs/common/techmap.v b/techlibs/common/techmap.v index c1efc378b..95223180d 100644 --- a/techlibs/common/techmap.v +++ b/techlibs/common/techmap.v @@ -364,7 +364,8 @@ module \$__div_mod_u (A, B, Y, R); end endgenerate endmodule -module \$__div_mod (A, B, Y, R); +// truncating signed division/modulo +module \$__div_mod_trunc (A, B, Y, R); parameter A_SIGNED = 0; parameter B_SIGNED = 0; parameter A_WIDTH = 1; @@ -420,7 +421,7 @@ module _90_div (A, B, Y); (* force_downto *) output [Y_WIDTH-1:0] Y; - \$__div_mod #( + \$__div_mod_trunc #( .A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(A_WIDTH), @@ -448,7 +449,79 @@ module _90_mod (A, B, Y); (* force_downto *) output [Y_WIDTH-1:0] Y; - \$__div_mod #( + \$__div_mod_trunc #( + .A_SIGNED(A_SIGNED), + .B_SIGNED(B_SIGNED), + .A_WIDTH(A_WIDTH), + .B_WIDTH(B_WIDTH), + .Y_WIDTH(Y_WIDTH) + ) div_mod ( + .A(A), + .B(B), + .R(Y) + ); +endmodule + +// flooring signed division/modulo +module \$__div_mod_floor (A, B, Y, R); + parameter A_SIGNED = 0; + parameter B_SIGNED = 0; + parameter A_WIDTH = 1; + parameter B_WIDTH = 1; + parameter Y_WIDTH = 1; + + localparam WIDTH = + A_WIDTH >= B_WIDTH && A_WIDTH >= Y_WIDTH ? A_WIDTH : + B_WIDTH >= A_WIDTH && B_WIDTH >= Y_WIDTH ? B_WIDTH : Y_WIDTH; + + input [A_WIDTH-1:0] A; + input [B_WIDTH-1:0] B; + output [Y_WIDTH-1:0] Y, R; + + wire [WIDTH-1:0] A_buf, B_buf; + \$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(WIDTH)) A_conv (.A(A), .Y(A_buf)); + \$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(WIDTH)) B_conv (.A(B), .Y(B_buf)); + + wire [WIDTH-1:0] A_buf_u, B_buf_u, Y_u, R_u, R_s; + assign A_buf_u = A_SIGNED && A_buf[WIDTH-1] ? -A_buf : A_buf; + assign B_buf_u = B_SIGNED && B_buf[WIDTH-1] ? -B_buf : B_buf; + + \$__div_mod_u #( + .WIDTH(WIDTH) + ) div_mod_u ( + .A(A_buf_u), + .B(B_buf_u), + .Y(Y_u), + .R(R_u) + ); + + // For negative results, if there was a remainder, subtract one to turn + // the round towards 0 into a round towards -inf + assign Y = A_SIGNED && B_SIGNED && (A_buf[WIDTH-1] != B_buf[WIDTH-1]) ? (R_u == 0 ? -Y_u : -Y_u-1) : Y_u; + + // truncating modulo + assign R_s = A_SIGNED && B_SIGNED && A_buf[WIDTH-1] ? -R_u : R_u; + // Flooring modulo differs from truncating modulo only if it is nonzero and + // A and B have different signs - then `floor - trunc = B` + assign R = (R_s != 0) && A_SIGNED && B_SIGNED && (A_buf[WIDTH-1] != B_buf[WIDTH-1]) ? $signed(B_buf) + $signed(R_s) : R_s; +endmodule + +(* techmap_celltype = "$modfloor" *) +module _90_modfloor (A, B, Y); + 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] Y; + + \$__div_mod_floor #( .A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(A_WIDTH), -- cgit v1.2.3 From edd8ff2c0778d97808869488cc7394151456c4ca Mon Sep 17 00:00:00 2001 From: Xiretza Date: Tue, 21 Apr 2020 12:51:58 +0200 Subject: Add flooring division operator The $div and $mod cells use truncating division semantics (rounding towards 0), as defined by e.g. Verilog. Another rounding mode, flooring (rounding towards negative infinity), can be used in e.g. VHDL. The new $divfloor cell provides this flooring division. This commit also fixes the handling of $div in opt_expr, which was previously optimized as if it was $divfloor. --- techlibs/common/simlib.v | 43 +++++++++++++++++++++++++++++++++++++++++++ techlibs/common/techmap.v | 28 ++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+) (limited to 'techlibs/common') diff --git a/techlibs/common/simlib.v b/techlibs/common/simlib.v index 57fc07caa..125b8e013 100644 --- a/techlibs/common/simlib.v +++ b/techlibs/common/simlib.v @@ -997,6 +997,12 @@ endmodule // -------------------------------------------------------- +// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| +//- +//- $div (A, B, Y) +//- +//- Division with truncated result (rounded towards 0). +//- module \$div (A, B, Y); parameter A_SIGNED = 0; @@ -1053,6 +1059,43 @@ endmodule // -------------------------------------------------------- +// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| +//- +//- $divfloor (A, B, Y) +//- +//- Division with floored result (rounded towards negative infinity). +//- +module \$divfloor (A, B, Y); + +parameter A_SIGNED = 0; +parameter B_SIGNED = 0; +parameter A_WIDTH = 0; +parameter B_WIDTH = 0; +parameter Y_WIDTH = 0; + +input [A_WIDTH-1:0] A; +input [B_WIDTH-1:0] B; +output [Y_WIDTH-1:0] Y; + +generate + if (A_SIGNED && B_SIGNED) begin:BLOCK1 + localparam WIDTH = + A_WIDTH >= B_WIDTH && A_WIDTH >= Y_WIDTH ? A_WIDTH : + B_WIDTH >= A_WIDTH && B_WIDTH >= Y_WIDTH ? B_WIDTH : Y_WIDTH; + wire [WIDTH:0] A_buf, B_buf, N_buf; + assign A_buf = $signed(A); + assign B_buf = $signed(B); + assign N_buf = (A[A_WIDTH-1] == B[B_WIDTH-1]) || A == 0 ? A_buf : $signed(A_buf - (B[B_WIDTH-1] ? B_buf+1 : B_buf-1)); + assign Y = $signed(N_buf) / $signed(B_buf); + end else begin:BLOCK2 + assign Y = A / B; + end +endgenerate + +endmodule + +// -------------------------------------------------------- + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| //- //- $modfloor (A, B, Y) diff --git a/techlibs/common/techmap.v b/techlibs/common/techmap.v index 95223180d..eafe8d4da 100644 --- a/techlibs/common/techmap.v +++ b/techlibs/common/techmap.v @@ -506,6 +506,34 @@ module \$__div_mod_floor (A, B, Y, R); assign R = (R_s != 0) && A_SIGNED && B_SIGNED && (A_buf[WIDTH-1] != B_buf[WIDTH-1]) ? $signed(B_buf) + $signed(R_s) : R_s; endmodule +(* techmap_celltype = "$divfloor" *) +module _90_divfloor (A, B, Y); + 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] Y; + + \$__div_mod_floor #( + .A_SIGNED(A_SIGNED), + .B_SIGNED(B_SIGNED), + .A_WIDTH(A_WIDTH), + .B_WIDTH(B_WIDTH), + .Y_WIDTH(Y_WIDTH) + ) div_mod ( + .A(A), + .B(B), + .Y(Y) + ); +endmodule + (* techmap_celltype = "$modfloor" *) module _90_modfloor (A, B, Y); parameter A_SIGNED = 0; -- cgit v1.2.3