diff --git a/build-i686.sh b/build-linux_i686.sh similarity index 100% rename from build-i686.sh rename to build-linux_i686.sh diff --git a/build-toolchain.sh b/build-toolchain.sh index e4b9bd8..2af0a80 100644 --- a/build-toolchain.sh +++ b/build-toolchain.sh @@ -30,11 +30,13 @@ cd icestorm if [ "$1" == "clean" ]; then make clean fi -mv Makefile Makefile.bk cp $WORK/packages/build_x86_64/Makefile.icetools Makefile +cp $WORK/packages/build_x86_64/Makefile.icepack icepack/Makefile +cp $WORK/packages/build_x86_64/Makefile.iceprog iceprog/Makefile +cp $WORK/packages/build_x86_64/Makefile.icetime icetime/Makefile make -j$(( $(nproc) -1)) make install DESTDIR=$TCDIR PREFIX="" -mv Makefile.bk Makefile + cd .. # Install Arachne-PNR @@ -43,11 +45,9 @@ cd arachne-pnr if [ "$1" == "clean" ]; then make clean fi -mv Makefile Makefile.bk cp $WORK/packages/build_x86_64/Makefile.arachne Makefile make -j$(( $(nproc) -1)) make install DESTDIR=$TCDIR PREFIX="" ICEBOX="$TCDIR/share/icebox" -mv Makefile.bk Makefile cd .. # Install Yosys @@ -56,11 +56,10 @@ cd yosys if [ "$1" == "clean" ]; then make clean fi -mv Makefile Makefile.bk + cp $WORK/packages/build_x86_64/Makefile.yosys Makefile make -j$nproc$(( $(nproc) -1)) || exit 1 make install DESTDIR=$TCDIR PREFIX="" -mv Makefile.bk Makefile cd .. # Package tarball diff --git a/crossbuild.sh b/crossbuild.sh index ca53f5b..1cbfcc5 100644 --- a/crossbuild.sh +++ b/crossbuild.sh @@ -50,3 +50,16 @@ cp $WORK/packages/windows/*.bin $WORK/windist/$NAME/share/arachne-pnr mkdir -p $WORK/windist/$NAME/share/icebox cp $WORK/packages/windows/*.txt $WORK/windist/$NAME/share/icebox + +# -- Build yosys +cd .. +git -C yosys pull || git clone https://github.com/cliffordwolf/yosys.git +cd yosys +cp $WORK/packages/windows/Makefile.yosys Makefile + +# Apply patches (temporal) +cp $WORK/packages/windows/patches/log.h $WORK/winbuild/yosys/kernel +cp $WORK/packages/windows/patches/blifparse.cc $WORK/winbuild/yosys/frontends/blif + +# Compile +make -j$(( $(nproc) -1)) diff --git a/packages/windows/Makefile.yosys b/packages/windows/Makefile.yosys new file mode 100644 index 0000000..8d70d4d --- /dev/null +++ b/packages/windows/Makefile.yosys @@ -0,0 +1,405 @@ + +CONFIG := mxe +# CONFIG := gcc +# CONFIG := emcc +# CONFIG := mxe + +# features (the more the better) +ENABLE_TCL := 0 +ENABLE_READLINE := 0 +ENABLE_ABC := 1 + +# clang sanitizers +SANITIZER = + +PREFIX ?= /usr/local +INSTALL_SUDO := + +TARGET_BINDIR := $(DESTDIR)$(PREFIX)/bin +TARGET_DATDIR := $(DESTDIR)$(PREFIX)/share/yosys + +EXE = +OBJS = +GENFILES = +EXTRA_OBJS = +EXTRA_TARGETS = +TARGETS = yosys$(EXE) yosys-config + +PRETTY = 0 +SMALL = 0 + +all: top-all + +YOSYS_SRC := $(dir $(firstword $(MAKEFILE_LIST))) +VPATH := $(YOSYS_SRC) + +CXXFLAGS += -Wall -Wextra -ggdb -I. -I"$(YOSYS_SRC)" -MD -D_YOSYS_ -fPIC -I$(DESTDIR)$(PREFIX)/include +LDFLAGS += -L$(DESTDIR)$(PREFIX)/lib -rdynamic +LDLIBS = -lstdc++ -lm -lrt +SED = sed +BISON = bison + +YOSYS_VER := 0.5+$(shell cd $(YOSYS_SRC) && test -d .git && { git log --author=clifford@clifford.at --oneline c3c9fbfb8c678.. | wc -l; }) +GIT_REV := $(shell cd $(YOSYS_SRC) && git rev-parse --short HEAD 2> /dev/null || echo UNKNOWN) +OBJS = kernel/version_$(GIT_REV).o + +# set 'ABCREV = default' to use abc/ as it is +# +# Note: If you do ABC development, make sure that 'abc' in this directory +# is just a symlink to your actual ABC working directory, as 'make mrproper' +# will remove the 'abc' directory and you do not want to accidentally +# delete your work on ABC.. +ABCREV = ae7d65e71adc +ABCPULL = 1 +ABCMKARGS = CC="$(CXX)" CXX="$(CXX)" + +define newline + + +endef + +ifneq ($(wildcard Makefile.conf),) +$(info $(subst $$--$$,$(newline),$(shell sed 's,^,[Makefile.conf] ,; s,$$,$$--$$,;' < Makefile.conf | tr -d '\n' | sed 's,\$$--\$$$$,,'))) +include Makefile.conf +endif + +ifeq ($(CONFIG),clang) +CXX = clang +LD = clang++ +CXXFLAGS += -std=c++11 -Os + +ifneq ($(SANITIZER),) +$(info [Clang Sanitizer] $(SANITIZER)) +CXXFLAGS += -g -O1 -fno-omit-frame-pointer -fno-optimize-sibling-calls -fsanitize=$(SANITIZER) +LDFLAGS += -g -fsanitize=$(SANITIZER) + +endif + +else ifeq ($(CONFIG),mxe) +CXX = i686-w64-mingw32-gcc +LD = i686-w64-mingw32-gcc +CXXFLAGS += -std=gnu++0x -Os -D_POSIX_SOURCE +CXXFLAGS := $(filter-out -fPIC,$(CXXFLAGS)) +LDFLAGS := $(filter-out -rdynamic,$(LDFLAGS)) -s +LDLIBS := $(filter-out -lrt,$(LDLIBS)) +ABCMKARGS += ARCHFLAGS="-DSIZEOF_VOID_P=4 -DSIZEOF_LONG=4 -DSIZEOF_INT=4 -DWIN32_NO_DLL -x c++ -fpermissive -w" +ABCMKARGS += LIBS="lib/x86/pthreadVC2.lib -s" ABC_USE_NO_READLINE=1 CC="$(CXX)" CXX="$(CXX)" +EXE = .exe + +endif + +ifeq ($(ENABLE_READLINE),1) +CXXFLAGS += -DYOSYS_ENABLE_READLINE +LDLIBS += -lreadline +ifeq ($(CONFIG),mxe) +LDLIBS += -lpdcurses +endif +endif + + +ifeq ($(ENABLE_TCL),1) +TCL_VERSION ?= tcl$(shell echo 'puts [info tclversion]' | tclsh) +TCL_INCLUDE ?= /usr/include/$(TCL_VERSION) +CXXFLAGS += -I$(TCL_INCLUDE) -DYOSYS_ENABLE_TCL +LDLIBS += -l$(TCL_VERSION) +endif + +ifeq ($(ENABLE_ABC),1) +CXXFLAGS += -DYOSYS_ENABLE_ABC +TARGETS += yosys-abc$(EXE) +endif + + +define add_share_file +EXTRA_TARGETS += $(subst //,/,$(1)/$(notdir $(2))) +$(subst //,/,$(1)/$(notdir $(2))): $(2) + $$(P) mkdir -p $(1) + $$(Q) cp "$(YOSYS_SRC)"/$(2) $(subst //,/,$(1)/$(notdir $(2))) +endef + +define add_gen_share_file +EXTRA_TARGETS += $(subst //,/,$(1)/$(notdir $(2))) +$(subst //,/,$(1)/$(notdir $(2))): $(2) + $$(P) mkdir -p $(1) + $$(Q) cp $(2) $(subst //,/,$(1)/$(notdir $(2))) +endef + +define add_include_file +$(eval $(call add_share_file,$(dir share/include/$(1)),$(1))) +endef + +ifeq ($(PRETTY), 1) +P_STATUS = 0 +P_OFFSET = 0 +P_UPDATE = $(eval P_STATUS=$(shell echo $(OBJS) yosys$(EXE) | gawk 'BEGIN { RS = " "; I = $(P_STATUS)+0; } $$1 == "$@" && NR > I { I = NR; } END { print I; }')) +P_SHOW = [$(shell gawk "BEGIN { N=$(words $(OBJS) yosys$(EXE)); printf \"%3d\", $(P_OFFSET)+90*$(P_STATUS)/N; exit; }")%] +P = @echo "$(if $(findstring $@,$(TARGETS) $(EXTRA_TARGETS)),$(eval P_OFFSET = 10))$(call P_UPDATE)$(call P_SHOW) Building $@"; +Q = @ +S = -s +else +P_SHOW = -> +P = +Q = +S = +endif + +$(eval $(call add_include_file,kernel/yosys.h)) +$(eval $(call add_include_file,kernel/hashlib.h)) +$(eval $(call add_include_file,kernel/log.h)) +$(eval $(call add_include_file,kernel/rtlil.h)) +$(eval $(call add_include_file,kernel/register.h)) +$(eval $(call add_include_file,kernel/celltypes.h)) +$(eval $(call add_include_file,kernel/consteval.h)) +$(eval $(call add_include_file,kernel/sigtools.h)) +$(eval $(call add_include_file,kernel/modtools.h)) +$(eval $(call add_include_file,kernel/macc.h)) +$(eval $(call add_include_file,kernel/utils.h)) +$(eval $(call add_include_file,kernel/satgen.h)) +$(eval $(call add_include_file,libs/ezsat/ezsat.h)) +$(eval $(call add_include_file,libs/ezsat/ezminisat.h)) +$(eval $(call add_include_file,libs/sha1/sha1.h)) +$(eval $(call add_include_file,passes/fsm/fsmdata.h)) +$(eval $(call add_include_file,backends/ilang/ilang_backend.h)) + +OBJS += kernel/driver.o kernel/register.o kernel/rtlil.o kernel/log.o kernel/calc.o kernel/yosys.o kernel/cellaigs.o +kernel/log.o: CXXFLAGS += -DYOSYS_SRC='"$(YOSYS_SRC)"' + +OBJS += libs/bigint/BigIntegerAlgorithms.o libs/bigint/BigInteger.o libs/bigint/BigIntegerUtils.o +OBJS += libs/bigint/BigUnsigned.o libs/bigint/BigUnsignedInABase.o + +OBJS += libs/sha1/sha1.o + +ifneq ($(SMALL),1) + +OBJS += libs/subcircuit/subcircuit.o + +OBJS += libs/ezsat/ezsat.o +OBJS += libs/ezsat/ezminisat.o + +OBJS += libs/minisat/Options.o +OBJS += libs/minisat/SimpSolver.o +OBJS += libs/minisat/Solver.o +OBJS += libs/minisat/System.o + +include $(YOSYS_SRC)/frontends/*/Makefile.inc +include $(YOSYS_SRC)/passes/*/Makefile.inc +include $(YOSYS_SRC)/backends/*/Makefile.inc +include $(YOSYS_SRC)/techlibs/*/Makefile.inc + +else + +include frontends/verilog/Makefile.inc +include frontends/ilang/Makefile.inc +include frontends/ast/Makefile.inc +include frontends/blif/Makefile.inc + +OBJS += passes/hierarchy/hierarchy.o +OBJS += passes/cmds/select.o +OBJS += passes/cmds/show.o +OBJS += passes/cmds/stat.o +OBJS += passes/cmds/cover.o +OBJS += passes/cmds/design.o +OBJS += passes/cmds/plugin.o + +include passes/proc/Makefile.inc +include passes/opt/Makefile.inc +include passes/techmap/Makefile.inc + +include backends/verilog/Makefile.inc +include backends/ilang/Makefile.inc + +include techlibs/common/Makefile.inc + +endif + +top-all: $(TARGETS) $(EXTRA_TARGETS) + @echo "" + @echo " Build successful." + @echo "" + +ifeq ($(CONFIG),emcc) +yosys.js: $(filter-out yosysjs-$(YOSYS_VER).zip,$(EXTRA_TARGETS)) +endif + +yosys$(EXE): $(OBJS) + $(P) $(LD) -o yosys$(EXE) $(LDFLAGS) $(OBJS) $(LDLIBS) + +libyosys.so: $(filter-out kernel/driver.o,$(OBJS)) + $(P) $(LD) -o libyosys.so -shared -Wl,-soname,libyosys.so $(LDFLAGS) $^ $(LDLIBS) + +%.o: %.cc + $(Q) mkdir -p $(dir $@) + $(P) $(CXX) -o $@ -c $(CPPFLAGS) $(CXXFLAGS) $< + +%.o: %.cpp + $(Q) mkdir -p $(dir $@) + $(P) $(CXX) -o $@ -c $(CPPFLAGS) $(CXXFLAGS) $< + +kernel/version_$(GIT_REV).cc: $(YOSYS_SRC)/Makefile + $(P) rm -f kernel/version_*.o kernel/version_*.d kernel/version_*.cc + $(Q) mkdir -p kernel && echo "namespace Yosys { extern const char *yosys_version_str; const char *yosys_version_str=\"Yosys $(YOSYS_VER) (git sha1 $(GIT_REV), $(notdir $(CXX)) ` \ + $(CXX) --version | tr ' ()' '\n' | grep '^[0-9]' | head -n1` $(filter -f% -m% -O% -DNDEBUG,$(CXXFLAGS)))\"; }" > kernel/version_$(GIT_REV).cc + +yosys-config: misc/yosys-config.in + $(P) $(SED) -e 's#@CXXFLAGS@#$(subst -I. -I"$(YOSYS_SRC)",-I"$(TARGET_DATDIR)/include",$(CXXFLAGS))#;' \ + -e 's#@CXX@#$(CXX)#;' -e 's#@LDFLAGS@#$(LDFLAGS)#;' -e 's#@LDLIBS@#$(LDLIBS)#;' \ + -e 's#@BINDIR@#$(TARGET_BINDIR)#;' -e 's#@DATDIR@#$(TARGET_DATDIR)#;' < $< > yosys-config + $(Q) chmod +x yosys-config + +abc/abc-$(ABCREV)$(EXE): + $(P) +ifneq ($(ABCREV),default) + $(Q) if ( cd abc 2> /dev/null && hg identify; ) | grep -q +; then \ + echo 'REEBE: NOP pbagnvaf ybpny zbqvsvpngvbaf! Frg NOPERI=qrsnhyg va Lbflf Znxrsvyr!' | tr 'A-Za-z' 'N-ZA-Mn-za-m'; false; \ + fi + $(Q) if test "`cd abc 2> /dev/null && hg identify | cut -f1 -d' '`" != "$(ABCREV)"; then \ + test $(ABCPULL) -ne 0 || { echo 'REEBE: NOP abg hc gb qngr naq NOPCHYY frg gb 0 va Znxrsvyr!' | tr 'A-Za-z' 'N-ZA-Mn-za-m'; exit 1; }; \ + echo "Pulling ABC from bitbucket.org:"; set -x; \ + test -d abc || hg clone https://bitbucket.org/alanmi/abc abc; \ + cd abc && $(MAKE) DEP= clean && hg pull && hg update -r $(ABCREV); \ + fi +endif + $(Q) rm -f abc/abc-[0-9a-f]* + $(Q) cd abc && $(MAKE) $(S) $(ABCMKARGS) PROG="abc-$(ABCREV)$(EXE)" MSG_PREFIX="$(eval P_OFFSET = 5)$(call P_SHOW)$(eval P_OFFSET = 10) ABC: " + +ifeq ($(ABCREV),default) +.PHONY: abc/abc-$(ABCREV)$(EXE) +endif + +yosys-abc$(EXE): abc/abc-$(ABCREV)$(EXE) + $(P) cp abc/abc-$(ABCREV)$(EXE) yosys-abc$(EXE) + +test: $(TARGETS) $(EXTRA_TARGETS) + +cd tests/simple && bash run-test.sh + +cd tests/hana && bash run-test.sh + +cd tests/asicworld && bash run-test.sh + +cd tests/realmath && bash run-test.sh + +cd tests/share && bash run-test.sh + +cd tests/fsm && bash run-test.sh + +cd tests/techmap && bash run-test.sh + +cd tests/memories && bash run-test.sh + +cd tests/bram && bash run-test.sh + +cd tests/various && bash run-test.sh + +cd tests/sat && bash run-test.sh + @echo "" + @echo " Passed \"make test\"." + @echo "" + +VALGRIND ?= valgrind --error-exitcode=1 --leak-check=full --show-reachable=yes --errors-for-leak-kinds=all + +vgtest: $(TARGETS) $(EXTRA_TARGETS) + $(VALGRIND) ./yosys -p 'setattr -mod -unset top; synth' $$( ls tests/simple/*.v | grep -v repwhile.v ) + @echo "" + @echo " Passed \"make vgtest\"." + @echo "" + +vloghtb: $(TARGETS) $(EXTRA_TARGETS) + +cd tests/vloghtb && bash run-test.sh + @echo "" + @echo " Passed \"make vloghtb\"." + @echo "" + +install: $(TARGETS) $(EXTRA_TARGETS) + $(INSTALL_SUDO) mkdir -p $(DESTDIR)$(PREFIX)/bin + $(INSTALL_SUDO) install $(TARGETS) $(DESTDIR)$(PREFIX)/bin/ + $(INSTALL_SUDO) mkdir -p $(DESTDIR)$(PREFIX)/share/yosys + $(INSTALL_SUDO) cp -r share/. $(DESTDIR)$(PREFIX)/share/yosys/. + +uninstall: + $(INSTALL_SUDO) rm -vf $(addprefix $(DESTDIR)$(PREFIX)/bin/,$(notdir $(TARGETS))) + $(INSTALL_SUDO) rm -rvf $(DESTDIR)$(PREFIX)/share/yosys/ + +update-manual: $(TARGETS) $(EXTRA_TARGETS) + cd manual && ../yosys -p 'help -write-tex-command-reference-manual' + +manual: $(TARGETS) $(EXTRA_TARGETS) + cd manual && bash appnotes.sh + cd manual && bash presentation.sh + cd manual && bash manual.sh + +clean: + rm -rf share + if test -d manual; then cd manual && sh clean.sh; fi + rm -f $(OBJS) $(GENFILES) $(TARGETS) $(EXTRA_TARGETS) $(EXTRA_OBJS) + rm -f kernel/version_*.o kernel/version_*.cc abc/abc-[0-9a-f]* + rm -f libs/*/*.d frontends/*/*.d passes/*/*.d backends/*/*.d kernel/*.d techlibs/*/*.d + rm -r abc + +clean-abc: + $(MAKE) -C abc DEP= clean + rm -f yosys-abc$(EXE) abc/abc-[0-9a-f]* + +mrproper: clean + git clean -xdf + +qtcreator: + { for file in $(basename $(OBJS)); do \ + for prefix in cc y l; do if [ -f $${file}.$${prefix} ]; then echo $$file.$${prefix}; fi; done \ + done; find backends frontends kernel libs passes -type f \( -name '*.h' -o -name '*.hh' \); } > qtcreator.files + { echo .; find backends frontends kernel libs passes -type f \( -name '*.h' -o -name '*.hh' \) -printf '%h\n' | sort -u; } > qtcreator.includes + touch qtcreator.config qtcreator.creator + +vcxsrc: $(GENFILES) $(EXTRA_TARGETS) + rm -rf yosys-win32-vcxsrc-$(YOSYS_VER){,.zip} + set -e; for f in `ls $(filter %.cc %.cpp,$(GENFILES)) $(addsuffix .cc,$(basename $(OBJS))) $(addsuffix .cpp,$(basename $(OBJS))) 2> /dev/null`; do \ + echo "Analyse: $$f" >&2; cpp -std=gnu++0x -MM -I. -D_YOSYS_ $$f; done | sed 's,.*:,,; s,//*,/,g; s,/[^/]*/\.\./,/,g; y, \\,\n\n,;' | grep '^[^/]' | sort -u | grep -v kernel/version_ > srcfiles.txt + bash misc/create_vcxsrc.sh yosys-win32-vcxsrc $(YOSYS_VER) $(GIT_REV) + echo "namespace Yosys { extern const char *yosys_version_str; const char *yosys_version_str=\"Yosys (Version Information Unavailable)\"; }" > kernel/version.cc + zip yosys-win32-vcxsrc-$(YOSYS_VER)/genfiles.zip $(GENFILES) kernel/version.cc + zip -r yosys-win32-vcxsrc-$(YOSYS_VER).zip yosys-win32-vcxsrc-$(YOSYS_VER)/ + rm -f srcfiles.txt kernel/version.cc + +ifeq ($(CONFIG),mxe) +mxebin: $(TARGETS) $(EXTRA_TARGETS) + rm -rf yosys-win32-mxebin-$(YOSYS_VER){,.zip} + mkdir -p yosys-win32-mxebin-$(YOSYS_VER) + cp -r yosys.exe share/ yosys-win32-mxebin-$(YOSYS_VER)/ +ifeq ($(ENABLE_ABC),1) + cp -r yosys-abc.exe abc/lib/x86/pthreadVC2.dll yosys-win32-mxebin-$(YOSYS_VER)/ +endif + echo -en 'This is Yosys $(YOSYS_VER) for Win32.\r\n' > yosys-win32-mxebin-$(YOSYS_VER)/readme.txt + echo -en 'Documentation at http://www.clifford.at/yosys/.\r\n' >> yosys-win32-mxebin-$(YOSYS_VER)/readme.txt + zip -r yosys-win32-mxebin-$(YOSYS_VER).zip yosys-win32-mxebin-$(YOSYS_VER)/ +endif + +config-clean: clean + rm -f Makefile.conf + +config-clang: clean + echo 'CONFIG := clang' > Makefile.conf + +config-gcc: clean + echo 'CONFIG := gcc' > Makefile.conf + +config-emcc: clean + echo 'CONFIG := emcc' > Makefile.conf + echo 'ENABLE_TCL := 0' >> Makefile.conf + echo 'ENABLE_ABC := 0' >> Makefile.conf + echo 'ENABLE_READLINE := 0' >> Makefile.conf + +config-mxe: clean + echo 'CONFIG := mxe' > Makefile.conf + echo 'ENABLE_TCL := 0' >> Makefile.conf + echo 'ENABLE_READLINE := 0' >> Makefile.conf + +config-gprof: clean + echo 'CONFIG := gcc' > Makefile.conf + +config-sudo: + echo "INSTALL_SUDO := sudo" >> Makefile.conf + +echo-yosys-ver: + @echo "$(YOSYS_VER)" + +echo-git-rev: + @echo "$(GIT_REV)" + +-include libs/*/*.d +-include frontends/*/*.d +-include passes/*/*.d +-include backends/*/*.d +-include kernel/*.d +-include techlibs/*/*.d + +.PHONY: all top-all abc test install install-abc manual clean mrproper qtcreator +.PHONY: config-clean config-clang config-gcc config-gprof config-sudo diff --git a/packages/windows/patches/README.txt b/packages/windows/patches/README.txt new file mode 100644 index 0000000..ed3fbae --- /dev/null +++ b/packages/windows/patches/README.txt @@ -0,0 +1,2 @@ +winbuild/yosys/kernel/log.h +winbuild/yosys/forntends/blif/blifparse.cc diff --git a/packages/windows/patches/blifparse.cc b/packages/windows/patches/blifparse.cc new file mode 100644 index 0000000..2029584 --- /dev/null +++ b/packages/windows/patches/blifparse.cc @@ -0,0 +1,420 @@ +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2012 Clifford Wolf + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#include "blifparse.h" + +YOSYS_NAMESPACE_BEGIN + +static bool read_next_line(char *&buffer, size_t &buffer_size, int &line_count, std::istream &f) +{ + int buffer_len = 0; + buffer[0] = 0; + + while (1) + { + buffer_len += strlen(buffer + buffer_len); + while (buffer_len > 0 && (buffer[buffer_len-1] == ' ' || buffer[buffer_len-1] == '\t' || + buffer[buffer_len-1] == '\r' || buffer[buffer_len-1] == '\n')) + buffer[--buffer_len] = 0; + + if (buffer_size-buffer_len < 4096) { + buffer_size *= 2; + buffer = (char*)realloc(buffer, buffer_size); + } + + if (buffer_len == 0 || buffer[buffer_len-1] == '\\') { + if (buffer_len > 0 && buffer[buffer_len-1] == '\\') + buffer[--buffer_len] = 0; + line_count++; + if (!f.getline(buffer+buffer_len, buffer_size-buffer_len)) + return false; + } else + return true; + } +} + +void parse_blif(RTLIL::Design *design, std::istream &f, std::string dff_name, bool run_clean) +{ + RTLIL::Module *module = nullptr; + RTLIL::Const *lutptr = NULL; + RTLIL::State lut_default_state = RTLIL::State::Sx; + int blif_maxnum = 0; + + auto blif_wire = [&](const std::string &wire_name) -> Wire* + { + if (wire_name[0] == '$') + { + for (int i = 0; i+1 < GetSize(wire_name); i++) + { + if (wire_name[i] != '$') + continue; + + int len = 0; + while (i+len+1 < GetSize(wire_name) && '0' <= wire_name[i+len+1] && wire_name[i+len+1] <= '9') + len++; + + if (len > 0) { + string num_str = wire_name.substr(i+1, len); + int num = atoi(num_str.c_str()) & 0x0fffffff; + blif_maxnum = std::max(blif_maxnum, num); + } + } + } + + IdString wire_id = RTLIL::escape_id(wire_name); + Wire *wire = module->wire(wire_id); + + if (wire == nullptr) + wire = module->addWire(wire_id); + + return wire; + }; + + dict *obj_attributes = nullptr; + dict *obj_parameters = nullptr; + + size_t buffer_size = 4096; + char *buffer = (char*)malloc(buffer_size); + int line_count = 0; + + while (1) + { + if (!read_next_line(buffer, buffer_size, line_count, f)) { + if (module != nullptr) + goto error; + free(buffer); + return; + } + + continue_without_read: + if (buffer[0] == '#') + continue; + + if (buffer[0] == '.') + { + if (lutptr) { + for (auto &bit : lutptr->bits) + if (bit == RTLIL::State::Sx) + bit = lut_default_state; + lutptr = NULL; + lut_default_state = RTLIL::State::Sx; + } + + char *cmd = strtok(buffer, " \t\r\n"); + + if (!strcmp(cmd, ".model")) { + if (module != nullptr) + goto error; + module = new RTLIL::Module; + module->name = RTLIL::escape_id(strtok(NULL, " \t\r\n")); + obj_attributes = &module->attributes; + obj_parameters = nullptr; + if (design->module(module->name)) + log_error("Duplicate definition of module %s in line %d!\n", log_id(module->name), line_count); + design->add(module); + continue; + } + + if (module == nullptr) + goto error; + + if (!strcmp(cmd, ".end")) + { + module->fixup_ports(); + + if (run_clean) + { + Const buffer_lut(vector({State::S0, State::S1})); + vector remove_cells; + + for (auto cell : module->cells()) + if (cell->type == "$lut" && cell->getParam("\\LUT") == buffer_lut) { + module->connect(cell->getPort("\\Y"), cell->getPort("\\A")); + remove_cells.push_back(cell); + } + + for (auto cell : remove_cells) + module->remove(cell); + + Wire *true_wire = module->wire("$true"); + Wire *false_wire = module->wire("$false"); + Wire *undef_wire = module->wire("$undef"); + + if (true_wire != nullptr) + module->rename(true_wire, stringf("$true$%d", ++blif_maxnum)); + + if (false_wire != nullptr) + module->rename(false_wire, stringf("$false$%d", ++blif_maxnum)); + + if (undef_wire != nullptr) + module->rename(undef_wire, stringf("$undef$%d", ++blif_maxnum)); + + autoidx = std::max(autoidx, blif_maxnum+1); + blif_maxnum = 0; + } + + module = nullptr; + obj_attributes = nullptr; + obj_parameters = nullptr; + continue; + } + + if (!strcmp(cmd, ".inputs") || !strcmp(cmd, ".outputs")) { + char *p; + while ((p = strtok(NULL, " \t\r\n")) != NULL) { + RTLIL::IdString wire_name(stringf("\\%s", p)); + RTLIL::Wire *wire = module->wire(wire_name); + if (wire == nullptr) + wire = module->addWire(wire_name); + if (!strcmp(cmd, ".inputs")) + wire->port_input = true; + else + wire->port_output = true; + } + obj_attributes = nullptr; + obj_parameters = nullptr; + continue; + } + + if (!strcmp(cmd, ".attr") || !strcmp(cmd, ".param")) { + char *n = strtok(NULL, " \t\r\n"); + char *v = strtok(NULL, "\r\n"); + IdString id_n = RTLIL::escape_id(n); + Const const_v; + if (v[0] == '"') { + std::string str(v+1); + if (str.back() == '"') + str.resize(str.size()-1); + const_v = Const(str); + } else { + int n = strlen(v); + const_v.bits.resize(n); + for (int i = 0; i < n; i++) + const_v.bits[i] = v[n-i-1] != '0' ? State::S1 : State::S0; + } + if (!strcmp(cmd, ".attr")) { + if (obj_attributes == nullptr) + goto error; + (*obj_attributes)[id_n] = const_v; + } else { + if (obj_parameters == nullptr) + goto error; + (*obj_parameters)[id_n] = const_v; + } + continue; + } + + if (!strcmp(cmd, ".latch")) + { + char *d = strtok(NULL, " \t\r\n"); + char *q = strtok(NULL, " \t\r\n"); + char *edge = strtok(NULL, " \t\r\n"); + char *clock = strtok(NULL, " \t\r\n"); + char *init = strtok(NULL, " \t\r\n"); + RTLIL::Cell *cell = nullptr; + + if (clock == nullptr && edge != nullptr) { + init = edge; + edge = nullptr; + } + + if (init != nullptr && (init[0] == '0' || init[0] == '1')) + blif_wire(d)->attributes["\\init"] = Const(init[0] == '1' ? 1 : 0, 1); + + if (clock == nullptr) + goto no_latch_clock; + + if (!strcmp(edge, "re")) + cell = module->addDff(NEW_ID, blif_wire(clock), blif_wire(d), blif_wire(q)); + else if (!strcmp(edge, "fe")) + cell = module->addDff(NEW_ID, blif_wire(clock), blif_wire(d), blif_wire(q), false); + else { + no_latch_clock: + cell = module->addCell(NEW_ID, dff_name); + cell->setPort("\\D", blif_wire(d)); + cell->setPort("\\Q", blif_wire(q)); + } + + obj_attributes = &cell->attributes; + obj_parameters = &cell->parameters; + continue; + } + + if (!strcmp(cmd, ".gate") || !strcmp(cmd, ".subckt")) + { + char *p = strtok(NULL, " \t\r\n"); + if (p == NULL) + goto error; + + IdString celltype = RTLIL::escape_id(p); + RTLIL::Cell *cell = module->addCell(NEW_ID, celltype); + + while ((p = strtok(NULL, " \t\r\n")) != NULL) { + char *q = strchr(p, '='); + if (q == NULL || !q[0] || !q[1]) + goto error; + *(q++) = 0; + cell->setPort(RTLIL::escape_id(p), blif_wire(q)); + } + + obj_attributes = &cell->attributes; + obj_parameters = &cell->parameters; + continue; + } + + obj_attributes = nullptr; + obj_parameters = nullptr; + + if (!strcmp(cmd, ".barbuf")) + { + char *p = strtok(NULL, " \t\r\n"); + if (p == NULL) + goto error; + + char *q = strtok(NULL, " \t\r\n"); + if (q == NULL) + goto error; + + module->connect(blif_wire(q), blif_wire(p)); + continue; + } + + if (!strcmp(cmd, ".names")) + { + char *p; + RTLIL::SigSpec input_sig, output_sig; + while ((p = strtok(NULL, " \t\r\n")) != NULL) + input_sig.append(blif_wire(p)); + output_sig = input_sig.extract(input_sig.size()-1, 1); + input_sig = input_sig.extract(0, input_sig.size()-1); + + if (input_sig.size() == 0) + { + RTLIL::State state = RTLIL::State::Sa; + while (1) { + if (!read_next_line(buffer, buffer_size, line_count, f)) + goto error; + for (int i = 0; buffer[i]; i++) { + if (buffer[i] == ' ' || buffer[i] == '\t') + continue; + if (i == 0 && buffer[i] == '.') + goto finished_parsing_constval; + if (buffer[i] == '0') { + if (state == RTLIL::State::S1) + goto error; + state = RTLIL::State::S0; + continue; + } + if (buffer[i] == '1') { + if (state == RTLIL::State::S0) + goto error; + state = RTLIL::State::S1; + continue; + } + goto error; + } + } + + finished_parsing_constval: + if (state == RTLIL::State::Sa) + state = RTLIL::State::S0; + if (output_sig.as_wire()->name == "$undef") + state = RTLIL::State::Sx; + module->connect(RTLIL::SigSig(output_sig, state)); + goto continue_without_read; + } + + RTLIL::Cell *cell = module->addCell(NEW_ID, "$lut"); + cell->parameters["\\WIDTH"] = RTLIL::Const(input_sig.size()); + cell->parameters["\\LUT"] = RTLIL::Const(RTLIL::State::Sx, 1 << input_sig.size()); + cell->setPort("\\A", input_sig); + cell->setPort("\\Y", output_sig); + lutptr = &cell->parameters.at("\\LUT"); + lut_default_state = RTLIL::State::Sx; + continue; + } + + goto error; + } + + if (lutptr == NULL) + goto error; + + char *input = strtok(buffer, " \t\r\n"); + char *output = strtok(NULL, " \t\r\n"); + + if (input == NULL || output == NULL || (strcmp(output, "0") && strcmp(output, "1"))) + goto error; + + int input_len = strlen(input); + if (input_len > 8) + goto error; + + for (int i = 0; i < (1 << input_len); i++) { + for (int j = 0; j < input_len; j++) { + char c1 = input[j]; + if (c1 != '-') { + char c2 = (i & (1 << j)) != 0 ? '1' : '0'; + if (c1 != c2) + goto try_next_value; + } + } + lutptr->bits.at(i) = !strcmp(output, "0") ? RTLIL::State::S0 : RTLIL::State::S1; + try_next_value:; + } + + lut_default_state = !strcmp(output, "0") ? RTLIL::State::S1 : RTLIL::State::S0; + } + +error: + log_error("Syntax error in line %d!\n", line_count); +} + +struct BlifFrontend : public Frontend { + BlifFrontend() : Frontend("blif", "read BLIF file") { } + virtual void help() + { + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| + log("\n"); + log(" read_blif [filename]\n"); + log("\n"); + log("Load modules from a BLIF file into the current design.\n"); + log("\n"); + } + virtual void execute(std::istream *&f, std::string filename, std::vector args, RTLIL::Design *design) + { + log_header("Executing BLIF frontend.\n"); + + size_t argidx; + for (argidx = 1; argidx < args.size(); argidx++) { + std::string arg = args[argidx]; + // if (arg == "-lib") { + // flag_lib = true; + // continue; + // } + break; + } + extra_args(f, filename, args, argidx); + + parse_blif(design, *f, "\\DFF", true); + } +} BlifFrontend; + +YOSYS_NAMESPACE_END + diff --git a/packages/windows/patches/log.h b/packages/windows/patches/log.h new file mode 100644 index 0000000..997d998 --- /dev/null +++ b/packages/windows/patches/log.h @@ -0,0 +1,278 @@ +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2012 Clifford Wolf + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#include "kernel/yosys.h" + +#ifndef LOG_H +#define LOG_H + +#include + +#ifndef _WIN32 +# include +# include +#endif + +#if defined(_MSC_VER) +// At least this is not in MSVC++ 2013. +# define __PRETTY_FUNCTION__ __FUNCTION__ +#endif + +// from libs/sha1/sha1.h +class SHA1; + +YOSYS_NAMESPACE_BEGIN + +#define S__LINE__sub2(x) #x +#define S__LINE__sub1(x) S__LINE__sub2(x) +#define S__LINE__ S__LINE__sub1(__LINE__) + +struct log_cmd_error_exception { }; + +extern std::vector log_files; +extern std::vector log_streams; +extern FILE *log_errfile; +extern SHA1 *log_hasher; + +extern bool log_time; +extern bool log_error_stderr; +extern bool log_cmd_error_throw; +extern bool log_quiet_warnings; +extern int log_verbose_level; +extern string log_last_error; + +void logv(const char *format, va_list ap); +void logv_header(const char *format, va_list ap); +void logv_warning(const char *format, va_list ap); +YS_NORETURN void logv_error(const char *format, va_list ap) YS_ATTRIBUTE(noreturn); + +void log(const char *format, ...) YS_ATTRIBUTE(format(printf, 1, 2)); +void log_header(const char *format, ...) YS_ATTRIBUTE(format(printf, 1, 2)); +void log_warning(const char *format, ...) YS_ATTRIBUTE(format(printf, 1, 2)); +YS_NORETURN void log_error(const char *format, ...) YS_ATTRIBUTE(format(printf, 1, 2), noreturn); +YS_NORETURN void log_cmd_error(const char *format, ...) YS_ATTRIBUTE(format(printf, 1, 2), noreturn); + +void log_spacer(); +void log_push(); +void log_pop(); + +void log_backtrace(const char *prefix, int levels); +void log_reset_stack(); +void log_flush(); + +const char *log_signal(const RTLIL::SigSpec &sig, bool autoint = true); +const char *log_id(RTLIL::IdString id); + +template static inline const char *log_id(T *obj) { + return log_id(obj->name); +} + +void log_cell(RTLIL::Cell *cell, std::string indent = ""); + +#ifndef NDEBUG +static inline void log_assert_worker(bool cond, const char *expr, const char *file, int line) { + if (!cond) log_error("Assert `%s' failed in %s:%d.\n", expr, file, line); +} +# define log_assert(_assert_expr_) YOSYS_NAMESPACE_PREFIX log_assert_worker(_assert_expr_, #_assert_expr_, __FILE__, __LINE__) +#else +# define log_assert(_assert_expr_) +#endif + +#define log_abort() YOSYS_NAMESPACE_PREFIX log_error("Abort in %s:%d.\n", __FILE__, __LINE__) +#define log_ping() YOSYS_NAMESPACE_PREFIX log("-- %s:%d %s --\n", __FILE__, __LINE__, __PRETTY_FUNCTION__) + + +// --------------------------------------------------- +// This is the magic behind the code coverage counters +// --------------------------------------------------- + +#if defined(YOSYS_ENABLE_COVER) && defined(__linux__) + +#define cover(_id) do { \ + static CoverData __d __attribute__((section("yosys_cover_list"), aligned(1), used)) = { __FILE__, __FUNCTION__, _id, __LINE__, 0 }; \ + __d.counter++; \ +} while (0) + +struct CoverData { + const char *file, *func, *id; + int line, counter; +} YS_ATTRIBUTE(packed); + +// this two symbols are created by the linker for the "yosys_cover_list" ELF section +extern "C" struct CoverData __start_yosys_cover_list[]; +extern "C" struct CoverData __stop_yosys_cover_list[]; + +extern dict> extra_coverage_data; + +void cover_extra(std::string parent, std::string id, bool increment = true); +dict> get_coverage_data(); + +#define cover_list(_id, ...) do { cover(_id); \ + std::string r = cover_list_worker(_id, __VA_ARGS__); \ + log_assert(r.empty()); \ +} while (0) + +static inline std::string cover_list_worker(std::string, std::string last) { + return last; +} + +template +std::string cover_list_worker(std::string prefix, std::string first, T... rest) { + std::string selected = cover_list_worker(prefix, rest...); + cover_extra(prefix, prefix + "." + first, first == selected); + return first == selected ? "" : selected; +} + +#else +# define cover(...) do { } while (0) +# define cover_list(...) do { } while (0) +#endif + + +// ------------------------------------------------------------ +// everything below this line are utilities for troubleshooting +// ------------------------------------------------------------ + +// simple timer for performance measurements +// toggle the '#if 1' to get a baseline for the performance penalty added by the measurement +struct PerformanceTimer +{ +#if 1 + int64_t total_ns; + + PerformanceTimer() { + total_ns = 0; + } + + static int64_t query() { +#if defined(_POSIX_TIMERS) && (_POSIX_TIMERS > 0) + struct timespec ts; + //clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts); + return int64_t(ts.tv_sec)*1000000000 + ts.tv_nsec; +#elif defined(RUSAGE_SELF) + struct rusage rusage; + int64_t t; + if (getrusage(RUSAGE_SELF, &rusage) == -1) { + log_cmd_error("getrusage failed!\n"); + log_abort(); + } + t = 1000000000ULL * (int64_t) rusage.ru_utime.tv_sec + (int64_t) rusage.ru_utime.tv_usec * 1000ULL; + t += 1000000000ULL * (int64_t) rusage.ru_stime.tv_sec + (int64_t) rusage.ru_stime.tv_usec * 1000ULL; + return t; +#elif _WIN32 + return 0; +#else + #error Dont know how to measure per-process CPU time. Need alternative method (times()/clocks()/gettimeofday()?). +#endif + } + + void reset() { + total_ns = 0; + } + + void begin() { + total_ns -= query(); + } + + void end() { + total_ns += query(); + } + + float sec() const { + return total_ns * 1e-9f; + } +#else + static int64_t query() { return 0; } + void reset() { } + void begin() { } + void end() { } + float sec() const { return 0; } +#endif +}; + +// simple API for quickly dumping values when debugging + +static inline void log_dump_val_worker(short v) { log("%d", v); } +static inline void log_dump_val_worker(unsigned short v) { log("%u", v); } +static inline void log_dump_val_worker(int v) { log("%d", v); } +static inline void log_dump_val_worker(unsigned int v) { log("%u", v); } +static inline void log_dump_val_worker(long int v) { log("%ld", v); } +static inline void log_dump_val_worker(unsigned long int v) { log("%lu", v); } +#ifndef _WIN32 +static inline void log_dump_val_worker(long long int v) { log("%lld", v); } +static inline void log_dump_val_worker(unsigned long long int v) { log("%lld", v); } +#endif +static inline void log_dump_val_worker(char c) { log(c >= 32 && c < 127 ? "'%c'" : "'\\x%02x'", c); } +static inline void log_dump_val_worker(unsigned char c) { log(c >= 32 && c < 127 ? "'%c'" : "'\\x%02x'", c); } +static inline void log_dump_val_worker(bool v) { log("%s", v ? "true" : "false"); } +static inline void log_dump_val_worker(double v) { log("%f", v); } +static inline void log_dump_val_worker(char *v) { log("%s", v); } +static inline void log_dump_val_worker(const char *v) { log("%s", v); } +static inline void log_dump_val_worker(std::string v) { log("%s", v.c_str()); } +static inline void log_dump_val_worker(PerformanceTimer p) { log("%f seconds", p.sec()); } +static inline void log_dump_args_worker(const char *p YS_ATTRIBUTE(unused)) { log_assert(*p == 0); } +void log_dump_val_worker(RTLIL::IdString v); +void log_dump_val_worker(RTLIL::SigSpec v); + +template +static inline void log_dump_val_worker(T *ptr) { log("%p", ptr); } + +template +void log_dump_args_worker(const char *p, T first, Args ... args) +{ + int next_p_state = 0; + const char *next_p = p; + while (*next_p && (next_p_state != 0 || *next_p != ',')) { + if (*next_p == '"') + do { + next_p++; + while (*next_p == '\\' && *(next_p + 1)) + next_p += 2; + } while (*next_p && *next_p != '"'); + if (*next_p == '\'') { + next_p++; + if (*next_p == '\\') + next_p++; + if (*next_p) + next_p++; + } + if (*next_p == '(' || *next_p == '[' || *next_p == '{') + next_p_state++; + if ((*next_p == ')' || *next_p == ']' || *next_p == '}') && next_p_state > 0) + next_p_state--; + next_p++; + } + log("\n\t%.*s => ", int(next_p - p), p); + if (*next_p == ',') + next_p++; + while (*next_p == ' ' || *next_p == '\t' || *next_p == '\r' || *next_p == '\n') + next_p++; + log_dump_val_worker(first); + log_dump_args_worker(next_p, args ...); +} + +#define log_dump(...) do { \ + log("DEBUG DUMP IN %s AT %s:%d:", __PRETTY_FUNCTION__, __FILE__, __LINE__); \ + log_dump_args_worker(#__VA_ARGS__, __VA_ARGS__); \ + log("\n"); \ +} while (0) + +YOSYS_NAMESPACE_END + +#endif