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/>