3
0
Fork 0
mirror of https://github.com/YosysHQ/yosys synced 2025-04-07 01:54:10 +00:00

Merge branch 'YosysHQ:master' into master

This commit is contained in:
Emil J 2022-11-08 22:02:23 +01:00 committed by GitHub
commit 15d41041d8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
28 changed files with 1270 additions and 85 deletions

View file

@ -14,7 +14,7 @@ jobs:
run: sudo apt-get install bison flex libreadline-dev tcl-dev libffi-dev
- name: Checkout repository
uses: actions/checkout@v3.0.0
uses: actions/checkout@v3
- name: Initialize CodeQL
uses: github/codeql-action/init@v2

21
.github/workflows/deprecated.yml vendored Normal file
View file

@ -0,0 +1,21 @@
name: Deprecated compilers
on: [push, pull_request]
jobs:
gcc48:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Build GCC 4.8
run: |
docker run --rm -v $(pwd):/work yosyshq/deprecated-compilers:1.0 make config-gcc-4.8
docker run --rm -v $(pwd):/work yosyshq/deprecated-compilers:1.0 make -j8
clang39:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Build Clang 3.9
run: |
docker run --rm -v $(pwd):/work yosyshq/deprecated-compilers:1.0 make CC=clang-3.9 CXX=clang-3.9 LD=clang-3.9 -j8

View file

@ -7,10 +7,10 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: mymindstorm/setup-emsdk@v11
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: Cache sources
id: cache-sources
uses: actions/cache@v2
uses: actions/cache@v3
with:
path: .
key: cache-yosys
@ -18,7 +18,7 @@ jobs:
run: |
make config-emcc
make YOSYS_VER=latest
- uses: actions/upload-artifact@v2
- uses: actions/upload-artifact@v3
with:
name: yosysjs
path: yosysjs-latest.zip

View file

@ -25,12 +25,6 @@ jobs:
- os: { id: ubuntu-20.04, name: focal }
compiler: 'gcc-10'
cpp_std: 'c++11'
- os: { id: ubuntu-18.04, name: bionic }
compiler: 'clang-3.9'
cpp_std: 'c++11'
- os: { id: ubuntu-18.04, name: bionic }
compiler: 'gcc-4.8'
cpp_std: 'c++11'
fail-fast: false
steps:
- name: Install Dependencies
@ -84,7 +78,7 @@ jobs:
$CXX --version
- name: Checkout Yosys
uses: actions/checkout@v2
uses: actions/checkout@v3
- name: Get iverilog
shell: bash
@ -93,7 +87,7 @@ jobs:
- name: Cache iverilog
id: cache-iverilog
uses: actions/cache@v2
uses: actions/cache@v3
with:
path: .local/
key: ${{ matrix.os.id }}-${{ hashFiles('iverilog/.git/refs/heads/master') }}
@ -109,15 +103,7 @@ jobs:
make -j${{ env.procs }}
make install
- name: Build yosys (gcc-4.8)
if: matrix.compiler == 'gcc-4.8'
shell: bash
run: |
make config-${{ matrix.compiler }}
make -j${{ env.procs }} CCXXSTD=${{ matrix.cpp_std }} CC=$CC CXX=$CC LD=$CC
- name: Build yosys
if: matrix.compiler != 'gcc-4.8'
shell: bash
run: |
make config-${CC%%-*}

View file

@ -35,7 +35,7 @@ jobs:
cc --version
- name: Checkout Yosys
uses: actions/checkout@v2
uses: actions/checkout@v3
- name: Get iverilog
shell: bash
@ -44,7 +44,7 @@ jobs:
- name: Cache iverilog
id: cache-iverilog
uses: actions/cache@v2
uses: actions/cache@v3
with:
path: .local/
key: ${{ matrix.os.id }}-${{ hashFiles('iverilog/.git/refs/heads/master') }}

View file

@ -10,15 +10,15 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Take last commit
id: log
run: echo "::set-output name=message::$(git log --no-merges -1 --oneline)"
run: echo "message=$(git log --no-merges -1 --oneline)" >> $GITHUB_OUTPUT
- name: Take repository
id: repo
run: echo "::set-output name=message::$GITHUB_REPOSITORY"
run: echo "message=$GITHUB_REPOSITORY" >> $GITHUB_OUTPUT
- name: Bump version
if: "!contains(steps.log.outputs.message, 'Bump version') && contains(steps.repo.outputs.message, 'YosysHQ/yosys')"
run: |

View file

@ -6,16 +6,16 @@ jobs:
yosys-vcxsrc:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: Cache sources
id: cache-sources
uses: actions/cache@v2
uses: actions/cache@v3
with:
path: .
key: cache-yosys
- name: Build
run: make vcxsrc YOSYS_VER=latest
- uses: actions/upload-artifact@v2
- uses: actions/upload-artifact@v3
with:
name: vcxsrc
path: yosys-win32-vcxsrc-latest.zip
@ -24,7 +24,7 @@ jobs:
runs-on: windows-2019
needs: yosys-vcxsrc
steps:
- uses: actions/download-artifact@v2
- uses: actions/download-artifact@v3
with:
name: vcxsrc
path: .

View file

@ -2,9 +2,27 @@
List of major changes and improvements between releases
=======================================================
Yosys 0.22 .. Yosys 0.22-dev
Yosys 0.23 .. Yosys 0.23-dev
--------------------------
Yosys 0.22 .. Yosys 0.23
--------------------------
* New commands and options
- Added option "-cross" to "miter" pass.
- Added option "-nocheck" to "equiv_opt" pass.
* Formal Verification
- yosys-smtbmc: Added "--detect-loops" option for checking if states are
unique in temporal induction counter examples.
* Verific support
- Added support for reading Liberty files using Verific library.
(Optinally enabled with ENABLE_VERIFIC_LIBERTY)
- Added option "-cells" to "verific -import" enabling import of
all cells from verific design.
* Various
- MinGW build (Windows) plugin support.
- Added YOSYS_ABORT_ON_LOG_ERROR environment variable for debugging.
Setting it to 1 causes abort() to be called when Yosys terminates with an
error message.

View file

@ -19,6 +19,7 @@ ENABLE_EDITLINE := 0
ENABLE_GHDL := 0
ENABLE_VERIFIC := 0
ENABLE_VERIFIC_EDIF := 0
ENABLE_VERIFIC_LIBERTY := 0
DISABLE_VERIFIC_EXTENSIONS := 0
DISABLE_VERIFIC_VHDL := 0
ENABLE_COVER := 1
@ -56,6 +57,9 @@ PROGRAM_PREFIX :=
OS := $(shell uname -s)
PREFIX ?= /usr/local
INSTALL_SUDO :=
ifneq ($(filter MINGW%,$(OS)),)
OS := MINGW
endif
ifneq ($(wildcard Makefile.conf),)
include Makefile.conf
@ -91,6 +95,13 @@ CXXSTD ?= c++11
CXXFLAGS := $(CXXFLAGS) -Wall -Wextra -ggdb -I. -I"$(YOSYS_SRC)" -MD -MP -D_YOSYS_ -fPIC -I$(PREFIX)/include
LDLIBS := $(LDLIBS) -lstdc++ -lm
PLUGIN_LDFLAGS :=
PLUGIN_LDLIBS :=
EXE_LDFLAGS :=
ifeq ($(OS), MINGW)
EXE_LDFLAGS := -Wl,--export-all-symbols -Wl,--out-implib,libyosys_exe.a
PLUGIN_LDFLAGS += -L"$(LIBDIR)"
PLUGIN_LDLIBS := -lyosys_exe
endif
PKG_CONFIG ?= pkg-config
SED ?= sed
@ -131,7 +142,7 @@ LDLIBS += -lrt
endif
endif
YOSYS_VER := 0.22+37
YOSYS_VER := 0.23+0
# Note: We arrange for .gitcommit to contain the (short) commit hash in
# tarballs generated with git-archive(1) using .gitattributes. The git repo
@ -147,7 +158,7 @@ endif
OBJS = kernel/version_$(GIT_REV).o
bumpversion:
sed -i "/^YOSYS_VER := / s/+[0-9][0-9]*$$/+`git log --oneline f109fa3.. | wc -l`/;" Makefile
sed -i "/^YOSYS_VER := / s/+[0-9][0-9]*$$/+`git log --oneline 7ce5011.. | wc -l`/;" Makefile
# set 'ABCREV = default' to use abc/ as it is
#
@ -436,8 +447,11 @@ endif
ifeq ($(ENABLE_PLUGINS),1)
CXXFLAGS += $(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) $(PKG_CONFIG) --silence-errors --cflags libffi) -DYOSYS_ENABLE_PLUGINS
ifeq ($(OS), MINGW)
CXXFLAGS += -Ilibs/dlfcn-win32
endif
LDLIBS += $(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) $(PKG_CONFIG) --silence-errors --libs libffi || echo -lffi)
ifneq ($(OS), $(filter $(OS),FreeBSD OpenBSD NetBSD))
ifneq ($(OS), $(filter $(OS),FreeBSD OpenBSD NetBSD MINGW))
LDLIBS += -ldl
endif
endif
@ -531,6 +545,10 @@ ifeq ($(ENABLE_VERIFIC_EDIF),1)
VERIFIC_COMPONENTS += edif
CXXFLAGS += -DVERIFIC_EDIF_SUPPORT
endif
ifeq ($(ENABLE_VERIFIC_LIBERTY),1)
VERIFIC_COMPONENTS += synlib
CXXFLAGS += -DVERIFIC_LIBERTY_SUPPORT
endif
ifneq ($(DISABLE_VERIFIC_EXTENSIONS),1)
VERIFIC_COMPONENTS += extensions
CXXFLAGS += -DYOSYSHQ_VERIFIC_EXTENSIONS
@ -646,6 +664,11 @@ OBJS += kernel/cellaigs.o kernel/celledges.o kernel/satgen.o kernel/qcsat.o kern
ifeq ($(ENABLE_ZLIB),1)
OBJS += kernel/fstdata.o
endif
ifeq ($(ENABLE_PLUGINS),1)
ifeq ($(OS), MINGW)
OBJS += libs/dlfcn-win32/dlfcn.o
endif
endif
kernel/log.o: CXXFLAGS += -DYOSYS_SRC='"$(YOSYS_SRC)"'
kernel/yosys.o: CXXFLAGS += -DYOSYS_DATDIR='"$(DATDIR)"' -DYOSYS_PROGRAM_PREFIX='"$(PROGRAM_PREFIX)"'
@ -724,7 +747,7 @@ yosys.js: $(filter-out yosysjs-$(YOSYS_VER).zip,$(EXTRA_TARGETS))
endif
$(PROGRAM_PREFIX)yosys$(EXE): $(OBJS)
$(P) $(LD) -o $(PROGRAM_PREFIX)yosys$(EXE) $(LDFLAGS) $(OBJS) $(LDLIBS)
$(P) $(LD) -o $(PROGRAM_PREFIX)yosys$(EXE) $(EXE_LDFLAGS) $(LDFLAGS) $(OBJS) $(LDLIBS)
libyosys.so: $(filter-out kernel/driver.o,$(OBJS))
ifeq ($(OS), Darwin)
@ -767,8 +790,8 @@ LDLIBS_NOVERIFIC = $(LDLIBS)
endif
$(PROGRAM_PREFIX)yosys-config: misc/yosys-config.in
$(P) $(SED) -e 's#@CXXFLAGS@#$(subst -I. -I"$(YOSYS_SRC)",-I"$(DATDIR)/include",$(strip $(CXXFLAGS_NOVERIFIC)))#;' \
-e 's#@CXX@#$(strip $(CXX))#;' -e 's#@LDFLAGS@#$(strip $(LDFLAGS) $(PLUGIN_LDFLAGS))#;' -e 's#@LDLIBS@#$(strip $(LDLIBS_NOVERIFIC))#;' \
$(P) $(SED) -e 's#@CXXFLAGS@#$(subst -Ilibs/dlfcn-win32,,$(subst -I. -I"$(YOSYS_SRC)",-I"$(DATDIR)/include",$(strip $(CXXFLAGS_NOVERIFIC))))#;' \
-e 's#@CXX@#$(strip $(CXX))#;' -e 's#@LDFLAGS@#$(strip $(LDFLAGS) $(PLUGIN_LDFLAGS))#;' -e 's#@LDLIBS@#$(strip $(LDLIBS_NOVERIFIC) $(PLUGIN_LDLIBS))#;' \
-e 's#@BINDIR@#$(strip $(BINDIR))#;' -e 's#@DATDIR@#$(strip $(DATDIR))#;' < $< > $(PROGRAM_PREFIX)yosys-config
$(Q) chmod +x $(PROGRAM_PREFIX)yosys-config
@ -916,6 +939,12 @@ ifeq ($(ENABLE_PYOSYS),1)
$(INSTALL_SUDO) cp misc/__init__.py $(DESTDIR)$(PYTHON_DESTDIR)/$(subst -,_,$(PROGRAM_PREFIX))pyosys/
endif
endif
ifeq ($(ENABLE_PLUGINS),1)
ifeq ($(OS), MINGW)
$(INSTALL_SUDO) mkdir -p $(DESTDIR)$(LIBDIR)
$(INSTALL_SUDO) cp libyosys_exe.a $(DESTDIR)$(LIBDIR)/
endif
endif
uninstall:
$(INSTALL_SUDO) rm -vf $(addprefix $(DESTDIR)$(BINDIR)/,$(notdir $(TARGETS)))
@ -1040,12 +1069,10 @@ config-mxe: clean
config-msys2-32: clean
echo 'CONFIG := msys2-32' > Makefile.conf
echo 'ENABLE_PLUGINS := 0' >> Makefile.conf
echo "PREFIX := $(MINGW_PREFIX)" >> Makefile.conf
config-msys2-64: clean
echo 'CONFIG := msys2-64' > Makefile.conf
echo 'ENABLE_PLUGINS := 0' >> Makefile.conf
echo "PREFIX := $(MINGW_PREFIX)" >> Makefile.conf
config-cygwin: clean

View file

@ -453,7 +453,6 @@ assert topmod in smt.modinfo
if cexfile is not None:
if not got_topt:
assume_skipped = 0
skip_steps = 0
num_steps = 0
@ -499,7 +498,6 @@ if aimfile is not None:
latch_map = dict()
if not got_topt:
assume_skipped = 0
skip_steps = 0
num_steps = 0
@ -633,7 +631,6 @@ if aimfile is not None:
if inywfile is not None:
if not got_topt:
assume_skipped = 0
skip_steps = 0
num_steps = 0

View file

@ -57,6 +57,11 @@ USING_YOSYS_NAMESPACE
#include "edif_file.h"
#endif
#ifdef VERIFIC_LIBERTY_SUPPORT
#include "synlib_file.h"
#include "SynlibGroup.h"
#endif
#include "VerificStream.h"
#include "FileSystem.h"
@ -2358,6 +2363,9 @@ void verific_import(Design *design, const std::map<std::string,std::string> &par
#endif
#ifdef VERIFIC_EDIF_SUPPORT
edif_file::Reset();
#endif
#ifdef VERIFIC_LIBERTY_SUPPORT
synlib_file::Reset();
#endif
Libset::Reset();
Message::Reset();
@ -2426,6 +2434,18 @@ struct VerificPass : public Pass {
log("Load the specified EDIF files into Verific.\n");
log("\n");
log("\n");
#endif
#ifdef VERIFIC_LIBERTY_SUPPORT
log(" verific {-liberty} <liberty-file>..\n");
log("\n");
log("Load the specified Liberty files into Verific.\n");
log("Default library when -work is not present is one specified in liberty file.\n");
log("To use from SystemVerilog or VHDL use -L to specify liberty library.");
log("\n");
log(" -lib\n");
log(" only create empty blackbox modules\n");
log("\n");
log("\n");
#endif
log(" verific {-f|-F} [-vlog95|-vlog2k|-sv2005|-sv2009|\n");
log(" -sv2012|-sv|-formal] <command-file>\n");
@ -2535,7 +2555,7 @@ struct VerificPass : public Pass {
log("\n");
log(" -cells\n");
log(" Import all cell definitions from Verific loaded libraries even if they are\n");
log(" unused in design. Useful with \"-edif\" option.\n");
log(" unused in design. Useful with \"-edif\" and \"-liberty\" option.\n");
log("\n");
log(" -chparam name value \n");
log(" Elaborate the specified top modules (all modules when -all given) using\n");
@ -2729,6 +2749,7 @@ struct VerificPass : public Pass {
int argidx = 1;
std::string work = "work";
bool is_work_set = false;
veri_file::RegisterCallBackVerificStream(&verific_read_cb);
if (GetSize(args) > argidx && (args[argidx] == "-set-error" || args[argidx] == "-set-warning" ||
@ -2813,6 +2834,7 @@ struct VerificPass : public Pass {
{
if (args[argidx] == "-work" && argidx+1 < GetSize(args)) {
work = args[++argidx];
is_work_set = true;
continue;
}
if (args[argidx] == "-L" && argidx+1 < GetSize(args)) {
@ -3001,6 +3023,42 @@ struct VerificPass : public Pass {
}
goto check_error;
}
#endif
#ifdef VERIFIC_LIBERTY_SUPPORT
if (GetSize(args) > argidx && args[argidx] == "-liberty") {
bool flag_lib = false;
for (argidx++; argidx < GetSize(args); argidx++) {
if (args[argidx] == "-lib") {
flag_lib = true;
continue;
}
if (args[argidx].compare(0, 1, "-") == 0) {
cmd_error(args, argidx, "unknown option");
goto check_error;
}
break;
}
while (argidx < GetSize(args)) {
std::string filename = frontent_rewrite(args, argidx, tmp_files);
if (!synlib_file::Read(filename.c_str(), is_work_set ? work.c_str() : nullptr))
log_cmd_error("Reading `%s' in LIBERTY mode failed.\n", filename.c_str());
SynlibLibrary *lib = synlib_file::GetLastLibraryAnalyzed();
if (lib && flag_lib) {
MapIter mi ;
Verific::Cell *c ;
FOREACH_CELL_OF_LIBRARY(lib->GetLibrary(),mi,c) {
MapIter ni ;
Netlist *nl;
FOREACH_NETLIST_OF_CELL(c, ni, nl) {
if (nl)
nl->MakeBlackBox();
}
}
}
}
goto check_error;
}
#endif
if (argidx < GetSize(args) && args[argidx] == "-pp")
{
@ -3293,6 +3351,9 @@ struct VerificPass : public Pass {
#endif
#ifdef VERIFIC_EDIF_SUPPORT
edif_file::Reset();
#endif
#ifdef VERIFIC_LIBERTY_SUPPORT
synlib_file::Reset();
#endif
Libset::Reset();
Message::Reset();
@ -3427,6 +3488,14 @@ struct ReadPass : public Pass {
log("\n");
log("\n");
#endif
log(" read {-liberty} <liberty-file>..\n");
log("\n");
log("Load the specified Liberty files.\n");
log("\n");
log(" -lib\n");
log(" only create empty blackbox modules\n");
log("\n");
log("\n");
log(" read {-f|-F} <command-file>\n");
log("\n");
log("Load and execute the specified command file. (Requires Verific.)\n");
@ -3531,6 +3600,15 @@ struct ReadPass : public Pass {
return;
}
#endif
if (args[1] == "-liberty") {
if (use_verific) {
args[0] = "verific";
} else {
args[0] = "read_liberty";
}
Pass::call(design, args);
return;
}
if (args[1] == "-f" || args[1] == "-F") {
if (use_verific) {
args[0] = "verific";

View file

@ -609,6 +609,36 @@ RTLIL::Const RTLIL::const_neg(const RTLIL::Const &arg1, const RTLIL::Const&, boo
return RTLIL::const_sub(zero, arg1_ext, true, signed1, result_len);
}
RTLIL::Const RTLIL::const_mux(const RTLIL::Const &arg1, const RTLIL::Const &arg2, const RTLIL::Const &arg3)
{
log_assert(arg2.size() == arg1.size());
if (arg3[0] == State::S0)
return arg1;
else if (arg3[0] == State::S1)
return arg2;
RTLIL::Const ret = arg1;
for (int i = 0; i < ret.size(); i++)
if (ret[i] != arg2[i])
ret[i] = State::Sx;
return ret;
}
RTLIL::Const RTLIL::const_pmux(const RTLIL::Const &arg1, const RTLIL::Const &arg2, const RTLIL::Const &arg3)
{
if (arg3.is_fully_zero())
return arg1;
if (!arg3.is_onehot())
return RTLIL::Const(State::Sx, arg1.size());
for (int i = 0; i < arg3.size(); i++)
if (arg3[i] == State::S1)
return RTLIL::Const(std::vector<RTLIL::State>(arg2.bits.begin() + i*arg1.bits.size(), arg2.bits.begin() + (i+1)*arg1.bits.size()));
log_abort(); // unreachable
}
RTLIL::Const RTLIL::const_bmux(const RTLIL::Const &arg1, const RTLIL::Const &arg2)
{
std::vector<RTLIL::State> t = arg1.bits;

View file

@ -488,16 +488,10 @@ struct CellTypes
static RTLIL::Const eval(RTLIL::Cell *cell, const RTLIL::Const &arg1, const RTLIL::Const &arg2, const RTLIL::Const &arg3, bool *errp = nullptr)
{
if (cell->type.in(ID($mux), ID($pmux), ID($_MUX_))) {
RTLIL::Const ret = arg1;
for (size_t i = 0; i < arg3.bits.size(); i++)
if (arg3.bits[i] == RTLIL::State::S1) {
std::vector<RTLIL::State> bits(arg2.bits.begin() + i*arg1.bits.size(), arg2.bits.begin() + (i+1)*arg1.bits.size());
ret = RTLIL::Const(bits);
}
return ret;
}
if (cell->type.in(ID($mux), ID($_MUX_)))
return const_mux(arg1, arg2, arg3);
if (cell->type == ID($pmux))
return const_pmux(arg1, arg2, arg3);
if (cell->type == ID($_AOI3_))
return eval_not(const_or(const_and(arg1, arg2, false, false, 1), arg3, false, false, 1));
if (cell->type == ID($_OAI3_))

View file

@ -78,7 +78,18 @@ uint64_t FstData::getStartTime() { return fstReaderGetStartTime(ctx); }
uint64_t FstData::getEndTime() { return fstReaderGetEndTime(ctx); }
static void normalize_brackets(std::string &str)
{
for (auto &c : str) {
if (c == '<')
c = '[';
else if (c == '>')
c = ']';
}
}
fstHandle FstData::getHandle(std::string name) {
normalize_brackets(name);
if (name_to_handle.find(name) != name_to_handle.end())
return name_to_handle[name];
else
@ -120,6 +131,7 @@ void FstData::extractVarNames()
var.is_reg = (fstVarType)h->u.var.typ == FST_VT_VCD_REG;
var.name = remove_spaces(h->u.var.name);
var.scope = fst_scope_name;
normalize_brackets(var.scope);
var.width = h->u.var.length;
vars.push_back(var);
if (!var.is_alias)
@ -134,35 +146,34 @@ void FstData::extractVarNames()
if (clean_name[0]=='\\')
clean_name = clean_name.substr(1);
size_t pos = clean_name.find_last_of("<");
if (pos != std::string::npos) {
if (pos != std::string::npos && clean_name.back() == '>') {
std::string mem_cell = clean_name.substr(0, pos);
normalize_brackets(mem_cell);
std::string addr = clean_name.substr(pos+1);
addr.pop_back(); // remove closing bracket
char *endptr;
int mem_addr = strtol(addr.c_str(), &endptr, 16);
if (*endptr) {
log_warning("Error parsing memory address in : %s\n", clean_name.c_str());
log_debug("Error parsing memory address in : %s\n", clean_name.c_str());
} else {
memory_to_handle[var.scope+"."+mem_cell][mem_addr] = var.id;
name_to_handle[stringf("%s.%s[%d]",var.scope.c_str(),mem_cell.c_str(),mem_addr)] = h->u.var.handle;
continue;
}
}
pos = clean_name.find_last_of("[");
if (pos != std::string::npos) {
if (pos != std::string::npos && clean_name.back() == ']') {
std::string mem_cell = clean_name.substr(0, pos);
normalize_brackets(mem_cell);
std::string addr = clean_name.substr(pos+1);
addr.pop_back(); // remove closing bracket
char *endptr;
int mem_addr = strtol(addr.c_str(), &endptr, 10);
if (*endptr) {
log_warning("Error parsing memory address in : %s\n", clean_name.c_str());
log_debug("Error parsing memory address in : %s\n", clean_name.c_str());
} else {
memory_to_handle[var.scope+"."+mem_cell][mem_addr] = var.id;
name_to_handle[stringf("%s.%s[%d]",var.scope.c_str(),mem_cell.c_str(),mem_addr)] = h->u.var.handle;
continue;
}
}
normalize_brackets(clean_name);
name_to_handle[var.scope+"."+clean_name] = h->u.var.handle;
break;
}
@ -241,6 +252,7 @@ void FstData::reconstructAllAtTimes(std::vector<fstHandle> &signal, uint64_t sta
past_data = last_data;
callback(last_time);
}
past_data = last_data;
callback(end_time);
}

View file

@ -393,6 +393,11 @@ void log_dump_val_worker(RTLIL::IdString v);
void log_dump_val_worker(RTLIL::SigSpec v);
void log_dump_val_worker(RTLIL::State v);
template<typename K, typename T, typename OPS> static inline void log_dump_val_worker(dict<K, T, OPS> &v);
template<typename K, typename OPS> static inline void log_dump_val_worker(pool<K, OPS> &v);
template<typename K> static inline void log_dump_val_worker(std::vector<K> &v);
template<typename T> static inline void log_dump_val_worker(T *ptr);
template<typename K, typename T, typename OPS>
static inline void log_dump_val_worker(dict<K, T, OPS> &v) {
log("{");

View file

@ -500,6 +500,8 @@ namespace RTLIL
RTLIL::Const const_pos (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len);
RTLIL::Const const_neg (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len);
RTLIL::Const const_mux (const RTLIL::Const &arg1, const RTLIL::Const &arg2, const RTLIL::Const &arg3);
RTLIL::Const const_pmux (const RTLIL::Const &arg1, const RTLIL::Const &arg2, const RTLIL::Const &arg3);
RTLIL::Const const_bmux (const RTLIL::Const &arg1, const RTLIL::Const &arg2);
RTLIL::Const const_demux (const RTLIL::Const &arg1, const RTLIL::Const &arg2);

820
libs/dlfcn-win32/dlfcn.cc Normal file
View file

@ -0,0 +1,820 @@
/*
* dlfcn-win32
* Copyright (c) 2007 Ramiro Polla
* Copyright (c) 2015 Tiancheng "Timothy" Gu
* Copyright (c) 2019 Pali Rohár <pali.rohar@gmail.com>
* Copyright (c) 2020 Ralf Habacker <ralf.habacker@freenet.de>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifdef _DEBUG
#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
#endif
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
/* Older versions do not have this type */
#if _WIN32_WINNT < 0x0500
typedef ULONG ULONG_PTR;
#endif
/* Older SDK versions do not have these macros */
#ifndef GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
#define GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS 0x4
#endif
#ifndef GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT
#define GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT 0x2
#endif
#ifdef _MSC_VER
/* https://docs.microsoft.com/en-us/cpp/intrinsics/returnaddress */
#pragma intrinsic( _ReturnAddress )
#else
/* https://gcc.gnu.org/onlinedocs/gcc/Return-Address.html */
#ifndef _ReturnAddress
#define _ReturnAddress( ) ( __builtin_extract_return_addr( __builtin_return_address( 0 ) ) )
#endif
#endif
#ifdef DLFCN_WIN32_SHARED
#define DLFCN_WIN32_EXPORTS
#endif
#include "dlfcn.h"
#if defined( _MSC_VER ) && _MSC_VER >= 1300
/* https://docs.microsoft.com/en-us/cpp/cpp/noinline */
#define DLFCN_NOINLINE __declspec( noinline )
#elif defined( __GNUC__ ) && ( ( __GNUC__ > 3 ) || ( __GNUC__ == 3 && __GNUC_MINOR__ >= 1 ) )
/* https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html */
#define DLFCN_NOINLINE __attribute__(( noinline ))
#else
#define DLFCN_NOINLINE
#endif
/* Note:
* MSDN says these functions are not thread-safe. We make no efforts to have
* any kind of thread safety.
*/
typedef struct local_object {
HMODULE hModule;
struct local_object *previous;
struct local_object *next;
} local_object;
static local_object first_object;
/* These functions implement a double linked list for the local objects. */
static local_object *local_search( HMODULE hModule )
{
local_object *pobject;
if( hModule == NULL )
return NULL;
for( pobject = &first_object; pobject; pobject = pobject->next )
if( pobject->hModule == hModule )
return pobject;
return NULL;
}
static BOOL local_add( HMODULE hModule )
{
local_object *pobject;
local_object *nobject;
if( hModule == NULL )
return TRUE;
pobject = local_search( hModule );
/* Do not add object again if it's already on the list */
if( pobject != NULL )
return TRUE;
for( pobject = &first_object; pobject->next; pobject = pobject->next );
nobject = (local_object *) malloc( sizeof( local_object ) );
if( !nobject )
return FALSE;
pobject->next = nobject;
nobject->next = NULL;
nobject->previous = pobject;
nobject->hModule = hModule;
return TRUE;
}
static void local_rem( HMODULE hModule )
{
local_object *pobject;
if( hModule == NULL )
return;
pobject = local_search( hModule );
if( pobject == NULL )
return;
if( pobject->next )
pobject->next->previous = pobject->previous;
if( pobject->previous )
pobject->previous->next = pobject->next;
free( pobject );
}
/* POSIX says dlerror( ) doesn't have to be thread-safe, so we use one
* static buffer.
* MSDN says the buffer cannot be larger than 64K bytes, so we set it to
* the limit.
*/
static char error_buffer[65535];
static BOOL error_occurred;
static void save_err_str( const char *str, DWORD dwMessageId )
{
DWORD ret;
size_t pos, len;
len = strlen( str );
if( len > sizeof( error_buffer ) - 5 )
len = sizeof( error_buffer ) - 5;
/* Format error message to:
* "<argument to function that failed>": <Windows localized error message>
*/
pos = 0;
error_buffer[pos++] = '"';
memcpy( error_buffer + pos, str, len );
pos += len;
error_buffer[pos++] = '"';
error_buffer[pos++] = ':';
error_buffer[pos++] = ' ';
ret = FormatMessageA( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dwMessageId,
MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ),
error_buffer + pos, (DWORD) ( sizeof( error_buffer ) - pos ), NULL );
pos += ret;
/* When FormatMessageA() fails it returns zero and does not touch buffer
* so add trailing null byte */
if( ret == 0 )
error_buffer[pos] = '\0';
if( pos > 1 )
{
/* POSIX says the string must not have trailing <newline> */
if( error_buffer[pos-2] == '\r' && error_buffer[pos-1] == '\n' )
error_buffer[pos-2] = '\0';
}
error_occurred = TRUE;
}
static void save_err_ptr_str( const void *ptr, DWORD dwMessageId )
{
char ptr_buf[2 + 2 * sizeof( ptr ) + 1];
char num;
size_t i;
ptr_buf[0] = '0';
ptr_buf[1] = 'x';
for( i = 0; i < 2 * sizeof( ptr ); i++ )
{
num = (char) ( ( ( (ULONG_PTR) ptr ) >> ( 8 * sizeof( ptr ) - 4 * ( i + 1 ) ) ) & 0xF );
ptr_buf[2 + i] = num + ( ( num < 0xA ) ? '0' : ( 'A' - 0xA ) );
}
ptr_buf[2 + 2 * sizeof( ptr )] = 0;
save_err_str( ptr_buf, dwMessageId );
}
static UINT MySetErrorMode( UINT uMode )
{
static BOOL (WINAPI *SetThreadErrorModePtr)(DWORD, DWORD *) = NULL;
static BOOL failed = FALSE;
HMODULE kernel32;
DWORD oldMode;
if( !failed && SetThreadErrorModePtr == NULL )
{
kernel32 = GetModuleHandleA( "Kernel32.dll" );
if( kernel32 != NULL )
SetThreadErrorModePtr = (BOOL (WINAPI *)(DWORD, DWORD *)) (LPVOID) GetProcAddress( kernel32, "SetThreadErrorMode" );
if( SetThreadErrorModePtr == NULL )
failed = TRUE;
}
if( !failed )
{
if( !SetThreadErrorModePtr( uMode, &oldMode ) )
return 0;
else
return oldMode;
}
else
{
return SetErrorMode( uMode );
}
}
static HMODULE MyGetModuleHandleFromAddress( const void *addr )
{
static BOOL (WINAPI *GetModuleHandleExAPtr)(DWORD, LPCSTR, HMODULE *) = NULL;
static BOOL failed = FALSE;
HMODULE kernel32;
HMODULE hModule;
MEMORY_BASIC_INFORMATION info;
SIZE_T sLen;
if( !failed && GetModuleHandleExAPtr == NULL )
{
kernel32 = GetModuleHandleA( "Kernel32.dll" );
if( kernel32 != NULL )
GetModuleHandleExAPtr = (BOOL (WINAPI *)(DWORD, LPCSTR, HMODULE *)) (LPVOID) GetProcAddress( kernel32, "GetModuleHandleExA" );
if( GetModuleHandleExAPtr == NULL )
failed = TRUE;
}
if( !failed )
{
/* If GetModuleHandleExA is available use it with GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS */
if( !GetModuleHandleExAPtr( GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, (const char *)addr, &hModule ) )
return NULL;
}
else
{
/* To get HMODULE from address use undocumented hack from https://stackoverflow.com/a/2396380
* The HMODULE of a DLL is the same value as the module's base address.
*/
sLen = VirtualQuery( addr, &info, sizeof( info ) );
if( sLen != sizeof( info ) )
return NULL;
hModule = (HMODULE) info.AllocationBase;
}
return hModule;
}
/* Load Psapi.dll at runtime, this avoids linking caveat */
static BOOL MyEnumProcessModules( HANDLE hProcess, HMODULE *lphModule, DWORD cb, LPDWORD lpcbNeeded )
{
static BOOL (WINAPI *EnumProcessModulesPtr)(HANDLE, HMODULE *, DWORD, LPDWORD) = NULL;
static BOOL failed = FALSE;
UINT uMode;
HMODULE psapi;
if( failed )
return FALSE;
if( EnumProcessModulesPtr == NULL )
{
/* Windows 7 and newer versions have K32EnumProcessModules in Kernel32.dll which is always pre-loaded */
psapi = GetModuleHandleA( "Kernel32.dll" );
if( psapi != NULL )
EnumProcessModulesPtr = (BOOL (WINAPI *)(HANDLE, HMODULE *, DWORD, LPDWORD)) (LPVOID) GetProcAddress( psapi, "K32EnumProcessModules" );
/* Windows Vista and older version have EnumProcessModules in Psapi.dll which needs to be loaded */
if( EnumProcessModulesPtr == NULL )
{
/* Do not let Windows display the critical-error-handler message box */
uMode = MySetErrorMode( SEM_FAILCRITICALERRORS );
psapi = LoadLibraryA( "Psapi.dll" );
if( psapi != NULL )
{
EnumProcessModulesPtr = (BOOL (WINAPI *)(HANDLE, HMODULE *, DWORD, LPDWORD)) (LPVOID) GetProcAddress( psapi, "EnumProcessModules" );
if( EnumProcessModulesPtr == NULL )
FreeLibrary( psapi );
}
MySetErrorMode( uMode );
}
if( EnumProcessModulesPtr == NULL )
{
failed = TRUE;
return FALSE;
}
}
return EnumProcessModulesPtr( hProcess, lphModule, cb, lpcbNeeded );
}
DLFCN_EXPORT
void *dlopen( const char *file, int mode )
{
HMODULE hModule;
UINT uMode;
error_occurred = FALSE;
/* Do not let Windows display the critical-error-handler message box */
uMode = MySetErrorMode( SEM_FAILCRITICALERRORS );
if( file == NULL )
{
/* POSIX says that if the value of file is NULL, a handle on a global
* symbol object must be provided. That object must be able to access
* all symbols from the original program file, and any objects loaded
* with the RTLD_GLOBAL flag.
* The return value from GetModuleHandle( ) allows us to retrieve
* symbols only from the original program file. EnumProcessModules() is
* used to access symbols from other libraries. For objects loaded
* with the RTLD_LOCAL flag, we create our own list later on. They are
* excluded from EnumProcessModules() iteration.
*/
hModule = GetModuleHandle( NULL );
if( !hModule )
save_err_str( "(null)", GetLastError( ) );
}
else
{
HANDLE hCurrentProc;
DWORD dwProcModsBefore, dwProcModsAfter;
char lpFileName[MAX_PATH];
size_t i, len;
len = strlen( file );
if( len >= sizeof( lpFileName ) )
{
save_err_str( file, ERROR_FILENAME_EXCED_RANGE );
hModule = NULL;
}
else
{
/* MSDN says backslashes *must* be used instead of forward slashes. */
for( i = 0; i < len; i++ )
{
if( file[i] == '/' )
lpFileName[i] = '\\';
else
lpFileName[i] = file[i];
}
lpFileName[len] = '\0';
hCurrentProc = GetCurrentProcess( );
if( MyEnumProcessModules( hCurrentProc, NULL, 0, &dwProcModsBefore ) == 0 )
dwProcModsBefore = 0;
/* POSIX says the search path is implementation-defined.
* LOAD_WITH_ALTERED_SEARCH_PATH is used to make it behave more closely
* to UNIX's search paths (start with system folders instead of current
* folder).
*/
hModule = LoadLibraryExA( lpFileName, NULL, LOAD_WITH_ALTERED_SEARCH_PATH );
if( !hModule )
{
save_err_str( lpFileName, GetLastError( ) );
}
else
{
if( MyEnumProcessModules( hCurrentProc, NULL, 0, &dwProcModsAfter ) == 0 )
dwProcModsAfter = 0;
/* If the object was loaded with RTLD_LOCAL, add it to list of local
* objects, so that its symbols cannot be retrieved even if the handle for
* the original program file is passed. POSIX says that if the same
* file is specified in multiple invocations, and any of them are
* RTLD_GLOBAL, even if any further invocations use RTLD_LOCAL, the
* symbols will remain global. If number of loaded modules was not
* changed after calling LoadLibraryEx(), it means that library was
* already loaded.
*/
if( (mode & RTLD_LOCAL) && dwProcModsBefore != dwProcModsAfter )
{
if( !local_add( hModule ) )
{
save_err_str( lpFileName, ERROR_NOT_ENOUGH_MEMORY );
FreeLibrary( hModule );
hModule = NULL;
}
}
else if( !(mode & RTLD_LOCAL) && dwProcModsBefore == dwProcModsAfter )
{
local_rem( hModule );
}
}
}
}
/* Return to previous state of the error-mode bit flags. */
MySetErrorMode( uMode );
return (void *) hModule;
}
DLFCN_EXPORT
int dlclose( void *handle )
{
HMODULE hModule = (HMODULE) handle;
BOOL ret;
error_occurred = FALSE;
ret = FreeLibrary( hModule );
/* If the object was loaded with RTLD_LOCAL, remove it from list of local
* objects.
*/
if( ret )
local_rem( hModule );
else
save_err_ptr_str( handle, GetLastError( ) );
/* dlclose's return value in inverted in relation to FreeLibrary's. */
ret = !ret;
return (int) ret;
}
DLFCN_NOINLINE /* Needed for _ReturnAddress() */
DLFCN_EXPORT
void *dlsym( void *handle, const char *name )
{
FARPROC symbol;
HMODULE hCaller;
HMODULE hModule;
DWORD dwMessageId;
error_occurred = FALSE;
symbol = NULL;
hCaller = NULL;
hModule = GetModuleHandle( NULL );
dwMessageId = 0;
if( handle == RTLD_DEFAULT )
{
/* The symbol lookup happens in the normal global scope; that is,
* a search for a symbol using this handle would find the same
* definition as a direct use of this symbol in the program code.
* So use same lookup procedure as when filename is NULL.
*/
handle = hModule;
}
else if( handle == RTLD_NEXT )
{
/* Specifies the next object after this one that defines name.
* This one refers to the object containing the invocation of dlsym().
* The next object is the one found upon the application of a load
* order symbol resolution algorithm. To get caller function of dlsym()
* use _ReturnAddress() intrinsic. To get HMODULE of caller function
* use MyGetModuleHandleFromAddress() which calls either standard
* GetModuleHandleExA() function or hack via VirtualQuery().
*/
hCaller = MyGetModuleHandleFromAddress( _ReturnAddress( ) );
if( hCaller == NULL )
{
dwMessageId = ERROR_INVALID_PARAMETER;
goto end;
}
}
if( handle != RTLD_NEXT )
{
symbol = GetProcAddress( (HMODULE) handle, name );
if( symbol != NULL )
goto end;
}
/* If the handle for the original program file is passed, also search
* in all globally loaded objects.
*/
if( hModule == handle || handle == RTLD_NEXT )
{
HANDLE hCurrentProc;
HMODULE *modules;
DWORD cbNeeded;
DWORD dwSize;
size_t i;
hCurrentProc = GetCurrentProcess( );
/* GetModuleHandle( NULL ) only returns the current program file. So
* if we want to get ALL loaded module including those in linked DLLs,
* we have to use EnumProcessModules( ).
*/
if( MyEnumProcessModules( hCurrentProc, NULL, 0, &dwSize ) != 0 )
{
modules = (HMODULE *)malloc( dwSize );
if( modules )
{
if( MyEnumProcessModules( hCurrentProc, modules, dwSize, &cbNeeded ) != 0 && dwSize == cbNeeded )
{
for( i = 0; i < dwSize / sizeof( HMODULE ); i++ )
{
if( handle == RTLD_NEXT && hCaller )
{
/* Next modules can be used for RTLD_NEXT */
if( hCaller == modules[i] )
hCaller = NULL;
continue;
}
if( local_search( modules[i] ) )
continue;
symbol = GetProcAddress( modules[i], name );
if( symbol != NULL )
{
free( modules );
goto end;
}
}
}
free( modules );
}
else
{
dwMessageId = ERROR_NOT_ENOUGH_MEMORY;
goto end;
}
}
}
end:
if( symbol == NULL )
{
if( !dwMessageId )
dwMessageId = ERROR_PROC_NOT_FOUND;
save_err_str( name, dwMessageId );
}
return *(void **) (&symbol);
}
DLFCN_EXPORT
char *dlerror( void )
{
/* If this is the second consecutive call to dlerror, return NULL */
if( !error_occurred )
return NULL;
/* POSIX says that invoking dlerror( ) a second time, immediately following
* a prior invocation, shall result in NULL being returned.
*/
error_occurred = FALSE;
return error_buffer;
}
/* See https://docs.microsoft.com/en-us/archive/msdn-magazine/2002/march/inside-windows-an-in-depth-look-into-the-win32-portable-executable-file-format-part-2
* for details */
/* Get specific image section */
static BOOL get_image_section( HMODULE module, int index, void **ptr, DWORD *size )
{
IMAGE_DOS_HEADER *dosHeader;
IMAGE_NT_HEADERS *ntHeaders;
IMAGE_OPTIONAL_HEADER *optionalHeader;
dosHeader = (IMAGE_DOS_HEADER *) module;
if( dosHeader->e_magic != IMAGE_DOS_SIGNATURE )
return FALSE;
ntHeaders = (IMAGE_NT_HEADERS *) ( (BYTE *) dosHeader + dosHeader->e_lfanew );
if( ntHeaders->Signature != IMAGE_NT_SIGNATURE )
return FALSE;
optionalHeader = &ntHeaders->OptionalHeader;
if( optionalHeader->Magic != IMAGE_NT_OPTIONAL_HDR_MAGIC )
return FALSE;
if( index < 0 || index > IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR )
return FALSE;
if( optionalHeader->DataDirectory[index].Size == 0 || optionalHeader->DataDirectory[index].VirtualAddress == 0 )
return FALSE;
if( size != NULL )
*size = optionalHeader->DataDirectory[index].Size;
*ptr = (void *)( (BYTE *) module + optionalHeader->DataDirectory[index].VirtualAddress );
return TRUE;
}
/* Return symbol name for a given address from export table */
static const char *get_export_symbol_name( HMODULE module, IMAGE_EXPORT_DIRECTORY *ied, const void *addr, void **func_address )
{
DWORD i;
void *candidateAddr = NULL;
int candidateIndex = -1;
BYTE *base = (BYTE *) module;
DWORD *functionAddressesOffsets = (DWORD *) (base + ied->AddressOfFunctions);
DWORD *functionNamesOffsets = (DWORD *) (base + ied->AddressOfNames);
USHORT *functionNameOrdinalsIndexes = (USHORT *) (base + ied->AddressOfNameOrdinals);
for( i = 0; i < ied->NumberOfFunctions; i++ )
{
if( (void *) ( base + functionAddressesOffsets[i] ) > addr || candidateAddr >= (void *) ( base + functionAddressesOffsets[i] ) )
continue;
candidateAddr = (void *) ( base + functionAddressesOffsets[i] );
candidateIndex = i;
}
if( candidateIndex == -1 )
return NULL;
*func_address = candidateAddr;
for( i = 0; i < ied->NumberOfNames; i++ )
{
if( functionNameOrdinalsIndexes[i] == candidateIndex )
return (const char *) ( base + functionNamesOffsets[i] );
}
return NULL;
}
static BOOL is_valid_address( const void *addr )
{
MEMORY_BASIC_INFORMATION info;
SIZE_T result;
if( addr == NULL )
return FALSE;
/* check valid pointer */
result = VirtualQuery( addr, &info, sizeof( info ) );
if( result == 0 || info.AllocationBase == NULL || info.AllocationProtect == 0 || info.AllocationProtect == PAGE_NOACCESS )
return FALSE;
return TRUE;
}
/* Return state if address points to an import thunk
*
* An import thunk is setup with a 'jmp' instruction followed by an
* absolute address (32bit) or relative offset (64bit) pointing into
* the import address table (iat), which is partially maintained by
* the runtime linker.
*/
static BOOL is_import_thunk( const void *addr )
{
return *(short *) addr == 0x25ff ? TRUE : FALSE;
}
/* Return adress from the import address table (iat),
* if the original address points to a thunk table entry.
*/
static void *get_address_from_import_address_table( void *iat, DWORD iat_size, const void *addr )
{
BYTE *thkp = (BYTE *) addr;
/* Get offset from thunk table (after instruction 0xff 0x25)
* 4018c8 <_VirtualQuery>: ff 25 4a 8a 00 00
*/
ULONG offset = *(ULONG *)( thkp + 2 );
#ifdef _WIN64
/* On 64 bit the offset is relative
* 4018c8: ff 25 4a 8a 00 00 jmpq *0x8a4a(%rip) # 40a318 <__imp_VirtualQuery>
* And can be also negative (MSVC in WDK)
* 100002f20: ff 25 3a e1 ff ff jmpq *-0x1ec6(%rip) # 0x100001060
* So cast to signed LONG type
*/
BYTE *ptr = (BYTE *)( thkp + 6 + (LONG) offset );
#else
/* On 32 bit the offset is absolute
* 4019b4: ff 25 90 71 40 00 jmp *0x40719
*/
BYTE *ptr = (BYTE *) offset;
#endif
if( !is_valid_address( ptr ) || ptr < (BYTE *) iat || ptr > (BYTE *) iat + iat_size )
return NULL;
return *(void **) ptr;
}
/* Holds module filename */
static char module_filename[2*MAX_PATH];
static BOOL fill_info( const void *addr, Dl_info *info )
{
HMODULE hModule;
DWORD dwSize;
IMAGE_EXPORT_DIRECTORY *ied;
void *funcAddress = NULL;
/* Get module of the specified address */
hModule = MyGetModuleHandleFromAddress( addr );
if( hModule == NULL )
return FALSE;
dwSize = GetModuleFileNameA( hModule, module_filename, sizeof( module_filename ) );
if( dwSize == 0 || dwSize == sizeof( module_filename ) )
return FALSE;
info->dli_fname = module_filename;
info->dli_fbase = (void *) hModule;
/* Find function name and function address in module's export table */
if( get_image_section( hModule, IMAGE_DIRECTORY_ENTRY_EXPORT, (void **) &ied, NULL ) )
info->dli_sname = get_export_symbol_name( hModule, ied, addr, &funcAddress );
else
info->dli_sname = NULL;
info->dli_saddr = info->dli_sname == NULL ? NULL : funcAddress != NULL ? funcAddress : (void *) addr;
return TRUE;
}
DLFCN_EXPORT
int dladdr( const void *addr, Dl_info *info )
{
if( info == NULL )
return 0;
if( !is_valid_address( addr ) )
return 0;
if( is_import_thunk( addr ) )
{
void *iat;
DWORD iatSize;
HMODULE hModule;
/* Get module of the import thunk address */
hModule = MyGetModuleHandleFromAddress( addr );
if( hModule == NULL )
return 0;
if( !get_image_section( hModule, IMAGE_DIRECTORY_ENTRY_IAT, &iat, &iatSize ) )
{
/* Fallback for cases where the iat is not defined,
* for example i586-mingw32msvc-gcc */
IMAGE_IMPORT_DESCRIPTOR *iid;
DWORD iidSize;
if( !get_image_section( hModule, IMAGE_DIRECTORY_ENTRY_IMPORT, (void **) &iid, &iidSize ) )
return 0;
if( iid == NULL || iid->Characteristics == 0 || iid->FirstThunk == 0 )
return 0;
iat = (void *)( (BYTE *) hModule + iid->FirstThunk );
/* We assume that in this case iid and iat's are in linear order */
iatSize = iidSize - (DWORD) ( (BYTE *) iat - (BYTE *) iid );
}
addr = get_address_from_import_address_table( iat, iatSize, addr );
if( !is_valid_address( addr ) )
return 0;
}
if( !fill_info( addr, info ) )
return 0;
return 1;
}
#ifdef DLFCN_WIN32_SHARED
BOOL WINAPI DllMain( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved )
{
(void) hinstDLL;
(void) fdwReason;
(void) lpvReserved;
return TRUE;
}
#endif

94
libs/dlfcn-win32/dlfcn.h Normal file
View file

@ -0,0 +1,94 @@
/*
* dlfcn-win32
* Copyright (c) 2007 Ramiro Polla
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef DLFCN_H
#define DLFCN_H
#ifdef __cplusplus
extern "C" {
#endif
#if defined(DLFCN_WIN32_SHARED)
#if defined(DLFCN_WIN32_EXPORTS)
# define DLFCN_EXPORT __declspec(dllexport)
#else
# define DLFCN_EXPORT __declspec(dllimport)
#endif
#else
# define DLFCN_EXPORT
#endif
/* Relocations are performed when the object is loaded. */
#define RTLD_NOW 0
/* Relocations are performed at an implementation-defined time.
* Windows API does not support lazy symbol resolving (when first reference
* to a given symbol occurs). So RTLD_LAZY implementation is same as RTLD_NOW.
*/
#define RTLD_LAZY RTLD_NOW
/* All symbols are available for relocation processing of other modules. */
#define RTLD_GLOBAL (1 << 1)
/* All symbols are not made available for relocation processing by other modules. */
#define RTLD_LOCAL (1 << 2)
/* These two were added in The Open Group Base Specifications Issue 6.
* Note: All other RTLD_* flags in any dlfcn.h are not standard compliant.
*/
/* The symbol lookup happens in the normal global scope. */
#define RTLD_DEFAULT ((void *)0)
/* Specifies the next object after this one that defines name. */
#define RTLD_NEXT ((void *)-1)
/* Structure filled in by dladdr() */
typedef struct dl_info
{
const char *dli_fname; /* Filename of defining object (thread unsafe and reused on every call to dladdr) */
void *dli_fbase; /* Load address of that object */
const char *dli_sname; /* Name of nearest lower symbol */
void *dli_saddr; /* Exact value of nearest symbol */
} Dl_info;
/* Open a symbol table handle. */
DLFCN_EXPORT void *dlopen(const char *file, int mode);
/* Close a symbol table handle. */
DLFCN_EXPORT int dlclose(void *handle);
/* Get the address of a symbol from a symbol table handle. */
DLFCN_EXPORT void *dlsym(void *handle, const char *name);
/* Get diagnostic information. */
DLFCN_EXPORT char *dlerror(void);
/* Translate address to symbolic information (no POSIX standard) */
DLFCN_EXPORT int dladdr(const void *addr, Dl_info *info);
#ifdef __cplusplus
}
#endif
#endif /* DLFCN_H */

View file

@ -3607,6 +3607,7 @@ static int fstReaderRecreateHierFile(struct fstReaderContext *xc)
fflush(xc->f);
#endif
zfd = dup(fileno(xc->f));
lseek(zfd, ftell(xc->f), SEEK_SET);
zhandle = gzdopen(zfd, "rb");
if (!zhandle) {
close(zfd);
@ -4272,6 +4273,7 @@ int fstReaderInit(struct fstReaderContext *xc)
#endif
zfd = dup(fileno(xc->f));
lseek(zfd, ftell(xc->f), SEEK_SET);
zhandle = gzdopen(zfd, "rb");
if (zhandle) {
for (offpnt = 0; offpnt < uclen; offpnt += FST_GZIO_LEN) {

View file

@ -902,6 +902,11 @@ widening it to 1-bit, or removing the cell altogether.
This command replaces clocked flip-flops with generic $ff cells that use the
implicit global clock. This is useful for formal verification of designs with
multiple clocks.
This pass assumes negative hold time for the async FF inputs. For example when
a reset deasserts with the clock edge, then the FF output will still drive the
reset value in the next cycle regardless of the data-in value at the time of
the clock edge.
\end{lstlisting}
\section{clkbufmap -- insert clock buffers on clock networks}
@ -1554,12 +1559,17 @@ after an optimization pass.
-undef
enable modelling of undef states during equiv_induct.
-nocheck
disable running check before and after the command under test.
The following commands are executed by this verification command:
run_pass:
hierarchy -auto-top
design -save preopt
check -assert (unless -nocheck)
[command]
check -assert (unless -nocheck)
design -stash postopt
prepare:
@ -3122,6 +3132,12 @@ detected.
call 'flatten -wb; opt_expr -keepdc -undriven;;' on the miter circuit.
-cross
allow output ports on the gold module to match input ports on the
gate module. This is useful when the gold module contains additional
logic to drive some of the gate module inputs.
miter -assert [options] module [miter_name]
Creates a miter circuit for property checking. All input ports are kept,
@ -3989,6 +4005,19 @@ the language version (and before file names) to set additional verilog defines.
Load the specified VHDL files. (Requires Verific.)
read {-edif} <edif-file>..
Load the specified EDIF files. (Requires Verific.)
read {-liberty} <liberty-file>..
Load the specified Liberty files.
-lib
only create empty blackbox modules
read {-f|-F} <command-file>
Load and execute the specified command file. (Requires Verific.)
@ -7926,6 +7955,20 @@ Like -sv, but define FORMAL instead of SYNTHESIS.
Load the specified VHDL files into Verific.
verific {-edif} <edif-file>..
Load the specified EDIF files into Verific.
verific {-liberty} <liberty-file>..
Load the specified Liberty files into Verific.
Default library when -work is not present is one specified in liberty file.
To use from SystemVerilog or VHDL use -L to specify liberty library.
-lib
only create empty blackbox modules
verific {-f|-F} [-vlog95|-vlog2k|-sv2005|-sv2009|
-sv2012|-sv|-formal] <command-file>
@ -8032,6 +8075,10 @@ Import options:
-fullinit
Keep all register initializations, even those for non-FF registers.
-cells
Import all cell definitions from Verific loaded libraries even if they are
unused in design. Useful with "-edif" and "-liberty" option.
-chparam name value
Elaborate the specified top modules (all modules when -all given) using
this parameter value. Modules on which this parameter does not exist will

View file

@ -1494,7 +1494,7 @@ skip_identity:
RTLIL::SigSpec input = assign_map(cell->getPort(ID::S));
RTLIL::SigSpec inA = assign_map(cell->getPort(ID::A));
RTLIL::SigSpec inB = assign_map(cell->getPort(ID::B));
if (input.is_fully_const())
if (input.is_fully_const() && (!keepdc || input.is_fully_def()))
ACTION_DO(ID::Y, input.as_bool() ? cell->getPort(ID::B) : cell->getPort(ID::A));
else if (inA == inB)
ACTION_DO(ID::Y, cell->getPort(ID::A));

View file

@ -31,6 +31,7 @@ void create_miter_equiv(struct Pass *that, std::vector<std::string> args, RTLIL:
bool flag_make_outcmp = false;
bool flag_make_assert = false;
bool flag_flatten = false;
bool flag_cross = false;
log_header(design, "Executing MITER pass (creating miter circuit).\n");
@ -57,6 +58,10 @@ void create_miter_equiv(struct Pass *that, std::vector<std::string> args, RTLIL:
flag_flatten = true;
continue;
}
if (args[argidx] == "-cross") {
flag_cross = true;
continue;
}
break;
}
if (argidx+3 != args.size() || args[argidx].compare(0, 1, "-") == 0)
@ -75,6 +80,7 @@ void create_miter_equiv(struct Pass *that, std::vector<std::string> args, RTLIL:
RTLIL::Module *gold_module = design->module(gold_name);
RTLIL::Module *gate_module = design->module(gate_name);
pool<Wire*> gold_cross_ports;
for (auto gold_wire : gold_module->wires()) {
if (gold_wire->port_id == 0)
@ -82,12 +88,17 @@ void create_miter_equiv(struct Pass *that, std::vector<std::string> args, RTLIL:
RTLIL::Wire *gate_wire = gate_module->wire(gold_wire->name);
if (gate_wire == nullptr)
goto match_gold_port_error;
if (gold_wire->width != gate_wire->width)
goto match_gold_port_error;
if (flag_cross && !gold_wire->port_input && gold_wire->port_output &&
gate_wire->port_input && !gate_wire->port_output) {
gold_cross_ports.insert(gold_wire);
continue;
}
if (gold_wire->port_input != gate_wire->port_input)
goto match_gold_port_error;
if (gold_wire->port_output != gate_wire->port_output)
goto match_gold_port_error;
if (gold_wire->width != gate_wire->width)
goto match_gold_port_error;
continue;
match_gold_port_error:
log_cmd_error("No matching port in gate module was found for %s!\n", gold_wire->name.c_str());
@ -99,12 +110,15 @@ void create_miter_equiv(struct Pass *that, std::vector<std::string> args, RTLIL:
RTLIL::Wire *gold_wire = gold_module->wire(gate_wire->name);
if (gold_wire == nullptr)
goto match_gate_port_error;
if (gate_wire->width != gold_wire->width)
goto match_gate_port_error;
if (flag_cross && !gold_wire->port_input && gold_wire->port_output &&
gate_wire->port_input && !gate_wire->port_output)
continue;
if (gate_wire->port_input != gold_wire->port_input)
goto match_gate_port_error;
if (gate_wire->port_output != gold_wire->port_output)
goto match_gate_port_error;
if (gate_wire->width != gold_wire->width)
goto match_gate_port_error;
continue;
match_gate_port_error:
log_cmd_error("No matching port in gold module was found for %s!\n", gate_wire->name.c_str());
@ -123,6 +137,14 @@ void create_miter_equiv(struct Pass *that, std::vector<std::string> args, RTLIL:
for (auto gold_wire : gold_module->wires())
{
if (gold_cross_ports.count(gold_wire))
{
RTLIL::Wire *w = miter_module->addWire("\\cross_" + RTLIL::unescape_id(gold_wire->name), gold_wire->width);
gold_cell->setPort(gold_wire->name, w);
gate_cell->setPort(gold_wire->name, w);
continue;
}
if (gold_wire->port_input)
{
RTLIL::Wire *w = miter_module->addWire("\\in_" + RTLIL::unescape_id(gold_wire->name), gold_wire->width);
@ -384,6 +406,12 @@ struct MiterPass : public Pass {
log(" call 'flatten -wb; opt_expr -keepdc -undriven;;' on the miter circuit.\n");
log("\n");
log("\n");
log(" -cross\n");
log(" allow output ports on the gold module to match input ports on the\n");
log(" gate module. This is useful when the gold module contains additional\n");
log(" logic to drive some of the gate module inputs.\n");
log("\n");
log("\n");
log(" miter -assert [options] module [miter_name]\n");
log("\n");
log("Creates a miter circuit for property checking. All input ports are kept,\n");

View file

@ -758,6 +758,7 @@ struct SatHelper
if (last_timestep == -2)
log(" no model variables selected for display.\n");
fprintf(f, "#%d\n", last_timestep+1);
fclose(f);
}

View file

@ -813,18 +813,6 @@ struct SimInstance
std::string v = shared->fst->valueOf(item.second);
did_something |= set_state(item.first, Const::from_string(v));
}
for (auto &it : ff_database)
{
ff_state_t &ff = it.second;
SigSpec dsig = it.second.data.sig_d;
Const value = get_state(dsig);
if (dsig.is_wire()) {
ff.past_d = value;
if (ff.data.has_aload)
ff.past_ad = value;
did_something |= true;
}
}
for (auto cell : module->cells())
{
if (cell->is_mem_cell()) {
@ -1019,6 +1007,16 @@ struct SimWorker : SimShared
top->update_ph3();
}
void initialize_stable_past()
{
if (debug)
log("\n-- ph1 (initialize) --\n");
top->update_ph1();
if (debug)
log("\n-- ph3 (initialize) --\n");
top->update_ph3();
}
void set_inports(pool<IdString> ports, State value)
{
for (auto portname : ports)
@ -1191,6 +1189,7 @@ struct SimWorker : SimShared
if (initial) {
did_something |= top->setInitState();
initialize_stable_past();
initial = false;
}
if (did_something)

View file

@ -22,6 +22,7 @@ kernel/register.o: techlibs/common/simlib_help.inc techlibs/common/simcells_help
$(eval $(call add_share_file,share,techlibs/common/simlib.v))
$(eval $(call add_share_file,share,techlibs/common/simcells.v))
$(eval $(call add_share_file,share,techlibs/common/techmap.v))
$(eval $(call add_share_file,share,techlibs/common/smtmap.v))
$(eval $(call add_share_file,share,techlibs/common/pmux2mux.v))
$(eval $(call add_share_file,share,techlibs/common/adff2dff.v))
$(eval $(call add_share_file,share,techlibs/common/dff2ff.v))

View file

@ -1279,14 +1279,9 @@ parameter WIDTH = 0;
input [WIDTH-1:0] A, B;
input S;
output reg [WIDTH-1:0] Y;
output [WIDTH-1:0] Y;
always @* begin
if (S)
Y = B;
else
Y = A;
end
assign Y = S ? B : A;
endmodule

28
techlibs/common/smtmap.v Normal file
View file

@ -0,0 +1,28 @@
(* techmap_celltype = "$pmux" *)
module smt_pmux (A, B, S, Y);
parameter WIDTH = 1;
parameter S_WIDTH = 1;
(* force_downto *)
input [WIDTH-1:0] A;
(* force_downto *)
input [WIDTH*S_WIDTH-1:0] B;
(* force_downto *)
input [S_WIDTH-1:0] S;
(* force_downto *)
output [WIDTH-1:0] Y;
(* force_downto *)
wire [WIDTH-1:0] Y_B;
genvar i, j;
generate
(* force_downto *)
wire [WIDTH*(S_WIDTH+1)-1:0] C;
assign C[WIDTH-1:0] = A;
for (i = 0; i < S_WIDTH; i = i + 1)
assign C[WIDTH*(i+2)-1:WIDTH*(i+1)] = S[i] ? B[WIDTH*(i+1)-1:WIDTH*i] : C[WIDTH*(i+1)-1:WIDTH*i];
assign Y = C[WIDTH*(S_WIDTH+1)-1:WIDTH*S_WIDTH];
endgenerate
endmodule

View file

@ -3,7 +3,7 @@ set -eu
source ../gen-tests-makefile.sh
echo "Generate FST for sim models"
find tb/* -name tb*.v | while read name; do
test_name=$(basename -s .v $name)
test_name=$(basename $name .v)
echo "Test $test_name"
verilog_name=${test_name:3}.v
iverilog -o tb/$test_name.out $name $verilog_name