mirror of
https://github.com/YosysHQ/yosys
synced 2025-09-10 19:51:27 +00:00
Merge 9f0d5d1aca
into c2291c10a6
This commit is contained in:
commit
ba24743e10
7 changed files with 254 additions and 2 deletions
14
Makefile
14
Makefile
|
@ -44,7 +44,12 @@ LINK_ABC := 0
|
|||
# Needed for environments that can't run executables (i.e. emscripten, wasm)
|
||||
DISABLE_SPAWN := 0
|
||||
# Needed for environments that don't have proper thread support (i.e. emscripten, wasm--for now)
|
||||
ENABLE_THREADS := 1
|
||||
ifeq ($(ENABLE_THREADS),1)
|
||||
DISABLE_ABC_THREADS := 0
|
||||
else
|
||||
DISABLE_ABC_THREADS := 1
|
||||
endif
|
||||
|
||||
# clang sanitizers
|
||||
SANITIZER =
|
||||
|
@ -300,6 +305,7 @@ DISABLE_SPAWN := 1
|
|||
|
||||
ifeq ($(ENABLE_ABC),1)
|
||||
LINK_ABC := 1
|
||||
ENABLE_THREADS := 0
|
||||
DISABLE_ABC_THREADS := 1
|
||||
endif
|
||||
|
||||
|
@ -457,6 +463,11 @@ CXXFLAGS := -Og -DDEBUG $(filter-out $(OPT_LEVEL),$(CXXFLAGS))
|
|||
STRIP :=
|
||||
endif
|
||||
|
||||
ifeq ($(ENABLE_THREADS),1)
|
||||
CXXFLAGS += -DYOSYS_ENABLE_THREADS
|
||||
LIBS += -lpthread
|
||||
endif
|
||||
|
||||
ifeq ($(ENABLE_ABC),1)
|
||||
CXXFLAGS += -DYOSYS_ENABLE_ABC
|
||||
ifeq ($(LINK_ABC),1)
|
||||
|
@ -612,6 +623,7 @@ $(eval $(call add_include_file,kernel/satgen.h))
|
|||
$(eval $(call add_include_file,kernel/scopeinfo.h))
|
||||
$(eval $(call add_include_file,kernel/sexpr.h))
|
||||
$(eval $(call add_include_file,kernel/sigtools.h))
|
||||
$(eval $(call add_include_file,kernel/threading.h))
|
||||
$(eval $(call add_include_file,kernel/timinginfo.h))
|
||||
$(eval $(call add_include_file,kernel/utils.h))
|
||||
$(eval $(call add_include_file,kernel/yosys.h))
|
||||
|
@ -638,7 +650,7 @@ OBJS += kernel/log_compat.o
|
|||
endif
|
||||
OBJS += kernel/binding.o kernel/tclapi.o
|
||||
OBJS += kernel/cellaigs.o kernel/celledges.o kernel/cost.o kernel/satgen.o kernel/scopeinfo.o kernel/qcsat.o kernel/mem.o kernel/ffmerge.o kernel/ff.o kernel/yw.o kernel/json.o kernel/fmt.o kernel/sexpr.o
|
||||
OBJS += kernel/drivertools.o kernel/functional.o
|
||||
OBJS += kernel/drivertools.o kernel/functional.o kernel/threading.o
|
||||
ifeq ($(ENABLE_ZLIB),1)
|
||||
OBJS += kernel/fstdata.o
|
||||
endif
|
||||
|
|
|
@ -580,6 +580,13 @@ void log_dump_val_worker(RTLIL::State v) {
|
|||
log("%s", log_signal(v));
|
||||
}
|
||||
|
||||
std::string signal_str(const RTLIL::SigSpec &sig, bool autoint)
|
||||
{
|
||||
std::stringstream buf;
|
||||
RTLIL_BACKEND::dump_sigspec(buf, sig, autoint);
|
||||
return buf.str();
|
||||
}
|
||||
|
||||
const char *log_signal(const RTLIL::SigSpec &sig, bool autoint)
|
||||
{
|
||||
std::stringstream buf;
|
||||
|
|
|
@ -253,6 +253,7 @@ extern dict<std::string, LogExpectedItem> log_expect_log, log_expect_warning, lo
|
|||
extern dict<std::string, LogExpectedItem> log_expect_prefix_log, log_expect_prefix_warning, log_expect_prefix_error;
|
||||
void log_check_expected();
|
||||
|
||||
std::string signal_str(const RTLIL::SigSpec &sig, bool autoint = true);
|
||||
const char *log_signal(const RTLIL::SigSpec &sig, bool autoint = true);
|
||||
const char *log_const(const RTLIL::Const &value, bool autoint = true);
|
||||
const char *log_id(const RTLIL::IdString &id);
|
||||
|
|
45
kernel/threading.cc
Normal file
45
kernel/threading.cc
Normal file
|
@ -0,0 +1,45 @@
|
|||
#include "kernel/yosys_common.h"
|
||||
#include "kernel/threading.h"
|
||||
|
||||
YOSYS_NAMESPACE_BEGIN
|
||||
|
||||
void DeferredLogs::flush()
|
||||
{
|
||||
for (auto &m : logs)
|
||||
if (m.error)
|
||||
YOSYS_NAMESPACE_PREFIX log_error("%s", m.text.c_str());
|
||||
else
|
||||
YOSYS_NAMESPACE_PREFIX log("%s", m.text.c_str());
|
||||
}
|
||||
|
||||
int ThreadPool::pool_size(int reserved_cores, int max_threads)
|
||||
{
|
||||
#ifdef YOSYS_ENABLE_THREADS
|
||||
int num_threads = std::min<int>(std::thread::hardware_concurrency() - reserved_cores, max_threads);
|
||||
return std::max(0, num_threads);
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
ThreadPool::ThreadPool(int pool_size, std::function<void(int)> b)
|
||||
: body(std::move(b))
|
||||
{
|
||||
#ifdef YOSYS_ENABLE_THREADS
|
||||
threads.reserve(pool_size);
|
||||
for (int i = 0; i < pool_size; i++)
|
||||
threads.emplace_back([i, this]{ body(i); });
|
||||
#else
|
||||
log_assert(pool_size == 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
ThreadPool::~ThreadPool()
|
||||
{
|
||||
#ifdef YOSYS_ENABLE_THREADS
|
||||
for (auto &t : threads)
|
||||
t.join();
|
||||
#endif
|
||||
}
|
||||
|
||||
YOSYS_NAMESPACE_END
|
186
kernel/threading.h
Normal file
186
kernel/threading.h
Normal file
|
@ -0,0 +1,186 @@
|
|||
#include <deque>
|
||||
|
||||
#ifdef YOSYS_ENABLE_THREADS
|
||||
#include <condition_variable>
|
||||
#include <mutex>
|
||||
#include <thread>
|
||||
#endif
|
||||
|
||||
#include "kernel/yosys_common.h"
|
||||
#include "kernel/log.h"
|
||||
|
||||
#ifndef YOSYS_THREADING_H
|
||||
#define YOSYS_THREADING_H
|
||||
|
||||
YOSYS_NAMESPACE_BEGIN
|
||||
|
||||
// Concurrent queue implementation. Not fast, but simple.
|
||||
// Multi-producer, multi-consumer, optionally bounded.
|
||||
// When YOSYS_ENABLE_THREADS is not defined, this is just a non-thread-safe non-blocking deque.
|
||||
template <typename T>
|
||||
class ConcurrentQueue
|
||||
{
|
||||
public:
|
||||
ConcurrentQueue(int capacity = INT_MAX)
|
||||
: capacity(capacity) {}
|
||||
// Push an element into the queue. If it's at capacity, block until there is room.
|
||||
void push_back(T t)
|
||||
{
|
||||
#ifdef YOSYS_ENABLE_THREADS
|
||||
std::unique_lock<std::mutex> lock(mutex);
|
||||
not_full_condition.wait(lock, [this] { return static_cast<int>(contents.size()) < capacity; });
|
||||
if (contents.empty())
|
||||
not_empty_condition.notify_one();
|
||||
#endif
|
||||
log_assert(!closed);
|
||||
contents.push_back(std::move(t));
|
||||
#ifdef YOSYS_ENABLE_THREADS
|
||||
if (static_cast<int>(contents.size()) < capacity)
|
||||
not_full_condition.notify_one();
|
||||
#endif
|
||||
}
|
||||
// Signal that no more elements will be produced. `pop_front()` will return nullopt.
|
||||
void close()
|
||||
{
|
||||
#ifdef YOSYS_ENABLE_THREADS
|
||||
std::unique_lock<std::mutex> lock(mutex);
|
||||
not_empty_condition.notify_all();
|
||||
#endif
|
||||
closed = true;
|
||||
}
|
||||
// Pop an element from the queue. Blocks until an element is available
|
||||
// or the queue is closed and empty.
|
||||
std::optional<T> pop_front()
|
||||
{
|
||||
return pop_front_internal(true);
|
||||
}
|
||||
// Pop an element from the queue. Does not block, just returns nullopt if the
|
||||
// queue is empty.
|
||||
std::optional<T> try_pop_front()
|
||||
{
|
||||
return pop_front_internal(false);
|
||||
}
|
||||
private:
|
||||
#ifdef YOSYS_ENABLE_THREADS
|
||||
std::optional<T> pop_front_internal(bool wait)
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(mutex);
|
||||
if (wait) {
|
||||
not_empty_condition.wait(lock, [this] { return !contents.empty() || closed; });
|
||||
}
|
||||
#else
|
||||
std::optional<T> pop_front_internal(bool)
|
||||
{
|
||||
#endif
|
||||
if (contents.empty())
|
||||
return std::nullopt;
|
||||
#ifdef YOSYS_ENABLE_THREADS
|
||||
if (static_cast<int>(contents.size()) == capacity)
|
||||
not_full_condition.notify_one();
|
||||
#endif
|
||||
T result = std::move(contents.front());
|
||||
contents.pop_front();
|
||||
#ifdef YOSYS_ENABLE_THREADS
|
||||
if (!contents.empty())
|
||||
not_empty_condition.notify_one();
|
||||
#endif
|
||||
return std::move(result);
|
||||
}
|
||||
|
||||
#ifdef YOSYS_ENABLE_THREADS
|
||||
std::mutex mutex;
|
||||
// Signals one waiter thread when the queue changes and is not full.
|
||||
std::condition_variable not_full_condition;
|
||||
// Signals one waiter thread when the queue changes and is not empty.
|
||||
std::condition_variable not_empty_condition;
|
||||
#endif
|
||||
std::deque<T> contents;
|
||||
int capacity;
|
||||
bool closed = false;
|
||||
};
|
||||
|
||||
class DeferredLogs
|
||||
{
|
||||
public:
|
||||
template <typename... Args>
|
||||
void log(FmtString<TypeIdentity<Args>...> fmt, Args... args)
|
||||
{
|
||||
logs.push_back({fmt.format(args...), false});
|
||||
}
|
||||
template <typename... Args>
|
||||
void log_error(FmtString<TypeIdentity<Args>...> fmt, Args... args)
|
||||
{
|
||||
logs.push_back({fmt.format(args...), true});
|
||||
}
|
||||
void flush();
|
||||
private:
|
||||
struct Message
|
||||
{
|
||||
std::string text;
|
||||
bool error;
|
||||
};
|
||||
std::vector<Message> logs;
|
||||
};
|
||||
|
||||
class ThreadPool
|
||||
{
|
||||
public:
|
||||
// Computes the number of worker threads to use.
|
||||
// `reserved_cores` cores are set aside for other threads (e.g. work on the main thread).
|
||||
// `max_threads` --- don't return more workers than this.
|
||||
// The result may be 0.
|
||||
static int pool_size(int reserved_cores, int max_threads);
|
||||
|
||||
// Create a pool of threads running the given closure (parameterized by thread number).
|
||||
// `pool_size` must be the result of a `pool_size()` call.
|
||||
ThreadPool(int pool_size, std::function<void(int)> b);
|
||||
ThreadPool(ThreadPool &&other) = delete;
|
||||
// Waits for all threads to terminate. Make sure those closures return!
|
||||
~ThreadPool();
|
||||
|
||||
// Return the number of threads in the pool.
|
||||
int num_threads() const
|
||||
{
|
||||
#ifdef YOSYS_ENABLE_THREADS
|
||||
return threads.size();
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
private:
|
||||
std::function<void(int)> body;
|
||||
#ifdef YOSYS_ENABLE_THREADS
|
||||
std::vector<std::thread> threads;
|
||||
#endif
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class ConcurrentStack
|
||||
{
|
||||
public:
|
||||
void push_back(T &&t) {
|
||||
#ifdef YOSYS_ENABLE_THREADS
|
||||
std::lock_guard<std::mutex> lock(mutex);
|
||||
#endif
|
||||
contents.push_back(std::move(t));
|
||||
}
|
||||
std::optional<T> try_pop_back() {
|
||||
#ifdef YOSYS_ENABLE_THREADS
|
||||
std::lock_guard<std::mutex> lock(mutex);
|
||||
#endif
|
||||
if (contents.empty())
|
||||
return std::nullopt;
|
||||
T result = std::move(contents.back());
|
||||
contents.pop_back();
|
||||
return result;
|
||||
}
|
||||
private:
|
||||
#ifdef YOSYS_ENABLE_THREADS
|
||||
std::mutex mutex;
|
||||
#endif
|
||||
std::vector<T> contents;
|
||||
};
|
||||
|
||||
YOSYS_NAMESPACE_END
|
||||
|
||||
#endif // YOSYS_THREADING_H
|
|
@ -177,7 +177,7 @@ int run_command(const std::string &command, std::function<void(const std::string
|
|||
|
||||
int ret = pclose(f);
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
return -2;
|
||||
#ifdef _WIN32
|
||||
return ret;
|
||||
#else
|
||||
|
|
|
@ -38,6 +38,7 @@ popd
|
|||
} > "$vcxsrc"/YosysVS/YosysVS.vcxproj.new
|
||||
|
||||
sed -i 's,</AdditionalIncludeDirectories>,</AdditionalIncludeDirectories>\n <LanguageStandard>stdcpp17</LanguageStandard>\n <AdditionalOptions>/Zc:__cplusplus %(AdditionalOptions)</AdditionalOptions>,g' "$vcxsrc"/YosysVS/YosysVS.vcxproj.new
|
||||
sed -i 's,<PreprocessorDefinitions>,<PreprocessorDefinitions>YOSYS_ENABLE_THREADS;,g' "$vcxsrc"/YosysVS/YosysVS.vcxproj.new
|
||||
if [ -f "/usr/include/FlexLexer.h" ] ; then
|
||||
sed -i 's,</AdditionalIncludeDirectories>,;..\\yosys\\libs\\flex</AdditionalIncludeDirectories>,g' "$vcxsrc"/YosysVS/YosysVS.vcxproj.new
|
||||
fi
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue