mirror of https://github.com/YosysHQ/nextpnr.git
Compare commits
7 Commits
d5c37d6354
...
6ad7c06795
| Author | SHA1 | Date |
|---|---|---|
|
|
6ad7c06795 | |
|
|
d8117e3cad | |
|
|
30669eca60 | |
|
|
35629d0a43 | |
|
|
a530283600 | |
|
|
c133d00e2e | |
|
|
c7cfb0aa4b |
|
|
@ -169,7 +169,7 @@ else()
|
|||
endif()
|
||||
endif()
|
||||
|
||||
set(boost_libs filesystem program_options iostreams system)
|
||||
set(boost_libs program_options iostreams)
|
||||
if (Threads_FOUND)
|
||||
list(APPEND boost_libs thread)
|
||||
endif()
|
||||
|
|
|
|||
|
|
@ -4,12 +4,10 @@ project(bba CXX)
|
|||
set(CMAKE_CXX_STANDARD 17)
|
||||
|
||||
find_package(Boost REQUIRED COMPONENTS
|
||||
program_options
|
||||
system)
|
||||
program_options)
|
||||
|
||||
add_executable(bbasm
|
||||
main.cc)
|
||||
target_link_libraries(bbasm LINK_PRIVATE
|
||||
${Boost_PROGRAM_OPTIONS_LIBRARY}
|
||||
${Boost_SYSTEM_LIBRARY})
|
||||
${Boost_PROGRAM_OPTIONS_LIBRARY})
|
||||
export(TARGETS bbasm FILE ${CMAKE_BINARY_DIR}/bba-export.cmake)
|
||||
|
|
|
|||
|
|
@ -28,9 +28,9 @@
|
|||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/algorithm/string/join.hpp>
|
||||
#include <boost/filesystem/path.hpp>
|
||||
#include <boost/program_options.hpp>
|
||||
#include <cinttypes>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <random>
|
||||
|
|
@ -276,14 +276,14 @@ bool CommandHandler::parseOptions()
|
|||
bool CommandHandler::executeBeforeContext()
|
||||
{
|
||||
if (vm.count("help") || argc == 1) {
|
||||
std::cerr << boost::filesystem::path(argv[0]).stem()
|
||||
std::cerr << std::filesystem::path(argv[0]).stem()
|
||||
<< " -- Next Generation Place and Route (Version " GIT_DESCRIBE_STR ")\n";
|
||||
std::cerr << options << "\n";
|
||||
return argc != 1;
|
||||
}
|
||||
|
||||
if (vm.count("version")) {
|
||||
std::cerr << boost::filesystem::path(argv[0]).stem()
|
||||
std::cerr << std::filesystem::path(argv[0]).stem()
|
||||
<< " -- Next Generation Place and Route (Version " GIT_DESCRIBE_STR ")\n";
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,15 +39,7 @@ struct Context : Arch, DeterministicRNG
|
|||
// True when detailed per-net timing is to be stored / reported
|
||||
bool detailed_timing_report = false;
|
||||
|
||||
ArchArgs arch_args;
|
||||
|
||||
Context(ArchArgs args) : Arch(args)
|
||||
{
|
||||
BaseCtx::as_ctx = this;
|
||||
arch_args = args;
|
||||
}
|
||||
|
||||
ArchArgs getArchArgs() { return arch_args; }
|
||||
Context(ArchArgs args) : Arch(args) { BaseCtx::as_ctx = this; }
|
||||
|
||||
// --------------------------------------------------------------
|
||||
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@
|
|||
#define NOMINMAX
|
||||
#include <windows.h>
|
||||
#endif
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/iostreams/device/mapped_file.hpp>
|
||||
#include <filesystem>
|
||||
#include "embed.h"
|
||||
#include "nextpnr.h"
|
||||
|
||||
|
|
@ -17,7 +17,7 @@ const void *get_chipdb(const std::string &filename)
|
|||
static std::map<std::string, boost::iostreams::mapped_file> files;
|
||||
if (!files.count(filename)) {
|
||||
std::string full_filename = EXTERNAL_CHIPDB_ROOT "/" + filename;
|
||||
if (boost::filesystem::exists(full_filename))
|
||||
if (std::filesystem::exists(full_filename))
|
||||
files[filename].open(full_filename, boost::iostreams::mapped_file::priv);
|
||||
}
|
||||
if (files.count(filename))
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@
|
|||
#include "pack.h"
|
||||
#include "validity_check.h"
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <filesystem>
|
||||
|
||||
NEXTPNR_NAMESPACE_BEGIN
|
||||
|
||||
|
|
@ -62,7 +62,7 @@ struct FabulousImpl : ViaductAPI
|
|||
ViaductAPI::init(ctx);
|
||||
h.init(ctx);
|
||||
fab_root = get_env_var("FAB_ROOT", ", set it to the fabulous build output or project path");
|
||||
if (boost::filesystem::exists(fab_root + "/.FABulous"))
|
||||
if (std::filesystem::exists(fab_root + "/.FABulous"))
|
||||
is_new_fab = true;
|
||||
else
|
||||
is_new_fab = false;
|
||||
|
|
|
|||
|
|
@ -368,7 +368,7 @@ void BaseMainWindow::open_json()
|
|||
if (!fileName.isEmpty()) {
|
||||
disableActions();
|
||||
if (ctx->settings.find(ctx->id("synth")) == ctx->settings.end()) {
|
||||
ArchArgs chipArgs = ctx->getArchArgs();
|
||||
ArchArgs chipArgs = ctx->args;
|
||||
ctx = std::unique_ptr<Context>(new Context(chipArgs));
|
||||
Q_EMIT contextChanged(ctx.get());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@
|
|||
#include "mainwindow.h"
|
||||
|
||||
#include <QMessageBox>
|
||||
#include <cstdlib>
|
||||
|
||||
static void initMainResource() { Q_INIT_RESOURCE(nextpnr); }
|
||||
|
||||
|
|
@ -46,7 +45,6 @@ void MainWindow::new_proj()
|
|||
{
|
||||
QMessageBox::critical(0, "Error",
|
||||
"Creating a new project not supported in himbächel mode, please re-start from command line.");
|
||||
std::exit(1);
|
||||
}
|
||||
|
||||
NEXTPNR_NAMESPACE_END
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@
|
|||
*/
|
||||
|
||||
#include "arch.h"
|
||||
#include <boost/filesystem/path.hpp>
|
||||
#include "archdefs.h"
|
||||
#include "chipdb.h"
|
||||
#include "log.h"
|
||||
|
|
@ -31,6 +30,8 @@
|
|||
#include "router2.h"
|
||||
#include "util.h"
|
||||
|
||||
#include <filesystem>
|
||||
|
||||
NEXTPNR_NAMESPACE_BEGIN
|
||||
|
||||
static constexpr int database_version = 6;
|
||||
|
|
@ -124,7 +125,7 @@ void Arch::load_chipdb(const std::string &path)
|
|||
db_path = proc_share_dirname();
|
||||
db_path += "himbaechel/";
|
||||
db_path += path;
|
||||
boost::filesystem::path p(db_path);
|
||||
std::filesystem::path p(db_path);
|
||||
db_path = p.make_preferred().string();
|
||||
}
|
||||
try {
|
||||
|
|
|
|||
|
|
@ -177,8 +177,9 @@ void GateMatePacker::pack_io()
|
|||
for (auto &p : ci.params) {
|
||||
|
||||
if (p.first.in(id_PIN_NAME, id_PIN_NAME_P, id_PIN_NAME_N)) {
|
||||
if (ctx->get_package_pin_bel(ctx->id(p.second.as_string())) == BelId())
|
||||
log_error("Unknown %s '%s' for cell '%s'.\n", p.first.c_str(ctx), p.second.as_string().c_str(),
|
||||
std::string pname = p.second.as_string();
|
||||
if (pname != "UNPLACED" && ctx->get_package_pin_bel(ctx->id(pname)) == BelId())
|
||||
log_error("Unknown %s '%s' for cell '%s'.\n", p.first.c_str(ctx), pname.c_str(),
|
||||
ci.name.c_str(ctx));
|
||||
keys.push_back(p.first);
|
||||
continue;
|
||||
|
|
@ -194,9 +195,15 @@ void GateMatePacker::pack_io()
|
|||
continue;
|
||||
if (ci.type.in(id_CC_TOBUF) && p.first.in(id_PULLUP, id_PULLDOWN, id_KEEPER))
|
||||
continue;
|
||||
if (ci.type.in(id_CC_OBUF, id_CC_TOBUF, id_CC_IOBUF) &&
|
||||
p.first.in(id_DRIVE, id_SLEW, id_DELAY_OBF, id_FF_OBF))
|
||||
continue;
|
||||
if (ci.type.in(id_CC_OBUF, id_CC_TOBUF, id_CC_IOBUF)) {
|
||||
if (p.first.in(id_DRIVE, id_SLEW)) {
|
||||
if (p.second.is_string && p.second.as_string() == "UNDEFINED")
|
||||
keys.push_back(p.first);
|
||||
continue;
|
||||
}
|
||||
if (p.first.in(id_DELAY_OBF, id_FF_OBF))
|
||||
continue;
|
||||
}
|
||||
if (ci.type.in(id_CC_LVDS_IBUF, id_CC_LVDS_IOBUF) && p.first.in(id_LVDS_RTERM, id_DELAY_IBF, id_FF_IBF))
|
||||
continue;
|
||||
if (ci.type.in(id_CC_LVDS_OBUF, id_CC_LVDS_TOBUF, id_CC_LVDS_IOBUF) &&
|
||||
|
|
|
|||
|
|
@ -70,8 +70,8 @@ static const DefaultParam serdes_defaults[] = {
|
|||
{id_RX_AFE_VCMSEL, 3, 4},
|
||||
{id_RX_CDR_CKP, 8, 0xF8},
|
||||
{id_RX_CDR_CKI, 8, 0},
|
||||
{id_RX_CDR_TRANS_TH, 9, 128},
|
||||
{id_RX_CDR_LOCK_CFG, 6, 0x0B},
|
||||
{id_RX_CDR_TRANS_TH, 7, 0x08},
|
||||
{id_RX_CDR_LOCK_CFG, 8, 0xD5},
|
||||
// { id_RX_CDR_LOCKED, 1, 0 },
|
||||
// { id_RX_CDR_FREQ_ACC_VAL, 15, 0 },
|
||||
// { id_RX_CDR_PHASE_ACC_VAL, 16, 0 },
|
||||
|
|
|
|||
|
|
@ -1038,6 +1038,9 @@ X(RPLLA)
|
|||
X(PLLVR)
|
||||
X(PLLA)
|
||||
|
||||
// ADC
|
||||
X(ADC)
|
||||
|
||||
// primitive attributes
|
||||
X(INIT)
|
||||
X(FF_USED)
|
||||
|
|
|
|||
|
|
@ -80,6 +80,7 @@ struct GowinCstReader
|
|||
constrained_cells.insert(std::make_pair(cellId, belId));
|
||||
}
|
||||
};
|
||||
pool<IdString> adc_ios; // bus#/X#Y#
|
||||
|
||||
log_info("Reading constraints...\n");
|
||||
try {
|
||||
|
|
@ -95,6 +96,7 @@ struct GowinCstReader
|
|||
std::regex hclkre =
|
||||
std::regex("INS_LOC +\"([^\"]+)\" +(TOP|RIGHT|BOTTOM|LEFT)SIDE\\[([0,1])\\] *;*[\\s\\S]*");
|
||||
std::regex clockre = std::regex("CLOCK_LOC +\"([^\"]+)\" +BUF([GS])(\\[([0-7])\\])?[^;]*;.*[\\s\\S]*");
|
||||
std::regex adcre = std::regex("USE_ADC_SRC +bus([0-9]) +IO([TRBL])([0-9]+) *;.*[\\s\\S]*");
|
||||
std::smatch match, match_attr, match_pinloc;
|
||||
std::string line, pinlines[2];
|
||||
std::vector<IdStringList> constrained_clkdivs;
|
||||
|
|
@ -104,7 +106,8 @@ struct GowinCstReader
|
|||
ioport,
|
||||
insloc,
|
||||
clock,
|
||||
hclk
|
||||
hclk,
|
||||
adc
|
||||
} cst_type;
|
||||
|
||||
while (!in.eof()) {
|
||||
|
|
@ -123,10 +126,14 @@ struct GowinCstReader
|
|||
if (std::regex_match(line, match, hclkre)) {
|
||||
cst_type = hclk;
|
||||
} else {
|
||||
if ((!line.empty()) && (line.rfind("//", 0) == std::string::npos)) {
|
||||
log_warning("Invalid constraint: %s\n", line.c_str());
|
||||
if (std::regex_match(line, match, adcre)) {
|
||||
cst_type = adc;
|
||||
} else {
|
||||
if ((!line.empty()) && (line.rfind("//", 0) == std::string::npos)) {
|
||||
log_warning("Invalid constraint: %s\n", line.c_str());
|
||||
}
|
||||
continue;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -135,11 +142,26 @@ struct GowinCstReader
|
|||
|
||||
IdString net = ctx->id(match[1]);
|
||||
auto it = ctx->cells.find(net);
|
||||
if (cst_type != clock && it == ctx->cells.end()) {
|
||||
if (cst_type != clock && cst_type != adc && it == ctx->cells.end()) {
|
||||
log_info("Cell %s not found\n", net.c_str(ctx));
|
||||
continue;
|
||||
}
|
||||
switch (cst_type) {
|
||||
case adc: { // USE_ADC_SRC bus# IOLOC
|
||||
int col = std::stoi(match[3]);
|
||||
int row = 1; // Top
|
||||
std::string side = match[2].str();
|
||||
if (side == "R") {
|
||||
row = col;
|
||||
col = ctx->getGridDimX();
|
||||
} else if (side == "B") {
|
||||
row = ctx->getGridDimY();
|
||||
} else if (side == "L") {
|
||||
row = col;
|
||||
col = 1;
|
||||
}
|
||||
adc_ios.insert(ctx->idf("%d/X%dY%d", std::stoi(match[1]), row - 1, col - 1));
|
||||
} break;
|
||||
case clock: { // CLOCK name BUFG|S=#
|
||||
std::string which_clock = match[2];
|
||||
std::string lw = match[4];
|
||||
|
|
@ -258,6 +280,25 @@ struct GowinCstReader
|
|||
for (auto &cell : constrained_cells) {
|
||||
log_info("Cell %s is constrained to %s\n", cell.first.c_str(ctx), cell.second.str(ctx).c_str());
|
||||
}
|
||||
if (!adc_ios.empty()) {
|
||||
log_info("ADC iobufs:\n");
|
||||
for (auto &bus_io : adc_ios) {
|
||||
log_info(" bus %s\n", bus_io.c_str(ctx));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!adc_ios.empty()) {
|
||||
for (auto &cell : ctx->cells) {
|
||||
auto &ci = *cell.second;
|
||||
|
||||
if (is_adc(&ci)) {
|
||||
int idx = 0;
|
||||
for (auto &bus_io : adc_ios) {
|
||||
ci.setAttr(ctx->idf("ADC_IO_%d", idx), bus_io.str(ctx));
|
||||
++idx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} catch (log_execution_error_exception) {
|
||||
|
|
|
|||
|
|
@ -179,7 +179,7 @@ void GowinImpl::init(Context *ctx)
|
|||
|
||||
gwu.init(ctx);
|
||||
|
||||
const ArchArgs &args = ctx->getArchArgs();
|
||||
const ArchArgs &args = ctx->args;
|
||||
|
||||
// package and speed class
|
||||
std::regex speedre = std::regex("(.*)(C[0-9]/I[0-9])$");
|
||||
|
|
|
|||
|
|
@ -100,6 +100,10 @@ inline bool is_userflash(const CellInfo *cell) { return type_is_userflash(cell->
|
|||
inline bool type_is_pll(IdString cell_type) { return cell_type.in(id_rPLL, id_PLLVR); }
|
||||
inline bool is_pll(const CellInfo *cell) { return type_is_pll(cell->type); }
|
||||
|
||||
// Return true if a cell is a ADC
|
||||
inline bool type_is_adc(IdString cell_type) { return cell_type.in(id_ADC); }
|
||||
inline bool is_adc(const CellInfo *cell) { return type_is_adc(cell->type); }
|
||||
|
||||
// Return true if a cell is a EMCU
|
||||
inline bool type_is_emcu(IdString cell_type) { return cell_type == id_EMCU; }
|
||||
inline bool is_emcu(const CellInfo *cell) { return type_is_emcu(cell->type); }
|
||||
|
|
@ -254,6 +258,8 @@ enum
|
|||
|
||||
PINCFG_Z = 400,
|
||||
|
||||
ADC_Z = 401,
|
||||
|
||||
// The two least significant bits encode Z for 9-bit adders and
|
||||
// multipliers, if they are equal to 0, then we get Z of their common
|
||||
// 18-bit equivalent.
|
||||
|
|
|
|||
|
|
@ -75,7 +75,8 @@ MIPIIBUF_Z = 302
|
|||
|
||||
DLLDLY_Z = 303 # : 305 reserve for 2 DLLDLYs
|
||||
|
||||
PINCFG_Z = 400 #
|
||||
PINCFG_Z = 400
|
||||
ADC_Z = 401
|
||||
|
||||
DSP_Z = 509
|
||||
|
||||
|
|
@ -463,7 +464,7 @@ def create_nodes(chip: Chip, db: chipdb):
|
|||
for i in range(5):
|
||||
nodes.append([NodeWire(x, y, f'COUT{i}'),
|
||||
NodeWire(x, y, f'CIN{i + 1}')]);
|
||||
# gobal carry chain
|
||||
# global carry chain
|
||||
if x > 1 and chip.tile_type_at(x - 1, y).extra_data.tile_class == chip.strs.id('LOGIC'):
|
||||
nodes.append([NodeWire(x, y, f'CIN0'),
|
||||
NodeWire(x - 1, y, f'COUT5')])
|
||||
|
|
@ -788,6 +789,17 @@ def create_extra_funcs(tt: TileType, db: chipdb, x: int, y: int):
|
|||
for pin, wire in desc['inputs'].items():
|
||||
tt.create_wire(wire, "PLL_I")
|
||||
tt.add_bel_pin(pll, pin, wire, PinType.INPUT)
|
||||
elif func == 'adc':
|
||||
pll = tt.create_bel("ADC", "ADC", z = ADC_Z)
|
||||
for pin, wire in desc['outputs'].items():
|
||||
tt.create_wire(wire, "ADC_O")
|
||||
tt.add_bel_pin(pll, pin, wire, PinType.OUTPUT)
|
||||
for pin, wire in desc['inputs'].items():
|
||||
if pin == 'CLK' or pin == 'MDRP_CLK':
|
||||
tt.create_wire(wire, "TILE_CLK")
|
||||
else:
|
||||
tt.create_wire(wire, "ADC_I")
|
||||
tt.add_bel_pin(pll, pin, wire, PinType.INPUT)
|
||||
elif func == 'gnd_source':
|
||||
# GND is the logic low level generator
|
||||
tt.create_wire('VSS', 'GND', const_value = 'VSS')
|
||||
|
|
|
|||
|
|
@ -2696,7 +2696,7 @@ struct GowinPacker
|
|||
divide_sdp(ci, new_cells);
|
||||
} else {
|
||||
log_error("The fix for SDP when ports A and B have different bit widths has not yet been implemented. "
|
||||
"Cell'%s'\n",
|
||||
"Cell: '%s'\n",
|
||||
ci->type.c_str(ctx));
|
||||
}
|
||||
}
|
||||
|
|
@ -3934,7 +3934,7 @@ struct GowinPacker
|
|||
pincfg_cell->connectPort(port, ctx->nets.at(ctx->id("$PACKER_VCC")).get());
|
||||
}
|
||||
|
||||
const ArchArgs &args = ctx->getArchArgs();
|
||||
const ArchArgs &args = ctx->args;
|
||||
|
||||
pincfg_cell->addInput(id_SSPI);
|
||||
if (args.options.count("sspi_as_gpio")) {
|
||||
|
|
@ -4073,6 +4073,34 @@ struct GowinPacker
|
|||
}
|
||||
}
|
||||
|
||||
// ===================================
|
||||
// ADC
|
||||
// ===================================
|
||||
void pack_adc(void)
|
||||
{
|
||||
log_info("Pack ADC...\n");
|
||||
|
||||
for (auto &cell : ctx->cells) {
|
||||
auto &ci = *cell.second;
|
||||
|
||||
if (is_adc(&ci)) {
|
||||
for (int i = 0; i < 14; ++i) {
|
||||
if (i < 2) {
|
||||
ci.renamePort(ctx->idf("MDRP_OPCODE[%d]", i), ctx->idf("MDRP_OPCODE%d", i));
|
||||
}
|
||||
if (i < 3) {
|
||||
ci.renamePort(ctx->idf("VSENCTL[%d]", i), ctx->idf("VSENCTL%d", i));
|
||||
}
|
||||
if (i < 8) {
|
||||
ci.renamePort(ctx->idf("MDRP_WDATA[%d]", i), ctx->idf("MDRP_WDATA%d", i));
|
||||
ci.renamePort(ctx->idf("MDRP_RDATA[%d]", i), ctx->idf("MDRP_RDATA%d", i));
|
||||
}
|
||||
ci.renamePort(ctx->idf("ADCVALUE[%d]", i), ctx->idf("ADCVALUE%d", i));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ===================================
|
||||
// HCLK -- CLKDIV and CLKDIV2 for now
|
||||
// ===================================
|
||||
|
|
@ -4557,6 +4585,9 @@ struct GowinPacker
|
|||
pack_pll();
|
||||
ctx->check();
|
||||
|
||||
pack_adc();
|
||||
ctx->check();
|
||||
|
||||
pack_bsram();
|
||||
ctx->check();
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue