mirror of https://github.com/YosysHQ/yosys.git
change ql-bram-types pass to use mode parameter; clean up primitive libraries
This commit is contained in:
parent
48c1fdc33d
commit
6682693888
|
@ -1,6 +1,6 @@
|
|||
OBJS += techlibs/quicklogic/synth_quicklogic.o
|
||||
OBJS += techlibs/quicklogic/ql-bram-merge.o
|
||||
OBJS += techlibs/quicklogic/quicklogic_eqn.o
|
||||
OBJS += techlibs/quicklogic/ql-bram-types.o
|
||||
|
||||
$(eval $(call add_share_file,share/quicklogic/common,techlibs/quicklogic/common/cells_sim.v))
|
||||
|
||||
|
|
|
@ -0,0 +1,165 @@
|
|||
/*
|
||||
* yosys -- Yosys Open SYnthesis Suite
|
||||
*
|
||||
* Copyright (C) 2023 N. Engelhardt <nak@yosyshq.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/log.h"
|
||||
#include "kernel/register.h"
|
||||
#include "kernel/rtlil.h"
|
||||
#include "kernel/sigtools.h"
|
||||
|
||||
USING_YOSYS_NAMESPACE
|
||||
PRIVATE_NAMESPACE_BEGIN
|
||||
|
||||
// ============================================================================
|
||||
|
||||
|
||||
struct QlBramTypesPass : public Pass {
|
||||
|
||||
QlBramTypesPass() : Pass("ql_bram_types", "Change TDP36K type to subtypes") {}
|
||||
|
||||
void help() override
|
||||
{
|
||||
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
|
||||
log("\n");
|
||||
log(" ql_bram_types [selection]\n");
|
||||
log("\n");
|
||||
log(" This pass changes the type of TDP36K cells to different types based on the\n");
|
||||
log(" configuration of the cell.\n");
|
||||
log("\n");
|
||||
}
|
||||
|
||||
int width_for_mode(int mode){
|
||||
// 1: mode = 3'b101;
|
||||
// 2: mode = 3'b110;
|
||||
// 4: mode = 3'b100;
|
||||
// 8,9: mode = 3'b001;
|
||||
// 16, 18: mode = 3'b010;
|
||||
// 32, 36: mode = 3'b011;
|
||||
switch (mode)
|
||||
{
|
||||
case 1:
|
||||
return 9;
|
||||
case 2:
|
||||
return 18;
|
||||
case 3:
|
||||
return 36;
|
||||
case 4:
|
||||
return 4;
|
||||
case 5:
|
||||
return 1;
|
||||
case 6:
|
||||
return 2;
|
||||
default:
|
||||
log_error("Invalid mode: %x", mode);
|
||||
}
|
||||
}
|
||||
|
||||
void execute(std::vector<std::string> args, RTLIL::Design *design) override
|
||||
{
|
||||
log_header(design, "Executing QL_BRAM_TYPES pass.\n");
|
||||
|
||||
size_t argidx = 1;
|
||||
extra_args(args, argidx, design);
|
||||
|
||||
for (RTLIL::Module* module : design->selected_modules())
|
||||
for (RTLIL::Cell* cell: module->selected_cells())
|
||||
{
|
||||
if (cell->type != ID(TDP36K) || !cell->hasParam(ID(MODE_BITS)))
|
||||
continue;
|
||||
|
||||
RTLIL::Const mode_bits = cell->getParam(ID(MODE_BITS));
|
||||
|
||||
bool split = mode_bits.extract(80).as_bool();
|
||||
|
||||
bool FMODE1_i = mode_bits.extract(13).as_bool();
|
||||
bool FMODE2_i = mode_bits.extract(54).as_bool();
|
||||
if (FMODE1_i != FMODE2_i) {
|
||||
log_debug("Can't change type of mixed use TDP36K block: FMODE1_i = %s, FMODE2_i = %s\n", FMODE1_i ? "true" : "false", FMODE2_i ? "true" : "false");
|
||||
continue;
|
||||
}
|
||||
bool is_fifo = FMODE1_i;
|
||||
|
||||
bool SYNC_FIFO1_i = mode_bits.extract(0).as_bool();
|
||||
bool SYNC_FIFO2_i = mode_bits.extract(41).as_bool();
|
||||
if (SYNC_FIFO1_i != SYNC_FIFO2_i) {
|
||||
log_debug("Can't change type of mixed use TDP36K block: SYNC_FIFO1_i = %s, SYNC_FIFO2_i = %s\n", SYNC_FIFO1_i ? "true" : "false", SYNC_FIFO2_i ? "true" : "false");
|
||||
continue;
|
||||
}
|
||||
bool sync_fifo = SYNC_FIFO1_i;
|
||||
|
||||
int RMODE_A1_i = mode_bits.extract(1, 3).as_int();
|
||||
int RMODE_B1_i = mode_bits.extract(4, 3).as_int();
|
||||
int WMODE_A1_i = mode_bits.extract(7, 3).as_int();
|
||||
int WMODE_B1_i = mode_bits.extract(10, 3).as_int();
|
||||
|
||||
int RMODE_A2_i = mode_bits.extract(42, 3).as_int();
|
||||
int RMODE_B2_i = mode_bits.extract(45, 3).as_int();
|
||||
int WMODE_A2_i = mode_bits.extract(48, 3).as_int();
|
||||
int WMODE_B2_i = mode_bits.extract(51, 3).as_int();
|
||||
|
||||
// TODO: should these be a warning or an error?
|
||||
if (RMODE_A1_i != WMODE_A1_i) {
|
||||
log_warning("Can't change type of misconfigured TDP36K block: Port A1 configured with read width = %d different from write width = %d\n", width_for_mode(RMODE_A1_i), width_for_mode(WMODE_A1_i));
|
||||
continue;
|
||||
}
|
||||
if (RMODE_B1_i != WMODE_B1_i) {
|
||||
log_warning("Can't change type of misconfigured TDP36K block: Port B1 configured with read width = %d different from write width = %d\n", width_for_mode(RMODE_B1_i), width_for_mode(WMODE_B1_i));
|
||||
continue;
|
||||
}
|
||||
if (RMODE_A2_i != WMODE_A2_i) {
|
||||
log_warning("Can't change type of misconfigured TDP36K block: Port A2 configured with read width = %d different from write width = %d\n", width_for_mode(RMODE_A2_i), width_for_mode(WMODE_A2_i));
|
||||
continue;
|
||||
}
|
||||
if (RMODE_B2_i != WMODE_B2_i) {
|
||||
log_warning("Can't change type of misconfigured TDP36K block: Port B2 configured with read width = %d different from write width = %d\n", width_for_mode(RMODE_B2_i), width_for_mode(WMODE_B2_i));
|
||||
continue;
|
||||
}
|
||||
|
||||
// TODO: For nonsplit blocks, should RMODE_A1_i == RMODE_A2_i etc be checked/enforced?
|
||||
|
||||
std::string type = "TDP36K";
|
||||
if (is_fifo) {
|
||||
type += "_FIFO_";
|
||||
if (sync_fifo)
|
||||
type += "SYNC_";
|
||||
else
|
||||
type += "ASYNC_";
|
||||
} else
|
||||
type += "_BRAM_";
|
||||
|
||||
if (split) {
|
||||
type += stringf("A1_X%d_", width_for_mode(RMODE_A1_i));
|
||||
type += stringf("B1_X%d_", width_for_mode(RMODE_B1_i));
|
||||
type += stringf("A2_X%d_", width_for_mode(RMODE_A2_i));
|
||||
type += stringf("B2_X%d_", width_for_mode(RMODE_B2_i));
|
||||
type += "split";
|
||||
} else {
|
||||
type += stringf("A_X%d_", width_for_mode(RMODE_A1_i));
|
||||
type += stringf("B_X%d_", width_for_mode(RMODE_B1_i));
|
||||
type += "nonsplit";
|
||||
}
|
||||
|
||||
cell->type = RTLIL::escape_id(type);
|
||||
log_debug("Changed type of memory cell %s to %s\n", log_id(cell->name), log_id(cell->type));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} QlBramMergePass;
|
||||
|
||||
PRIVATE_NAMESPACE_END
|
|
@ -71,11 +71,11 @@ module _80_quicklogic_alu (A, B, CI, BI, X, Y, CO);
|
|||
generate if (Y_WIDTH > 2) begin
|
||||
for (i = 0; i < Y_WIDTH-2; i = i + 1) begin:slice
|
||||
adder_carry my_adder (
|
||||
.cin(C[i]),
|
||||
.g(AA[i]),
|
||||
.p(S[i]),
|
||||
.cout(C[i+1]),
|
||||
.sumout(Y[i])
|
||||
.cin (C[i]),
|
||||
.g (AA[i]),
|
||||
.p (S[i]),
|
||||
.cout (C[i+1]),
|
||||
.sumout (Y[i])
|
||||
);
|
||||
end
|
||||
end endgenerate
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
// **AUTOGENERATED FILE** **DO NOT EDIT**
|
||||
// Generated by qlf_k6n10f/generate_bram_types_sim.py at 2023-05-02 10:42:53.971682+00:00
|
||||
// Generated by generate_bram_types_sim.py at 2023-08-17 16:34:43.930013+00:00
|
||||
`timescale 1ns /10ps
|
||||
|
||||
module TDP36K_BRAM_A_X1_B_X1_nonsplit (
|
||||
RESET_ni,
|
||||
|
|
|
@ -982,10 +982,10 @@ assign BE_A2_i = WR2_BE;
|
|||
|
||||
assign REN_B1_i = REN1_i;
|
||||
assign WEN_B1_i = 1'b0;
|
||||
assign BE_B1_i = 4'h0;
|
||||
assign BE_B1_i = 2'h0;
|
||||
assign REN_B2_i = REN2_i;
|
||||
assign WEN_B2_i = 1'b0;
|
||||
assign BE_B2_i = 4'h0;
|
||||
assign BE_B2_i = 2'h0;
|
||||
|
||||
generate
|
||||
if (WR1_DATA_WIDTH == 18) begin
|
||||
|
@ -1394,10 +1394,10 @@ assign BE_A2_i = WR2_BE;
|
|||
|
||||
assign REN_B1_i = REN1_i;
|
||||
assign WEN_B1_i = 1'b0;
|
||||
assign BE_B1_i = 4'h0;
|
||||
assign BE_B1_i = 2'h0;
|
||||
assign REN_B2_i = REN2_i;
|
||||
assign WEN_B2_i = 1'b0;
|
||||
assign BE_B2_i = 4'h0;
|
||||
assign BE_B2_i = 2'h0;
|
||||
|
||||
generate
|
||||
if (WR1_DATA_WIDTH == 18) begin
|
||||
|
|
|
@ -109,7 +109,7 @@ module sh_dff(
|
|||
input wire C
|
||||
);
|
||||
|
||||
initial Q <= 1'b0;
|
||||
initial Q = 1'b0;
|
||||
always @(posedge C)
|
||||
Q <= D;
|
||||
|
||||
|
@ -153,7 +153,7 @@ module dff(
|
|||
(* clkbuf_sink *)
|
||||
input wire C
|
||||
);
|
||||
initial Q <= 1'b0;
|
||||
initial Q = 1'b0;
|
||||
|
||||
always @(posedge C)
|
||||
Q <= D;
|
||||
|
@ -172,7 +172,7 @@ module dffn(
|
|||
(* clkbuf_sink *)
|
||||
input wire C
|
||||
);
|
||||
initial Q <= 1'b0;
|
||||
initial Q = 1'b0;
|
||||
|
||||
always @(negedge C)
|
||||
Q <= D;
|
||||
|
@ -194,7 +194,7 @@ module dffsre(
|
|||
input wire R,
|
||||
input wire S
|
||||
);
|
||||
initial Q <= 1'b0;
|
||||
initial Q = 1'b0;
|
||||
|
||||
always @(posedge C or negedge S or negedge R)
|
||||
if (!R)
|
||||
|
@ -228,7 +228,7 @@ module dffnsre(
|
|||
input wire R,
|
||||
input wire S
|
||||
);
|
||||
initial Q <= 1'b0;
|
||||
initial Q = 1'b0;
|
||||
|
||||
always @(negedge C or negedge S or negedge R)
|
||||
if (!R)
|
||||
|
@ -262,7 +262,7 @@ module sdffsre(
|
|||
input wire R,
|
||||
input wire S
|
||||
);
|
||||
initial Q <= 1'b0;
|
||||
initial Q = 1'b0;
|
||||
|
||||
always @(posedge C)
|
||||
if (!R)
|
||||
|
@ -292,7 +292,7 @@ module sdffnsre(
|
|||
input wire R,
|
||||
input wire S
|
||||
);
|
||||
initial Q <= 1'b0;
|
||||
initial Q = 1'b0;
|
||||
|
||||
always @(negedge C)
|
||||
if (!R)
|
||||
|
@ -321,7 +321,7 @@ module latchsre (
|
|||
input wire G,
|
||||
input wire E
|
||||
);
|
||||
initial Q <= 1'b0;
|
||||
initial Q = 1'b0;
|
||||
|
||||
always @*
|
||||
begin
|
||||
|
@ -352,7 +352,7 @@ module latchnsre (
|
|||
input wire G,
|
||||
input wire E
|
||||
);
|
||||
initial Q <= 1'b0;
|
||||
initial Q = 1'b0;
|
||||
|
||||
always @*
|
||||
begin
|
||||
|
|
|
@ -0,0 +1,246 @@
|
|||
import sys
|
||||
from datetime import datetime, timezone
|
||||
|
||||
def generate(filename):
|
||||
with open(filename, "w") as f:
|
||||
f.write("// **AUTOGENERATED FILE** **DO NOT EDIT**\n")
|
||||
f.write(f"// Generated by {sys.argv[0]} at {datetime.now(timezone.utc)}\n")
|
||||
|
||||
f.write("`timescale 1ns /10ps\n")
|
||||
for a_width in [1,2,4,9,18,36]:
|
||||
for b_width in [1,2,4,9,18,36]:
|
||||
f.write(f"""
|
||||
module TDP36K_BRAM_A_X{a_width}_B_X{b_width}_nonsplit (
|
||||
RESET_ni,
|
||||
WEN_A1_i, WEN_B1_i,
|
||||
REN_A1_i, REN_B1_i,
|
||||
CLK_A1_i, CLK_B1_i,
|
||||
BE_A1_i, BE_B1_i,
|
||||
ADDR_A1_i, ADDR_B1_i,
|
||||
WDATA_A1_i, WDATA_B1_i,
|
||||
RDATA_A1_o, RDATA_B1_o,
|
||||
FLUSH1_i,
|
||||
WEN_A2_i, WEN_B2_i,
|
||||
REN_A2_i, REN_B2_i,
|
||||
CLK_A2_i, CLK_B2_i,
|
||||
BE_A2_i, BE_B2_i,
|
||||
ADDR_A2_i, ADDR_B2_i,
|
||||
WDATA_A2_i, WDATA_B2_i,
|
||||
RDATA_A2_o, RDATA_B2_o,
|
||||
FLUSH2_i
|
||||
);
|
||||
|
||||
parameter [80:0] MODE_BITS = 81'd0;
|
||||
|
||||
input wire RESET_ni;
|
||||
input wire WEN_A1_i, WEN_B1_i;
|
||||
input wire REN_A1_i, REN_B1_i;
|
||||
input wire WEN_A2_i, WEN_B2_i;
|
||||
input wire REN_A2_i, REN_B2_i;
|
||||
|
||||
(* clkbuf_sink *)
|
||||
input wire CLK_A1_i;
|
||||
(* clkbuf_sink *)
|
||||
input wire CLK_B1_i;
|
||||
(* clkbuf_sink *)
|
||||
input wire CLK_A2_i;
|
||||
(* clkbuf_sink *)
|
||||
input wire CLK_B2_i;
|
||||
|
||||
input wire [ 1:0] BE_A1_i, BE_B1_i;
|
||||
input wire [14:0] ADDR_A1_i, ADDR_B1_i;
|
||||
input wire [17:0] WDATA_A1_i, WDATA_B1_i;
|
||||
output wire [17:0] RDATA_A1_o, RDATA_B1_o;
|
||||
|
||||
input wire FLUSH1_i;
|
||||
|
||||
input wire [ 1:0] BE_A2_i, BE_B2_i;
|
||||
input wire [13:0] ADDR_A2_i, ADDR_B2_i;
|
||||
input wire [17:0] WDATA_A2_i, WDATA_B2_i;
|
||||
output wire [17:0] RDATA_A2_o, RDATA_B2_o;
|
||||
|
||||
input wire FLUSH2_i;
|
||||
|
||||
TDP36K #(.MODE_BITS(MODE_BITS)) bram (
|
||||
.RESET_ni (RESET_ni),
|
||||
.WEN_A1_i (WEN_A1_i), .WEN_B1_i (WEN_B1_i),
|
||||
.REN_A1_i (REN_A1_i), .REN_B1_i (REN_B1_i),
|
||||
.CLK_A1_i (CLK_A1_i), .CLK_B1_i (CLK_B1_i),
|
||||
.BE_A1_i (BE_A1_i), .BE_B1_i (BE_B1_i),
|
||||
.ADDR_A1_i (ADDR_A1_i), .ADDR_B1_i (ADDR_B1_i),
|
||||
.WDATA_A1_i (WDATA_A1_i), .WDATA_B1_i (WDATA_B1_i),
|
||||
.RDATA_A1_o (RDATA_A1_o), .RDATA_B1_o (RDATA_B1_o),
|
||||
.FLUSH1_i (FLUSH1_i),
|
||||
.WEN_A2_i (WEN_A2_i), .WEN_B2_i (WEN_B2_i),
|
||||
.REN_A2_i (REN_A2_i), .REN_B2_i (REN_B2_i),
|
||||
.CLK_A2_i (CLK_A2_i), .CLK_B2_i (CLK_B2_i),
|
||||
.BE_A2_i (BE_A2_i), .BE_B2_i (BE_B2_i),
|
||||
.ADDR_A2_i (ADDR_A2_i), .ADDR_B2_i (ADDR_B2_i),
|
||||
.WDATA_A2_i (WDATA_A2_i), .WDATA_B2_i (WDATA_B2_i),
|
||||
.RDATA_A2_o (RDATA_A2_o), .RDATA_B2_o (RDATA_B2_o),
|
||||
.FLUSH2_i (FLUSH2_i)
|
||||
);
|
||||
|
||||
`ifdef SDF_SIM
|
||||
specify
|
||||
(negedge RESET_ni => (RDATA_A1_o +: WDATA_A1_i)) = 0;
|
||||
(negedge RESET_ni => (RDATA_B1_o +: WDATA_B1_i)) = 0;
|
||||
(negedge RESET_ni => (RDATA_A2_o +: WDATA_A2_i)) = 0;
|
||||
(negedge RESET_ni => (RDATA_B2_o +: WDATA_B2_i)) = 0;
|
||||
(posedge CLK_A1_i => (RDATA_A1_o +: WDATA_A1_i)) = 0;
|
||||
(posedge CLK_B1_i => (RDATA_B1_o +: WDATA_B1_i)) = 0;
|
||||
(posedge CLK_A2_i => (RDATA_A2_o +: WDATA_A2_i)) = 0;
|
||||
(posedge CLK_B2_i => (RDATA_B2_o +: WDATA_B2_i)) = 0;
|
||||
$setuphold(posedge CLK_A1_i, RESET_ni, 0, 0);
|
||||
$setuphold(posedge CLK_A1_i, FLUSH1_i, 0, 0);
|
||||
$setuphold(posedge CLK_A1_i, WEN_A1_i, 0, 0);
|
||||
$setuphold(posedge CLK_A1_i, REN_A1_i, 0, 0);
|
||||
$setuphold(posedge CLK_A1_i, BE_A1_i, 0, 0);
|
||||
$setuphold(posedge CLK_A1_i, ADDR_A1_i, 0, 0);
|
||||
$setuphold(posedge CLK_A1_i, WDATA_A1_i, 0, 0);
|
||||
$setuphold(posedge CLK_B1_i, RESET_ni, 0, 0);
|
||||
$setuphold(posedge CLK_B1_i, WEN_B1_i, 0, 0);
|
||||
$setuphold(posedge CLK_B1_i, REN_B1_i, 0, 0);
|
||||
$setuphold(posedge CLK_B1_i, BE_B1_i, 0, 0);
|
||||
$setuphold(posedge CLK_B1_i, ADDR_B1_i, 0, 0);
|
||||
$setuphold(posedge CLK_B1_i, WDATA_B1_i, 0, 0);
|
||||
$setuphold(posedge CLK_A2_i, RESET_ni, 0, 0);
|
||||
$setuphold(posedge CLK_A2_i, FLUSH2_i, 0, 0);
|
||||
$setuphold(posedge CLK_A2_i, WEN_A2_i, 0, 0);
|
||||
$setuphold(posedge CLK_A2_i, REN_A2_i, 0, 0);
|
||||
$setuphold(posedge CLK_A2_i, BE_A2_i, 0, 0);
|
||||
$setuphold(posedge CLK_A2_i, ADDR_A2_i, 0, 0);
|
||||
$setuphold(posedge CLK_A2_i, WDATA_A2_i, 0, 0);
|
||||
$setuphold(posedge CLK_B2_i, RESET_ni, 0, 0);
|
||||
$setuphold(posedge CLK_B2_i, WEN_B2_i, 0, 0);
|
||||
$setuphold(posedge CLK_B2_i, REN_B2_i, 0, 0);
|
||||
$setuphold(posedge CLK_B2_i, BE_B2_i, 0, 0);
|
||||
$setuphold(posedge CLK_B2_i, ADDR_B2_i, 0, 0);
|
||||
$setuphold(posedge CLK_B2_i, WDATA_B2_i, 0, 0);
|
||||
endspecify
|
||||
`endif
|
||||
endmodule
|
||||
""")
|
||||
|
||||
for a1_width in [1,2,4,9,18]:
|
||||
for b1_width in [1,2,4,9,18]:
|
||||
for a2_width in [1,2,4,9,18]:
|
||||
for b2_width in [1,2,4,9,18]:
|
||||
f.write(f"""
|
||||
module TDP36K_BRAM_A1_X{a1_width}_B1_X{b1_width}_A2_X{a2_width}_B2_X{b2_width}_split (
|
||||
RESET_ni,
|
||||
WEN_A1_i, WEN_B1_i,
|
||||
REN_A1_i, REN_B1_i,
|
||||
CLK_A1_i, CLK_B1_i,
|
||||
BE_A1_i, BE_B1_i,
|
||||
ADDR_A1_i, ADDR_B1_i,
|
||||
WDATA_A1_i, WDATA_B1_i,
|
||||
RDATA_A1_o, RDATA_B1_o,
|
||||
FLUSH1_i,
|
||||
WEN_A2_i, WEN_B2_i,
|
||||
REN_A2_i, REN_B2_i,
|
||||
CLK_A2_i, CLK_B2_i,
|
||||
BE_A2_i, BE_B2_i,
|
||||
ADDR_A2_i, ADDR_B2_i,
|
||||
WDATA_A2_i, WDATA_B2_i,
|
||||
RDATA_A2_o, RDATA_B2_o,
|
||||
FLUSH2_i
|
||||
);
|
||||
|
||||
parameter [80:0] MODE_BITS = 81'd0;
|
||||
|
||||
input wire RESET_ni;
|
||||
input wire WEN_A1_i, WEN_B1_i;
|
||||
input wire REN_A1_i, REN_B1_i;
|
||||
input wire WEN_A2_i, WEN_B2_i;
|
||||
input wire REN_A2_i, REN_B2_i;
|
||||
|
||||
(* clkbuf_sink *)
|
||||
input wire CLK_A1_i;
|
||||
(* clkbuf_sink *)
|
||||
input wire CLK_B1_i;
|
||||
(* clkbuf_sink *)
|
||||
input wire CLK_A2_i;
|
||||
(* clkbuf_sink *)
|
||||
input wire CLK_B2_i;
|
||||
|
||||
input wire [ 1:0] BE_A1_i, BE_B1_i;
|
||||
input wire [14:0] ADDR_A1_i, ADDR_B1_i;
|
||||
input wire [17:0] WDATA_A1_i, WDATA_B1_i;
|
||||
output wire [17:0] RDATA_A1_o, RDATA_B1_o;
|
||||
|
||||
input wire FLUSH1_i;
|
||||
|
||||
input wire [ 1:0] BE_A2_i, BE_B2_i;
|
||||
input wire [13:0] ADDR_A2_i, ADDR_B2_i;
|
||||
input wire [17:0] WDATA_A2_i, WDATA_B2_i;
|
||||
output wire [17:0] RDATA_A2_o, RDATA_B2_o;
|
||||
|
||||
input wire FLUSH2_i;
|
||||
|
||||
TDP36K #(.MODE_BITS(MODE_BITS)) bram (
|
||||
.RESET_ni (RESET_ni),
|
||||
.WEN_A1_i (WEN_A1_i), .WEN_B1_i (WEN_B1_i),
|
||||
.REN_A1_i (REN_A1_i), .REN_B1_i (REN_B1_i),
|
||||
.CLK_A1_i (CLK_A1_i), .CLK_B1_i (CLK_B1_i),
|
||||
.BE_A1_i (BE_A1_i), .BE_B1_i (BE_B1_i),
|
||||
.ADDR_A1_i (ADDR_A1_i), .ADDR_B1_i (ADDR_B1_i),
|
||||
.WDATA_A1_i (WDATA_A1_i), .WDATA_B1_i (WDATA_B1_i),
|
||||
.RDATA_A1_o (RDATA_A1_o), .RDATA_B1_o (RDATA_B1_o),
|
||||
.FLUSH1_i (FLUSH1_i),
|
||||
.WEN_A2_i (WEN_A2_i), .WEN_B2_i (WEN_B2_i),
|
||||
.REN_A2_i (REN_A2_i), .REN_B2_i (REN_B2_i),
|
||||
.CLK_A2_i (CLK_A2_i), .CLK_B2_i (CLK_B2_i),
|
||||
.BE_A2_i (BE_A2_i), .BE_B2_i (BE_B2_i),
|
||||
.ADDR_A2_i (ADDR_A2_i), .ADDR_B2_i (ADDR_B2_i),
|
||||
.WDATA_A2_i (WDATA_A2_i), .WDATA_B2_i (WDATA_B2_i),
|
||||
.RDATA_A2_o (RDATA_A2_o), .RDATA_B2_o (RDATA_B2_o),
|
||||
.FLUSH2_i (FLUSH2_i)
|
||||
);
|
||||
|
||||
`ifdef SDF_SIM
|
||||
specify
|
||||
(negedge RESET_ni => (RDATA_A1_o +: WDATA_A1_i)) = 0;
|
||||
(negedge RESET_ni => (RDATA_B1_o +: WDATA_B1_i)) = 0;
|
||||
(negedge RESET_ni => (RDATA_A2_o +: WDATA_A2_i)) = 0;
|
||||
(negedge RESET_ni => (RDATA_B2_o +: WDATA_B2_i)) = 0;
|
||||
(posedge CLK_A1_i => (RDATA_A1_o +: WDATA_A1_i)) = 0;
|
||||
(posedge CLK_B1_i => (RDATA_B1_o +: WDATA_B1_i)) = 0;
|
||||
(posedge CLK_A2_i => (RDATA_A2_o +: WDATA_A2_i)) = 0;
|
||||
(posedge CLK_B2_i => (RDATA_B2_o +: WDATA_B2_i)) = 0;
|
||||
$setuphold(posedge CLK_A1_i, RESET_ni, 0, 0);
|
||||
$setuphold(posedge CLK_A1_i, FLUSH1_i, 0, 0);
|
||||
$setuphold(posedge CLK_A1_i, WEN_A1_i, 0, 0);
|
||||
$setuphold(posedge CLK_A1_i, REN_A1_i, 0, 0);
|
||||
$setuphold(posedge CLK_A1_i, BE_A1_i, 0, 0);
|
||||
$setuphold(posedge CLK_A1_i, ADDR_A1_i, 0, 0);
|
||||
$setuphold(posedge CLK_A1_i, WDATA_A1_i, 0, 0);
|
||||
$setuphold(posedge CLK_B1_i, RESET_ni, 0, 0);
|
||||
$setuphold(posedge CLK_B1_i, WEN_B1_i, 0, 0);
|
||||
$setuphold(posedge CLK_B1_i, REN_B1_i, 0, 0);
|
||||
$setuphold(posedge CLK_B1_i, BE_B1_i, 0, 0);
|
||||
$setuphold(posedge CLK_B1_i, ADDR_B1_i, 0, 0);
|
||||
$setuphold(posedge CLK_B1_i, WDATA_B1_i, 0, 0);
|
||||
$setuphold(posedge CLK_A2_i, RESET_ni, 0, 0);
|
||||
$setuphold(posedge CLK_A2_i, FLUSH2_i, 0, 0);
|
||||
$setuphold(posedge CLK_A2_i, WEN_A2_i, 0, 0);
|
||||
$setuphold(posedge CLK_A2_i, REN_A2_i, 0, 0);
|
||||
$setuphold(posedge CLK_A2_i, BE_A2_i, 0, 0);
|
||||
$setuphold(posedge CLK_A2_i, ADDR_A2_i, 0, 0);
|
||||
$setuphold(posedge CLK_A2_i, WDATA_A2_i, 0, 0);
|
||||
$setuphold(posedge CLK_B2_i, RESET_ni, 0, 0);
|
||||
$setuphold(posedge CLK_B2_i, WEN_B2_i, 0, 0);
|
||||
$setuphold(posedge CLK_B2_i, REN_B2_i, 0, 0);
|
||||
$setuphold(posedge CLK_B2_i, BE_B2_i, 0, 0);
|
||||
$setuphold(posedge CLK_B2_i, ADDR_B2_i, 0, 0);
|
||||
$setuphold(posedge CLK_B2_i, WDATA_B2_i, 0, 0);
|
||||
endspecify
|
||||
`endif
|
||||
endmodule
|
||||
""")
|
||||
|
||||
if __name__ == "__main__":
|
||||
filename = "bram_types_sim.v"
|
||||
if len(sys.argv) > 1:
|
||||
filename = sys.argv[1]
|
||||
generate(filename)
|
|
@ -1,100 +0,0 @@
|
|||
/*
|
||||
* Copyright 2020-2022 F4PGA Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
*/
|
||||
|
||||
#include "kernel/sigtools.h"
|
||||
#include "kernel/yosys.h"
|
||||
|
||||
USING_YOSYS_NAMESPACE
|
||||
PRIVATE_NAMESPACE_BEGIN
|
||||
|
||||
struct QuicklogicEqnPass : public Pass {
|
||||
QuicklogicEqnPass() : Pass("quicklogic_eqn", "Quicklogic: Calculate equations for luts") {}
|
||||
void help() override
|
||||
{
|
||||
log("\n");
|
||||
log(" quicklogic_eqn [selection]\n");
|
||||
log("\n");
|
||||
log("Calculate equations for luts since bitstream generator depends on it.\n");
|
||||
log("\n");
|
||||
}
|
||||
|
||||
Const init2eqn(Const init, int inputs)
|
||||
{
|
||||
std::string init_bits = init.as_string();
|
||||
const char *names[] = {"I0", "I1", "I2", "I3", "I4"};
|
||||
|
||||
std::string eqn;
|
||||
int width = (int)pow(2, inputs);
|
||||
for (int i = 0; i < width; i++) {
|
||||
if (init_bits[width - 1 - i] == '1') {
|
||||
eqn += "(";
|
||||
for (int j = 0; j < inputs; j++) {
|
||||
if (i & (1 << j))
|
||||
eqn += names[j];
|
||||
else
|
||||
eqn += std::string("~") + names[j];
|
||||
|
||||
if (j != (inputs - 1))
|
||||
eqn += "*";
|
||||
}
|
||||
eqn += ")+";
|
||||
}
|
||||
}
|
||||
if (eqn.empty())
|
||||
return Const("0");
|
||||
eqn = eqn.substr(0, eqn.length() - 1);
|
||||
return Const(eqn);
|
||||
}
|
||||
|
||||
void execute(std::vector<std::string> args, RTLIL::Design *design) override
|
||||
{
|
||||
log_header(design, "Executing Quicklogic_EQN pass (calculate equations for luts).\n");
|
||||
|
||||
extra_args(args, args.size(), design);
|
||||
|
||||
int cnt = 0;
|
||||
for (auto module : design->selected_modules()) {
|
||||
for (auto cell : module->selected_cells()) {
|
||||
if (cell->type == ID(LUT1)) {
|
||||
cell->setParam(ID(EQN), init2eqn(cell->getParam(ID::INIT), 1));
|
||||
cnt++;
|
||||
}
|
||||
if (cell->type == ID(LUT2)) {
|
||||
cell->setParam(ID(EQN), init2eqn(cell->getParam(ID::INIT), 2));
|
||||
cnt++;
|
||||
}
|
||||
if (cell->type == ID(LUT3)) {
|
||||
cell->setParam(ID(EQN), init2eqn(cell->getParam(ID::INIT), 3));
|
||||
cnt++;
|
||||
}
|
||||
if (cell->type == ID(LUT4)) {
|
||||
cell->setParam(ID(EQN), init2eqn(cell->getParam(ID::INIT), 4));
|
||||
cnt++;
|
||||
}
|
||||
if (cell->type == ID(LUT5)) {
|
||||
cell->setParam(ID(EQN), init2eqn(cell->getParam(ID::INIT), 5));
|
||||
cnt++;
|
||||
}
|
||||
}
|
||||
}
|
||||
log_header(design, "Updated %d of LUT* elements with equation.\n", cnt);
|
||||
}
|
||||
} QuicklogicEqnPass;
|
||||
|
||||
PRIVATE_NAMESPACE_END
|
|
@ -129,10 +129,6 @@ struct SynthQuickLogicPass : public ScriptPass {
|
|||
blif_file = args[++argidx];
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-edif" && argidx + 1 < args.size()) {
|
||||
edif_file = args[++argidx];
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-verilog" && argidx+1 < args.size()) {
|
||||
verilog_file = args[++argidx];
|
||||
continue;
|
||||
|
@ -141,15 +137,15 @@ struct SynthQuickLogicPass : public ScriptPass {
|
|||
abc9 = false;
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-nocarry") {
|
||||
if (args[argidx] == "-nocarry" || args[argidx] == "-no_adder") {
|
||||
inferAdder = false;
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-nobram") {
|
||||
if (args[argidx] == "-nobram" || args[argidx] == "-no_bram") {
|
||||
nobram = true;
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-bramtypes") {
|
||||
if (args[argidx] == "-bramtypes" || args[argidx] == "-bram_types") {
|
||||
bramTypes = true;
|
||||
continue;
|
||||
}
|
||||
|
@ -230,61 +226,8 @@ struct SynthQuickLogicPass : public ScriptPass {
|
|||
run("techmap -autoproc -map " + lib_path + family + "/brams_map.v");
|
||||
run("techmap -map " + lib_path + family + "/brams_final_map.v");
|
||||
|
||||
if (help_mode) {
|
||||
run("chtype -set TDP36K_<mode> t:TDP36K a:<mode>", "(if -bram_types)");
|
||||
}
|
||||
else if (bramTypes) {
|
||||
for (int a_dwidth : {1, 2, 4, 9, 18, 36})
|
||||
for (int b_dwidth: {1, 2, 4, 9, 18, 36}) {
|
||||
run(stringf("chtype -set TDP36K_BRAM_A_X%d_B_X%d_nonsplit t:TDP36K a:is_inferred=0 %%i "
|
||||
"a:is_fifo=0 %%i a:port_a_dwidth=%d %%i a:port_b_dwidth=%d %%i",
|
||||
a_dwidth, b_dwidth, a_dwidth, b_dwidth));
|
||||
|
||||
run(stringf("chtype -set TDP36K_FIFO_ASYNC_A_X%d_B_X%d_nonsplit t:TDP36K a:is_inferred=0 %%i "
|
||||
"a:is_fifo=1 %%i a:sync_fifo=0 %%i a:port_a_dwidth=%d %%i a:port_b_dwidth=%d %%i",
|
||||
a_dwidth, b_dwidth, a_dwidth, b_dwidth));
|
||||
|
||||
run(stringf("chtype -set TDP36K_FIFO_SYNC_A_X%d_B_X%d_nonsplit t:TDP36K a:is_inferred=0 %%i "
|
||||
"a:is_fifo=1 %%i a:sync_fifo=1 %%i a:port_a_dwidth=%d %%i a:port_b_dwidth=%d %%i",
|
||||
a_dwidth, b_dwidth, a_dwidth, b_dwidth));
|
||||
}
|
||||
|
||||
for (int a1_dwidth : {1, 2, 4, 9, 18})
|
||||
for (int b1_dwidth: {1, 2, 4, 9, 18})
|
||||
for (int a2_dwidth : {1, 2, 4, 9, 18})
|
||||
for (int b2_dwidth: {1, 2, 4, 9, 18}) {
|
||||
run(stringf("chtype -set TDP36K_BRAM_A1_X%d_B1_X%d_A2_X%d_B2_X%d_split t:TDP36K a:is_inferred=0 %%i "
|
||||
"a:is_split=1 %%i a:is_fifo=0 %%i "
|
||||
"a:port_a1_dwidth=%d %%i a:port_b1_dwidth=%d %%i a:port_a2_dwidth=%d %%i a:port_b2_dwidth=%d %%i",
|
||||
a1_dwidth, b1_dwidth, a2_dwidth, b2_dwidth, a1_dwidth, b1_dwidth, a2_dwidth, b2_dwidth));
|
||||
|
||||
run(stringf("chtype -set TDP36K_FIFO_ASYNC_A1_X%d_B1_X%d_A2_X%d_B2_X%d_split t:TDP36K a:is_inferred=0 %%i "
|
||||
"a:is_split=1 %%i a:is_fifo=1 %%i a:sync_fifo=0 %%i "
|
||||
"a:port_a1_dwidth=%d %%i a:port_b1_dwidth=%d %%i a:port_a2_dwidth=%d %%i a:port_b2_dwidth=%d %%i",
|
||||
a1_dwidth, b1_dwidth, a2_dwidth, b2_dwidth, a1_dwidth, b1_dwidth, a2_dwidth, b2_dwidth));
|
||||
|
||||
run(stringf("chtype -set TDP36K_FIFO_SYNC_A1_X%d_B1_X%d_A2_X%d_B2_X%d_split t:TDP36K a:is_inferred=0 %%i "
|
||||
"a:is_split=1 %%i a:is_fifo=1 %%i a:sync_fifo=1 %%i "
|
||||
"a:port_a1_dwidth=%d %%i a:port_b1_dwidth=%d %%i a:port_a2_dwidth=%d %%i a:port_b2_dwidth=%d %%i",
|
||||
a1_dwidth, b1_dwidth, a2_dwidth, b2_dwidth, a1_dwidth, b1_dwidth, a2_dwidth, b2_dwidth));
|
||||
}
|
||||
|
||||
|
||||
for (int a_width : {1, 2, 4, 9, 18, 36})
|
||||
for (int b_width: {1, 2, 4, 9, 18, 36}) {
|
||||
run(stringf("chtype -set TDP36K_BRAM_A_X%d_B_X%d_nonsplit t:TDP36K a:is_inferred=1 %%i "
|
||||
"a:port_a_width=%d %%i a:port_b_width=%d %%i",
|
||||
a_width, b_width, a_width, b_width));
|
||||
}
|
||||
|
||||
for (int a1_width : {1, 2, 4, 9, 18})
|
||||
for (int b1_width: {1, 2, 4, 9, 18})
|
||||
for (int a2_width : {1, 2, 4, 9, 18})
|
||||
for (int b2_width: {1, 2, 4, 9, 18}) {
|
||||
run(stringf("chtype -set TDP36K_BRAM_A1_X%d_B1_X%d_A2_X%d_B2_X%d_split t:TDP36K a:is_inferred=1 %%i "
|
||||
"a:port_a1_width=%d %%i a:port_b1_width=%d %%i a:port_a2_width=%d %%i a:port_b2_width=%d %%i",
|
||||
a1_width, b1_width, a2_width, b2_width, a1_width, b1_width, a2_width, b2_width));
|
||||
}
|
||||
if (help_mode || bramTypes) {
|
||||
run("ql_bram_types");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -393,13 +336,6 @@ struct SynthQuickLogicPass : public ScriptPass {
|
|||
run(stringf("write_verilog -noattr -nohex %s", help_mode ? "<file-name>" : verilog_file.c_str()));
|
||||
}
|
||||
}
|
||||
|
||||
if (check_label("edif", "(if -edif)")) {
|
||||
if (!edif_file.empty() || help_mode) {
|
||||
run("splitnets -ports -format ()");
|
||||
run(stringf("write_edif -nogndvcc -attrprop -pvector par %s %s", top_opt.c_str(), edif_file.c_str()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} SynthQuicklogicPass;
|
||||
|
|
Loading…
Reference in New Issue