From 889e1fc19fb7afbc747ae8a4b4ce68eae7f43391 Mon Sep 17 00:00:00 2001 From: David Shah Date: Tue, 17 Jul 2018 11:28:59 +0200 Subject: ecp5: Adding cell definitions Signed-off-by: David Shah --- ecp5/cells.cc | 124 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ecp5/cells.h | 59 ++++++++++++++++++++++++++++ 2 files changed, 183 insertions(+) create mode 100644 ecp5/cells.cc create mode 100644 ecp5/cells.h diff --git a/ecp5/cells.cc b/ecp5/cells.cc new file mode 100644 index 00000000..ddd1130d --- /dev/null +++ b/ecp5/cells.cc @@ -0,0 +1,124 @@ +/* + * nextpnr -- Next Generation Place and Route + * + * Copyright (C) 2018 David Shah + * + * 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 "cells.h" +#include "log.h" +#include "util.h" +#include "design_utils.h" + +NEXTPNR_NAMESPACE_BEGIN + +void add_port(const Context *ctx, CellInfo *cell, std::string name, PortType dir) +{ + IdString id = ctx->id(name); + cell->ports[id] = PortInfo{id, nullptr, dir}; +} + + +std::unique_ptr create_ecp5_cell(Context *ctx, IdString type, std::string name = "") { + static int auto_idx = 0; + std::unique_ptr new_cell = std::unique_ptr(new CellInfo()); + if (name.empty()) { + new_cell->name = ctx->id("$nextpnr_" + type.str(ctx) + "_" + std::to_string(auto_idx++)); + } else { + new_cell->name = ctx->id(name); + } + new_cell->type = type; + if (type == ctx->id("TRELLIS_LC")) { + new_cell->params[ctx->id("MODE")] = "LOGIC"; + new_cell->params[ctx->id("GSR")] = "DISABLED"; + new_cell->params[ctx->id("SRMODE")] = "LSR_OVER_CE"; + new_cell->params[ctx->id("CEMUX")] = "1"; + new_cell->params[ctx->id("CLKMUX")] = "CLK"; + new_cell->params[ctx->id("LSRMUX")] = "LSR"; + new_cell->params[ctx->id("LUT0_INITVAL")] = "0"; + new_cell->params[ctx->id("LUT1_INITVAL")] = "0"; + new_cell->params[ctx->id("REG0_SD")] = "0"; + new_cell->params[ctx->id("REG1_SD")] = "0"; + new_cell->params[ctx->id("REG0_REGSET")] = "RESET"; + new_cell->params[ctx->id("REG1_REGSET")] = "RESET"; + new_cell->params[ctx->id("CCU2_INJECT1_0")] = "NO"; + new_cell->params[ctx->id("CCU2_INJECT1_1")] = "NO"; + new_cell->params[ctx->id("WREMUX")] = "WRE"; + + add_port(ctx, new_cell.get(), "A0", PORT_IN); + add_port(ctx, new_cell.get(), "B0", PORT_IN); + add_port(ctx, new_cell.get(), "C0", PORT_IN); + add_port(ctx, new_cell.get(), "D0", PORT_IN); + + add_port(ctx, new_cell.get(), "A1", PORT_IN); + add_port(ctx, new_cell.get(), "B1", PORT_IN); + add_port(ctx, new_cell.get(), "C1", PORT_IN); + add_port(ctx, new_cell.get(), "D1", PORT_IN); + + add_port(ctx, new_cell.get(), "M0", PORT_IN); + add_port(ctx, new_cell.get(), "M1", PORT_IN); + + add_port(ctx, new_cell.get(), "FCI", PORT_IN); + add_port(ctx, new_cell.get(), "FXA", PORT_IN); + add_port(ctx, new_cell.get(), "FXB", PORT_IN); + + add_port(ctx, new_cell.get(), "CLK", PORT_IN); + add_port(ctx, new_cell.get(), "LSR", PORT_IN); + add_port(ctx, new_cell.get(), "CE", PORT_IN); + + add_port(ctx, new_cell.get(), "DI0", PORT_IN); + add_port(ctx, new_cell.get(), "DI1", PORT_IN); + + add_port(ctx, new_cell.get(), "WD0", PORT_IN); + add_port(ctx, new_cell.get(), "WD1", PORT_IN); + add_port(ctx, new_cell.get(), "WAD0", PORT_IN); + add_port(ctx, new_cell.get(), "WAD1", PORT_IN); + add_port(ctx, new_cell.get(), "WAD2", PORT_IN); + add_port(ctx, new_cell.get(), "WAD3", PORT_IN); + add_port(ctx, new_cell.get(), "WRE", PORT_IN); + add_port(ctx, new_cell.get(), "WCK", PORT_IN); + + add_port(ctx, new_cell.get(), "F0", PORT_OUT); + add_port(ctx, new_cell.get(), "Q0", PORT_OUT); + add_port(ctx, new_cell.get(), "F1", PORT_OUT); + add_port(ctx, new_cell.get(), "Q1", PORT_OUT); + + add_port(ctx, new_cell.get(), "FCO", PORT_OUT); + add_port(ctx, new_cell.get(), "OFX0", PORT_OUT); + add_port(ctx, new_cell.get(), "OFX1", PORT_OUT); + + add_port(ctx, new_cell.get(), "WDO0", PORT_OUT); + add_port(ctx, new_cell.get(), "WDO1", PORT_OUT); + add_port(ctx, new_cell.get(), "WDO2", PORT_OUT); + add_port(ctx, new_cell.get(), "WDO3", PORT_OUT); + add_port(ctx, new_cell.get(), "WADO0", PORT_OUT); + add_port(ctx, new_cell.get(), "WADO1", PORT_OUT); + add_port(ctx, new_cell.get(), "WADO2", PORT_OUT); + add_port(ctx, new_cell.get(), "WADO3", PORT_OUT); + } else if (type == ctx->id("TRELLIS_IO")) { + new_cell->params[ctx->id("DIR")] = "INPUT"; + new_cell->attrs[ctx->id("IO_TYPE")] = "LVCMOS33"; + + add_port(ctx, new_cell.get(), "B", PORT_INOUT); + add_port(ctx, new_cell.get(), "I", PORT_IN); + add_port(ctx, new_cell.get(), "T", PORT_IN); + add_port(ctx, new_cell.get(), "O", PORT_OUT); + } else { + log_error("unable to create ECP5 cell of type %s", type.c_str(ctx)); + } + return new_cell; +} + +NEXTPNR_NAMESPACE_END diff --git a/ecp5/cells.h b/ecp5/cells.h new file mode 100644 index 00000000..e2bda4e9 --- /dev/null +++ b/ecp5/cells.h @@ -0,0 +1,59 @@ +/* + * nextpnr -- Next Generation Place and Route + * + * Copyright (C) 2018 David Shah + * + * 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. + * + */ + +#ifndef ECP5_CELLS_H +#define ECP5_CELLS_H + +#include "nextpnr.h" + +NEXTPNR_NAMESPACE_BEGIN + + +// Create a standard ECP5 cell and return it +// Name will be automatically assigned if not specified +std::unique_ptr create_ecp5_cell(Context *ctx, IdString type, std::string name = ""); + +// Return true if a cell is a LUT +inline bool is_lut(const BaseCtx *ctx, const CellInfo *cell) +{ return cell->type == ctx->id("LUT4"); } + +// Return true if a cell is a flipflop +inline bool is_ff(const BaseCtx *ctx, const CellInfo *cell) +{ + return cell->type == ctx->id("TRELLIS_FF"); +} + +inline bool is_carry(const BaseCtx *ctx, const CellInfo *cell) +{ return cell->type == ctx->id("CCU2C"); } + +inline bool is_lc(const BaseCtx *ctx, const CellInfo *cell) +{ return cell->type == ctx->id("TRELLIS_LC"); } + +inline bool is_dpram(const BaseCtx *ctx, const CellInfo *cell) +{ return cell->type == ctx->id("TRELLIS_DPR16X4"); } + +inline bool is_pfumx(const BaseCtx *ctx, const CellInfo *cell) +{ return cell->type == ctx->id("PFUMX"); } + +inline bool is_l6mux(const BaseCtx *ctx, const CellInfo *cell) +{ return cell->type == ctx->id("L6MUX21"); } + +NEXTPNR_NAMESPACE_END + +#endif -- cgit v1.2.3