change ql-bram-types pass to use mode parameter; clean up primitive libraries

This commit is contained in:
N. Engelhardt 2023-08-14 16:20:36 +02:00 committed by Martin Povišer
parent 48c1fdc33d
commit 6682693888
13 changed files with 74503 additions and 74255 deletions

View File

@ -1,6 +1,6 @@
OBJS += techlibs/quicklogic/synth_quicklogic.o OBJS += techlibs/quicklogic/synth_quicklogic.o
OBJS += techlibs/quicklogic/ql-bram-merge.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)) $(eval $(call add_share_file,share/quicklogic/common,techlibs/quicklogic/common/cells_sim.v))

View File

@ -31,184 +31,184 @@ PRIVATE_NAMESPACE_BEGIN
struct QlBramMergeWorker { struct QlBramMergeWorker {
const RTLIL::IdString split_cell_type = ID($__QLF_TDP36K); const RTLIL::IdString split_cell_type = ID($__QLF_TDP36K);
const RTLIL::IdString merged_cell_type = ID($__QLF_TDP36K_MERGED); const RTLIL::IdString merged_cell_type = ID($__QLF_TDP36K_MERGED);
// can be used to record parameter values that have to match on both sides // can be used to record parameter values that have to match on both sides
typedef dict<RTLIL::IdString, RTLIL::Const> MergeableGroupKeyType; typedef dict<RTLIL::IdString, RTLIL::Const> MergeableGroupKeyType;
RTLIL::Module *module; RTLIL::Module *module;
dict<MergeableGroupKeyType, pool<RTLIL::Cell*>> mergeable_groups; dict<MergeableGroupKeyType, pool<RTLIL::Cell*>> mergeable_groups;
QlBramMergeWorker(RTLIL::Module* module) : module(module) QlBramMergeWorker(RTLIL::Module* module) : module(module)
{ {
for (RTLIL::Cell* cell : module->selected_cells()) for (RTLIL::Cell* cell : module->selected_cells())
{ {
if(cell->type != split_cell_type) continue; if(cell->type != split_cell_type) continue;
if(!cell->hasParam(ID(OPTION_SPLIT))) continue; if(!cell->hasParam(ID(OPTION_SPLIT))) continue;
if(cell->getParam(ID(OPTION_SPLIT)) != RTLIL::Const(1, 32)) continue; if(cell->getParam(ID(OPTION_SPLIT)) != RTLIL::Const(1, 32)) continue;
mergeable_groups[get_key(cell)].insert(cell); mergeable_groups[get_key(cell)].insert(cell);
} }
} }
static MergeableGroupKeyType get_key(RTLIL::Cell* cell) static MergeableGroupKeyType get_key(RTLIL::Cell* cell)
{ {
MergeableGroupKeyType key; MergeableGroupKeyType key;
// For now, there are no restrictions on which cells can be merged // For now, there are no restrictions on which cells can be merged
(void) cell; (void) cell;
return key; return key;
} }
const dict<RTLIL::IdString, RTLIL::IdString>& param_map(bool second) const dict<RTLIL::IdString, RTLIL::IdString>& param_map(bool second)
{ {
static const dict<RTLIL::IdString, RTLIL::IdString> bram1_map = { static const dict<RTLIL::IdString, RTLIL::IdString> bram1_map = {
{ ID(INIT), ID(INIT1) }, { ID(INIT), ID(INIT1) },
{ ID(PORT_A_WIDTH), ID(PORT_A1_WIDTH) }, { ID(PORT_A_WIDTH), ID(PORT_A1_WIDTH) },
{ ID(PORT_B_WIDTH), ID(PORT_B1_WIDTH) }, { ID(PORT_B_WIDTH), ID(PORT_B1_WIDTH) },
{ ID(PORT_A_WR_BE_WIDTH), ID(PORT_A1_WR_BE_WIDTH) }, { ID(PORT_A_WR_BE_WIDTH), ID(PORT_A1_WR_BE_WIDTH) },
{ ID(PORT_B_WR_BE_WIDTH), ID(PORT_B1_WR_BE_WIDTH) } { ID(PORT_B_WR_BE_WIDTH), ID(PORT_B1_WR_BE_WIDTH) }
}; };
static const dict<RTLIL::IdString, RTLIL::IdString> bram2_map = { static const dict<RTLIL::IdString, RTLIL::IdString> bram2_map = {
{ ID(INIT), ID(INIT2) }, { ID(INIT), ID(INIT2) },
{ ID(PORT_A_WIDTH), ID(PORT_A2_WIDTH) }, { ID(PORT_A_WIDTH), ID(PORT_A2_WIDTH) },
{ ID(PORT_B_WIDTH), ID(PORT_B2_WIDTH) }, { ID(PORT_B_WIDTH), ID(PORT_B2_WIDTH) },
{ ID(PORT_A_WR_BE_WIDTH), ID(PORT_A2_WR_BE_WIDTH) }, { ID(PORT_A_WR_BE_WIDTH), ID(PORT_A2_WR_BE_WIDTH) },
{ ID(PORT_B_WR_BE_WIDTH), ID(PORT_B2_WR_BE_WIDTH) } { ID(PORT_B_WR_BE_WIDTH), ID(PORT_B2_WR_BE_WIDTH) }
}; };
if(second) if(second)
return bram2_map; return bram2_map;
else else
return bram1_map; return bram1_map;
} }
const dict<RTLIL::IdString, RTLIL::IdString>& port_map(bool second) const dict<RTLIL::IdString, RTLIL::IdString>& port_map(bool second)
{ {
static const dict<RTLIL::IdString, RTLIL::IdString> bram1_map = { static const dict<RTLIL::IdString, RTLIL::IdString> bram1_map = {
{ ID(PORT_A_CLK), ID(PORT_A1_CLK) }, { ID(PORT_A_CLK), ID(PORT_A1_CLK) },
{ ID(PORT_B_CLK), ID(PORT_B1_CLK) }, { ID(PORT_B_CLK), ID(PORT_B1_CLK) },
{ ID(PORT_A_CLK_EN), ID(PORT_A1_CLK_EN) }, { ID(PORT_A_CLK_EN), ID(PORT_A1_CLK_EN) },
{ ID(PORT_B_CLK_EN), ID(PORT_B1_CLK_EN) }, { ID(PORT_B_CLK_EN), ID(PORT_B1_CLK_EN) },
{ ID(PORT_A_ADDR), ID(PORT_A1_ADDR) }, { ID(PORT_A_ADDR), ID(PORT_A1_ADDR) },
{ ID(PORT_B_ADDR), ID(PORT_B1_ADDR) }, { ID(PORT_B_ADDR), ID(PORT_B1_ADDR) },
{ ID(PORT_A_WR_DATA), ID(PORT_A1_WR_DATA) }, { ID(PORT_A_WR_DATA), ID(PORT_A1_WR_DATA) },
{ ID(PORT_B_WR_DATA), ID(PORT_B1_WR_DATA) }, { ID(PORT_B_WR_DATA), ID(PORT_B1_WR_DATA) },
{ ID(PORT_A_WR_EN), ID(PORT_A1_WR_EN) }, { ID(PORT_A_WR_EN), ID(PORT_A1_WR_EN) },
{ ID(PORT_B_WR_EN), ID(PORT_B1_WR_EN) }, { ID(PORT_B_WR_EN), ID(PORT_B1_WR_EN) },
{ ID(PORT_A_WR_BE), ID(PORT_A1_WR_BE) }, { ID(PORT_A_WR_BE), ID(PORT_A1_WR_BE) },
{ ID(PORT_B_WR_BE), ID(PORT_B1_WR_BE) }, { ID(PORT_B_WR_BE), ID(PORT_B1_WR_BE) },
{ ID(PORT_A_RD_DATA), ID(PORT_A1_RD_DATA) }, { ID(PORT_A_RD_DATA), ID(PORT_A1_RD_DATA) },
{ ID(PORT_B_RD_DATA), ID(PORT_B1_RD_DATA) } { ID(PORT_B_RD_DATA), ID(PORT_B1_RD_DATA) }
}; };
static const dict<RTLIL::IdString, RTLIL::IdString> bram2_map = { static const dict<RTLIL::IdString, RTLIL::IdString> bram2_map = {
{ ID(PORT_A_CLK), ID(PORT_A2_CLK) }, { ID(PORT_A_CLK), ID(PORT_A2_CLK) },
{ ID(PORT_B_CLK), ID(PORT_B2_CLK) }, { ID(PORT_B_CLK), ID(PORT_B2_CLK) },
{ ID(PORT_A_CLK_EN), ID(PORT_A2_CLK_EN) }, { ID(PORT_A_CLK_EN), ID(PORT_A2_CLK_EN) },
{ ID(PORT_B_CLK_EN), ID(PORT_B2_CLK_EN) }, { ID(PORT_B_CLK_EN), ID(PORT_B2_CLK_EN) },
{ ID(PORT_A_ADDR), ID(PORT_A2_ADDR) }, { ID(PORT_A_ADDR), ID(PORT_A2_ADDR) },
{ ID(PORT_B_ADDR), ID(PORT_B2_ADDR) }, { ID(PORT_B_ADDR), ID(PORT_B2_ADDR) },
{ ID(PORT_A_WR_DATA), ID(PORT_A2_WR_DATA) }, { ID(PORT_A_WR_DATA), ID(PORT_A2_WR_DATA) },
{ ID(PORT_B_WR_DATA), ID(PORT_B2_WR_DATA) }, { ID(PORT_B_WR_DATA), ID(PORT_B2_WR_DATA) },
{ ID(PORT_A_WR_EN), ID(PORT_A2_WR_EN) }, { ID(PORT_A_WR_EN), ID(PORT_A2_WR_EN) },
{ ID(PORT_B_WR_EN), ID(PORT_B2_WR_EN) }, { ID(PORT_B_WR_EN), ID(PORT_B2_WR_EN) },
{ ID(PORT_A_WR_BE), ID(PORT_A2_WR_BE) }, { ID(PORT_A_WR_BE), ID(PORT_A2_WR_BE) },
{ ID(PORT_B_WR_BE), ID(PORT_B2_WR_BE) }, { ID(PORT_B_WR_BE), ID(PORT_B2_WR_BE) },
{ ID(PORT_A_RD_DATA), ID(PORT_A2_RD_DATA) }, { ID(PORT_A_RD_DATA), ID(PORT_A2_RD_DATA) },
{ ID(PORT_B_RD_DATA), ID(PORT_B2_RD_DATA) } { ID(PORT_B_RD_DATA), ID(PORT_B2_RD_DATA) }
}; };
if(second) if(second)
return bram2_map; return bram2_map;
else else
return bram1_map; return bram1_map;
} }
void merge_brams(RTLIL::Cell* bram1, RTLIL::Cell* bram2) void merge_brams(RTLIL::Cell* bram1, RTLIL::Cell* bram2)
{ {
// Create the new cell // Create the new cell
RTLIL::Cell* merged = module->addCell(NEW_ID, merged_cell_type); RTLIL::Cell* merged = module->addCell(NEW_ID, merged_cell_type);
log_debug("Merging split BRAM cells %s and %s -> %s\n", log_id(bram1->name), log_id(bram2->name), log_id(merged->name)); log_debug("Merging split BRAM cells %s and %s -> %s\n", log_id(bram1->name), log_id(bram2->name), log_id(merged->name));
for (auto &it : param_map(false)) for (auto &it : param_map(false))
{ {
if(bram1->hasParam(it.first)) if(bram1->hasParam(it.first))
merged->setParam(it.second, bram1->getParam(it.first)); merged->setParam(it.second, bram1->getParam(it.first));
} }
for (auto &it : param_map(true)) for (auto &it : param_map(true))
{ {
if(bram2->hasParam(it.first)) if(bram2->hasParam(it.first))
merged->setParam(it.second, bram2->getParam(it.first)); merged->setParam(it.second, bram2->getParam(it.first));
} }
for (auto &it : port_map(false)) for (auto &it : port_map(false))
{ {
if (bram1->hasPort(it.first)) if (bram1->hasPort(it.first))
merged->setPort(it.second, bram1->getPort(it.first)); merged->setPort(it.second, bram1->getPort(it.first));
else else
log_error("Can't find port %s on cell %s!\n", log_id(it.first), log_id(bram1->name)); log_error("Can't find port %s on cell %s!\n", log_id(it.first), log_id(bram1->name));
} }
for (auto &it : port_map(true)) for (auto &it : port_map(true))
{ {
if (bram2->hasPort(it.first)) if (bram2->hasPort(it.first))
merged->setPort(it.second, bram2->getPort(it.first)); merged->setPort(it.second, bram2->getPort(it.first));
else else
log_error("Can't find port %s on cell %s!\n", log_id(it.first), log_id(bram2->name)); log_error("Can't find port %s on cell %s!\n", log_id(it.first), log_id(bram2->name));
} }
merged->attributes = bram1->attributes; merged->attributes = bram1->attributes;
for (auto attr: bram2->attributes) for (auto attr: bram2->attributes)
if (!merged->has_attribute(attr.first)) if (!merged->has_attribute(attr.first))
merged->attributes.insert(attr); merged->attributes.insert(attr);
// Remove the old cells // Remove the old cells
module->remove(bram1); module->remove(bram1);
module->remove(bram2); module->remove(bram2);
} }
void merge_bram_groups() void merge_bram_groups()
{ {
for (auto &it : mergeable_groups) for (auto &it : mergeable_groups)
{ {
while (it.second.size() > 1) while (it.second.size() > 1)
{ {
merge_brams(it.second.pop(), it.second.pop()); merge_brams(it.second.pop(), it.second.pop());
} }
} }
} }
}; };
struct QlBramMergePass : public Pass { struct QlBramMergePass : public Pass {
QlBramMergePass() : Pass("ql_bram_merge", "Infers QuickLogic k6n10f BRAM pairs that can operate independently") {} QlBramMergePass() : Pass("ql_bram_merge", "Infers QuickLogic k6n10f BRAM pairs that can operate independently") {}
void help() override void help() override
{ {
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n"); log("\n");
log(" ql_bram_merge [selection]\n"); log(" ql_bram_merge [selection]\n");
log("\n"); log("\n");
log(" This pass identifies k6n10f 18K BRAM cells and packs pairs of them together\n"); log(" This pass identifies k6n10f 18K BRAM cells and packs pairs of them together\n");
log(" into a TDP36K cell operating in split mode\n"); log(" into a TDP36K cell operating in split mode\n");
log("\n"); log("\n");
} }
void execute(std::vector<std::string> args, RTLIL::Design *design) override void execute(std::vector<std::string> args, RTLIL::Design *design) override
{ {
log_header(design, "Executing QL_BRAM_MERGE pass.\n"); log_header(design, "Executing QL_BRAM_MERGE pass.\n");
size_t argidx = 1; size_t argidx = 1;
extra_args(args, argidx, design); extra_args(args, argidx, design);
for (RTLIL::Module* module : design->selected_modules()) for (RTLIL::Module* module : design->selected_modules())
{ {
QlBramMergeWorker worker(module); QlBramMergeWorker worker(module);
worker.merge_bram_groups(); worker.merge_bram_groups();
} }
} }
} QlBramMergePass; } QlBramMergePass;

View File

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

View File

@ -56,43 +56,43 @@ module _80_quicklogic_alu (A, B, CI, BI, X, Y, CO);
(* force_downto *) (* force_downto *)
wire [Y_WIDTH-1:0] S = {AA ^ BB}; wire [Y_WIDTH-1:0] S = {AA ^ BB};
assign CO[Y_WIDTH-1:0] = C[Y_WIDTH:1]; assign CO[Y_WIDTH-1:0] = C[Y_WIDTH:1];
//assign CO[Y_WIDTH-1] = co; //assign CO[Y_WIDTH-1] = co;
generate generate
adder_carry intermediate_adder ( adder_carry intermediate_adder (
.cin ( ), .cin ( ),
.cout (C[0]), .cout (C[0]),
.p (1'b0), .p (1'b0),
.g (CI), .g (CI),
.sumout () .sumout ()
); );
endgenerate endgenerate
genvar i; genvar i;
generate if (Y_WIDTH > 2) begin generate if (Y_WIDTH > 2) begin
for (i = 0; i < Y_WIDTH-2; i = i + 1) begin:slice for (i = 0; i < Y_WIDTH-2; i = i + 1) begin:slice
adder_carry my_adder ( adder_carry my_adder (
.cin(C[i]), .cin (C[i]),
.g(AA[i]), .g (AA[i]),
.p(S[i]), .p (S[i]),
.cout(C[i+1]), .cout (C[i+1]),
.sumout(Y[i]) .sumout (Y[i])
); );
end end
end endgenerate end endgenerate
generate generate
adder_carry final_adder ( adder_carry final_adder (
.cin (C[Y_WIDTH-2]), .cin (C[Y_WIDTH-2]),
.cout (), .cout (),
.p (1'b0), .p (1'b0),
.g (1'b0), .g (1'b0),
.sumout (co) .sumout (co)
); );
endgenerate endgenerate
assign Y[Y_WIDTH-2] = S[Y_WIDTH-2] ^ co; assign Y[Y_WIDTH-2] = S[Y_WIDTH-2] ^ co;
assign C[Y_WIDTH-1] = S[Y_WIDTH-2] ? co : AA[Y_WIDTH-2]; assign C[Y_WIDTH-1] = S[Y_WIDTH-2] ? co : AA[Y_WIDTH-2];
assign Y[Y_WIDTH-1] = S[Y_WIDTH-1] ^ C[Y_WIDTH-1]; assign Y[Y_WIDTH-1] = S[Y_WIDTH-1] ^ C[Y_WIDTH-1];
assign C[Y_WIDTH] = S[Y_WIDTH-1] ? C[Y_WIDTH-1] : AA[Y_WIDTH-1]; assign C[Y_WIDTH] = S[Y_WIDTH-1] ? C[Y_WIDTH-1] : AA[Y_WIDTH-1];
assign X = S; assign X = S;
endmodule endmodule

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -19,104 +19,104 @@
`default_nettype none `default_nettype none
(* abc9_lut=1 *) (* abc9_lut=1 *)
module LUT1(output wire O, input wire I0); module LUT1(output wire O, input wire I0);
parameter [1:0] INIT = 0; parameter [1:0] INIT = 0;
assign O = I0 ? INIT[1] : INIT[0]; assign O = I0 ? INIT[1] : INIT[0];
specify specify
(I0 => O) = 74; (I0 => O) = 74;
endspecify endspecify
endmodule endmodule
(* abc9_lut=2 *) (* abc9_lut=2 *)
module LUT2(output wire O, input wire I0, I1); module LUT2(output wire O, input wire I0, I1);
parameter [3:0] INIT = 0; parameter [3:0] INIT = 0;
wire [ 1: 0] s1 = I1 ? INIT[ 3: 2] : INIT[ 1: 0]; wire [ 1: 0] s1 = I1 ? INIT[ 3: 2] : INIT[ 1: 0];
assign O = I0 ? s1[1] : s1[0]; assign O = I0 ? s1[1] : s1[0];
specify specify
(I0 => O) = 116; (I0 => O) = 116;
(I1 => O) = 74; (I1 => O) = 74;
endspecify endspecify
endmodule endmodule
(* abc9_lut=3 *) (* abc9_lut=3 *)
module LUT3(output wire O, input wire I0, I1, I2); module LUT3(output wire O, input wire I0, I1, I2);
parameter [7:0] INIT = 0; parameter [7:0] INIT = 0;
wire [ 3: 0] s2 = I2 ? INIT[ 7: 4] : INIT[ 3: 0]; wire [ 3: 0] s2 = I2 ? INIT[ 7: 4] : INIT[ 3: 0];
wire [ 1: 0] s1 = I1 ? s2[ 3: 2] : s2[ 1: 0]; wire [ 1: 0] s1 = I1 ? s2[ 3: 2] : s2[ 1: 0];
assign O = I0 ? s1[1] : s1[0]; assign O = I0 ? s1[1] : s1[0];
specify specify
(I0 => O) = 162; (I0 => O) = 162;
(I1 => O) = 116; (I1 => O) = 116;
(I2 => O) = 174; (I2 => O) = 174;
endspecify endspecify
endmodule endmodule
(* abc9_lut=3 *) (* abc9_lut=3 *)
module LUT4(output wire O, input wire I0, I1, I2, I3); module LUT4(output wire O, input wire I0, I1, I2, I3);
parameter [15:0] INIT = 0; parameter [15:0] INIT = 0;
wire [ 7: 0] s3 = I3 ? INIT[15: 8] : INIT[ 7: 0]; wire [ 7: 0] s3 = I3 ? INIT[15: 8] : INIT[ 7: 0];
wire [ 3: 0] s2 = I2 ? s3[ 7: 4] : s3[ 3: 0]; wire [ 3: 0] s2 = I2 ? s3[ 7: 4] : s3[ 3: 0];
wire [ 1: 0] s1 = I1 ? s2[ 3: 2] : s2[ 1: 0]; wire [ 1: 0] s1 = I1 ? s2[ 3: 2] : s2[ 1: 0];
assign O = I0 ? s1[1] : s1[0]; assign O = I0 ? s1[1] : s1[0];
specify specify
(I0 => O) = 201; (I0 => O) = 201;
(I1 => O) = 162; (I1 => O) = 162;
(I2 => O) = 116; (I2 => O) = 116;
(I3 => O) = 74; (I3 => O) = 74;
endspecify endspecify
endmodule endmodule
(* abc9_lut=3 *) (* abc9_lut=3 *)
module LUT5(output wire O, input wire I0, I1, I2, I3, I4); module LUT5(output wire O, input wire I0, I1, I2, I3, I4);
parameter [31:0] INIT = 0; parameter [31:0] INIT = 0;
wire [15: 0] s4 = I4 ? INIT[31:16] : INIT[15: 0]; wire [15: 0] s4 = I4 ? INIT[31:16] : INIT[15: 0];
wire [ 7: 0] s3 = I3 ? s4[15: 8] : s4[ 7: 0]; wire [ 7: 0] s3 = I3 ? s4[15: 8] : s4[ 7: 0];
wire [ 3: 0] s2 = I2 ? s3[ 7: 4] : s3[ 3: 0]; wire [ 3: 0] s2 = I2 ? s3[ 7: 4] : s3[ 3: 0];
wire [ 1: 0] s1 = I1 ? s2[ 3: 2] : s2[ 1: 0]; wire [ 1: 0] s1 = I1 ? s2[ 3: 2] : s2[ 1: 0];
assign O = I0 ? s1[1] : s1[0]; assign O = I0 ? s1[1] : s1[0];
specify specify
(I0 => O) = 228; (I0 => O) = 228;
(I1 => O) = 189; (I1 => O) = 189;
(I2 => O) = 143; (I2 => O) = 143;
(I3 => O) = 100; (I3 => O) = 100;
(I4 => O) = 55; (I4 => O) = 55;
endspecify endspecify
endmodule endmodule
(* abc9_lut=5 *) (* abc9_lut=5 *)
module LUT6(output wire O, input wire I0, I1, I2, I3, I4, I5); module LUT6(output wire O, input wire I0, I1, I2, I3, I4, I5);
parameter [63:0] INIT = 0; parameter [63:0] INIT = 0;
wire [31: 0] s5 = I5 ? INIT[63:32] : INIT[31: 0]; wire [31: 0] s5 = I5 ? INIT[63:32] : INIT[31: 0];
wire [15: 0] s4 = I4 ? s5[31:16] : s5[15: 0]; wire [15: 0] s4 = I4 ? s5[31:16] : s5[15: 0];
wire [ 7: 0] s3 = I3 ? s4[15: 8] : s4[ 7: 0]; wire [ 7: 0] s3 = I3 ? s4[15: 8] : s4[ 7: 0];
wire [ 3: 0] s2 = I2 ? s3[ 7: 4] : s3[ 3: 0]; wire [ 3: 0] s2 = I2 ? s3[ 7: 4] : s3[ 3: 0];
wire [ 1: 0] s1 = I1 ? s2[ 3: 2] : s2[ 1: 0]; wire [ 1: 0] s1 = I1 ? s2[ 3: 2] : s2[ 1: 0];
assign O = I0 ? s1[1] : s1[0]; assign O = I0 ? s1[1] : s1[0];
specify specify
(I0 => O) = 251; (I0 => O) = 251;
(I1 => O) = 212; (I1 => O) = 212;
(I2 => O) = 166; (I2 => O) = 166;
(I3 => O) = 123; (I3 => O) = 123;
(I4 => O) = 77; (I4 => O) = 77;
(I5 => O) = 43; (I5 => O) = 43;
endspecify endspecify
endmodule endmodule
(* abc9_flop, lib_whitebox *) (* abc9_flop, lib_whitebox *)
module sh_dff( module sh_dff(
output reg Q, output reg Q,
input wire D, input wire D,
(* clkbuf_sink *) (* clkbuf_sink *)
input wire C input wire C
); );
initial Q <= 1'b0; initial Q = 1'b0;
always @(posedge C) always @(posedge C)
Q <= D; Q <= D;
specify specify
(posedge C => (Q +: D)) = 0; (posedge C => (Q +: D)) = 0;
$setuphold(posedge C, D, 0, 0); $setuphold(posedge C, D, 0, 0);
endspecify endspecify
endmodule endmodule
@ -124,253 +124,253 @@ endmodule
(* blackbox *) (* blackbox *)
(* keep *) (* keep *)
module adder_carry( module adder_carry(
output wire sumout, output wire sumout,
(* abc9_carry *) (* abc9_carry *)
output wire cout, output wire cout,
input wire p, input wire p,
input wire g, input wire g,
(* abc9_carry *) (* abc9_carry *)
input wire cin input wire cin
); );
assign sumout = p ^ cin; assign sumout = p ^ cin;
assign cout = p ? cin : g; assign cout = p ? cin : g;
specify specify
(p => sumout) = 35; (p => sumout) = 35;
(g => sumout) = 35; (g => sumout) = 35;
(cin => sumout) = 40; (cin => sumout) = 40;
(p => cout) = 67; (p => cout) = 67;
(g => cout) = 65; (g => cout) = 65;
(cin => cout) = 69; (cin => cout) = 69;
endspecify endspecify
endmodule endmodule
(* abc9_flop, lib_whitebox *) (* abc9_flop, lib_whitebox *)
module dff( module dff(
output reg Q, output reg Q,
input wire D, input wire D,
(* clkbuf_sink *) (* clkbuf_sink *)
input wire C input wire C
); );
initial Q <= 1'b0; initial Q = 1'b0;
always @(posedge C) always @(posedge C)
Q <= D; Q <= D;
specify specify
(posedge C=>(Q+:D)) = 285; (posedge C=>(Q+:D)) = 285;
$setuphold(posedge C, D, 56, 0); $setuphold(posedge C, D, 56, 0);
endspecify endspecify
endmodule endmodule
(* abc9_flop, lib_whitebox *) (* abc9_flop, lib_whitebox *)
module dffn( module dffn(
output reg Q, output reg Q,
input wire D, input wire D,
(* clkbuf_sink *) (* clkbuf_sink *)
input wire C input wire C
); );
initial Q <= 1'b0; initial Q = 1'b0;
always @(negedge C) always @(negedge C)
Q <= D; Q <= D;
specify specify
(negedge C=>(Q+:D)) = 285; (negedge C=>(Q+:D)) = 285;
$setuphold(negedge C, D, 56, 0); $setuphold(negedge C, D, 56, 0);
endspecify endspecify
endmodule endmodule
(* abc9_flop, lib_whitebox *) (* abc9_flop, lib_whitebox *)
module dffsre( module dffsre(
output reg Q, output reg Q,
input wire D, input wire D,
(* clkbuf_sink *) (* clkbuf_sink *)
input wire C, input wire C,
input wire E, input wire E,
input wire R, input wire R,
input wire S input wire S
); );
initial Q <= 1'b0; initial Q = 1'b0;
always @(posedge C or negedge S or negedge R) always @(posedge C or negedge S or negedge R)
if (!R) if (!R)
Q <= 1'b0; Q <= 1'b0;
else if (!S) else if (!S)
Q <= 1'b1; Q <= 1'b1;
else if (E) else if (E)
Q <= D; Q <= D;
specify specify
(posedge C => (Q +: D)) = 280; (posedge C => (Q +: D)) = 280;
(R => Q) = 0; (R => Q) = 0;
(S => Q) = 0; (S => Q) = 0;
$setuphold(posedge C, D, 56, 0); $setuphold(posedge C, D, 56, 0);
$setuphold(posedge C, E, 32, 0); $setuphold(posedge C, E, 32, 0);
$setuphold(posedge C, R, 0, 0); $setuphold(posedge C, R, 0, 0);
$setuphold(posedge C, S, 0, 0); $setuphold(posedge C, S, 0, 0);
$recrem(posedge R, posedge C, 0, 0); $recrem(posedge R, posedge C, 0, 0);
$recrem(posedge S, posedge C, 0, 0); $recrem(posedge S, posedge C, 0, 0);
endspecify endspecify
endmodule endmodule
(* abc9_flop, lib_whitebox *) (* abc9_flop, lib_whitebox *)
module dffnsre( module dffnsre(
output reg Q, output reg Q,
input wire D, input wire D,
(* clkbuf_sink *) (* clkbuf_sink *)
input wire C, input wire C,
input wire E, input wire E,
input wire R, input wire R,
input wire S input wire S
); );
initial Q <= 1'b0; initial Q = 1'b0;
always @(negedge C or negedge S or negedge R) always @(negedge C or negedge S or negedge R)
if (!R) if (!R)
Q <= 1'b0; Q <= 1'b0;
else if (!S) else if (!S)
Q <= 1'b1; Q <= 1'b1;
else if (E) else if (E)
Q <= D; Q <= D;
specify specify
(negedge C => (Q +: D)) = 280; (negedge C => (Q +: D)) = 280;
(R => Q) = 0; (R => Q) = 0;
(S => Q) = 0; (S => Q) = 0;
$setuphold(negedge C, D, 56, 0); $setuphold(negedge C, D, 56, 0);
$setuphold(negedge C, E, 32, 0); $setuphold(negedge C, E, 32, 0);
$setuphold(negedge C, R, 0, 0); $setuphold(negedge C, R, 0, 0);
$setuphold(negedge C, S, 0, 0); $setuphold(negedge C, S, 0, 0);
$recrem(posedge R, negedge C, 0, 0); $recrem(posedge R, negedge C, 0, 0);
$recrem(posedge S, negedge C, 0, 0); $recrem(posedge S, negedge C, 0, 0);
endspecify endspecify
endmodule endmodule
(* abc9_flop, lib_whitebox *) (* abc9_flop, lib_whitebox *)
module sdffsre( module sdffsre(
output reg Q, output reg Q,
input wire D, input wire D,
(* clkbuf_sink *) (* clkbuf_sink *)
input wire C, input wire C,
input wire E, input wire E,
input wire R, input wire R,
input wire S input wire S
); );
initial Q <= 1'b0; initial Q = 1'b0;
always @(posedge C) always @(posedge C)
if (!R) if (!R)
Q <= 1'b0; Q <= 1'b0;
else if (!S) else if (!S)
Q <= 1'b1; Q <= 1'b1;
else if (E) else if (E)
Q <= D; Q <= D;
specify specify
(posedge C => (Q +: D)) = 280; (posedge C => (Q +: D)) = 280;
$setuphold(posedge C, D, 56, 0); $setuphold(posedge C, D, 56, 0);
$setuphold(posedge C, R, 32, 0); $setuphold(posedge C, R, 32, 0);
$setuphold(posedge C, S, 0, 0); $setuphold(posedge C, S, 0, 0);
$setuphold(posedge C, E, 0, 0); $setuphold(posedge C, E, 0, 0);
endspecify endspecify
endmodule endmodule
(* abc9_flop, lib_whitebox *) (* abc9_flop, lib_whitebox *)
module sdffnsre( module sdffnsre(
output reg Q, output reg Q,
input wire D, input wire D,
(* clkbuf_sink *) (* clkbuf_sink *)
input wire C, input wire C,
input wire E, input wire E,
input wire R, input wire R,
input wire S input wire S
); );
initial Q <= 1'b0; initial Q = 1'b0;
always @(negedge C) always @(negedge C)
if (!R) if (!R)
Q <= 1'b0; Q <= 1'b0;
else if (!S) else if (!S)
Q <= 1'b1; Q <= 1'b1;
else if (E) else if (E)
Q <= D; Q <= D;
specify specify
(negedge C => (Q +: D)) = 280; (negedge C => (Q +: D)) = 280;
$setuphold(negedge C, D, 56, 0); $setuphold(negedge C, D, 56, 0);
$setuphold(negedge C, R, 32, 0); $setuphold(negedge C, R, 32, 0);
$setuphold(negedge C, S, 0, 0); $setuphold(negedge C, S, 0, 0);
$setuphold(negedge C, E, 0, 0); $setuphold(negedge C, E, 0, 0);
endspecify endspecify
endmodule endmodule
(* abc9_flop, lib_whitebox *) (* abc9_flop, lib_whitebox *)
module latchsre ( module latchsre (
output reg Q, output reg Q,
input wire S, input wire S,
input wire R, input wire R,
input wire D, input wire D,
input wire G, input wire G,
input wire E input wire E
); );
initial Q <= 1'b0; initial Q = 1'b0;
always @* always @*
begin begin
if (!R) if (!R)
Q <= 1'b0; Q <= 1'b0;
else if (!S) else if (!S)
Q <= 1'b1; Q <= 1'b1;
else if (E && G) else if (E && G)
Q <= D; Q <= D;
end end
specify specify
(posedge G => (Q +: D)) = 0; (posedge G => (Q +: D)) = 0;
$setuphold(posedge G, D, 0, 0); $setuphold(posedge G, D, 0, 0);
$setuphold(posedge G, E, 0, 0); $setuphold(posedge G, E, 0, 0);
$setuphold(posedge G, R, 0, 0); $setuphold(posedge G, R, 0, 0);
$setuphold(posedge G, S, 0, 0); $setuphold(posedge G, S, 0, 0);
endspecify endspecify
endmodule endmodule
(* abc9_flop, lib_whitebox *) (* abc9_flop, lib_whitebox *)
module latchnsre ( module latchnsre (
output reg Q, output reg Q,
input wire S, input wire S,
input wire R, input wire R,
input wire D, input wire D,
input wire G, input wire G,
input wire E input wire E
); );
initial Q <= 1'b0; initial Q = 1'b0;
always @* always @*
begin begin
if (!R) if (!R)
Q <= 1'b0; Q <= 1'b0;
else if (!S) else if (!S)
Q <= 1'b1; Q <= 1'b1;
else if (E && !G) else if (E && !G)
Q <= D; Q <= D;
end end
specify specify
(negedge G => (Q +: D)) = 0; (negedge G => (Q +: D)) = 0;
$setuphold(negedge G, D, 0, 0); $setuphold(negedge G, D, 0, 0);
$setuphold(negedge G, E, 0, 0); $setuphold(negedge G, E, 0, 0);
$setuphold(negedge G, R, 0, 0); $setuphold(negedge G, R, 0, 0);
$setuphold(negedge G, S, 0, 0); $setuphold(negedge G, S, 0, 0);
endspecify endspecify
endmodule endmodule

View File

@ -16,116 +16,116 @@
// DFF, asynchronous set/reset, enable // DFF, asynchronous set/reset, enable
module \$_DFFSRE_PNNP_ (C, S, R, E, D, Q); module \$_DFFSRE_PNNP_ (C, S, R, E, D, Q);
input C; input C;
input S; input S;
input R; input R;
input E; input E;
input D; input D;
output Q; output Q;
dffsre _TECHMAP_REPLACE_ (.Q(Q), .D(D), .C(C), .E(E), .R(R), .S(S)); dffsre _TECHMAP_REPLACE_ (.Q(Q), .D(D), .C(C), .E(E), .R(R), .S(S));
endmodule endmodule
module \$_DFFSRE_NNNP_ (C, S, R, E, D, Q); module \$_DFFSRE_NNNP_ (C, S, R, E, D, Q);
input C; input C;
input S; input S;
input R; input R;
input E; input E;
input D; input D;
output Q; output Q;
dffnsre _TECHMAP_REPLACE_ (.Q(Q), .D(D), .C(C), .E(E), .R(R), .S(S)); dffnsre _TECHMAP_REPLACE_ (.Q(Q), .D(D), .C(C), .E(E), .R(R), .S(S));
endmodule endmodule
// DFF, synchronous set or reset, enable // DFF, synchronous set or reset, enable
module \$_SDFFE_PN0P_ (D, C, R, E, Q); module \$_SDFFE_PN0P_ (D, C, R, E, Q);
input D; input D;
input C; input C;
input R; input R;
input E; input E;
output Q; output Q;
sdffsre _TECHMAP_REPLACE_ (.Q(Q), .D(D), .C(C), .E(E), .R(R), .S(1'b1)); sdffsre _TECHMAP_REPLACE_ (.Q(Q), .D(D), .C(C), .E(E), .R(R), .S(1'b1));
endmodule endmodule
module \$_SDFFE_PN1P_ (D, C, R, E, Q); module \$_SDFFE_PN1P_ (D, C, R, E, Q);
input D; input D;
input C; input C;
input R; input R;
input E; input E;
output Q; output Q;
sdffsre _TECHMAP_REPLACE_ (.Q(Q), .D(D), .C(C), .E(E), .R(1'b1), .S(R)); sdffsre _TECHMAP_REPLACE_ (.Q(Q), .D(D), .C(C), .E(E), .R(1'b1), .S(R));
endmodule endmodule
module \$_SDFFE_NN0P_ (D, C, R, E, Q); module \$_SDFFE_NN0P_ (D, C, R, E, Q);
input D; input D;
input C; input C;
input R; input R;
input E; input E;
output Q; output Q;
sdffnsre _TECHMAP_REPLACE_ (.Q(Q), .D(D), .C(C), .E(E), .R(R), .S(1'b1)); sdffnsre _TECHMAP_REPLACE_ (.Q(Q), .D(D), .C(C), .E(E), .R(R), .S(1'b1));
endmodule endmodule
module \$_SDFFE_NN1P_ (D, C, R, E, Q); module \$_SDFFE_NN1P_ (D, C, R, E, Q);
input D; input D;
input C; input C;
input R; input R;
input E; input E;
output Q; output Q;
sdffnsre _TECHMAP_REPLACE_ (.Q(Q), .D(D), .C(C), .E(E), .R(1'b1), .S(R)); sdffnsre _TECHMAP_REPLACE_ (.Q(Q), .D(D), .C(C), .E(E), .R(1'b1), .S(R));
endmodule endmodule
// Latch, no set/reset, no enable // Latch, no set/reset, no enable
module \$_DLATCH_P_ (input E, D, output Q); module \$_DLATCH_P_ (input E, D, output Q);
latchsre _TECHMAP_REPLACE_ (.D(D), .Q(Q), .E(1'b1), .G(E), .R(1'b1), .S(1'b1)); latchsre _TECHMAP_REPLACE_ (.D(D), .Q(Q), .E(1'b1), .G(E), .R(1'b1), .S(1'b1));
endmodule endmodule
module \$_DLATCH_N_ (input E, D, output Q); module \$_DLATCH_N_ (input E, D, output Q);
latchnsre _TECHMAP_REPLACE_ (.D(D), .Q(Q), .E(1'b1), .G(E), .R(1'b1), .S(1'b1)); latchnsre _TECHMAP_REPLACE_ (.D(D), .Q(Q), .E(1'b1), .G(E), .R(1'b1), .S(1'b1));
endmodule endmodule
// Latch with async set and reset and enable // Latch with async set and reset and enable
module \$_DLATCHSR_PPP_ (input E, S, R, D, output Q); module \$_DLATCHSR_PPP_ (input E, S, R, D, output Q);
latchsre _TECHMAP_REPLACE_ (.D(D), .Q(Q), .E(1'b1), .G(E), .R(!R), .S(!S)); latchsre _TECHMAP_REPLACE_ (.D(D), .Q(Q), .E(1'b1), .G(E), .R(!R), .S(!S));
endmodule endmodule
module \$_DLATCHSR_NPP_ (input E, S, R, D, output Q); module \$_DLATCHSR_NPP_ (input E, S, R, D, output Q);
latchnsre _TECHMAP_REPLACE_ (.D(D), .Q(Q), .E(1'b1), .G(E), .R(!R), .S(!S)); latchnsre _TECHMAP_REPLACE_ (.D(D), .Q(Q), .E(1'b1), .G(E), .R(!R), .S(!S));
endmodule endmodule
module \$__SHREG_DFF_P_ (D, Q, C); module \$__SHREG_DFF_P_ (D, Q, C);
input D; input D;
input C; input C;
output Q; output Q;
parameter DEPTH = 2; parameter DEPTH = 2;
reg [DEPTH-2:0] q; reg [DEPTH-2:0] q;
genvar i; genvar i;
generate for (i = 0; i < DEPTH; i = i + 1) begin: slice generate for (i = 0; i < DEPTH; i = i + 1) begin: slice
// First in chain // First in chain
generate if (i == 0) begin generate if (i == 0) begin
sh_dff #() shreg_beg ( sh_dff #() shreg_beg (
.Q(q[i]), .Q(q[i]),
.D(D), .D(D),
.C(C) .C(C)
); );
end endgenerate end endgenerate
// Middle in chain // Middle in chain
generate if (i > 0 && i != DEPTH-1) begin generate if (i > 0 && i != DEPTH-1) begin
sh_dff #() shreg_mid ( sh_dff #() shreg_mid (
.Q(q[i]), .Q(q[i]),
.D(q[i-1]), .D(q[i-1]),
.C(C) .C(C)
); );
end endgenerate end endgenerate
// Last in chain // Last in chain
generate if (i == DEPTH-1) begin generate if (i == DEPTH-1) begin
sh_dff #() shreg_end ( sh_dff #() shreg_end (
.Q(Q), .Q(Q),
.D(q[i-1]), .D(q[i-1]),
.C(C) .C(C)
); );
end endgenerate end endgenerate
end: slice end: slice
endgenerate endgenerate

View File

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

View File

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

View File

@ -129,10 +129,6 @@ struct SynthQuickLogicPass : public ScriptPass {
blif_file = args[++argidx]; blif_file = args[++argidx];
continue; continue;
} }
if (args[argidx] == "-edif" && argidx + 1 < args.size()) {
edif_file = args[++argidx];
continue;
}
if (args[argidx] == "-verilog" && argidx+1 < args.size()) { if (args[argidx] == "-verilog" && argidx+1 < args.size()) {
verilog_file = args[++argidx]; verilog_file = args[++argidx];
continue; continue;
@ -141,15 +137,15 @@ struct SynthQuickLogicPass : public ScriptPass {
abc9 = false; abc9 = false;
continue; continue;
} }
if (args[argidx] == "-nocarry") { if (args[argidx] == "-nocarry" || args[argidx] == "-no_adder") {
inferAdder = false; inferAdder = false;
continue; continue;
} }
if (args[argidx] == "-nobram") { if (args[argidx] == "-nobram" || args[argidx] == "-no_bram") {
nobram = true; nobram = true;
continue; continue;
} }
if (args[argidx] == "-bramtypes") { if (args[argidx] == "-bramtypes" || args[argidx] == "-bram_types") {
bramTypes = true; bramTypes = true;
continue; continue;
} }
@ -230,61 +226,8 @@ struct SynthQuickLogicPass : public ScriptPass {
run("techmap -autoproc -map " + lib_path + family + "/brams_map.v"); run("techmap -autoproc -map " + lib_path + family + "/brams_map.v");
run("techmap -map " + lib_path + family + "/brams_final_map.v"); run("techmap -map " + lib_path + family + "/brams_final_map.v");
if (help_mode) { if (help_mode || bramTypes) {
run("chtype -set TDP36K_<mode> t:TDP36K a:<mode>", "(if -bram_types)"); run("ql_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));
}
} }
} }
@ -393,13 +336,6 @@ struct SynthQuickLogicPass : public ScriptPass {
run(stringf("write_verilog -noattr -nohex %s", help_mode ? "<file-name>" : verilog_file.c_str())); 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; } SynthQuicklogicPass;