gowin: Himbaechel. Use pin functions info
Use information about pin functions in the clock router. Signed-off-by: YRabbit <rabbit@yrabbit.cyou>
This commit is contained in:
parent
b2ec06dfe8
commit
6eeac1cabf
@ -29,14 +29,16 @@
|
||||
|
||||
#include "globals.h"
|
||||
#include "gowin.h"
|
||||
#include "gowin_utils.h"
|
||||
|
||||
NEXTPNR_NAMESPACE_BEGIN
|
||||
|
||||
struct GowinGlobalRouter
|
||||
{
|
||||
Context *ctx;
|
||||
GowinUtils gwu;
|
||||
|
||||
GowinGlobalRouter(Context *ctx) : ctx(ctx){};
|
||||
GowinGlobalRouter(Context *ctx) : ctx(ctx) { gwu.init(ctx); };
|
||||
|
||||
// allow io->global, global->global and global->tile clock
|
||||
bool global_pip_filter(PipId pip) const
|
||||
@ -157,8 +159,18 @@ struct GowinGlobalRouter
|
||||
|
||||
bool driver_is_clksrc(const PortRef &driver)
|
||||
{
|
||||
// XXX dedicated pins
|
||||
return driver.port == id_O;
|
||||
// dedicated pins
|
||||
if (CellTypePort(driver) == CellTypePort(id_IBUF, id_O)) {
|
||||
|
||||
NPNR_ASSERT(driver.cell->bel != BelId());
|
||||
IdStringList pin_func = gwu.get_pin_funcs(driver.cell->bel);
|
||||
for (size_t i = 0; i < pin_func.size(); ++i) {
|
||||
if (pin_func[i].str(ctx).rfind("GCLKT", 0) == 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void run(void)
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "cst.h"
|
||||
#include "globals.h"
|
||||
#include "gowin.h"
|
||||
#include "gowin_utils.h"
|
||||
#include "pack.h"
|
||||
|
||||
NEXTPNR_NAMESPACE_BEGIN
|
||||
@ -38,6 +39,7 @@ struct GowinImpl : HimbaechelAPI
|
||||
|
||||
private:
|
||||
HimbaechelHelpers h;
|
||||
GowinUtils gwu;
|
||||
|
||||
IdString chip;
|
||||
IdString partno;
|
||||
@ -70,6 +72,8 @@ void GowinImpl::init(Context *ctx)
|
||||
h.init(ctx);
|
||||
HimbaechelAPI::init(ctx);
|
||||
|
||||
gwu.init(ctx);
|
||||
|
||||
const ArchArgs &args = ctx->getArchArgs();
|
||||
// These fields go in the header of the output JSON file and can help
|
||||
// gowin_pack support different architectures
|
||||
|
@ -348,6 +348,7 @@ def create_ssram_tiletype(chip: Chip, db: chipdb, x: int, y: int, ttyp: int):
|
||||
tt.add_bel_pin(ff, f"WRE", "LSR2", PinType.INPUT)
|
||||
return (ttyp, tt)
|
||||
|
||||
# pinouts, packages...
|
||||
_tbrlre = re.compile(r"IO([TBRL])(\d+)(\w)")
|
||||
def create_packages(chip: Chip, db: chipdb):
|
||||
def ioloc_to_tile_bel(ioloc):
|
||||
|
25
himbaechel/uarch/gowin/gowin_utils.cc
Normal file
25
himbaechel/uarch/gowin/gowin_utils.cc
Normal file
@ -0,0 +1,25 @@
|
||||
#include "gowin_utils.h"
|
||||
|
||||
#include "log.h"
|
||||
#include "nextpnr.h"
|
||||
#include "util.h"
|
||||
|
||||
NEXTPNR_NAMESPACE_BEGIN
|
||||
|
||||
// pin functions: GCLKT_4, SSPI_CS, READY etc
|
||||
IdStringList GowinUtils::get_pin_funcs(BelId bel)
|
||||
{
|
||||
IdStringList bel_name = ctx->getBelName(bel);
|
||||
|
||||
const PadInfoPOD *pins = ctx->package_info->pads.get();
|
||||
size_t len = ctx->package_info->pads.ssize();
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
const PadInfoPOD *pin = &pins[i];
|
||||
if (IdString(pin->tile) == bel_name[0] && IdString(pin->bel) == bel_name[1]) {
|
||||
return IdStringList::parse(ctx, IdString(pin->pad_function).str(ctx));
|
||||
}
|
||||
}
|
||||
return IdStringList();
|
||||
}
|
||||
|
||||
NEXTPNR_NAMESPACE_END
|
24
himbaechel/uarch/gowin/gowin_utils.h
Normal file
24
himbaechel/uarch/gowin/gowin_utils.h
Normal file
@ -0,0 +1,24 @@
|
||||
#ifndef GOWIN_UTILS_H
|
||||
#define GOWIN_UTILS_H
|
||||
|
||||
#include "idstringlist.h"
|
||||
#include "nextpnr_namespaces.h"
|
||||
#include "nextpnr_types.h"
|
||||
|
||||
NEXTPNR_NAMESPACE_BEGIN
|
||||
|
||||
struct GowinUtils
|
||||
{
|
||||
Context *ctx;
|
||||
|
||||
GowinUtils() {}
|
||||
|
||||
void init(Context *ctx) { this->ctx = ctx; }
|
||||
|
||||
// pin functions: GCLKT_4, SSPI_CS, READY etc
|
||||
IdStringList get_pin_funcs(BelId bel);
|
||||
};
|
||||
|
||||
NEXTPNR_NAMESPACE_END
|
||||
|
||||
#endif
|
@ -305,8 +305,8 @@ struct GowinPacker
|
||||
// create ALU chain
|
||||
void pack_alus(void)
|
||||
{
|
||||
static CellTypePort cell_alu_cout = CellTypePort(id_ALU, id_COUT);
|
||||
static CellTypePort cell_alu_cin = CellTypePort(id_ALU, id_CIN);
|
||||
const CellTypePort cell_alu_cout = CellTypePort(id_ALU, id_COUT);
|
||||
const CellTypePort cell_alu_cin = CellTypePort(id_ALU, id_CIN);
|
||||
std::vector<std::unique_ptr<CellInfo>> new_cells;
|
||||
|
||||
log_info("Pack ALUs...\n");
|
||||
@ -409,12 +409,12 @@ struct GowinPacker
|
||||
void constrain_lutffs(void)
|
||||
{
|
||||
// Constrain directly connected LUTs and FFs together to use dedicated resources
|
||||
auto lut_outs = pool<CellTypePort>{{id_LUT1, id_F}, {id_LUT2, id_F}, {id_LUT3, id_F}, {id_LUT4, id_F}};
|
||||
auto dff_ins = pool<CellTypePort>{{id_DFF, id_D}, {id_DFFE, id_D}, {id_DFFN, id_D}, {id_DFFNE, id_D},
|
||||
{id_DFFS, id_D}, {id_DFFSE, id_D}, {id_DFFNS, id_D}, {id_DFFNSE, id_D},
|
||||
{id_DFFR, id_D}, {id_DFFRE, id_D}, {id_DFFNR, id_D}, {id_DFFNRE, id_D},
|
||||
{id_DFFP, id_D}, {id_DFFPE, id_D}, {id_DFFNP, id_D}, {id_DFFNPE, id_D},
|
||||
{id_DFFC, id_D}, {id_DFFCE, id_D}, {id_DFFNC, id_D}, {id_DFFNCE, id_D}};
|
||||
const pool<CellTypePort> lut_outs{{id_LUT1, id_F}, {id_LUT2, id_F}, {id_LUT3, id_F}, {id_LUT4, id_F}};
|
||||
const pool<CellTypePort> dff_ins{{id_DFF, id_D}, {id_DFFE, id_D}, {id_DFFN, id_D}, {id_DFFNE, id_D},
|
||||
{id_DFFS, id_D}, {id_DFFSE, id_D}, {id_DFFNS, id_D}, {id_DFFNSE, id_D},
|
||||
{id_DFFR, id_D}, {id_DFFRE, id_D}, {id_DFFNR, id_D}, {id_DFFNRE, id_D},
|
||||
{id_DFFP, id_D}, {id_DFFPE, id_D}, {id_DFFNP, id_D}, {id_DFFNPE, id_D},
|
||||
{id_DFFC, id_D}, {id_DFFCE, id_D}, {id_DFFNC, id_D}, {id_DFFNCE, id_D}};
|
||||
|
||||
int lutffs = h.constrain_cell_pairs(lut_outs, dff_ins, 1);
|
||||
log_info("Constrained %d LUTFF pairs.\n", lutffs);
|
||||
|
Loading…
Reference in New Issue
Block a user