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))
|
||||
|
||||
|
|
|
@ -31,184 +31,184 @@ PRIVATE_NAMESPACE_BEGIN
|
|||
|
||||
struct QlBramMergeWorker {
|
||||
|
||||
const RTLIL::IdString split_cell_type = ID($__QLF_TDP36K);
|
||||
const RTLIL::IdString merged_cell_type = ID($__QLF_TDP36K_MERGED);
|
||||
const RTLIL::IdString split_cell_type = ID($__QLF_TDP36K);
|
||||
const RTLIL::IdString merged_cell_type = ID($__QLF_TDP36K_MERGED);
|
||||
|
||||
// can be used to record parameter values that have to match on both sides
|
||||
typedef dict<RTLIL::IdString, RTLIL::Const> MergeableGroupKeyType;
|
||||
// can be used to record parameter values that have to match on both sides
|
||||
typedef dict<RTLIL::IdString, RTLIL::Const> MergeableGroupKeyType;
|
||||
|
||||
RTLIL::Module *module;
|
||||
dict<MergeableGroupKeyType, pool<RTLIL::Cell*>> mergeable_groups;
|
||||
RTLIL::Module *module;
|
||||
dict<MergeableGroupKeyType, pool<RTLIL::Cell*>> mergeable_groups;
|
||||
|
||||
QlBramMergeWorker(RTLIL::Module* module) : module(module)
|
||||
{
|
||||
for (RTLIL::Cell* cell : module->selected_cells())
|
||||
{
|
||||
if(cell->type != split_cell_type) continue;
|
||||
if(!cell->hasParam(ID(OPTION_SPLIT))) continue;
|
||||
if(cell->getParam(ID(OPTION_SPLIT)) != RTLIL::Const(1, 32)) continue;
|
||||
mergeable_groups[get_key(cell)].insert(cell);
|
||||
}
|
||||
}
|
||||
QlBramMergeWorker(RTLIL::Module* module) : module(module)
|
||||
{
|
||||
for (RTLIL::Cell* cell : module->selected_cells())
|
||||
{
|
||||
if(cell->type != split_cell_type) continue;
|
||||
if(!cell->hasParam(ID(OPTION_SPLIT))) continue;
|
||||
if(cell->getParam(ID(OPTION_SPLIT)) != RTLIL::Const(1, 32)) continue;
|
||||
mergeable_groups[get_key(cell)].insert(cell);
|
||||
}
|
||||
}
|
||||
|
||||
static MergeableGroupKeyType get_key(RTLIL::Cell* cell)
|
||||
{
|
||||
MergeableGroupKeyType key;
|
||||
// For now, there are no restrictions on which cells can be merged
|
||||
(void) cell;
|
||||
return key;
|
||||
}
|
||||
static MergeableGroupKeyType get_key(RTLIL::Cell* cell)
|
||||
{
|
||||
MergeableGroupKeyType key;
|
||||
// For now, there are no restrictions on which cells can be merged
|
||||
(void) cell;
|
||||
return key;
|
||||
}
|
||||
|
||||
const dict<RTLIL::IdString, RTLIL::IdString>& param_map(bool second)
|
||||
{
|
||||
static const dict<RTLIL::IdString, RTLIL::IdString> bram1_map = {
|
||||
{ ID(INIT), ID(INIT1) },
|
||||
{ ID(PORT_A_WIDTH), ID(PORT_A1_WIDTH) },
|
||||
{ ID(PORT_B_WIDTH), ID(PORT_B1_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) }
|
||||
};
|
||||
static const dict<RTLIL::IdString, RTLIL::IdString> bram2_map = {
|
||||
{ ID(INIT), ID(INIT2) },
|
||||
{ ID(PORT_A_WIDTH), ID(PORT_A2_WIDTH) },
|
||||
{ ID(PORT_B_WIDTH), ID(PORT_B2_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) }
|
||||
};
|
||||
const dict<RTLIL::IdString, RTLIL::IdString>& param_map(bool second)
|
||||
{
|
||||
static const dict<RTLIL::IdString, RTLIL::IdString> bram1_map = {
|
||||
{ ID(INIT), ID(INIT1) },
|
||||
{ ID(PORT_A_WIDTH), ID(PORT_A1_WIDTH) },
|
||||
{ ID(PORT_B_WIDTH), ID(PORT_B1_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) }
|
||||
};
|
||||
static const dict<RTLIL::IdString, RTLIL::IdString> bram2_map = {
|
||||
{ ID(INIT), ID(INIT2) },
|
||||
{ ID(PORT_A_WIDTH), ID(PORT_A2_WIDTH) },
|
||||
{ ID(PORT_B_WIDTH), ID(PORT_B2_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) }
|
||||
};
|
||||
|
||||
if(second)
|
||||
return bram2_map;
|
||||
else
|
||||
return bram1_map;
|
||||
}
|
||||
if(second)
|
||||
return bram2_map;
|
||||
else
|
||||
return bram1_map;
|
||||
}
|
||||
|
||||
const dict<RTLIL::IdString, RTLIL::IdString>& port_map(bool second)
|
||||
{
|
||||
static const dict<RTLIL::IdString, RTLIL::IdString> bram1_map = {
|
||||
{ ID(PORT_A_CLK), ID(PORT_A1_CLK) },
|
||||
{ ID(PORT_B_CLK), ID(PORT_B1_CLK) },
|
||||
{ ID(PORT_A_CLK_EN), ID(PORT_A1_CLK_EN) },
|
||||
{ ID(PORT_B_CLK_EN), ID(PORT_B1_CLK_EN) },
|
||||
{ ID(PORT_A_ADDR), ID(PORT_A1_ADDR) },
|
||||
{ ID(PORT_B_ADDR), ID(PORT_B1_ADDR) },
|
||||
{ ID(PORT_A_WR_DATA), ID(PORT_A1_WR_DATA) },
|
||||
{ ID(PORT_B_WR_DATA), ID(PORT_B1_WR_DATA) },
|
||||
{ ID(PORT_A_WR_EN), ID(PORT_A1_WR_EN) },
|
||||
{ ID(PORT_B_WR_EN), ID(PORT_B1_WR_EN) },
|
||||
{ ID(PORT_A_WR_BE), ID(PORT_A1_WR_BE) },
|
||||
{ ID(PORT_B_WR_BE), ID(PORT_B1_WR_BE) },
|
||||
{ ID(PORT_A_RD_DATA), ID(PORT_A1_RD_DATA) },
|
||||
{ ID(PORT_B_RD_DATA), ID(PORT_B1_RD_DATA) }
|
||||
};
|
||||
static const dict<RTLIL::IdString, RTLIL::IdString> bram2_map = {
|
||||
{ ID(PORT_A_CLK), ID(PORT_A2_CLK) },
|
||||
{ ID(PORT_B_CLK), ID(PORT_B2_CLK) },
|
||||
{ ID(PORT_A_CLK_EN), ID(PORT_A2_CLK_EN) },
|
||||
{ ID(PORT_B_CLK_EN), ID(PORT_B2_CLK_EN) },
|
||||
{ ID(PORT_A_ADDR), ID(PORT_A2_ADDR) },
|
||||
{ ID(PORT_B_ADDR), ID(PORT_B2_ADDR) },
|
||||
{ ID(PORT_A_WR_DATA), ID(PORT_A2_WR_DATA) },
|
||||
{ ID(PORT_B_WR_DATA), ID(PORT_B2_WR_DATA) },
|
||||
{ ID(PORT_A_WR_EN), ID(PORT_A2_WR_EN) },
|
||||
{ ID(PORT_B_WR_EN), ID(PORT_B2_WR_EN) },
|
||||
{ ID(PORT_A_WR_BE), ID(PORT_A2_WR_BE) },
|
||||
{ ID(PORT_B_WR_BE), ID(PORT_B2_WR_BE) },
|
||||
{ ID(PORT_A_RD_DATA), ID(PORT_A2_RD_DATA) },
|
||||
{ ID(PORT_B_RD_DATA), ID(PORT_B2_RD_DATA) }
|
||||
};
|
||||
const dict<RTLIL::IdString, RTLIL::IdString>& port_map(bool second)
|
||||
{
|
||||
static const dict<RTLIL::IdString, RTLIL::IdString> bram1_map = {
|
||||
{ ID(PORT_A_CLK), ID(PORT_A1_CLK) },
|
||||
{ ID(PORT_B_CLK), ID(PORT_B1_CLK) },
|
||||
{ ID(PORT_A_CLK_EN), ID(PORT_A1_CLK_EN) },
|
||||
{ ID(PORT_B_CLK_EN), ID(PORT_B1_CLK_EN) },
|
||||
{ ID(PORT_A_ADDR), ID(PORT_A1_ADDR) },
|
||||
{ ID(PORT_B_ADDR), ID(PORT_B1_ADDR) },
|
||||
{ ID(PORT_A_WR_DATA), ID(PORT_A1_WR_DATA) },
|
||||
{ ID(PORT_B_WR_DATA), ID(PORT_B1_WR_DATA) },
|
||||
{ ID(PORT_A_WR_EN), ID(PORT_A1_WR_EN) },
|
||||
{ ID(PORT_B_WR_EN), ID(PORT_B1_WR_EN) },
|
||||
{ ID(PORT_A_WR_BE), ID(PORT_A1_WR_BE) },
|
||||
{ ID(PORT_B_WR_BE), ID(PORT_B1_WR_BE) },
|
||||
{ ID(PORT_A_RD_DATA), ID(PORT_A1_RD_DATA) },
|
||||
{ ID(PORT_B_RD_DATA), ID(PORT_B1_RD_DATA) }
|
||||
};
|
||||
static const dict<RTLIL::IdString, RTLIL::IdString> bram2_map = {
|
||||
{ ID(PORT_A_CLK), ID(PORT_A2_CLK) },
|
||||
{ ID(PORT_B_CLK), ID(PORT_B2_CLK) },
|
||||
{ ID(PORT_A_CLK_EN), ID(PORT_A2_CLK_EN) },
|
||||
{ ID(PORT_B_CLK_EN), ID(PORT_B2_CLK_EN) },
|
||||
{ ID(PORT_A_ADDR), ID(PORT_A2_ADDR) },
|
||||
{ ID(PORT_B_ADDR), ID(PORT_B2_ADDR) },
|
||||
{ ID(PORT_A_WR_DATA), ID(PORT_A2_WR_DATA) },
|
||||
{ ID(PORT_B_WR_DATA), ID(PORT_B2_WR_DATA) },
|
||||
{ ID(PORT_A_WR_EN), ID(PORT_A2_WR_EN) },
|
||||
{ ID(PORT_B_WR_EN), ID(PORT_B2_WR_EN) },
|
||||
{ ID(PORT_A_WR_BE), ID(PORT_A2_WR_BE) },
|
||||
{ ID(PORT_B_WR_BE), ID(PORT_B2_WR_BE) },
|
||||
{ ID(PORT_A_RD_DATA), ID(PORT_A2_RD_DATA) },
|
||||
{ ID(PORT_B_RD_DATA), ID(PORT_B2_RD_DATA) }
|
||||
};
|
||||
|
||||
if(second)
|
||||
return bram2_map;
|
||||
else
|
||||
return bram1_map;
|
||||
}
|
||||
if(second)
|
||||
return bram2_map;
|
||||
else
|
||||
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
|
||||
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));
|
||||
// Create the new cell
|
||||
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));
|
||||
|
||||
for (auto &it : param_map(false))
|
||||
{
|
||||
if(bram1->hasParam(it.first))
|
||||
merged->setParam(it.second, bram1->getParam(it.first));
|
||||
}
|
||||
for (auto &it : param_map(true))
|
||||
{
|
||||
if(bram2->hasParam(it.first))
|
||||
merged->setParam(it.second, bram2->getParam(it.first));
|
||||
}
|
||||
for (auto &it : param_map(false))
|
||||
{
|
||||
if(bram1->hasParam(it.first))
|
||||
merged->setParam(it.second, bram1->getParam(it.first));
|
||||
}
|
||||
for (auto &it : param_map(true))
|
||||
{
|
||||
if(bram2->hasParam(it.first))
|
||||
merged->setParam(it.second, bram2->getParam(it.first));
|
||||
}
|
||||
|
||||
for (auto &it : port_map(false))
|
||||
{
|
||||
if (bram1->hasPort(it.first))
|
||||
merged->setPort(it.second, bram1->getPort(it.first));
|
||||
else
|
||||
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))
|
||||
{
|
||||
if (bram2->hasPort(it.first))
|
||||
merged->setPort(it.second, bram2->getPort(it.first));
|
||||
else
|
||||
log_error("Can't find port %s on cell %s!\n", log_id(it.first), log_id(bram2->name));
|
||||
}
|
||||
merged->attributes = bram1->attributes;
|
||||
for (auto attr: bram2->attributes)
|
||||
if (!merged->has_attribute(attr.first))
|
||||
merged->attributes.insert(attr);
|
||||
for (auto &it : port_map(false))
|
||||
{
|
||||
if (bram1->hasPort(it.first))
|
||||
merged->setPort(it.second, bram1->getPort(it.first));
|
||||
else
|
||||
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))
|
||||
{
|
||||
if (bram2->hasPort(it.first))
|
||||
merged->setPort(it.second, bram2->getPort(it.first));
|
||||
else
|
||||
log_error("Can't find port %s on cell %s!\n", log_id(it.first), log_id(bram2->name));
|
||||
}
|
||||
merged->attributes = bram1->attributes;
|
||||
for (auto attr: bram2->attributes)
|
||||
if (!merged->has_attribute(attr.first))
|
||||
merged->attributes.insert(attr);
|
||||
|
||||
// Remove the old cells
|
||||
module->remove(bram1);
|
||||
module->remove(bram2);
|
||||
// Remove the old cells
|
||||
module->remove(bram1);
|
||||
module->remove(bram2);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void merge_bram_groups()
|
||||
{
|
||||
for (auto &it : mergeable_groups)
|
||||
{
|
||||
while (it.second.size() > 1)
|
||||
{
|
||||
merge_brams(it.second.pop(), it.second.pop());
|
||||
}
|
||||
}
|
||||
}
|
||||
void merge_bram_groups()
|
||||
{
|
||||
for (auto &it : mergeable_groups)
|
||||
{
|
||||
while (it.second.size() > 1)
|
||||
{
|
||||
merge_brams(it.second.pop(), it.second.pop());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
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
|
||||
{
|
||||
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
|
||||
log("\n");
|
||||
log(" ql_bram_merge [selection]\n");
|
||||
log("\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("\n");
|
||||
}
|
||||
void help() override
|
||||
{
|
||||
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
|
||||
log("\n");
|
||||
log(" ql_bram_merge [selection]\n");
|
||||
log("\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("\n");
|
||||
}
|
||||
|
||||
|
||||
|
||||
void execute(std::vector<std::string> args, RTLIL::Design *design) override
|
||||
{
|
||||
log_header(design, "Executing QL_BRAM_MERGE pass.\n");
|
||||
void execute(std::vector<std::string> args, RTLIL::Design *design) override
|
||||
{
|
||||
log_header(design, "Executing QL_BRAM_MERGE pass.\n");
|
||||
|
||||
size_t argidx = 1;
|
||||
extra_args(args, argidx, design);
|
||||
size_t argidx = 1;
|
||||
extra_args(args, argidx, design);
|
||||
|
||||
for (RTLIL::Module* module : design->selected_modules())
|
||||
{
|
||||
QlBramMergeWorker worker(module);
|
||||
worker.merge_bram_groups();
|
||||
}
|
||||
}
|
||||
for (RTLIL::Module* module : design->selected_modules())
|
||||
{
|
||||
QlBramMergeWorker worker(module);
|
||||
worker.merge_bram_groups();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} QlBramMergePass;
|
||||
|
|
|
@ -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
|
|
@ -56,43 +56,43 @@ module _80_quicklogic_alu (A, B, CI, BI, X, Y, CO);
|
|||
(* force_downto *)
|
||||
wire [Y_WIDTH-1:0] S = {AA ^ BB};
|
||||
assign CO[Y_WIDTH-1:0] = C[Y_WIDTH:1];
|
||||
//assign CO[Y_WIDTH-1] = co;
|
||||
//assign CO[Y_WIDTH-1] = co;
|
||||
|
||||
generate
|
||||
adder_carry intermediate_adder (
|
||||
.cin ( ),
|
||||
.cout (C[0]),
|
||||
.p (1'b0),
|
||||
.g (CI),
|
||||
.sumout ()
|
||||
);
|
||||
adder_carry intermediate_adder (
|
||||
.cin ( ),
|
||||
.cout (C[0]),
|
||||
.p (1'b0),
|
||||
.g (CI),
|
||||
.sumout ()
|
||||
);
|
||||
endgenerate
|
||||
genvar i;
|
||||
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
|
||||
end endgenerate
|
||||
generate
|
||||
adder_carry final_adder (
|
||||
.cin (C[Y_WIDTH-2]),
|
||||
.cout (),
|
||||
.p (1'b0),
|
||||
.g (1'b0),
|
||||
.sumout (co)
|
||||
);
|
||||
adder_carry final_adder (
|
||||
.cin (C[Y_WIDTH-2]),
|
||||
.cout (),
|
||||
.p (1'b0),
|
||||
.g (1'b0),
|
||||
.sumout (co)
|
||||
);
|
||||
endgenerate
|
||||
|
||||
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 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;
|
||||
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
|
@ -19,104 +19,104 @@
|
|||
`default_nettype none
|
||||
(* abc9_lut=1 *)
|
||||
module LUT1(output wire O, input wire I0);
|
||||
parameter [1:0] INIT = 0;
|
||||
assign O = I0 ? INIT[1] : INIT[0];
|
||||
specify
|
||||
(I0 => O) = 74;
|
||||
endspecify
|
||||
parameter [1:0] INIT = 0;
|
||||
assign O = I0 ? INIT[1] : INIT[0];
|
||||
specify
|
||||
(I0 => O) = 74;
|
||||
endspecify
|
||||
endmodule
|
||||
|
||||
(* abc9_lut=2 *)
|
||||
module LUT2(output wire O, input wire I0, I1);
|
||||
parameter [3:0] INIT = 0;
|
||||
wire [ 1: 0] s1 = I1 ? INIT[ 3: 2] : INIT[ 1: 0];
|
||||
assign O = I0 ? s1[1] : s1[0];
|
||||
specify
|
||||
(I0 => O) = 116;
|
||||
(I1 => O) = 74;
|
||||
endspecify
|
||||
parameter [3:0] INIT = 0;
|
||||
wire [ 1: 0] s1 = I1 ? INIT[ 3: 2] : INIT[ 1: 0];
|
||||
assign O = I0 ? s1[1] : s1[0];
|
||||
specify
|
||||
(I0 => O) = 116;
|
||||
(I1 => O) = 74;
|
||||
endspecify
|
||||
endmodule
|
||||
|
||||
(* abc9_lut=3 *)
|
||||
module LUT3(output wire O, input wire I0, I1, I2);
|
||||
parameter [7:0] INIT = 0;
|
||||
wire [ 3: 0] s2 = I2 ? INIT[ 7: 4] : INIT[ 3: 0];
|
||||
wire [ 1: 0] s1 = I1 ? s2[ 3: 2] : s2[ 1: 0];
|
||||
assign O = I0 ? s1[1] : s1[0];
|
||||
specify
|
||||
(I0 => O) = 162;
|
||||
(I1 => O) = 116;
|
||||
(I2 => O) = 174;
|
||||
endspecify
|
||||
parameter [7:0] INIT = 0;
|
||||
wire [ 3: 0] s2 = I2 ? INIT[ 7: 4] : INIT[ 3: 0];
|
||||
wire [ 1: 0] s1 = I1 ? s2[ 3: 2] : s2[ 1: 0];
|
||||
assign O = I0 ? s1[1] : s1[0];
|
||||
specify
|
||||
(I0 => O) = 162;
|
||||
(I1 => O) = 116;
|
||||
(I2 => O) = 174;
|
||||
endspecify
|
||||
endmodule
|
||||
|
||||
(* abc9_lut=3 *)
|
||||
module LUT4(output wire O, input wire I0, I1, I2, I3);
|
||||
parameter [15:0] INIT = 0;
|
||||
wire [ 7: 0] s3 = I3 ? INIT[15: 8] : INIT[ 7: 0];
|
||||
wire [ 3: 0] s2 = I2 ? s3[ 7: 4] : s3[ 3: 0];
|
||||
wire [ 1: 0] s1 = I1 ? s2[ 3: 2] : s2[ 1: 0];
|
||||
assign O = I0 ? s1[1] : s1[0];
|
||||
specify
|
||||
(I0 => O) = 201;
|
||||
(I1 => O) = 162;
|
||||
(I2 => O) = 116;
|
||||
(I3 => O) = 74;
|
||||
endspecify
|
||||
parameter [15:0] INIT = 0;
|
||||
wire [ 7: 0] s3 = I3 ? INIT[15: 8] : INIT[ 7: 0];
|
||||
wire [ 3: 0] s2 = I2 ? s3[ 7: 4] : s3[ 3: 0];
|
||||
wire [ 1: 0] s1 = I1 ? s2[ 3: 2] : s2[ 1: 0];
|
||||
assign O = I0 ? s1[1] : s1[0];
|
||||
specify
|
||||
(I0 => O) = 201;
|
||||
(I1 => O) = 162;
|
||||
(I2 => O) = 116;
|
||||
(I3 => O) = 74;
|
||||
endspecify
|
||||
endmodule
|
||||
|
||||
(* abc9_lut=3 *)
|
||||
module LUT5(output wire O, input wire I0, I1, I2, I3, I4);
|
||||
parameter [31:0] INIT = 0;
|
||||
wire [15: 0] s4 = I4 ? INIT[31:16] : INIT[15: 0];
|
||||
wire [ 7: 0] s3 = I3 ? s4[15: 8] : s4[ 7: 0];
|
||||
wire [ 3: 0] s2 = I2 ? s3[ 7: 4] : s3[ 3: 0];
|
||||
wire [ 1: 0] s1 = I1 ? s2[ 3: 2] : s2[ 1: 0];
|
||||
assign O = I0 ? s1[1] : s1[0];
|
||||
specify
|
||||
(I0 => O) = 228;
|
||||
(I1 => O) = 189;
|
||||
(I2 => O) = 143;
|
||||
(I3 => O) = 100;
|
||||
(I4 => O) = 55;
|
||||
endspecify
|
||||
parameter [31:0] INIT = 0;
|
||||
wire [15: 0] s4 = I4 ? INIT[31:16] : INIT[15: 0];
|
||||
wire [ 7: 0] s3 = I3 ? s4[15: 8] : s4[ 7: 0];
|
||||
wire [ 3: 0] s2 = I2 ? s3[ 7: 4] : s3[ 3: 0];
|
||||
wire [ 1: 0] s1 = I1 ? s2[ 3: 2] : s2[ 1: 0];
|
||||
assign O = I0 ? s1[1] : s1[0];
|
||||
specify
|
||||
(I0 => O) = 228;
|
||||
(I1 => O) = 189;
|
||||
(I2 => O) = 143;
|
||||
(I3 => O) = 100;
|
||||
(I4 => O) = 55;
|
||||
endspecify
|
||||
endmodule
|
||||
|
||||
(* abc9_lut=5 *)
|
||||
module LUT6(output wire O, input wire I0, I1, I2, I3, I4, I5);
|
||||
parameter [63:0] INIT = 0;
|
||||
wire [31: 0] s5 = I5 ? INIT[63:32] : INIT[31: 0];
|
||||
wire [15: 0] s4 = I4 ? s5[31:16] : s5[15: 0];
|
||||
wire [ 7: 0] s3 = I3 ? s4[15: 8] : s4[ 7: 0];
|
||||
wire [ 3: 0] s2 = I2 ? s3[ 7: 4] : s3[ 3: 0];
|
||||
wire [ 1: 0] s1 = I1 ? s2[ 3: 2] : s2[ 1: 0];
|
||||
assign O = I0 ? s1[1] : s1[0];
|
||||
specify
|
||||
(I0 => O) = 251;
|
||||
(I1 => O) = 212;
|
||||
(I2 => O) = 166;
|
||||
(I3 => O) = 123;
|
||||
(I4 => O) = 77;
|
||||
(I5 => O) = 43;
|
||||
endspecify
|
||||
parameter [63:0] INIT = 0;
|
||||
wire [31: 0] s5 = I5 ? INIT[63:32] : INIT[31: 0];
|
||||
wire [15: 0] s4 = I4 ? s5[31:16] : s5[15: 0];
|
||||
wire [ 7: 0] s3 = I3 ? s4[15: 8] : s4[ 7: 0];
|
||||
wire [ 3: 0] s2 = I2 ? s3[ 7: 4] : s3[ 3: 0];
|
||||
wire [ 1: 0] s1 = I1 ? s2[ 3: 2] : s2[ 1: 0];
|
||||
assign O = I0 ? s1[1] : s1[0];
|
||||
specify
|
||||
(I0 => O) = 251;
|
||||
(I1 => O) = 212;
|
||||
(I2 => O) = 166;
|
||||
(I3 => O) = 123;
|
||||
(I4 => O) = 77;
|
||||
(I5 => O) = 43;
|
||||
endspecify
|
||||
endmodule
|
||||
|
||||
(* abc9_flop, lib_whitebox *)
|
||||
module sh_dff(
|
||||
output reg Q,
|
||||
input wire D,
|
||||
(* clkbuf_sink *)
|
||||
input wire C
|
||||
output reg Q,
|
||||
input wire D,
|
||||
(* clkbuf_sink *)
|
||||
input wire C
|
||||
);
|
||||
|
||||
initial Q <= 1'b0;
|
||||
always @(posedge C)
|
||||
Q <= D;
|
||||
|
||||
specify
|
||||
(posedge C => (Q +: D)) = 0;
|
||||
$setuphold(posedge C, D, 0, 0);
|
||||
endspecify
|
||||
initial Q = 1'b0;
|
||||
always @(posedge C)
|
||||
Q <= D;
|
||||
|
||||
specify
|
||||
(posedge C => (Q +: D)) = 0;
|
||||
$setuphold(posedge C, D, 0, 0);
|
||||
endspecify
|
||||
|
||||
endmodule
|
||||
|
||||
|
@ -124,253 +124,253 @@ endmodule
|
|||
(* blackbox *)
|
||||
(* keep *)
|
||||
module adder_carry(
|
||||
output wire sumout,
|
||||
(* abc9_carry *)
|
||||
output wire cout,
|
||||
input wire p,
|
||||
input wire g,
|
||||
(* abc9_carry *)
|
||||
input wire cin
|
||||
output wire sumout,
|
||||
(* abc9_carry *)
|
||||
output wire cout,
|
||||
input wire p,
|
||||
input wire g,
|
||||
(* abc9_carry *)
|
||||
input wire cin
|
||||
);
|
||||
assign sumout = p ^ cin;
|
||||
assign cout = p ? cin : g;
|
||||
|
||||
specify
|
||||
(p => sumout) = 35;
|
||||
(g => sumout) = 35;
|
||||
(cin => sumout) = 40;
|
||||
(p => cout) = 67;
|
||||
(g => cout) = 65;
|
||||
(cin => cout) = 69;
|
||||
endspecify
|
||||
assign sumout = p ^ cin;
|
||||
assign cout = p ? cin : g;
|
||||
|
||||
specify
|
||||
(p => sumout) = 35;
|
||||
(g => sumout) = 35;
|
||||
(cin => sumout) = 40;
|
||||
(p => cout) = 67;
|
||||
(g => cout) = 65;
|
||||
(cin => cout) = 69;
|
||||
endspecify
|
||||
|
||||
endmodule
|
||||
|
||||
(* abc9_flop, lib_whitebox *)
|
||||
module dff(
|
||||
output reg Q,
|
||||
input wire D,
|
||||
(* clkbuf_sink *)
|
||||
input wire C
|
||||
output reg Q,
|
||||
input wire D,
|
||||
(* clkbuf_sink *)
|
||||
input wire C
|
||||
);
|
||||
initial Q <= 1'b0;
|
||||
initial Q = 1'b0;
|
||||
|
||||
always @(posedge C)
|
||||
Q <= D;
|
||||
always @(posedge C)
|
||||
Q <= D;
|
||||
|
||||
specify
|
||||
(posedge C=>(Q+:D)) = 285;
|
||||
$setuphold(posedge C, D, 56, 0);
|
||||
endspecify
|
||||
specify
|
||||
(posedge C=>(Q+:D)) = 285;
|
||||
$setuphold(posedge C, D, 56, 0);
|
||||
endspecify
|
||||
|
||||
endmodule
|
||||
|
||||
(* abc9_flop, lib_whitebox *)
|
||||
module dffn(
|
||||
output reg Q,
|
||||
input wire D,
|
||||
(* clkbuf_sink *)
|
||||
input wire C
|
||||
output reg Q,
|
||||
input wire D,
|
||||
(* clkbuf_sink *)
|
||||
input wire C
|
||||
);
|
||||
initial Q <= 1'b0;
|
||||
initial Q = 1'b0;
|
||||
|
||||
always @(negedge C)
|
||||
Q <= D;
|
||||
|
||||
specify
|
||||
(negedge C=>(Q+:D)) = 285;
|
||||
$setuphold(negedge C, D, 56, 0);
|
||||
endspecify
|
||||
always @(negedge C)
|
||||
Q <= D;
|
||||
|
||||
specify
|
||||
(negedge C=>(Q+:D)) = 285;
|
||||
$setuphold(negedge C, D, 56, 0);
|
||||
endspecify
|
||||
|
||||
endmodule
|
||||
|
||||
(* abc9_flop, lib_whitebox *)
|
||||
module dffsre(
|
||||
output reg Q,
|
||||
input wire D,
|
||||
(* clkbuf_sink *)
|
||||
input wire C,
|
||||
input wire E,
|
||||
input wire R,
|
||||
input wire S
|
||||
output reg Q,
|
||||
input wire D,
|
||||
(* clkbuf_sink *)
|
||||
input wire C,
|
||||
input wire E,
|
||||
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)
|
||||
Q <= 1'b0;
|
||||
else if (!S)
|
||||
Q <= 1'b1;
|
||||
else if (E)
|
||||
Q <= D;
|
||||
always @(posedge C or negedge S or negedge R)
|
||||
if (!R)
|
||||
Q <= 1'b0;
|
||||
else if (!S)
|
||||
Q <= 1'b1;
|
||||
else if (E)
|
||||
Q <= D;
|
||||
|
||||
specify
|
||||
(posedge C => (Q +: D)) = 280;
|
||||
(R => Q) = 0;
|
||||
(S => Q) = 0;
|
||||
$setuphold(posedge C, D, 56, 0);
|
||||
$setuphold(posedge C, E, 32, 0);
|
||||
$setuphold(posedge C, R, 0, 0);
|
||||
$setuphold(posedge C, S, 0, 0);
|
||||
$recrem(posedge R, posedge C, 0, 0);
|
||||
$recrem(posedge S, posedge C, 0, 0);
|
||||
endspecify
|
||||
specify
|
||||
(posedge C => (Q +: D)) = 280;
|
||||
(R => Q) = 0;
|
||||
(S => Q) = 0;
|
||||
$setuphold(posedge C, D, 56, 0);
|
||||
$setuphold(posedge C, E, 32, 0);
|
||||
$setuphold(posedge C, R, 0, 0);
|
||||
$setuphold(posedge C, S, 0, 0);
|
||||
$recrem(posedge R, posedge C, 0, 0);
|
||||
$recrem(posedge S, posedge C, 0, 0);
|
||||
endspecify
|
||||
|
||||
endmodule
|
||||
|
||||
(* abc9_flop, lib_whitebox *)
|
||||
module dffnsre(
|
||||
output reg Q,
|
||||
input wire D,
|
||||
(* clkbuf_sink *)
|
||||
input wire C,
|
||||
input wire E,
|
||||
input wire R,
|
||||
input wire S
|
||||
output reg Q,
|
||||
input wire D,
|
||||
(* clkbuf_sink *)
|
||||
input wire C,
|
||||
input wire E,
|
||||
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)
|
||||
Q <= 1'b0;
|
||||
else if (!S)
|
||||
Q <= 1'b1;
|
||||
else if (E)
|
||||
Q <= D;
|
||||
|
||||
specify
|
||||
(negedge C => (Q +: D)) = 280;
|
||||
(R => Q) = 0;
|
||||
(S => Q) = 0;
|
||||
$setuphold(negedge C, D, 56, 0);
|
||||
$setuphold(negedge C, E, 32, 0);
|
||||
$setuphold(negedge C, R, 0, 0);
|
||||
$setuphold(negedge C, S, 0, 0);
|
||||
$recrem(posedge R, negedge C, 0, 0);
|
||||
$recrem(posedge S, negedge C, 0, 0);
|
||||
endspecify
|
||||
always @(negedge C or negedge S or negedge R)
|
||||
if (!R)
|
||||
Q <= 1'b0;
|
||||
else if (!S)
|
||||
Q <= 1'b1;
|
||||
else if (E)
|
||||
Q <= D;
|
||||
|
||||
specify
|
||||
(negedge C => (Q +: D)) = 280;
|
||||
(R => Q) = 0;
|
||||
(S => Q) = 0;
|
||||
$setuphold(negedge C, D, 56, 0);
|
||||
$setuphold(negedge C, E, 32, 0);
|
||||
$setuphold(negedge C, R, 0, 0);
|
||||
$setuphold(negedge C, S, 0, 0);
|
||||
$recrem(posedge R, negedge C, 0, 0);
|
||||
$recrem(posedge S, negedge C, 0, 0);
|
||||
endspecify
|
||||
|
||||
endmodule
|
||||
|
||||
(* abc9_flop, lib_whitebox *)
|
||||
module sdffsre(
|
||||
output reg Q,
|
||||
input wire D,
|
||||
(* clkbuf_sink *)
|
||||
input wire C,
|
||||
input wire E,
|
||||
input wire R,
|
||||
input wire S
|
||||
output reg Q,
|
||||
input wire D,
|
||||
(* clkbuf_sink *)
|
||||
input wire C,
|
||||
input wire E,
|
||||
input wire R,
|
||||
input wire S
|
||||
);
|
||||
initial Q <= 1'b0;
|
||||
initial Q = 1'b0;
|
||||
|
||||
always @(posedge C)
|
||||
if (!R)
|
||||
Q <= 1'b0;
|
||||
else if (!S)
|
||||
Q <= 1'b1;
|
||||
else if (E)
|
||||
Q <= D;
|
||||
|
||||
specify
|
||||
(posedge C => (Q +: D)) = 280;
|
||||
$setuphold(posedge C, D, 56, 0);
|
||||
$setuphold(posedge C, R, 32, 0);
|
||||
$setuphold(posedge C, S, 0, 0);
|
||||
$setuphold(posedge C, E, 0, 0);
|
||||
endspecify
|
||||
always @(posedge C)
|
||||
if (!R)
|
||||
Q <= 1'b0;
|
||||
else if (!S)
|
||||
Q <= 1'b1;
|
||||
else if (E)
|
||||
Q <= D;
|
||||
|
||||
specify
|
||||
(posedge C => (Q +: D)) = 280;
|
||||
$setuphold(posedge C, D, 56, 0);
|
||||
$setuphold(posedge C, R, 32, 0);
|
||||
$setuphold(posedge C, S, 0, 0);
|
||||
$setuphold(posedge C, E, 0, 0);
|
||||
endspecify
|
||||
|
||||
endmodule
|
||||
|
||||
(* abc9_flop, lib_whitebox *)
|
||||
module sdffnsre(
|
||||
output reg Q,
|
||||
input wire D,
|
||||
(* clkbuf_sink *)
|
||||
input wire C,
|
||||
input wire E,
|
||||
input wire R,
|
||||
input wire S
|
||||
output reg Q,
|
||||
input wire D,
|
||||
(* clkbuf_sink *)
|
||||
input wire C,
|
||||
input wire E,
|
||||
input wire R,
|
||||
input wire S
|
||||
);
|
||||
initial Q <= 1'b0;
|
||||
initial Q = 1'b0;
|
||||
|
||||
always @(negedge C)
|
||||
if (!R)
|
||||
Q <= 1'b0;
|
||||
else if (!S)
|
||||
Q <= 1'b1;
|
||||
else if (E)
|
||||
Q <= D;
|
||||
|
||||
specify
|
||||
(negedge C => (Q +: D)) = 280;
|
||||
$setuphold(negedge C, D, 56, 0);
|
||||
$setuphold(negedge C, R, 32, 0);
|
||||
$setuphold(negedge C, S, 0, 0);
|
||||
$setuphold(negedge C, E, 0, 0);
|
||||
endspecify
|
||||
always @(negedge C)
|
||||
if (!R)
|
||||
Q <= 1'b0;
|
||||
else if (!S)
|
||||
Q <= 1'b1;
|
||||
else if (E)
|
||||
Q <= D;
|
||||
|
||||
specify
|
||||
(negedge C => (Q +: D)) = 280;
|
||||
$setuphold(negedge C, D, 56, 0);
|
||||
$setuphold(negedge C, R, 32, 0);
|
||||
$setuphold(negedge C, S, 0, 0);
|
||||
$setuphold(negedge C, E, 0, 0);
|
||||
endspecify
|
||||
|
||||
endmodule
|
||||
|
||||
(* abc9_flop, lib_whitebox *)
|
||||
module latchsre (
|
||||
output reg Q,
|
||||
input wire S,
|
||||
input wire R,
|
||||
input wire D,
|
||||
input wire G,
|
||||
input wire E
|
||||
output reg Q,
|
||||
input wire S,
|
||||
input wire R,
|
||||
input wire D,
|
||||
input wire G,
|
||||
input wire E
|
||||
);
|
||||
initial Q <= 1'b0;
|
||||
initial Q = 1'b0;
|
||||
|
||||
always @*
|
||||
begin
|
||||
if (!R)
|
||||
Q <= 1'b0;
|
||||
else if (!S)
|
||||
Q <= 1'b1;
|
||||
else if (E && G)
|
||||
Q <= D;
|
||||
end
|
||||
|
||||
specify
|
||||
(posedge G => (Q +: D)) = 0;
|
||||
$setuphold(posedge G, D, 0, 0);
|
||||
$setuphold(posedge G, E, 0, 0);
|
||||
$setuphold(posedge G, R, 0, 0);
|
||||
$setuphold(posedge G, S, 0, 0);
|
||||
endspecify
|
||||
always @*
|
||||
begin
|
||||
if (!R)
|
||||
Q <= 1'b0;
|
||||
else if (!S)
|
||||
Q <= 1'b1;
|
||||
else if (E && G)
|
||||
Q <= D;
|
||||
end
|
||||
|
||||
specify
|
||||
(posedge G => (Q +: D)) = 0;
|
||||
$setuphold(posedge G, D, 0, 0);
|
||||
$setuphold(posedge G, E, 0, 0);
|
||||
$setuphold(posedge G, R, 0, 0);
|
||||
$setuphold(posedge G, S, 0, 0);
|
||||
endspecify
|
||||
|
||||
endmodule
|
||||
|
||||
(* abc9_flop, lib_whitebox *)
|
||||
module latchnsre (
|
||||
output reg Q,
|
||||
input wire S,
|
||||
input wire R,
|
||||
input wire D,
|
||||
input wire G,
|
||||
input wire E
|
||||
output reg Q,
|
||||
input wire S,
|
||||
input wire R,
|
||||
input wire D,
|
||||
input wire G,
|
||||
input wire E
|
||||
);
|
||||
initial Q <= 1'b0;
|
||||
initial Q = 1'b0;
|
||||
|
||||
always @*
|
||||
begin
|
||||
if (!R)
|
||||
Q <= 1'b0;
|
||||
else if (!S)
|
||||
Q <= 1'b1;
|
||||
else if (E && !G)
|
||||
Q <= D;
|
||||
end
|
||||
|
||||
specify
|
||||
(negedge G => (Q +: D)) = 0;
|
||||
$setuphold(negedge G, D, 0, 0);
|
||||
$setuphold(negedge G, E, 0, 0);
|
||||
$setuphold(negedge G, R, 0, 0);
|
||||
$setuphold(negedge G, S, 0, 0);
|
||||
endspecify
|
||||
always @*
|
||||
begin
|
||||
if (!R)
|
||||
Q <= 1'b0;
|
||||
else if (!S)
|
||||
Q <= 1'b1;
|
||||
else if (E && !G)
|
||||
Q <= D;
|
||||
end
|
||||
|
||||
specify
|
||||
(negedge G => (Q +: D)) = 0;
|
||||
$setuphold(negedge G, D, 0, 0);
|
||||
$setuphold(negedge G, E, 0, 0);
|
||||
$setuphold(negedge G, R, 0, 0);
|
||||
$setuphold(negedge G, S, 0, 0);
|
||||
endspecify
|
||||
|
||||
endmodule
|
||||
|
||||
|
|
|
@ -16,116 +16,116 @@
|
|||
|
||||
// DFF, asynchronous set/reset, enable
|
||||
module \$_DFFSRE_PNNP_ (C, S, R, E, D, Q);
|
||||
input C;
|
||||
input S;
|
||||
input R;
|
||||
input E;
|
||||
input D;
|
||||
output Q;
|
||||
dffsre _TECHMAP_REPLACE_ (.Q(Q), .D(D), .C(C), .E(E), .R(R), .S(S));
|
||||
input C;
|
||||
input S;
|
||||
input R;
|
||||
input E;
|
||||
input D;
|
||||
output Q;
|
||||
dffsre _TECHMAP_REPLACE_ (.Q(Q), .D(D), .C(C), .E(E), .R(R), .S(S));
|
||||
endmodule
|
||||
|
||||
module \$_DFFSRE_NNNP_ (C, S, R, E, D, Q);
|
||||
input C;
|
||||
input S;
|
||||
input R;
|
||||
input E;
|
||||
input D;
|
||||
output Q;
|
||||
dffnsre _TECHMAP_REPLACE_ (.Q(Q), .D(D), .C(C), .E(E), .R(R), .S(S));
|
||||
input C;
|
||||
input S;
|
||||
input R;
|
||||
input E;
|
||||
input D;
|
||||
output Q;
|
||||
dffnsre _TECHMAP_REPLACE_ (.Q(Q), .D(D), .C(C), .E(E), .R(R), .S(S));
|
||||
endmodule
|
||||
|
||||
// DFF, synchronous set or reset, enable
|
||||
module \$_SDFFE_PN0P_ (D, C, R, E, Q);
|
||||
input D;
|
||||
input C;
|
||||
input R;
|
||||
input E;
|
||||
output Q;
|
||||
sdffsre _TECHMAP_REPLACE_ (.Q(Q), .D(D), .C(C), .E(E), .R(R), .S(1'b1));
|
||||
input D;
|
||||
input C;
|
||||
input R;
|
||||
input E;
|
||||
output Q;
|
||||
sdffsre _TECHMAP_REPLACE_ (.Q(Q), .D(D), .C(C), .E(E), .R(R), .S(1'b1));
|
||||
endmodule
|
||||
|
||||
module \$_SDFFE_PN1P_ (D, C, R, E, Q);
|
||||
input D;
|
||||
input C;
|
||||
input R;
|
||||
input E;
|
||||
output Q;
|
||||
sdffsre _TECHMAP_REPLACE_ (.Q(Q), .D(D), .C(C), .E(E), .R(1'b1), .S(R));
|
||||
input D;
|
||||
input C;
|
||||
input R;
|
||||
input E;
|
||||
output Q;
|
||||
sdffsre _TECHMAP_REPLACE_ (.Q(Q), .D(D), .C(C), .E(E), .R(1'b1), .S(R));
|
||||
endmodule
|
||||
|
||||
module \$_SDFFE_NN0P_ (D, C, R, E, Q);
|
||||
input D;
|
||||
input C;
|
||||
input R;
|
||||
input E;
|
||||
output Q;
|
||||
sdffnsre _TECHMAP_REPLACE_ (.Q(Q), .D(D), .C(C), .E(E), .R(R), .S(1'b1));
|
||||
input D;
|
||||
input C;
|
||||
input R;
|
||||
input E;
|
||||
output Q;
|
||||
sdffnsre _TECHMAP_REPLACE_ (.Q(Q), .D(D), .C(C), .E(E), .R(R), .S(1'b1));
|
||||
endmodule
|
||||
|
||||
module \$_SDFFE_NN1P_ (D, C, R, E, Q);
|
||||
input D;
|
||||
input C;
|
||||
input R;
|
||||
input E;
|
||||
output Q;
|
||||
sdffnsre _TECHMAP_REPLACE_ (.Q(Q), .D(D), .C(C), .E(E), .R(1'b1), .S(R));
|
||||
input D;
|
||||
input C;
|
||||
input R;
|
||||
input E;
|
||||
output Q;
|
||||
sdffnsre _TECHMAP_REPLACE_ (.Q(Q), .D(D), .C(C), .E(E), .R(1'b1), .S(R));
|
||||
endmodule
|
||||
|
||||
// Latch, no set/reset, no enable
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
// Latch with async set and reset and enable
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
module \$__SHREG_DFF_P_ (D, Q, C);
|
||||
input D;
|
||||
input C;
|
||||
output Q;
|
||||
input D;
|
||||
input C;
|
||||
output Q;
|
||||
|
||||
parameter DEPTH = 2;
|
||||
parameter DEPTH = 2;
|
||||
|
||||
reg [DEPTH-2:0] q;
|
||||
reg [DEPTH-2:0] q;
|
||||
|
||||
genvar i;
|
||||
generate for (i = 0; i < DEPTH; i = i + 1) begin: slice
|
||||
genvar i;
|
||||
generate for (i = 0; i < DEPTH; i = i + 1) begin: slice
|
||||
|
||||
// First in chain
|
||||
generate if (i == 0) begin
|
||||
sh_dff #() shreg_beg (
|
||||
.Q(q[i]),
|
||||
.D(D),
|
||||
.C(C)
|
||||
);
|
||||
end endgenerate
|
||||
// Middle in chain
|
||||
generate if (i > 0 && i != DEPTH-1) begin
|
||||
sh_dff #() shreg_mid (
|
||||
.Q(q[i]),
|
||||
.D(q[i-1]),
|
||||
.C(C)
|
||||
);
|
||||
end endgenerate
|
||||
// Last in chain
|
||||
generate if (i == DEPTH-1) begin
|
||||
sh_dff #() shreg_end (
|
||||
.Q(Q),
|
||||
.D(q[i-1]),
|
||||
.C(C)
|
||||
);
|
||||
end endgenerate
|
||||
// First in chain
|
||||
generate if (i == 0) begin
|
||||
sh_dff #() shreg_beg (
|
||||
.Q(q[i]),
|
||||
.D(D),
|
||||
.C(C)
|
||||
);
|
||||
end endgenerate
|
||||
// Middle in chain
|
||||
generate if (i > 0 && i != DEPTH-1) begin
|
||||
sh_dff #() shreg_mid (
|
||||
.Q(q[i]),
|
||||
.D(q[i-1]),
|
||||
.C(C)
|
||||
);
|
||||
end endgenerate
|
||||
// Last in chain
|
||||
generate if (i == DEPTH-1) begin
|
||||
sh_dff #() shreg_end (
|
||||
.Q(Q),
|
||||
.D(q[i-1]),
|
||||
.C(C)
|
||||
);
|
||||
end endgenerate
|
||||
end: slice
|
||||
endgenerate
|
||||
|
||||
|
|
|
@ -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