Merge remote-tracking branch 'origin' into facade
diff --git a/.gitmodules b/.gitmodules index d01ee12..7d0eaf4 100644 --- a/.gitmodules +++ b/.gitmodules
@@ -1,4 +1,4 @@ [submodule "database"] path = database - url = https://github.com/cr1901/prjtrellis-db.git + url = https://github.com/cr1901/prjtrellis-db.git branch = facade
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 610dd92..197c404 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md
@@ -21,59 +21,6 @@ follow the open source best practice of using the [Contributor Covenant](https://www.contributor-covenant.org/) for our Code of Conduct. -### Sign your work - -To improve tracking of who did what, we follow the Linux Kernel's -["sign your work" system](https://github.com/wking/signed-off-by). -This is also called a -["DCO" or "Developer's Certificate of Origin"](https://developercertificate.org/). - -**All** commits are required to include this sign off and we use the -[Probot DCO App](https://github.com/probot/dco) to check pull requests for -this. - -The sign-off is a simple line at the end of the explanation for the -patch, which certifies that you wrote it or otherwise have the right to -pass it on as a open-source patch. The rules are pretty simple: if you -can certify the below: - - Developer's Certificate of Origin 1.1 - - By making a contribution to this project, I certify that: - - (a) The contribution was created in whole or in part by me and I - have the right to submit it under the open source license - indicated in the file; or - - (b) The contribution is based upon previous work that, to the best - of my knowledge, is covered under an appropriate open source - license and I have the right under that license to submit that - work with modifications, whether created in whole or in part - by me, under the same open source license (unless I am - permitted to submit under a different license), as indicated - in the file; or - - (c) The contribution was provided directly to me by some other - person who certified (a), (b) or (c) and I have not modified - it. - - (d) I understand and agree that this project and the contribution - are public and that a record of the contribution (including all - personal information I submit with it, including my sign-off) is - maintained indefinitely and may be redistributed consistent with - this project or the open source license(s) involved. - -then you just add a line saying - - Signed-off-by: Random J Developer <random@developer.example.org> - -using your real name (sorry, no pseudonyms or anonymous contributions.) - - - - - - ---- This file is generated from [README.md](README.md), please edit that file then
diff --git a/README.md b/README.md index a3c7c62..cce4822 100644 --- a/README.md +++ b/README.md
@@ -18,7 +18,7 @@ Clone the Project Trellis repository and download the latest database: - git clone --recursive https://github.com/SymbiFlow/prjtrellis + git clone --recursive https://github.com/YosysHQ/prjtrellis Install _libtrellis_ and associated tools. You _must_ run `cmake` from the libtrellis directory. Out-of-tree builds are currently unsupported when coupled with `nextpnr`: @@ -60,8 +60,8 @@ ## For Developers Project Trellis documents the Lattice ECP5 bit-stream format and internal architecture. Current documentation is -located in machine-readable format in [prjtrellis-db](https://github.com/SymbiFlow/prjtrellis-db) -and is also [published online as HTML](https://symbiflow.github.io/prjtrellis-db/). +located in machine-readable format in [prjtrellis-db](https://github.com/YosysHQ/prjtrellis-db) +and is also [published online as HTML](https://yosyshq.github.io/prjtrellis-db/). This repository contains both tools and scripts which allow you to document the bit-stream format of Lattice ECP5 series FPGAs. @@ -148,7 +148,7 @@ ### Database Instead of downloading the -[compiled part database](https://github.com/SymbiFlow/prjtrellis-db), +[compiled part database](https://github.com/YosysHQ/prjtrellis-db), it can also be created from scratch. However, this procedure takes several hours, even on a decent workstation. First, the empty reference bitstreams and the tile layout must be created
diff --git a/libtrellis/CMakeLists.txt b/libtrellis/CMakeLists.txt index c6ab645..a904497 100644 --- a/libtrellis/CMakeLists.txt +++ b/libtrellis/CMakeLists.txt
@@ -29,7 +29,24 @@ set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON) endif() endif() -set(boost_libs filesystem thread program_options system) +if (WASI) + set(USE_THREADS OFF) + add_definitions( + -DBOOST_EXCEPTION_DISABLE + -DBOOST_NO_EXCEPTIONS + -DBOOST_SP_NO_ATOMIC_ACCESS + -DBOOST_AC_DISABLE_THREADS + -DBOOST_NO_CXX11_HDR_MUTEX + ) +else() + set(USE_THREADS ON) +endif() +set(boost_libs filesystem program_options system) +if (USE_THREADS) + list(APPEND boost_libs thread) +else() + add_definitions(-DNO_THREADS) +endif() set(Boost_NO_BOOST_CMAKE ON) find_package(PythonInterp 3.5 REQUIRED) @@ -180,6 +197,13 @@ target_link_libraries(${PROGRAM_PREFIX}ecpmulti trellis ${Boost_LIBRARIES} ${CMAKE_DL_LIBS} ${link_param}) setup_rpath(${PROGRAM_PREFIX}ecpmulti) +if (WASI) + foreach (tool ecpbram ecppack ecpunpack ecppll ecpmulti) + # set(CMAKE_EXECUTABLE_SUFFIX) breaks CMake tests for some reason + set_property(TARGET ${PROGRAM_PREFIX}${tool} PROPERTY SUFFIX ".wasm") + endforeach() +endif() + if (BUILD_SHARED) install(TARGETS trellis ${PROGRAM_PREFIX}ecpbram ${PROGRAM_PREFIX}ecppack ${PROGRAM_PREFIX}ecppll ${PROGRAM_PREFIX}ecpunpack ${PROGRAM_PREFIX}ecpmulti ${PythonInstallTarget} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/${PROGRAM_PREFIX}trellis
diff --git a/libtrellis/include/BitDatabase.hpp b/libtrellis/include/BitDatabase.hpp index 6708ac6..26c88ca 100644 --- a/libtrellis/include/BitDatabase.hpp +++ b/libtrellis/include/BitDatabase.hpp
@@ -7,8 +7,10 @@ #include <cstdint> #include <boost/optional.hpp> #include <mutex> +#ifndef NO_THREADS #include <boost/thread/shared_mutex.hpp> #include <atomic> +#endif #include <set> #include <unordered_set> #include "Util.hpp" @@ -331,8 +333,12 @@ private: explicit TileBitDatabase(const string &filename); +#ifdef NO_THREADS + bool dirty = false; +#else mutable boost::shared_mutex db_mutex; atomic<bool> dirty{false}; +#endif map<string, MuxBits> muxes; map<string, WordSettingBits> words; map<string, EnumSettingBits> enums;
diff --git a/libtrellis/include/DatabasePath.hpp b/libtrellis/include/DatabasePath.hpp index cab8a29..288f670 100644 --- a/libtrellis/include/DatabasePath.hpp +++ b/libtrellis/include/DatabasePath.hpp
@@ -6,6 +6,15 @@ #if BOOST_VERSION >= 106100 +#if defined(__wasm) + +std::string get_database_path() +{ + return "/share/trellis/database"; +} + +#else + #include <boost/dll/runtime_symbol_info.hpp> std::string get_database_path() @@ -16,6 +25,8 @@ return database_folder; } +#endif + #else /*
diff --git a/libtrellis/src/Bels.cpp b/libtrellis/src/Bels.cpp index 40c03e4..61b9dff 100644 --- a/libtrellis/src/Bels.cpp +++ b/libtrellis/src/Bels.cpp
@@ -261,6 +261,7 @@ bel.type = graph.ident("EHXPLLL"); bel.loc.x = x; bel.loc.y = y; + bel.z = 0; auto add_input = [&](const std::string &pin) { graph.add_bel_input(bel, graph.ident(pin), x, y, graph.ident(fmt("J" << pin << "_PLL"))); }; @@ -508,7 +509,7 @@ add_output("DTROUT" + std::to_string(i)); } else if (name == "USRMCLK") { postfix = "CCLK"; - bel.z = 0; + bel.z = 1; add_input("PADDO"); add_input("PADDT"); add_output("PADDI");
diff --git a/libtrellis/src/BitDatabase.cpp b/libtrellis/src/BitDatabase.cpp index 9cf5ad3..5a571c8 100644 --- a/libtrellis/src/BitDatabase.cpp +++ b/libtrellis/src/BitDatabase.cpp
@@ -6,8 +6,10 @@ #include <algorithm> #include <fstream> +#ifndef NO_THREADS #include <boost/thread/shared_lock_guard.hpp> #include <boost/thread/lock_guard.hpp> +#endif #include <boost/range/algorithm/copy.hpp> #include <boost/range/adaptors.hpp> @@ -335,7 +337,9 @@ void TileBitDatabase::config_to_tile_cram(const TileConfig &cfg, CRAMView &tile, bool is_tilegroup, set<string> *tg_matches) const { +#ifndef NO_THREADS boost::shared_lock_guard<boost::shared_mutex> guard(db_mutex); +#endif for (auto arc : cfg.carcs) muxes.at(arc.sink).set_driver(tile, arc.source); set<string> found_words, found_enums; @@ -397,7 +401,9 @@ TileConfig TileBitDatabase::tile_cram_to_config(const CRAMView &tile) const { +#ifndef NO_THREADS boost::shared_lock_guard<boost::shared_mutex> guard(db_mutex); +#endif TileConfig cfg; BitSet coverage; for (auto mux : muxes) { @@ -431,7 +437,9 @@ void TileBitDatabase::load() { +#ifndef NO_THREADS boost::lock_guard<boost::shared_mutex> guard(db_mutex); +#endif ifstream in(filename); if (!in) { throw runtime_error("failed to open tilebit database file " + filename); @@ -466,7 +474,9 @@ void TileBitDatabase::save() { +#ifndef NO_THREADS boost::lock_guard<boost::shared_mutex> guard(db_mutex); +#endif ofstream out(filename); if (!out) { throw runtime_error("failed to open tilebit database file " + filename + " for writing"); @@ -488,7 +498,9 @@ vector<string> TileBitDatabase::get_sinks() const { +#ifndef NO_THREADS boost::shared_lock_guard<boost::shared_mutex> guard(db_mutex); +#endif vector<string> result; boost::copy(muxes | boost::adaptors::map_keys, back_inserter(result)); return result; @@ -496,13 +508,17 @@ MuxBits TileBitDatabase::get_mux_data_for_sink(const string &sink) const { +#ifndef NO_THREADS boost::shared_lock_guard<boost::shared_mutex> guard(db_mutex); +#endif return muxes.at(sink); } vector<string> TileBitDatabase::get_settings_words() const { +#ifndef NO_THREADS boost::shared_lock_guard<boost::shared_mutex> guard(db_mutex); +#endif vector<string> result; boost::copy(words | boost::adaptors::map_keys, back_inserter(result)); return result; @@ -510,13 +526,17 @@ WordSettingBits TileBitDatabase::get_data_for_setword(const string &name) const { +#ifndef NO_THREADS boost::shared_lock_guard<boost::shared_mutex> guard(db_mutex); +#endif return words.at(name); } vector<string> TileBitDatabase::get_settings_enums() const { +#ifndef NO_THREADS boost::shared_lock_guard<boost::shared_mutex> guard(db_mutex); +#endif vector<string> result; boost::copy(enums | boost::adaptors::map_keys, back_inserter(result)); return result; @@ -524,13 +544,17 @@ EnumSettingBits TileBitDatabase::get_data_for_enum(const string &name) const { +#ifndef NO_THREADS boost::shared_lock_guard<boost::shared_mutex> guard(db_mutex); +#endif return enums.at(name); } vector<FixedConnection> TileBitDatabase::get_fixed_conns() const { +#ifndef NO_THREADS boost::shared_lock_guard<boost::shared_mutex> guard(db_mutex); +#endif vector<FixedConnection> result; for (const auto &csink : fixed_conns) { for (const auto &conn : csink.second) { @@ -560,7 +584,9 @@ void TileBitDatabase::add_routing(const TileInfo &tile, RoutingGraph &graph) const { +#ifndef NO_THREADS boost::shared_lock_guard<boost::shared_mutex> guard(db_mutex); +#endif int row, col; tie(row, col) = tile.get_row_col(); Location loc(col, row); @@ -603,7 +629,9 @@ void TileBitDatabase::add_mux_arc(const ArcData &arc) { +#ifndef NO_THREADS boost::lock_guard<boost::shared_mutex> guard(db_mutex); +#endif dirty = true; if (muxes.find(arc.sink) == muxes.end()) { MuxBits mux; @@ -630,7 +658,9 @@ void TileBitDatabase::add_setting_word(const WordSettingBits &wsb) { +#ifndef NO_THREADS boost::lock_guard<boost::shared_mutex> guard(db_mutex); +#endif dirty = true; if (words.find(wsb.name) != words.end()) { WordSettingBits &curr = words.at(wsb.name); @@ -653,7 +683,9 @@ void TileBitDatabase::add_setting_enum(const EnumSettingBits &esb) { +#ifndef NO_THREADS boost::lock_guard<boost::shared_mutex> guard(db_mutex); +#endif dirty = true; if (enums.find(esb.name) != enums.end()) { EnumSettingBits &curr = enums.at(esb.name); @@ -677,7 +709,9 @@ void TileBitDatabase::add_fixed_conn(const Trellis::FixedConnection &conn) { +#ifndef NO_THREADS boost::lock_guard<boost::shared_mutex> guard(db_mutex); +#endif fixed_conns[conn.sink].insert(conn); dirty = true; } @@ -691,19 +725,25 @@ void TileBitDatabase::remove_fixed_sink(const string &sink) { +#ifndef NO_THREADS boost::lock_guard<boost::shared_mutex> guard(db_mutex); +#endif fixed_conns.erase(sink); } void TileBitDatabase::remove_setting_enum(const string &enum_name) { +#ifndef NO_THREADS boost::lock_guard<boost::shared_mutex> guard(db_mutex); +#endif enums.erase(enum_name); } void TileBitDatabase::remove_setting_word(const string &word_name) { +#ifndef NO_THREADS boost::lock_guard<boost::shared_mutex> guard(db_mutex); +#endif words.erase(word_name); }
diff --git a/libtrellis/src/Database.cpp b/libtrellis/src/Database.cpp index e4ac515..5f70c08 100644 --- a/libtrellis/src/Database.cpp +++ b/libtrellis/src/Database.cpp
@@ -19,7 +19,9 @@ // Cache Tilegrid data, to save time parsing it again static map<string, pt::ptree> tilegrid_cache; +#ifndef NO_THREADS static mutex tilegrid_cache_mutex; +#endif void load_database(string root) { db_root = root; @@ -201,7 +203,9 @@ string tilegrid_path = db_root + "/" + part.family + "/" + part.device + "/tilegrid.json"; { ChipInfo info = get_chip_info(part); +#ifndef NO_THREADS lock_guard <mutex> lock(tilegrid_cache_mutex); +#endif if (tilegrid_cache.find(part.device) == tilegrid_cache.end()) { pt::ptree tg_parsed; pt::read_json(tilegrid_path, tg_parsed); @@ -237,10 +241,14 @@ } static unordered_map<TileLocator, shared_ptr<TileBitDatabase>> bitdb_store; +#ifndef NO_THREADS static mutex bitdb_store_mutex; +#endif shared_ptr<TileBitDatabase> get_tile_bitdata(const TileLocator &tile) { +#ifndef NO_THREADS lock_guard <mutex> bitdb_store_lg(bitdb_store_mutex); +#endif if (bitdb_store.find(tile) == bitdb_store.end()) { assert(!db_root.empty()); string bitdb_path = db_root + "/" + tile.family + "/tiledata/" + tile.tiletype + "/bits.db";
diff --git a/libtrellis/tools/ecpbram.cpp b/libtrellis/tools/ecpbram.cpp index a1bc205..7e424f1 100644 --- a/libtrellis/tools/ecpbram.cpp +++ b/libtrellis/tools/ecpbram.cpp
@@ -41,6 +41,7 @@ #include "Chip.hpp" #include "Database.hpp" #include "DatabasePath.hpp" +#include "wasmexcept.hpp" using std::map; using std::pair; @@ -124,11 +125,6 @@ int main(int argc, char **argv) { bool verbose = false; -#ifdef _WIN32 - uint32_t seed_nr = GetCurrentProcessId(); -#else - uint32_t seed_nr = getpid(); -#endif namespace po = boost::program_options; std::string database_folder = get_database_path();; @@ -197,14 +193,26 @@ return 1; } + // If -s is provided: seed with the given value. + // If -s is not provided: seed with the PID and current time, which are unlikely + // to repeat simultaneously. + uint32_t seed_nr; if (vm.count("seed")) { seed_nr = vm.at("seed").as<int>(); if (verbose) fprintf(stderr, "Seed: %d\n", seed_nr); + } else { +#if defined(__wasm) + seed_nr = 0; +#elif defined(_WIN32) + seed_nr = GetCurrentProcessId(); +#else + seed_nr = getpid(); +#endif } - x = uint64_t(seed_nr) << 32; + x = uint64_t(seed_nr) << 32; x ^= uint64_t(seed_nr) << 20; x ^= uint64_t(seed_nr);
diff --git a/libtrellis/tools/ecpmulti.cpp b/libtrellis/tools/ecpmulti.cpp index 83232e1..20ddaec 100644 --- a/libtrellis/tools/ecpmulti.cpp +++ b/libtrellis/tools/ecpmulti.cpp
@@ -6,6 +6,7 @@ #include "DatabasePath.hpp" #include "Tile.hpp" #include "version.hpp" +#include "wasmexcept.hpp" #include <iostream> #include <boost/program_options.hpp> #include <stdexcept>
diff --git a/libtrellis/tools/ecppack.cpp b/libtrellis/tools/ecppack.cpp index d6aea40..6bf2895 100644 --- a/libtrellis/tools/ecppack.cpp +++ b/libtrellis/tools/ecppack.cpp
@@ -6,7 +6,7 @@ #include "Tile.hpp" #include "BitDatabase.hpp" #include "version.hpp" - +#include "wasmexcept.hpp" #include <iostream> #include <boost/program_options.hpp> #include <stdexcept>
diff --git a/libtrellis/tools/ecppll.cpp b/libtrellis/tools/ecppll.cpp index 13e6b26..a3e5b3c 100644 --- a/libtrellis/tools/ecppll.cpp +++ b/libtrellis/tools/ecppll.cpp
@@ -37,6 +37,7 @@ #include <string> #include <boost/program_options.hpp> #include "version.hpp" +#include "wasmexcept.hpp" using namespace std; enum class pll_mode{
diff --git a/libtrellis/tools/ecpunpack.cpp b/libtrellis/tools/ecpunpack.cpp index a5752a8..1029356 100644 --- a/libtrellis/tools/ecpunpack.cpp +++ b/libtrellis/tools/ecpunpack.cpp
@@ -4,6 +4,7 @@ #include "Database.hpp" #include "DatabasePath.hpp" #include "version.hpp" +#include "wasmexcept.hpp" #include <iostream> #include <boost/optional.hpp> #include <boost/program_options.hpp>
diff --git a/libtrellis/tools/wasmexcept.hpp b/libtrellis/tools/wasmexcept.hpp new file mode 100644 index 0000000..657d9dc --- /dev/null +++ b/libtrellis/tools/wasmexcept.hpp
@@ -0,0 +1,19 @@ +#if defined(__wasm) + +#include <cstdint> +#include <iostream> + +extern "C" { +// FIXME: WASI does not currently support exceptions. +void *__cxa_allocate_exception(size_t thrown_size) throw() { return malloc(thrown_size); } +bool __cxa_uncaught_exception() throw(); +void __cxa_throw(void *thrown_exception, struct std::type_info *tinfo, void (*dest)(void *)) { std::terminate(); } +} + +namespace boost { +void throw_exception(std::exception const &e) { + std::cerr << "boost::exception(): " << e.what() << std::endl; +} +} // namespace boost + +#endif
diff --git a/tools/html_all.py b/tools/html_all.py index 42edfcd..a796ee6 100755 --- a/tools/html_all.py +++ b/tools/html_all.py
@@ -28,8 +28,8 @@ <h1>Project Trellis HTML Documentation</h1> <p>Project Trellis is a project to document the ECP5 bitstream and internal architecture.</p> <p>This repository contains HTML documentation automatically generated from the -<a href="https://github.com/SymbiFlow/prjtrellis">Project Trellis</a> database. The equivalent -machine-readable data is located in <a href="https://github.com/SymbiFlow/prjtrellis-db">prjtrellis-db.<a/> +<a href="https://github.com/YosysHQ/prjtrellis">Project Trellis</a> database. The equivalent +machine-readable data is located in <a href="https://github.com/YosysHQ/prjtrellis-db">prjtrellis-db.<a/> Data generated includes tilemap data and bitstream data for many tile types. Click on any tile to see its bitstream documentation. </p> @@ -38,7 +38,7 @@ on the <a href="http://prjtrellis.readthedocs.io/en/latest/">Read the Docs</a> site.</p> <p>This HTML documentation was generated at ${datetime} from prjtrellis-db commit -<a href="https://github.com/SymbiFlow/prjtrellis-db/tree/${commit}">${commit}</a>.</p> +<a href="https://github.com/YosysHQ/prjtrellis-db/tree/${commit}">${commit}</a>.</p> <hr/> $docs_toc <hr/>