Merge pull request #859 from yrabbit/gowin-packages

gowin: Add partnumbers and packages to the chipdb
This commit is contained in:
gatecat 2021-11-07 08:12:12 +00:00 committed by GitHub
commit b7207b0885
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 53 additions and 17 deletions

View File

@ -65,4 +65,4 @@ RUN set -e -x ;\
PATH=$PATH:$HOME/.cargo/bin cargo install --path prjoxide PATH=$PATH:$HOME/.cargo/bin cargo install --path prjoxide
RUN set -e -x ;\ RUN set -e -x ;\
pip3 install apycula==0.0.1a9 pip3 install apycula==0.0.1a12

View File

@ -670,13 +670,16 @@ void Arch::addMuxBels(const DatabasePOD *db, int row, int col)
Arch::Arch(ArchArgs args) : args(args) Arch::Arch(ArchArgs args) : args(args)
{ {
family = args.family; family = args.family;
device = args.device;
// Load database // Load database
std::string chipdb = stringf("gowin/chipdb-%s.bin", family.c_str()); std::string chipdb = stringf("gowin/chipdb-%s.bin", family.c_str());
auto db = reinterpret_cast<const DatabasePOD *>(get_chipdb(chipdb)); auto db = reinterpret_cast<const DatabasePOD *>(get_chipdb(chipdb));
if (db == nullptr) if (db == nullptr) {
log_error("Failed to load chipdb '%s'\n", chipdb.c_str()); log_error("Failed to load chipdb '%s'\n", chipdb.c_str());
}
if (db->version != chipdb_version) {
log_error("Incorrect chipdb version %u is used. Version %u is required\n", db->version, chipdb_version);
}
if (db->family.get() != family) { if (db->family.get() != family) {
log_error("Database is for family '%s' but provided device is family '%s'.\n", db->family.get(), log_error("Database is for family '%s' but provided device is family '%s'.\n", db->family.get(),
family.c_str()); family.c_str());
@ -685,37 +688,58 @@ Arch::Arch(ArchArgs args) : args(args)
for (size_t i = 0; i < db->num_ids; i++) { for (size_t i = 0; i < db->num_ids; i++) {
IdString::initialize_add(this, db->id_strs[i].get(), uint32_t(i) + db->num_constids); IdString::initialize_add(this, db->id_strs[i].get(), uint32_t(i) + db->num_constids);
} }
// setup package
IdString package_name;
IdString device_id;
IdString speed_id;
for (unsigned int i = 0; i < db->num_partnumbers; i++) {
auto partnumber = &db->partnumber_packages[i];
// std::cout << IdString(partnumber->name_id).str(this) << IdString(partnumber->package_id).str(this) <<
// std::endl;
if (IdString(partnumber->name_id) == id(args.partnumber)) {
package_name = IdString(partnumber->package_id);
device_id = IdString(partnumber->device_id);
speed_id = IdString(partnumber->speed_id);
break;
}
}
if (package_name == IdString()) {
log_error("Unsuported partnumber '%s'.\n", args.partnumber.c_str());
}
// setup timing info // setup timing info
speed = nullptr; speed = nullptr;
for (unsigned int i = 0; i < db->num_speeds; i++) { for (unsigned int i = 0; i < db->num_speeds; i++) {
const TimingClassPOD *tc = &db->speeds[i]; const TimingClassPOD *tc = &db->speeds[i];
// std::cout << IdString(tc->name_id).str(this) << std::endl; // std::cout << IdString(tc->name_id).str(this) << std::endl;
if (IdString(tc->name_id) == id(args.speed)) { if (IdString(tc->name_id) == speed_id) {
speed = tc->groups.get(); speed = tc->groups.get();
break; break;
} }
} }
if (speed == nullptr) { if (speed == nullptr) {
log_error("Unsuported speed grade '%s'.\n", args.speed.c_str()); log_error("Unsuported speed grade '%s'.\n", speed_id.c_str(this));
} }
const VariantPOD *variant = nullptr; const VariantPOD *variant = nullptr;
for (unsigned int i = 0; i < db->num_variants; i++) { for (unsigned int i = 0; i < db->num_variants; i++) {
auto var = &db->variants[i]; auto var = &db->variants[i];
// std::cout << IdString(var->name_id).str(this) << std::endl; // std::cout << IdString(var->name_id).str(this) << std::endl;
if (IdString(var->name_id) == id(args.device)) { if (IdString(var->name_id) == device_id) {
variant = var; variant = var;
break; break;
} }
} }
if (variant == nullptr) { if (variant == nullptr) {
log_error("Unsuported device grade '%s'.\n", args.device.c_str()); log_error("Unsuported device grade '%s'.\n", device_id.c_str(this));
} }
package = nullptr; package = nullptr;
for (unsigned int i = 0; i < variant->num_packages; i++) { for (unsigned int i = 0; i < variant->num_packages; i++) {
auto pkg = &variant->packages[i]; auto pkg = &variant->packages[i];
// std::cout << IdString(pkg->name_id).str(this) << std::endl; // std::cout << IdString(pkg->name_id).str(this) << std::endl;
if (IdString(pkg->name_id) == id(args.package)) { if (IdString(pkg->name_id) == package_name) {
package = pkg; package = pkg;
break; break;
} }
@ -724,9 +748,15 @@ Arch::Arch(ArchArgs args) : args(args)
// std::cout << IdString(pin.src_id).str(this) << " " << IdString(pin.dest_id).str(this) << std::endl; // std::cout << IdString(pin.src_id).str(this) << " " << IdString(pin.dest_id).str(this) << std::endl;
// } // }
} }
if (package == nullptr) { if (package == nullptr) {
log_error("Unsuported package '%s'.\n", args.package.c_str()); log_error("Unsuported package '%s'.\n", package_name.c_str(this));
} }
//
log_info("Series:%s Device:%s Package:%s Speed:%s\n", family.c_str(), device_id.c_str(this),
package_name.c_str(this), speed_id.c_str(this));
// setup db // setup db
char buf[32]; char buf[32];
// The reverse order of the enumeration simplifies the creation // The reverse order of the enumeration simplifies the creation

View File

@ -131,6 +131,13 @@ NPNR_PACKED_STRUCT(struct TimingClassPOD {
RelPtr<TimingGroupsPOD> groups; RelPtr<TimingGroupsPOD> groups;
}); });
NPNR_PACKED_STRUCT(struct PartnumberPOD {
uint32_t name_id;
uint32_t package_id;
uint32_t device_id;
uint32_t speed_id;
});
NPNR_PACKED_STRUCT(struct PackagePOD { NPNR_PACKED_STRUCT(struct PackagePOD {
uint32_t name_id; uint32_t name_id;
uint32_t num_pins; uint32_t num_pins;
@ -153,6 +160,8 @@ NPNR_PACKED_STRUCT(struct DatabasePOD {
RelPtr<GlobalAliasPOD> aliases; RelPtr<GlobalAliasPOD> aliases;
uint32_t num_speeds; uint32_t num_speeds;
RelPtr<TimingClassPOD> speeds; RelPtr<TimingClassPOD> speeds;
uint32_t num_partnumbers;
RelPtr<PartnumberPOD> partnumber_packages;
uint32_t num_variants; uint32_t num_variants;
RelPtr<VariantPOD> variants; RelPtr<VariantPOD> variants;
uint16_t num_constids; uint16_t num_constids;
@ -162,10 +171,8 @@ NPNR_PACKED_STRUCT(struct DatabasePOD {
struct ArchArgs struct ArchArgs
{ {
std::string device;
std::string family; std::string family;
std::string speed; std::string partnumber;
std::string package;
// y = mx + c relationship between distance and delay for interconnect // y = mx + c relationship between distance and delay for interconnect
// delay estimates // delay estimates
double delayScale = 0.4, delayOffset = 0.4; double delayScale = 0.4, delayOffset = 0.4;
@ -447,6 +454,8 @@ struct Arch : BaseArch<ArchRanges>
bool cellsCompatible(const CellInfo **cells, int count) const; bool cellsCompatible(const CellInfo **cells, int count) const;
// start Z for the MUX2LUT5 bels // start Z for the MUX2LUT5 bels
int const mux_0_z = 10; int const mux_0_z = 10;
// chip db version
unsigned int const chipdb_version = 1;
std::vector<IdString> cell_types; std::vector<IdString> cell_types;

View File

@ -54,7 +54,7 @@ po::options_description GowinCommandHandler::getArchOptions()
std::unique_ptr<Context> GowinCommandHandler::createContext(dict<std::string, Property> &values) std::unique_ptr<Context> GowinCommandHandler::createContext(dict<std::string, Property> &values)
{ {
std::regex devicere = std::regex("GW1N([A-Z]*)-(LV|UV|UX)([0-9])(C?)([A-Z]{2}[0-9]+)(C[0-9]/I[0-9])"); std::regex devicere = std::regex("GW1N([A-Z]*)-(LV|UV|UX)([0-9])(C?).*");
std::smatch match; std::smatch match;
std::string device = vm["device"].as<std::string>(); std::string device = vm["device"].as<std::string>();
if (!std::regex_match(device, match, devicere)) { if (!std::regex_match(device, match, devicere)) {
@ -62,8 +62,6 @@ std::unique_ptr<Context> GowinCommandHandler::createContext(dict<std::string, Pr
} }
ArchArgs chipArgs; ArchArgs chipArgs;
char buf[36]; char buf[36];
snprintf(buf, 36, "GW1N%s-%s%s", match[1].str().c_str(), match[3].str().c_str(), match[4].str().c_str());
chipArgs.device = buf;
// GW1N and GW1NR variants share the same database. // GW1N and GW1NR variants share the same database.
// Most Gowin devices are a System in Package with some SDRAM wirebonded to a GPIO bank. // Most Gowin devices are a System in Package with some SDRAM wirebonded to a GPIO bank.
// However, it appears that the S series with embedded ARM core are unique silicon. // However, it appears that the S series with embedded ARM core are unique silicon.
@ -73,8 +71,7 @@ std::unique_ptr<Context> GowinCommandHandler::createContext(dict<std::string, Pr
snprintf(buf, 36, "GW1N-%s", match[3].str().c_str()); snprintf(buf, 36, "GW1N-%s", match[3].str().c_str());
} }
chipArgs.family = buf; chipArgs.family = buf;
chipArgs.package = match[5]; chipArgs.partnumber = match[0];
chipArgs.speed = match[6];
return std::unique_ptr<Context>(new Context(chipArgs)); return std::unique_ptr<Context>(new Context(chipArgs));
} }