From 3373921ec3b9b534fab5e51314d1aaee6dd74d7c Mon Sep 17 00:00:00 2001 From: sripathi-muralitharan Date: Sun, 25 Apr 2021 11:44:40 -0700 Subject: [PATCH 01/70] compilation.mk * This file compiles all the files using x86 GCC or RISC-V GCC * It also compiles BlackParrot-specific assembly files --- .../platforms/dromajo-vcs/compilation.mk | 71 +++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 libraries/platforms/dromajo-vcs/compilation.mk diff --git a/libraries/platforms/dromajo-vcs/compilation.mk b/libraries/platforms/dromajo-vcs/compilation.mk new file mode 100644 index 000000000..e40788fe8 --- /dev/null +++ b/libraries/platforms/dromajo-vcs/compilation.mk @@ -0,0 +1,71 @@ +# Copyright (c) 2019, University of Washington All rights reserved. +# +# Redistribution and use in source and binary forms, with or without modification, +# are permitted provided that the following conditions are met: +# +# Redistributions of source code must retain the above copyright notice, this list +# of conditions and the following disclaimer. +# +# Redistributions in binary form must reproduce the above copyright notice, this +# list of conditions and the following disclaimer in the documentation and/or +# other materials provided with the distribution. +# +# Neither the name of the copyright holder nor the names of its contributors may +# be used to endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# This Makefile fragment defines rules for compilation of the C/C++ +# files for running regression tests. + +ORANGE=\033[0;33m +RED=\033[0;31m +NC=\033[0m + +# This file REQUIRES several variables to be set. They are typically +# set by the Makefile that includes this makefile.. +# +DEFINES += -UVCS -D_DRAMFS +INCLUDES += -I$(LIBRARIES_PATH) +INCLUDES += -I$(BSG_PLATFORM_PATH)/software/include +INCLUDES += -I$(BLACKPARROT_DIR)/sdk/perch + +CXXFLAGS += $(DEFINES) -march=rv64imafd -mabi=lp64 -mcmodel=medany +CFLAGS += $(DEFINES) -march=rv64imafd -mabi=lp64 -mcmodel=medany +SFLAGS += $(DEFINES) -march=rv64imafd -mabi=lp64 -mcmodel=medany + +export RV_CC = $(BLACKPARROT_DIR)/sdk/install/bin/riscv64-unknown-elf-dramfs-gcc +export RV_CXX = $(BLACKPARROT_DIR)/sdk/install/bin/riscv64-unknown-elf-dramfs-g++ +export RV_LD = $(RV_CXX) +export RV_AR = $(BLACKPARROT_DIR)/sdk/install/bin/riscv64-unknown-elf-dramfs-ar +export RV_RANLIB = $(BLACKPARROT_DIR)/sdk/install/bin/riscv64-unknown-elf-dramfs-ranlib + +# each regression target needs to build its .o from a .c and .h of the +# same name +%.o: %.c + $(RV_CC) -c -o $@ $< $(INCLUDES) $(CFLAGS) $(CDEFINES) + +# ... or a .cpp and .hpp of the same name +%.o: %.cpp + $(RV_CXX) -c -o $@ $< $(INCLUDES) $(CXXFLAGS) $(CXXDEFINES) + +%.o: %.S + $(RV_CC) -c -o $@ $< $(INCLUDES) $(SFLAGS) + +.PRECIOUS: %.o + +.PHONY: platform.compilation.clean +platform.compilation.clean: + rm -rf *.o + +compilation.clean: platform.compilation.clean From e0786eb1e9bf48ff4816d7bd4a934204c6503b60 Mon Sep 17 00:00:00 2001 From: sripathi-muralitharan Date: Sun, 25 Apr 2021 11:55:47 -0700 Subject: [PATCH 02/70] hardware.mk * This file adds all sources to compile the necessary hardware. BlackParrot sources * need to be added here in the future * Note: As of this commit, this file is an exact copy of the one in bigblade-vcs --- libraries/platforms/dromajo-vcs/hardware.mk | 155 ++++++++++++++++++++ 1 file changed, 155 insertions(+) create mode 100644 libraries/platforms/dromajo-vcs/hardware.mk diff --git a/libraries/platforms/dromajo-vcs/hardware.mk b/libraries/platforms/dromajo-vcs/hardware.mk new file mode 100644 index 000000000..17db5eca2 --- /dev/null +++ b/libraries/platforms/dromajo-vcs/hardware.mk @@ -0,0 +1,155 @@ +# Copyright (c) 2019, University of Washington All rights reserved. +# +# Redistribution and use in source and binary forms, with or without modification, +# are permitted provided that the following conditions are met: +# +# Redistributions of source code must retain the above copyright notice, this list +# of conditions and the following disclaimer. +# +# Redistributions in binary form must reproduce the above copyright notice, this +# list of conditions and the following disclaimer in the documentation and/or +# other materials provided with the distribution. +# +# Neither the name of the copyright holder nor the names of its contributors may +# be used to endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# hardware.mk: Platform-specific HDL listing. +# +# For simulation platforms, it also describes how to build the +# simulation "libraries" that are required by CAD tools. +# +# This file should be included from bsg_replicant/hardware/hardware.mk. It checks +# BSG_PLATFORM_PATH, BASEJUMP_STL_DIR, BSG_MANYCORE_DIR, etc. + +# BSG_MACHINE_NAME: The name of the target machine. Should be defined +# in $(BSG_MACHINE_PATH)/Makefile.machine.include, which is included +# by hardware.mk +ifndef BSG_MACHINE_NAME +$(error $(shell echo -e "$(RED)BSG MAKE ERROR: BSG_MACHINE_NAME is not defined$(NC)")) +endif + +# The following variables are set by $(BSG_F1_DIR)/hdk.mk, which will fail if +# hdk_setup.sh has not been run, or environment.mk is not included +# +# HDK_SHELL_DESIGN_DIR: Path to the directory containing all the AWS "shell" IP +# AWS_FPGA_REPO_DIR: Path to the clone of the aws-fpga repo +# HDK_COMMON_DIR: Path to HDK 'common' directory w/ libraries for cosimluation. +# SDK_DIR: Path to the SDK directory in the aws-fpga repo +include $(BSG_F1_DIR)/hdk.mk + +################################################################################ +# Simulation Sources +################################################################################ +VSOURCES += $(BASEJUMP_STL_DIR)/bsg_test/bsg_nonsynth_clock_gen.v +VSOURCES += $(BASEJUMP_STL_DIR)/bsg_test/bsg_nonsynth_reset_gen.v + +POD_TRACE_GEN_PY = $(BSG_MANYCORE_DIR)/testbenches/py/pod_trace_gen.py +$(BSG_MACHINE_PATH)/bsg_tag_boot_rom.tr: $(BSG_MACHINE_PATH)/Makefile.machine.include + env python2 $(POD_TRACE_GEN_PY) $(BSG_MACHINE_PODS_X) $(BSG_MACHINE_PODS_Y) $(BSG_MACHINE_NOC_COORD_X_WIDTH) > $@ + +ASCII_TO_ROM_PY = $(BASEJUMP_STL_DIR)/bsg_mem/bsg_ascii_to_rom.py +$(BSG_MACHINE_PATH)/bsg_tag_boot_rom.v: $(BSG_MACHINE_PATH)/bsg_tag_boot_rom.tr + env python2 $(ASCII_TO_ROM_PY) $< bsg_tag_boot_rom > $@ + +VSOURCES += $(BSG_MACHINE_PATH)/bsg_tag_boot_rom.v +VSOURCES += $(BASEJUMP_STL_DIR)/bsg_fsb/bsg_fsb_node_trace_replay.v +VSOURCES += $(BASEJUMP_STL_DIR)/bsg_tag/bsg_tag_trace_replay.v +VSOURCES += $(BASEJUMP_STL_DIR)/bsg_tag/bsg_tag_master.v + +# DMA Interface +VSOURCES += $(BSG_MANYCORE_DIR)/testbenches/common/v/vcache_dma_to_dram_channel_map.v +VSOURCES += $(BASEJUMP_STL_DIR)/bsg_mem/bsg_nonsynth_mem_1r1w_sync_dma.v +VSOURCES += $(BASEJUMP_STL_DIR)/bsg_mem/bsg_nonsynth_mem_1r1w_sync_mask_write_byte_dma.v +VSOURCES += $(BASEJUMP_STL_DIR)/bsg_mem/bsg_nonsynth_mem_1rw_sync_mask_write_byte_dma.v + +# DRAMSim3 +VSOURCES += $(BASEJUMP_STL_DIR)/bsg_test/bsg_dramsim3_pkg.v +VSOURCES += $(BASEJUMP_STL_DIR)/bsg_test/bsg_nonsynth_dramsim3.v +VSOURCES += $(BASEJUMP_STL_DIR)/bsg_test/bsg_nonsynth_dramsim3_map.v +VSOURCES += $(BASEJUMP_STL_DIR)/bsg_test/bsg_nonsynth_dramsim3_unmap.v + +VSOURCES += $(BASEJUMP_STL_DIR)/bsg_cache/bsg_cache_to_test_dram.v +VSOURCES += $(BASEJUMP_STL_DIR)/bsg_cache/bsg_cache_to_test_dram_tx.v +VSOURCES += $(BASEJUMP_STL_DIR)/bsg_cache/bsg_cache_to_test_dram_rx.v +VSOURCES += $(BASEJUMP_STL_DIR)/bsg_cache/bsg_cache_to_test_dram_rx_reorder.v + +# Infinite Memory +VSOURCES += $(BSG_MANYCORE_DIR)/testbenches/common/v/bsg_nonsynth_mem_infinite.v + +# Profiling +VSOURCES += $(BSG_MANYCORE_DIR)/testbenches/common/v/bsg_manycore_profile_pkg.v +VSOURCES += $(BASEJUMP_STL_DIR)/bsg_misc/bsg_cycle_counter.v + +# Core Profiler/Trace +VSOURCES += $(BASEJUMP_STL_DIR)/bsg_test/bsg_nonsynth_dpi_gpio.v +VSOURCES += $(BSG_MANYCORE_DIR)/testbenches/common/v/instr_trace.v +VSOURCES += $(BSG_MANYCORE_DIR)/testbenches/common/v/vanilla_core_trace.v +VSOURCES += $(BSG_MANYCORE_DIR)/testbenches/common/v/vanilla_core_profiler.v +# We reuse the print_stat_snoop module from aws-vcs +VSOURCES += $(LIBRARIES_PATH)/platforms/aws-vcs/hardware/bsg_print_stat_snoop.v + +VSOURCES += $(BSG_MANYCORE_DIR)/testbenches/common/v/router_profiler.v +VSOURCES += $(BSG_MANYCORE_DIR)/testbenches/common/v/remote_load_trace.v + +# Memory Profilers +VSOURCES += $(BSG_MANYCORE_DIR)/testbenches/common/v/vcache_profiler.v +VSOURCES += $(BSG_MANYCORE_DIR)/testbenches/common/v/vcache_non_blocking_profiler.v +VSOURCES += $(BSG_MANYCORE_DIR)/testbenches/common/v/infinite_mem_profiler.v + +VSOURCES += $(BSG_MANYCORE_DIR)/testbenches/common/v/bsg_nonsynth_manycore_tag_master.v +VSOURCES += $(BSG_MANYCORE_DIR)/testbenches/common/v/bsg_nonsynth_manycore_io_complex.v +VSOURCES += $(BSG_MANYCORE_DIR)/testbenches/common/v/bsg_nonsynth_manycore_spmd_loader.v +VSOURCES += $(BSG_MANYCORE_DIR)/testbenches/common/v/bsg_nonsynth_manycore_monitor.v +VSOURCES += $(BSG_MANYCORE_DIR)/testbenches/common/v/bsg_nonsynth_wormhole_test_mem.v +VSOURCES += $(BSG_MANYCORE_DIR)/testbenches/common/v/bsg_manycore_vcache_wh_to_cache_dma.v +VSOURCES += $(BSG_MANYCORE_DIR)/testbenches/common/v/bsg_nonsynth_manycore_testbench.v + +VSOURCES += $(BASEJUMP_STL_DIR)/bsg_dataflow/bsg_serial_in_parallel_out_full.v +VSOURCES += $(BASEJUMP_STL_DIR)/bsg_dataflow/bsg_round_robin_1_to_n.v +VSOURCES += $(BASEJUMP_STL_DIR)/bsg_dataflow/bsg_one_fifo.v + +VSOURCES += $(LIBRARIES_PATH)/platforms/aws-fpga/hardware/bsg_manycore_endpoint_to_fifos_pkg.v +VSOURCES += $(LIBRARIES_PATH)/platforms/aws-fpga/hardware/bsg_manycore_endpoint_to_fifos.v + +VSOURCES += $(BSG_MANYCORE_DIR)/testbenches/common/v/vanilla_core_saif_dumper.v + +################################################################################ +# DPI-Specific Sources +################################################################################ + +VSOURCES += $(BSG_MANYCORE_DIR)/v/bsg_manycore_link_sif_async_buffer.v +VSOURCES += $(BASEJUMP_STL_DIR)/bsg_test/bsg_nonsynth_dpi_from_fifo.v +VSOURCES += $(BASEJUMP_STL_DIR)/bsg_test/bsg_nonsynth_dpi_to_fifo.v +VSOURCES += $(BASEJUMP_STL_DIR)/bsg_test/bsg_nonsynth_dpi_rom.v +VSOURCES += $(BSG_MANYCORE_DIR)/testbenches/dpi/bsg_nonsynth_dpi_manycore.v + +VSOURCES += $(BASEJUMP_STL_DIR)/bsg_test/bsg_nonsynth_dpi_cycle_counter.v + +################################################################################ +# Top-level files +################################################################################ +# Top-level module name +BSG_DESIGN_TOP := replicant_tb_top + +VSOURCES += $(LIBRARIES_PATH)/platforms/bigblade-vcs/hardware/dpi_top.sv + +VINCLUDES += $(BSG_PLATFORM_PATH)/hardware +VINCLUDES += $(BSG_PLATFORM_PATH) + + +hardware.clean: machine.hardware.clean + +machine.hardware.clean: + rm -rf $(BSG_MACHINE_PATH)/bsg_tag_boot_rom.tr $(BSG_MACHINE_PATH)/bsg_tag_boot_rom.v From 3bd401bf1844532333cd3110bb97848bc120489e Mon Sep 17 00:00:00 2001 From: sripathi-muralitharan Date: Sun, 25 Apr 2021 11:58:23 -0700 Subject: [PATCH 03/70] execution.mk * This file contains runtime simulation options and targets. Modifications * maybe required for BlackParrot * Note: As of this commit, this file is the same as the one in bigblade-vcs --- libraries/platforms/dromajo-vcs/execution.mk | 71 ++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 libraries/platforms/dromajo-vcs/execution.mk diff --git a/libraries/platforms/dromajo-vcs/execution.mk b/libraries/platforms/dromajo-vcs/execution.mk new file mode 100644 index 000000000..6699ca592 --- /dev/null +++ b/libraries/platforms/dromajo-vcs/execution.mk @@ -0,0 +1,71 @@ +# Copyright (c) 2019, University of Washington All rights reserved. +# +# Redistribution and use in source and binary forms, with or without modification, +# are permitted provided that the following conditions are met: +# +# Redistributions of source code must retain the above copyright notice, this list +# of conditions and the following disclaimer. +# +# Redistributions in binary form must reproduce the above copyright notice, this +# list of conditions and the following disclaimer in the documentation and/or +# other materials provided with the distribution. +# +# Neither the name of the copyright holder nor the names of its contributors may +# be used to endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +# All simulations should run with +ntb_random_seed_automatic. +# +# From the VCS MX User-Guide: +ntb_random_seed_automatic Picks a unique value to +# supply as the first seed used by a testbench. The value is determined by +# combining the time of day, host name and process id. This ensures that no two +# simulations have the same starting seed. +SIM_ARGS += +ntb_random_seed_automatic + +# These are the execution rules for the binaries. We can't pass +# C-style arguments through the command line, so instead we specify +# them as the VCS plusarg argument +c_args. Users can specify C-style +# arguments using the C_ARGS make variable. + +%.log: % $(BSG_MANYCORE_KERNELS) + ./$< $(SIM_ARGS) +c_args="$(C_ARGS)" 2>&1 | tee $@ + +vanilla_stats.csv vcache_stats.csv router_stat.csv: % : %.profile.log + +%.saif: %.saifgen.log ; + +%.vpd: SIM_ARGS += +vpdfile+$(@:.debug.log=.vpd) +%.vpd: %.debug.log ; + +%.dve: %.vpd + $(DVE) -full64 -vpd $< & + +.PRECIOUS: %.log + +.PHONY: platform.execution.clean %.log %.vpd +platform.execution.clean: + rm -rf vanilla_stats.csv + rm -rf infinite_mem_stats.csv + rm -rf vcache_stats.csv + rm -rf vanilla_operation_trace.csv + rm -rf operation_trace.csv + rm -rf vcache_operation_trace.csv + rm -rf router_stat.csv + rm -rf remote_load_trace.csv + rm -rf vanilla.log + rm -rf *.vpd + rm -rf dramsim3.json dramsim3.tag.json dramsim3.txt dramsim3epoch.json + +execution.clean: platform.execution.clean From a8dd554a1140430647f7023eaabc95594a9a08b5 Mon Sep 17 00:00:00 2001 From: sripathi-muralitharan Date: Sun, 25 Apr 2021 12:03:56 -0700 Subject: [PATCH 04/70] library.mk * This file contains a list of objects (platform and library) that need to be * be compiled. * It includes lists of Dromajo files to compile * It includes a list of C++/C/ASM sources required for BlackParrot * It heavily reworks the compilation flow for BlackParrot --- libraries/platforms/dromajo-vcs/library.mk | 144 +++++++++++++++++++++ 1 file changed, 144 insertions(+) create mode 100644 libraries/platforms/dromajo-vcs/library.mk diff --git a/libraries/platforms/dromajo-vcs/library.mk b/libraries/platforms/dromajo-vcs/library.mk new file mode 100644 index 000000000..2b0aeddd6 --- /dev/null +++ b/libraries/platforms/dromajo-vcs/library.mk @@ -0,0 +1,144 @@ +# Copyright (c) 2019, University of Washington All rights reserved. +# +# Redistribution and use in source and binary forms, with or without modification, +# are permitted provided that the following conditions are met: +# +# Redistributions of source code must retain the above copyright notice, this list +# of conditions and the following disclaimer. +# +# Redistributions in binary form must reproduce the above copyright notice, this +# list of conditions and the following disclaimer in the documentation and/or +# other materials provided with the distribution. +# +# Neither the name of the copyright holder nor the names of its contributors may +# be used to endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# Dromajo/BlackParrot uses riscv-newlib for compilation +__NEWLIB = 1 +DROMAJO_DIR = $(BLACKPARROT_DIR)/sdk/dromajo + +# Compile the platform-level code and features with the library +LIB_CXXSOURCES += $(LIBRARIES_PATH)/features/tracer/noimpl/bsg_manycore_tracer.cpp +LIB_CXXSOURCES += $(LIBRARIES_PATH)/features/profiler/noimpl/bsg_manycore_profiler.cpp +LIB_CXXSOURCES += $(BSG_PLATFORM_PATH)/bsg_manycore_platform.cpp + +LIB_CSOURCES += $(BSG_PLATFORM_PATH)/software/src/flockfile.c +LIB_CSOURCES += $(BSG_PLATFORM_PATH)/software/src/funlockfile.c +LIB_CSOURCES += $(BSG_PLATFORM_PATH)/software/src/argp/argp-ba.c +LIB_CSOURCES += $(BSG_PLATFORM_PATH)/software/src/argp/argp-eexst.c +LIB_CSOURCES += $(BSG_PLATFORM_PATH)/software/src/argp/argp-fmtstream.c +LIB_CSOURCES += $(BSG_PLATFORM_PATH)/software/src/argp/argp-fs-xinl.c +LIB_CSOURCES += $(BSG_PLATFORM_PATH)/software/src/argp/argp-help.c +LIB_CSOURCES += $(BSG_PLATFORM_PATH)/software/src/argp/argp-parse.c +LIB_CSOURCES += $(BSG_PLATFORM_PATH)/software/src/argp/argp-pv.c +LIB_CSOURCES += $(BSG_PLATFORM_PATH)/software/src/argp/argp-pvh.c +LIB_CSOURCES += $(BSG_PLATFORM_PATH)/software/src/argp/argp-xinl.c +LIB_CSOURCES += $(BSG_PLATFORM_PATH)/software/src/bp_utils.c +LIB_CSOURCES += $(BLACKPARROT_DIR)/sdk/perch/bsg_newlib_intf.c +LIB_CSOURCES += $(BLACKPARROT_DIR)/sdk/perch/emulation.c + +LIB_SSOURCES += $(BLACKPARROT_DIR)/sdk/perch/atomics.S +LIB_SSOURCES += $(BLACKPARROT_DIR)/sdk/perch/exception.S +LIB_SSOURCES += $(BLACKPARROT_DIR)/sdk/perch/muldiv.S +LIB_SSOURCES += $(BSG_PLATFORM_PATH)/software/src/crt0.S + +# For now, use the noimpl version of the features +include $(LIBRARIES_PATH)/features/dma/noimpl/feature.mk + +$(DMA_FEATURE_OBJECTS): INCLUDES += -I$(BSG_PLATFORM_PATH)/software/include +$(DMA_FEATURE_OBJECTS): CFLAGS += -march=rv64imafd -mcmodel=medany -mabi=lp64 -D_BSD_SOURCE -D_XOPEN_SOURCE=500 +$(DMA_FEATURE_OBJECTS): CXXFLAGS += -march=rv64imafd -mcmodel=medany -mabi=lp64 -D_BSD_SOURCE -D_XOPEN_SOURCE=500 + +# Add the riscv-newlib specific includes for the library +$(LIB_OBJECTS) $(LIB_OBJECTS_CUDA_POD_REPL): INCLUDES := -I$(BSG_PLATFORM_PATH)/software/include +$(LIB_OBJECTS) $(LIB_OBJECTS_CUDA_POD_REPL): INCLUDES += -I$(BLACKPARROT_DIR)/sdk/perch + +# Make the litteFS file system +$(BSG_PLATFORM_PATH)/lfs.o: + $(MAKE) -C $(BLACKPARROT_DIR)/sdk/bp-tests lfs.cpp + $(RV_CXX) $(BLACKPARROT_DIR)/sdk/bp-tests/lfs.cpp -c -o $@ $(CXXFLAGS) $(INCLUDES) + +# Compile the feature libraries with the manycore runtime +$(LIB_OBJECTS) $(LIB_OBJECTS_CUDA_POD_REPL): INCLUDES += -I$(LIBRARIES_PATH)/features/profiler +$(LIB_OBJECTS) $(LIB_OBJECTS_CUDA_POD_REPL): INCLUDES += -I$(LIBRARIES_PATH)/features/tracer + +DROMAJO_CXXSOURCES += $(DROMAJO_DIR)/src/cutils.cpp +DROMAJO_CXXSOURCES += $(DROMAJO_DIR)/src/dromajo_cosim.cpp +DROMAJO_CXXSOURCES += $(DROMAJO_DIR)/src/dromajo_main.cpp +DROMAJO_CXXSOURCES += $(DROMAJO_DIR)/src/dromajo_manycore.cpp +DROMAJO_CXXSOURCES += $(DROMAJO_DIR)/src/dw_apb_uart.cpp +DROMAJO_CXXSOURCES += $(DROMAJO_DIR)/src/elf64.cpp +DROMAJO_CXXSOURCES += $(DROMAJO_DIR)/src/fs.cpp +DROMAJO_CXXSOURCES += $(DROMAJO_DIR)/src/fs_disk.cpp +DROMAJO_CXXSOURCES += $(DROMAJO_DIR)/src/iomem.cpp +DROMAJO_CXXSOURCES += $(DROMAJO_DIR)/src/json.cpp +DROMAJO_CXXSOURCES += $(DROMAJO_DIR)/src/machine.cpp +DROMAJO_CXXSOURCES += $(DROMAJO_DIR)/src/pci.cpp +DROMAJO_CXXSOURCES += $(DROMAJO_DIR)/src/riscv_cpu.cpp +DROMAJO_CXXSOURCES += $(DROMAJO_DIR)/src/riscv_machine.cpp +DROMAJO_CXXSOURCES += $(DROMAJO_DIR)/src/softfp.cpp +DROMAJO_CXXSOURCES += $(DROMAJO_DIR)/src/virtio.cpp + +DROMAJO_OBJECTS += $(patsubst %cpp,%o,$(DROMAJO_CXXSOURCES)) + +$(DROMAJO_OBJECTS): INCLUDES := -I$(DROMAJO_DIR)/include +$(DROMAJO_OBJECTS): INCLUDES += -I$(BSG_PLATFORM_PATH)/software/include/dromajo +$(DROMAJO_OBJECTS): CXXFLAGS := -std=c++11 -fPIC -Wall -Wno-parentheses -MMD -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_GNU_SOURCE -D__STDC_FORMAT_MACROS -std=gnu++11 +$(DROMAJO_OBJECTS): LDFLAGS := -fPIC + +PLATFORM_CXXSOURCES += $(BSG_PLATFORM_PATH)/bsg_manycore_simulator.cpp + +PLATFORM_OBJECTS += $(patsubst %cpp,%o,$(PLATFORM_CXXSOURCES)) +PLATFORM_OBJECTS += $(patsubst %c,%o,$(PLATFORM_CSOURCES)) + +$(PLATFORM_OBJECTS): $(DROMAJO_OBJECTS) +$(PLATFORM_OBJECTS): INCLUDES := -I$(LIBRARIES_PATH) +$(PLATFORM_OBJECTS): INCLUDES += -I$(LIBRARIES_PATH)/platforms/dpi-verilator +$(PLATFORM_OBJECTS): INCLUDES += -I$(BSG_MACHINE_PATH)/notrace/ +$(PLATFORM_OBJECTS): INCLUDES += -I$(BSG_PLATFORM_PATH) +$(PLATFORM_OBJECTS): INCLUDES += -I$(VCS_HOME)/linux64/lib/ +$(PLATFORM_OBJECTS): INCLUDES += -I$(BSG_MANYCORE_DIR)/testbenches/dpi/ +$(PLATFORM_OBJECTS): INCLUDES += -I$(BASEJUMP_STL_DIR)/bsg_test/ +$(PLATFORM_OBJECTS): INCLUDES += -I$(BLACKPARROT_DIR)/sdk/dromajo/include +$(PLATFORM_OBJECTS): CFLAGS := -std=c11 -fPIC -DVCS -D_GNU_SOURCE -DVERILATOR -D_BSD_SOURCE -D_XOPEN_SOURCE=500 $(INCLUDES) +$(PLATFORM_OBJECTS): CXXFLAGS := -std=c++11 -fPIC -DVCS -D_GNU_SOURCE -DVERILATOR -D_BSD_SOURCE -D_XOPEN_SOURCE=500 $(INCLUDES) +$(PLATFORM_OBJECTS): LDFLAGS := -fPIC +$(PLATFORM_OBJECTS): RV_CXX = $(CXX) + +# Mirror the extensions linux installation in /usr/lib provides so +# that we can use -lbsg_manycore_runtime +$(BSG_PLATFORM_PATH)/libbsg_manycore_runtime.a.1: %.a.1: %.so.1.0 + ln -sf $(basename $(basename $@)).so.1.0 $@ + +$(BSG_PLATFORM_PATH)/libbsgmc_cuda_legacy_pod_repl.a.1: %.a.1: %.so.1.0 + ln -sf $(basename $(basename $@)).so.1.0 $@ + +$(BSG_PLATFORM_PATH)/libbsg_manycore_runtime.a: %: %.1 + ln -sf $@.1 $@ + +$(BSG_PLATFORM_PATH)/libbsgmc_cuda_legacy_pod_repl.a: %: %.1 + ln -sf $@.1 $@ + +platform.clean: + rm -f $(PLATFORM_OBJECTS) + rm -f $(DROMAJO_OBJECTS) + rm -f $(BSG_PLATFORM_PATH)/lfs.o + rm -f $(BSG_PLATFORM_PATH)/libbsg_manycore_runtime.a + rm -f $(BSG_PLATFORM_PATH)/libbsg_manycore_runtime.a.1 + rm -f $(BSG_PLATFORM_PATH)/libbsgmc_cuda_legacy_pod_repl.a + rm -f $(BSG_PLATFORM_PATH)/libbsgmc_cuda_legacy_pod_repl.a.1 + rm -f $(BSG_PLATFORM_PATH)/bsg_manycore_platform.so + +libraries.clean: platform.clean From 65adfb3745075b2fb2f923d59d44338977597d12 Mon Sep 17 00:00:00 2001 From: sripathi-muralitharan Date: Sun, 25 Apr 2021 12:06:05 -0700 Subject: [PATCH 05/70] link.mk * This file compiles the VCS executables and links the correct object files * It now generates a RISC-V binary that runs on Dromajo/BlackParrot * and an x86 binary linked with VCS * Minor refactors are made to compile the necessary libraries correctly --- libraries/platforms/dromajo-vcs/link.mk | 170 ++++++++++++++++++++++++ 1 file changed, 170 insertions(+) create mode 100644 libraries/platforms/dromajo-vcs/link.mk diff --git a/libraries/platforms/dromajo-vcs/link.mk b/libraries/platforms/dromajo-vcs/link.mk new file mode 100644 index 000000000..e9d698c9d --- /dev/null +++ b/libraries/platforms/dromajo-vcs/link.mk @@ -0,0 +1,170 @@ +# Copyright (c) 2019, University of Washington All rights reserved. +# +# Redistribution and use in source and binary forms, with or without modification, +# are permitted provided that the following conditions are met: +# +# Redistributions of source code must retain the above copyright notice, this list +# of conditions and the following disclaimer. +# +# Redistributions in binary form must reproduce the above copyright notice, this +# list of conditions and the following disclaimer in the documentation and/or +# other materials provided with the distribution. +# +# Neither the name of the copyright holder nor the names of its contributors may +# be used to endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# This Makefile fragment defines all of the rules for linking +# aws-vcs binaries + +ORANGE=\033[0;33m +RED=\033[0;31m +NC=\033[0m + +# This file REQUIRES several variables to be set. They are typically set by the +# Makefile that includes this fragment... + +# BSG_PLATFORM_PATH: The path to the testbenches folder in BSG F1 +ifndef BSG_PLATFORM_PATH +$(error $(shell echo -e "$(RED)BSG MAKE ERROR: BSG_PLATFORM_PATH is not defined$(NC)")) +endif + +# hardware.mk is the file list for the simulation RTL. It includes the +# platform specific hardware.mk file. +include $(HARDWARE_PATH)/hardware.mk + +# libraries.mk defines how to build libbsg_manycore_runtime.so, which is +# pre-linked against all other simulation binaries. +include $(LIBRARIES_PATH)/libraries.mk + +# VHEADERS must be compiled before VSOURCES. +VDEFINES += BSG_MACHINE_ORIGIN_X_CORD=$(BSG_MACHINE_ORIGIN_COORD_X) +VDEFINES += BSG_MACHINE_ORIGIN_Y_CORD=$(BSG_MACHINE_ORIGIN_COORD_Y) +VDEFINES += HOST_MODULE_PATH=replicant_tb_top +VDEFINES += BSG_MACHINE_DRAMSIM3_PKG=$(BSG_MACHINE_MEM_DRAMSIM3_PKG) +VLOGAN_SOURCES += $(VHEADERS) $(VSOURCES) +VLOGAN_INCLUDES += $(foreach inc,$(VINCLUDES),+incdir+"$(inc)") +VLOGAN_DEFINES += $(foreach def,$(VDEFINES),+define+"$(def)") +VLOGAN_VFLAGS += -timescale=1ps/1ps +VLOGAN_VFLAGS += -sverilog +VLOGAN_VFLAGS += +systemverilogext+.svh +systemverilogext+.sv +VLOGAN_VFLAGS += +libext+.sv +libext+.v +libext+.vh +libext+.svh +VLOGAN_VFLAGS += -full64 -lca -assert svaext +VLOGAN_VFLAGS += -undef_vcs_macro +VLOGAN_FLAGS = $(VLOGAN_VFLAGS) $(VLOGAN_DEFINES) $(VLOGAN_INCLUDES) $(VLOGAN_SOURCES) + +$(BSG_MACHINE_PATH)/$(BSG_PLATFORM): + mkdir -p $@ + +$(BSG_MACHINE_PATH)/$(BSG_PLATFORM)/synopsys_sim.setup: | $(BSG_MACHINE_PATH)/$(BSG_PLATFORM) + echo "replicant_tb_top : $(BSG_MACHINE_PATH)/$(BSG_PLATFORM)/vcs_simlibs/replicant_tb_top/64" >> $@; + +# The SAIF-generation simulation and fast simulation (exec) turns off the profilers using macros +# so it must be compiled into a separate library. +$(BSG_MACHINE_PATH)/$(BSG_PLATFORM)/synopsys_sim.saifgen: | $(BSG_MACHINE_PATH)/$(BSG_PLATFORM) + echo "replicant_tb_top : $(BSG_MACHINE_PATH)/$(BSG_PLATFORM)/vcs_simlibs/replicant_tb_top_saifgen/64" >> $@; + +$(BSG_MACHINE_PATH)/$(BSG_PLATFORM)/synopsys_sim.exec: | $(BSG_MACHINE_PATH)/$(BSG_PLATFORM) + echo "replicant_tb_top : $(BSG_MACHINE_PATH)/$(BSG_PLATFORM)/vcs_simlibs/replicant_tb_top_exec/64" >> $@; + +$(BSG_MACHINE_PATH)/$(BSG_PLATFORM)/vcs_simlibs/replicant_tb_top/AN.DB: $(BSG_MACHINE_PATH)/$(BSG_PLATFORM)/synopsys_sim.setup $(VLOGAN_SOURCES) + SYNOPSYS_SIM_SETUP=$< vlogan -work replicant_tb_top $(VLOGAN_FLAGS) -l $(BSG_MACHINE_PATH)/$(BSG_PLATFORM)/vlogan.log + +$(BSG_MACHINE_PATH)/$(BSG_PLATFORM)/vcs_simlibs/replicant_tb_top_saifgen/AN.DB $(BSG_MACHINE_PATH)/$(BSG_PLATFORM)/vcs_simlibs/replicant_tb_top_exec/AN.DB: VDEFINES += BSG_MACHINE_DISABLE_VCORE_PROFILING +$(BSG_MACHINE_PATH)/$(BSG_PLATFORM)/vcs_simlibs/replicant_tb_top_saifgen/AN.DB $(BSG_MACHINE_PATH)/$(BSG_PLATFORM)/vcs_simlibs/replicant_tb_top_exec/AN.DB: VDEFINES += BSG_MACHINE_DISABLE_CACHE_PROFILING +$(BSG_MACHINE_PATH)/$(BSG_PLATFORM)/vcs_simlibs/replicant_tb_top_saifgen/AN.DB $(BSG_MACHINE_PATH)/$(BSG_PLATFORM)/vcs_simlibs/replicant_tb_top_exec/AN.DB: VDEFINES += BSG_MACHINE_DISABLE_ROUTER_PROFILING + +$(BSG_MACHINE_PATH)/$(BSG_PLATFORM)/vcs_simlibs/replicant_tb_top_saifgen/AN.DB: VDEFINES += BSG_MACHINE_ENABLE_SAIF +$(BSG_MACHINE_PATH)/$(BSG_PLATFORM)/vcs_simlibs/replicant_tb_top_saifgen/AN.DB: $(BSG_MACHINE_PATH)/$(BSG_PLATFORM)/synopsys_sim.saifgen $(VLOGAN_SOURCES) + SYNOPSYS_SIM_SETUP=$< vlogan -work replicant_tb_top -debug_access+pp $(VLOGAN_FLAGS) -l $(BSG_MACHINE_PATH)/$(BSG_PLATFORM)/vlogan.saifgen.log + +$(BSG_MACHINE_PATH)/$(BSG_PLATFORM)/vcs_simlibs/replicant_tb_top_exec/AN.DB: $(BSG_MACHINE_PATH)/$(BSG_PLATFORM)/synopsys_sim.exec $(VLOGAN_SOURCES) + SYNOPSYS_SIM_SETUP=$< vlogan -work replicant_tb_top $(VLOGAN_FLAGS) -l $(BSG_MACHINE_PATH)/$(BSG_PLATFORM)/vlogan.exec.log + +# libbsg_manycore_platform will be compiled in $(BSG_PLATFORM_PATH) +LDFLAGS += -lbsg_manycore_platform -lm +LDFLAGS += -L$(BSG_PLATFORM_PATH) -Wl,-rpath=$(BSG_PLATFORM_PATH) + +VCS_LDFLAGS += $(foreach def,$(LDFLAGS),-LDFLAGS "$(def)") +VCS_VFLAGS += -M -L -ntb_opts tb_timescale=1ps/1ps -lca +VCS_VFLAGS += -timescale=1ps/1ps -sverilog -full64 -licqueue -q +VCS_VFLAGS += +warn=noLCA_FEATURES_ENABLED +VCS_VFLAGS += +warn=noMC-FCNAFTMI +VCS_VFLAGS += +lint=all,TFIPC-L,noSVA-UA,noSVA-NSVU,noVCDE,noSVA-AECASR +VCS_FLAGS = $(VCS_LDFLAGS) $(VCS_VFLAGS) + +TEST_CSOURCES += $(filter %.c,$(TEST_SOURCES)) +TEST_CXXSOURCES += $(filter %.cpp,$(TEST_SOURCES)) +TEST_OBJECTS += $(TEST_CXXSOURCES:.cpp=.o) +TEST_OBJECTS += $(TEST_CSOURCES:.c=.o) + +$(BSG_PLATFORM_PATH)/test.riscv: $(TEST_OBJECTS) +$(BSG_PLATFORM_PATH)/test.riscv: $(BSG_PLATFORM_PATH)/lfs.o +$(BSG_PLATFORM_PATH)/test.riscv: $(BSG_PLATFORM_PATH)/libbsg_manycore_runtime.a +$(BSG_PLATFORM_PATH)/test.riscv: $(BSG_PLATFORM_PATH)/libbsgmc_cuda_legacy_pod_repl.a +$(BSG_PLATFORM_PATH)/test.riscv: LDFLAGS := -T$(BLACKPARROT_DIR)/sdk/linker/riscv.ld -L$(BSG_PLATFORM_PATH) -static -nostartfiles -lstdc++ -lbsg_manycore_runtime +$(BSG_PLATFORM_PATH)/test.riscv: + $(RV_CXX) -D_DRAMFS -o $@ $(BSG_PLATFORM_PATH)/software/src/crt0.o $(BSG_PLATFORM_PATH)/lfs.o $< $(LDFLAGS) + +$(BSG_PLATFORM_PATH)/libbsg_manycore_platform.so: $(PLATFORM_OBJECTS) +$(BSG_PLATFORM_PATH)/libbsg_manycore_platform.so: LDFLAGS := -fPIC +$(BSG_PLATFORM_PATH)/libbsg_manycore_platform.so: + $(CXX) -shared -Wl,-soname,$(basename $(notdir $@)) -o $@ $^ $(LDFLAGS) + +# VCS Generates an executable file by linking the TEST_OBJECTS with +# the the VCS work libraries for the design, and the runtime shared +# libraries + +%.saifgen %.debug: VCS_VFLAGS += -debug_pp +%.debug: VCS_VFLAGS += +plusarg_save +vcs+vcdpluson +vcs+vcdplusmemon +memcbk + +%.debug %.profile: $(BSG_PLATFORM_PATH)/libbsg_manycore_platform.so $(BSG_PLATFORM_PATH)/test.riscv $(BSG_MACHINE_PATH)/$(BSG_PLATFORM)/vcs_simlibs/replicant_tb_top/AN.DB $(PLATFORM_OBJECTS) + SYNOPSYS_SIM_SETUP=$(BSG_MACHINE_PATH)/$(BSG_PLATFORM)/synopsys_sim.setup \ + vcs -top replicant_tb_top $(PLATFORM_OBJECTS) $(VCS_FLAGS) -Mdirectory=$@.tmp -l $@.vcs.log -o $@ + +%.saifgen: $(BSG_PLATFORM_PATH)/libbsg_manycore_platform.so $(BSG_PLATFORM_PATH)/test.riscv $(BSG_MACHINE_PATH)/$(BSG_PLATFORM)/vcs_simlibs/replicant_tb_top_saifgen/AN.DB $(PLATFORM_OBJECTS) + SYNOPSYS_SIM_SETUP=$(BSG_MACHINE_PATH)/$(BSG_PLATFORM)/synopsys_sim.saifgen \ + vcs -top replicant_tb_top $(PLATFORM_OBJECTS) $(VCS_FLAGS) -Mdirectory=$@.tmp -l $@.vcs.log -o $@ + +%.exec: $(BSG_PLATFORM_PATH)/libbsg_manycore_platform.so $(BSG_PLATFORM_PATH)/test.riscv $(BSG_MACHINE_PATH)/$(BSG_PLATFORM)/vcs_simlibs/replicant_tb_top_exec/AN.DB $(PLATFORM_OBJECTS) + SYNOPSYS_SIM_SETUP=$(BSG_MACHINE_PATH)/$(BSG_PLATFORM)/synopsys_sim.exec \ + vcs -top replicant_tb_top $(PLATFORM_OBJECTS) $(VCS_FLAGS) -Mdirectory=$@.tmp -l $@.vcs.log -o $@ + +.PRECIOUS:%.debug %.profile %.saifgen %.exec + +# When running recursive regression, make is launched in independent, +# non-communicating parallel processes that try to build these objects +# in parallel. That is no-bueno. We define REGRESSION_PREBUILD so that +# regression tests can build them before launching parallel +# compilation and execution +REGRESSION_PREBUILD += $(BSG_MACHINE_PATH)/$(BSG_PLATFORM)/vcs_simlibs/replicant_tb_top/AN.DB +REGRESSION_PREBUILD += $(BSG_MACHINE_PATH)/$(BSG_PLATFORM)/vcs_simlibs/replicant_tb_top_exec/AN.DB +REGRESSION_PREBUILD += $(BSG_MACHINE_PATH)/$(BSG_PLATFORM)/vcs_simlibs/replicant_tb_top_saifgen/AN.DB +REGRESSION_PREBUILD += $(BSG_PLATFORM_PATH)/libbsgmc_cuda_legacy_pod_repl.a +REGRESSION_PREBUILD += $(BSG_PLATFORM_PATH)/libbsg_manycore_runtime.a + +.PHONY: platform.link.clean +platform.link.clean: + rm -rf $(BSG_MACHINE_PATH)/$(BSG_PLATFORM)/ + rm -rf $(BSG_PLATFORM_PATH)/msg_config + rm -rf ucli.key + rm -rf .cxl* *.jou + rm -rf *.daidir *.tmp + rm -rf *.jou + rm -rf *.vcs.log + rm -rf vc_hdrs.h + rm -rf *.debug *.profile *.saifgen *.exec + +link.clean: platform.link.clean ; + From d4c714f79cb80b65c7ea120e48681789f4c43adc Mon Sep 17 00:00:00 2001 From: sripathi-muralitharan Date: Sun, 25 Apr 2021 11:46:34 -0700 Subject: [PATCH 06/70] hardware/dpi_top.sv * This file/folder contains all the hardware resources required for Dromajo+HammerBlade * Note: As of this commit, this file is an exact copy from bigblade-vcs --- .../platforms/dromajo-vcs/hardware/dpi_top.sv | 357 ++++++++++++++++++ 1 file changed, 357 insertions(+) create mode 100644 libraries/platforms/dromajo-vcs/hardware/dpi_top.sv diff --git a/libraries/platforms/dromajo-vcs/hardware/dpi_top.sv b/libraries/platforms/dromajo-vcs/hardware/dpi_top.sv new file mode 100644 index 000000000..1d8cdf339 --- /dev/null +++ b/libraries/platforms/dromajo-vcs/hardware/dpi_top.sv @@ -0,0 +1,357 @@ +module replicant_tb_top + import bsg_manycore_pkg::*; + import bsg_bladerunner_pkg::*; + (); + + // Uncomment this to enable VCD Dumping + /* + initial begin + $display("[%0t] Tracing to vlt_dump.vcd...\n", $time); + $dumpfile("dump.vcd"); + $dumpvars(); + end + */ + initial begin + #0; + + $display("==================== BSG MACHINE SETTINGS: ===================="); + + $display("[INFO][TESTBENCH] bsg_machine_pods_x_gp = %d", bsg_machine_pods_x_gp); + $display("[INFO][TESTBENCH] bsg_machine_pods_y_gp = %d", bsg_machine_pods_y_gp); + + $display("[INFO][TESTBENCH] bsg_machine_pod_tiles_x_gp = %d", bsg_machine_pod_tiles_x_gp); + $display("[INFO][TESTBENCH] bsg_machine_pod_tiles_y_gp = %d", bsg_machine_pod_tiles_y_gp); + $display("[INFO][TESTBENCH] bsg_machine_pod_tiles_subarray_x_gp = %d", bsg_machine_pod_tiles_subarray_x_gp); + $display("[INFO][TESTBENCH] bsg_machine_pod_tiles_subarray_y_gp = %d", bsg_machine_pod_tiles_subarray_y_gp); + $display("[INFO][TESTBENCH] bsg_machine_pod_llcache_rows_gp = %d", bsg_machine_pod_llcache_rows_gp); + + $display("[INFO][TESTBENCH] bsg_machine_noc_cfg_gp = %s", bsg_machine_noc_cfg_gp.name()); + $display("[INFO][TESTBENCH] bsg_machine_noc_ruche_factor_X_gp = %d", bsg_machine_noc_ruche_factor_X_gp); + + $display("[INFO][TESTBENCH] bsg_machine_noc_epa_width_gp = %d", bsg_machine_noc_epa_width_gp); + $display("[INFO][TESTBENCH] bsg_machine_noc_data_width_gp = %d", bsg_machine_noc_data_width_gp); + $display("[INFO][TESTBENCH] bsg_machine_noc_coord_x_width_gp = %d", bsg_machine_noc_coord_x_width_gp); + $display("[INFO][TESTBENCH] bsg_machine_noc_coord_y_width_gp = %d", bsg_machine_noc_coord_y_width_gp); + $display("[INFO][TESTBENCH] bsg_machine_noc_pod_coord_x_width_gp = %d", bsg_machine_noc_pod_coord_x_width_gp); + $display("[INFO][TESTBENCH] bsg_machine_noc_pod_coord_y_width_gp = %d", bsg_machine_noc_pod_coord_y_width_gp); + + $display("[INFO][TESTBENCH] bsg_machine_llcache_sets_gp = %d", bsg_machine_llcache_sets_gp); + $display("[INFO][TESTBENCH] bsg_machine_llcache_ways_gp = %d", bsg_machine_llcache_ways_gp); + $display("[INFO][TESTBENCH] bsg_machine_llcache_line_words_gp = %d", bsg_machine_llcache_line_words_gp); + $display("[INFO][TESTBENCH] bsg_machine_llcache_words_gp = %d", bsg_machine_llcache_words_gp); + $display("[INFO][TESTBENCH] bsg_machine_llcache_miss_fifo_els_gp = %d", bsg_machine_llcache_miss_fifo_els_gp); + $display("[INFO][TESTBENCH] bsg_machine_llcache_channel_width_gp = %d", bsg_machine_llcache_channel_width_gp); + $display("[INFO][TESTBENCH] bsg_machine_llcache_dram_channel_ratio_gp = %d", bsg_machine_llcache_dram_channel_ratio_gp); + + $display("[INFO][TESTBENCH] bsg_machine_dram_bank_words_gp = %d", bsg_machine_dram_bank_words_gp); + $display("[INFO][TESTBENCH] bsg_machine_dram_channels_gp = %d", bsg_machine_dram_channels_gp); + $display("[INFO][TESTBENCH] bsg_machine_dram_words_gp = %d", bsg_machine_dram_words_gp); + $display("[INFO][TESTBENCH] bsg_machine_dram_cfg_gp = %s", bsg_machine_dram_cfg_gp.name()); + + $display("[INFO][TESTBENCH] bsg_machine_io_coord_x_gp = %d", bsg_machine_io_coord_x_gp); + $display("[INFO][TESTBENCH] bsg_machine_io_coord_y_gp = %d", bsg_machine_io_coord_y_gp); + + $display("[INFO][TESTBENCH] bsg_machine_enable_vcore_profiling_lp = %d", bsg_machine_enable_vcore_profiling_lp); + $display("[INFO][TESTBENCH] bsg_machine_enable_router_profiling_lp= %d", bsg_machine_enable_router_profiling_lp); + $display("[INFO][TESTBENCH] bsg_machine_enable_cache_profiling_lp = %d", bsg_machine_enable_cache_profiling_lp); + + $display("[INFO][TESTBENCH] bsg_machine_name_gp = %s", bsg_machine_name_gp); + end + + localparam bsg_machine_llcache_data_width_lp = bsg_machine_noc_data_width_gp; + localparam bsg_machine_llcache_addr_width_lp=(bsg_machine_noc_epa_width_gp-1+`BSG_SAFE_CLOG2(bsg_machine_noc_data_width_gp>>3)); + + localparam bsg_machine_wh_flit_width_lp = bsg_machine_llcache_channel_width_gp; + localparam bsg_machine_wh_ruche_factor_lp = 2; + localparam bsg_machine_wh_cid_width_lp = `BSG_SAFE_CLOG2(bsg_machine_wh_ruche_factor_lp*2); + localparam bsg_machine_wh_len_width_lp = `BSG_SAFE_CLOG2(1 + ((bsg_machine_llcache_line_words_gp * bsg_machine_llcache_data_width_lp) / bsg_machine_llcache_channel_width_gp)); + localparam bsg_machine_wh_coord_width_lp = bsg_machine_noc_coord_x_width_gp; + +// These are macros... for reasons. +`ifndef BSG_MACHINE_DISABLE_VCORE_PROFILING + localparam bsg_machine_enable_vcore_profiling_lp = 1; +`else + localparam bsg_machine_enable_vcore_profiling_lp = 0; +`endif + +`ifndef BSG_MACHINE_DISABLE_ROUTER_PROFILING + localparam bsg_machine_enable_router_profiling_lp = 1; +`else + localparam bsg_machine_enable_router_profiling_lp = 0; +`endif + +`ifndef BSG_MACHINE_DISABLE_CACHE_PROFILING + localparam bsg_machine_enable_cache_profiling_lp = 1; +`else + localparam bsg_machine_enable_cache_profiling_lp = 0; +`endif + + // Clock generator period + localparam lc_cycle_time_ps_lp = 1000; + + // Reset generator depth + localparam reset_depth_lp = 3; + + // Global Counter for Profilers, Tracing, Debugging + localparam global_counter_width_lp = 64; + logic [global_counter_width_lp-1:0] global_ctr; + + logic host_clk; + logic host_reset; + + // bsg_nonsynth_clock_gen and bsg_nonsynth_reset_gen BOTH have bit + // inputs and outputs (they're non-synthesizable). Casting between + // logic and bit can produce unexpected edges as logic types switch + // from X to 0/1 at Time 0 in simulation. This means that the input + // and outputs of both modules must have type bit, AND the wires + // between them. Therefore, we use bit_clk and bit_reset for the + // inputs/outputs of these modules to avoid unexpected + // negative/positive edges and other modules can choose between bit + // version (for non-synthesizable modules) and the logic version + // (otherwise). + bit bit_clk; + bit bit_reset; + logic core_clk; + logic core_reset; + + // reset_done is deasserted when tag programming is done. + logic core_reset_done_lo, core_reset_done_r; + + logic mem_clk; + logic mem_reset; + + logic cache_clk; + logic cache_reset; + + // Snoop wires for Print Stat + logic print_stat_v; + logic [bsg_machine_noc_data_width_gp-1:0] print_stat_tag; + + logic [bsg_machine_noc_coord_x_width_gp-1:0] host_x_coord_li = (bsg_machine_noc_coord_x_width_gp)'(bsg_machine_io_coord_x_gp); + logic [bsg_machine_noc_coord_y_width_gp-1:0] host_y_coord_li = (bsg_machine_noc_coord_y_width_gp)'(bsg_machine_io_coord_y_gp); + + `declare_bsg_manycore_link_sif_s(bsg_machine_noc_epa_width_gp, bsg_machine_noc_data_width_gp, bsg_machine_noc_coord_x_width_gp, bsg_machine_noc_coord_y_width_gp); + + bsg_manycore_link_sif_s host_link_sif_li; + bsg_manycore_link_sif_s host_link_sif_lo; + + // Trace Enable wire for runtime argument to enable tracing (+trace) + logic trace_en; + logic log_en; + logic dpi_trace_en; + logic dpi_log_en; + logic tag_done_lo; + assign trace_en = dpi_trace_en; + assign log_en = dpi_log_en; + + // -Verilator uses a clock generator that is controlled by C/C++ + // (bsg_nonsynth_dpi_clock_gen), whereas VCS uses the normal + // nonsynthesizable clock generator (bsg_nonsynth_clock_gen) +`ifdef VERILATOR + bsg_nonsynth_dpi_clock_gen +`else + bsg_nonsynth_clock_gen +`endif + #(.cycle_time_p(lc_cycle_time_ps_lp)) + core_clk_gen + (.o(bit_clk)); + assign core_clk = bit_clk; + + bsg_nonsynth_reset_gen + #( + .num_clocks_p(1) + ,.reset_cycles_lo_p(0) + ,.reset_cycles_hi_p(16) + ) + reset_gen + ( + .clk_i(bit_clk) + ,.async_reset_o(bit_reset) + ); + assign core_reset = bit_reset; + + bsg_nonsynth_manycore_testbench + #( + .num_pods_x_p(bsg_machine_pods_x_gp) + ,.num_pods_y_p(bsg_machine_pods_y_gp) + ,.pod_x_cord_width_p(bsg_machine_noc_pod_coord_x_width_gp) + ,.pod_y_cord_width_p(bsg_machine_noc_pod_coord_y_width_gp) + + ,.num_tiles_x_p(bsg_machine_pod_tiles_x_gp) + ,.num_tiles_y_p(bsg_machine_pod_tiles_y_gp) + ,.num_subarray_x_p(bsg_machine_pod_tiles_subarray_x_gp) + ,.num_subarray_y_p(bsg_machine_pod_tiles_subarray_y_gp) + + ,.x_cord_width_p(bsg_machine_noc_coord_x_width_gp) + ,.y_cord_width_p(bsg_machine_noc_coord_y_width_gp) + + ,.addr_width_p(bsg_machine_noc_epa_width_gp) + ,.data_width_p(bsg_machine_noc_data_width_gp) + ,.dmem_size_p(bsg_machine_core_dmem_words_gp) + ,.icache_entries_p(bsg_machine_core_icache_entries_gp) + ,.icache_tag_width_p(bsg_machine_core_icache_tag_width_gp) + + ,.ruche_factor_X_p(bsg_machine_noc_ruche_factor_X_gp) + + ,.num_vcache_rows_p(bsg_machine_pod_llcache_rows_gp) + ,.num_vcaches_per_channel_p(bsg_machine_llcache_dram_channel_ratio_gp) + ,.vcache_data_width_p(bsg_machine_llcache_data_width_lp) + ,.vcache_addr_width_p(bsg_machine_llcache_addr_width_lp) + ,.vcache_size_p(bsg_machine_llcache_words_gp) + ,.vcache_sets_p(bsg_machine_llcache_sets_gp) + ,.vcache_ways_p(bsg_machine_llcache_ways_gp) + ,.vcache_block_size_in_words_p(bsg_machine_llcache_line_words_gp) + ,.vcache_dma_data_width_p(bsg_machine_llcache_channel_width_gp) + + ,.wh_flit_width_p(bsg_machine_wh_flit_width_lp) + ,.wh_ruche_factor_p(bsg_machine_wh_ruche_factor_lp) + ,.wh_cid_width_p(bsg_machine_wh_cid_width_lp) + ,.wh_len_width_p(bsg_machine_wh_len_width_lp) + ,.wh_cord_width_p(bsg_machine_wh_coord_width_lp) + + ,.bsg_manycore_mem_cfg_p(bsg_machine_dram_cfg_gp) + ,.bsg_dram_size_p(bsg_machine_dram_words_gp) + + ,.enable_vcore_profiling_p(bsg_machine_enable_vcore_profiling_lp) + ,.enable_router_profiling_p(bsg_machine_enable_router_profiling_lp) + ,.enable_cache_profiling_p(bsg_machine_enable_cache_profiling_lp) + ,.hetero_type_vec_p(bsg_machine_hetero_type_vec_gp) + + ,.reset_depth_p(reset_depth_lp) + ) + testbench + ( + .clk_i(core_clk) + ,.reset_i(core_reset) + + ,.io_link_sif_i(host_link_sif_li) + ,.io_link_sif_o(host_link_sif_lo) + + ,.tag_done_o(core_reset_done_lo) + ); + + bsg_nonsynth_dpi_gpio + #( + .width_p(2) + ,.init_o_p('0) + ,.use_output_p('1) + ,.debug_p('1) + ) + trace_control + (.gpio_o({dpi_log_en, dpi_trace_en}) + ,.gpio_i('0) + ); + + // -------------------------------------------------------------------------- + // IO Complex + // -------------------------------------------------------------------------- + localparam dpi_fifo_width_lp = (1 << $clog2(`bsg_manycore_packet_width(bsg_machine_noc_epa_width_gp,bsg_machine_noc_data_width_gp,bsg_machine_noc_coord_x_width_gp,bsg_machine_noc_coord_y_width_gp))); + localparam ep_fifo_els_lp = 4; + assign host_clk = core_clk; + assign host_reset = core_reset; + + bsg_nonsynth_dpi_manycore + #( + .x_cord_width_p(bsg_machine_noc_coord_x_width_gp) + ,.y_cord_width_p(bsg_machine_noc_coord_y_width_gp) + ,.addr_width_p(bsg_machine_noc_epa_width_gp) + ,.data_width_p(bsg_machine_noc_data_width_gp) + ,.ep_fifo_els_p(ep_fifo_els_lp) + ,.dpi_fifo_els_p(bsg_machine_dpi_fifo_els_gp) + ,.fifo_width_p(128) // It would be better to read this from somewhere + ,.rom_els_p(bsg_machine_rom_els_gp) + ,.rom_width_p(bsg_machine_rom_width_gp) + ,.rom_arr_p(bsg_machine_rom_arr_gp) + ,.max_out_credits_p(bsg_machine_io_credits_max_gp) + ) + mc_dpi + ( + .clk_i(host_clk) + // DR: I don't particularly like this, but we'll leave it for now + ,.reset_i(host_reset | (~core_reset_done_r)) + ,.reset_done_i(core_reset_done_lo) + + // manycore link + ,.link_sif_i(host_link_sif_lo) + ,.link_sif_o(host_link_sif_li) + ,.my_x_i(host_x_coord_li) + ,.my_y_i(host_y_coord_li) + ); + + bsg_dff_chain + #( + .width_p(1) + ,.num_stages_p(reset_depth_lp) + ) + reset_dff + ( + .clk_i(core_clk) + ,.data_i(core_reset_done_lo) + ,.data_o(core_reset_done_r) + ); + + bsg_nonsynth_dpi_cycle_counter + #(.width_p(global_counter_width_lp)) + ctr + ( + .clk_i(core_clk) + ,.reset_i(core_reset) + ,.ctr_r_o(global_ctr) + ); + + bsg_print_stat_snoop + #( + .data_width_p(bsg_machine_noc_data_width_gp) + ,.addr_width_p(bsg_machine_noc_epa_width_gp) + ,.x_cord_width_p(bsg_machine_noc_coord_x_width_gp) + ,.y_cord_width_p(bsg_machine_noc_coord_y_width_gp) + ) + print_stat_snoop + ( + .loader_link_sif_in_i(host_link_sif_lo) // output from manycore + ,.loader_link_sif_out_i(host_link_sif_li) // output from host + + ,.print_stat_v_o(print_stat_v) + ,.print_stat_tag_o(print_stat_tag) + ); + + // In VCS, the C/C++ testbench is controlled by the + // simulator. Therefore, we need to "call into" the C/C++ program + // using the cosim_main function, during the initial block. + // + // DPI Calls in cosim_main will cause simulator time to progress. + // + // This mirrors the DPI functions in aws simulation +`ifndef VERILATOR + import "DPI-C" context task cosim_main(output int unsigned exit_code, input string args); + initial begin + int exit_code; + string args; + longint t; + $value$plusargs("c_args=%s", args); + replicant_tb_top.cosim_main(exit_code, args); + if(exit_code < 0) begin + $display("BSG COSIM FAIL: Test failed with exit code: %d", exit_code); + $fatal; + end else begin + $display("BSG COSIM PASS: Test passed!"); + $finish; + end + end + +`endif + +`ifdef BSG_MACHINE_ENABLE_SAIF + wor saif_en = 0; + + bind vanilla_core vanilla_core_saif_dumper + #( + ) + saif_dumper + ( + .* + ,.saif_en_i($root.`HOST_MODULE_PATH.saif_en) + ,.saif_en_o($root.`HOST_MODULE_PATH.saif_en) + ); +`endif +endmodule From 501d63a4fc9009779b2cc684ffd8bf6b710e848a Mon Sep 17 00:00:00 2001 From: sripathi-muralitharan Date: Sun, 25 Apr 2021 11:49:13 -0700 Subject: [PATCH 07/70] bsg_manycore_platform.cpp * This C++ file implements the platform-specific functions for Dromajo+HammerBlade * Platforms calls to features return HB_MC_NOIMPL * Packet transmission and receipt are handled by Dromajo by writing to * memory-mapped addresses * This file is compiled using the RISC-V toolchain --- .../dromajo-vcs/bsg_manycore_platform.cpp | 408 ++++++++++++++++++ 1 file changed, 408 insertions(+) create mode 100644 libraries/platforms/dromajo-vcs/bsg_manycore_platform.cpp diff --git a/libraries/platforms/dromajo-vcs/bsg_manycore_platform.cpp b/libraries/platforms/dromajo-vcs/bsg_manycore_platform.cpp new file mode 100644 index 000000000..2f4669a8d --- /dev/null +++ b/libraries/platforms/dromajo-vcs/bsg_manycore_platform.cpp @@ -0,0 +1,408 @@ +// Copyright (c) 2020, University of Washington All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// Redistributions of source code must retain the above copyright notice, this list +// of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above copyright notice, this +// list of conditions and the following disclaimer in the documentation and/or +// other materials provided with the distribution. +// +// Neither the name of the copyright holder nor the names of its contributors may +// be used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include +#include +#include +#include + +#include + +/* these are convenience macros that are only good for one line prints */ +#define manycore_pr_dbg(mc, fmt, ...) \ + bsg_pr_dbg("%s: " fmt, mc->name, ##__VA_ARGS__) + +#define manycore_pr_err(mc, fmt, ...) \ + bsg_pr_err("%s: " fmt, mc->name, ##__VA_ARGS__) + +#define manycore_pr_warn(mc, fmt, ...) \ + bsg_pr_warn("%s: " fmt, mc->name, ##__VA_ARGS__) + +#define manycore_pr_info(mc, fmt, ...) \ + bsg_pr_info("%s: " fmt, mc->name, ##__VA_ARGS__) + +////////////////////////// RISC-V Host <--> Manycore API ////////////////////////// + +// Memory mapped addresses to interact with the manycore bridge +// BlackParrot writes to these addresses to interact with the manycore +// Manycore device base address +#define MC_BASE_ADDR 0x500000 +// BP --> Manycore Requests +#define BP_TO_MC_REQ_FIFO_ADDR 0x1000 +#define BP_TO_MC_REQ_CREDITS_ADDR 0x2000 +// Manycore --> BP Responses +#define MC_TO_BP_RESP_FIFO_ADDR 0x3000 +#define MC_TO_BP_RESP_ENTRIES_ADDR 0x4000 +// Manycore --> BP Requests +#define MC_TO_BP_REQ_FIFO_ADDR 0x5000 +#define MC_TO_BP_REQ_ENTRIES_ADDR 0x6000 + +/* + * Reads the manycore bridge for number of credits remaining in the endpoint + * @returns number of credits in the manycore bridge enddpoint + */ +int hb_mc_platform_get_credits() { + uint32_t *bp_to_mc_req_credits_addr = (uint32_t *) (MC_BASE_ADDR + BP_TO_MC_REQ_CREDITS_ADDR); + int credits = int(*bp_to_mc_req_credits_addr); + return credits; +} + +/* + * Writes a 128-bit manycore packet in 32-bit chunks to the manycore bridge FIFO + * @param[in] pkt --> Pointer to the manycore packet + */ +void hb_mc_platform_write_to_manycore_bridge(hb_mc_packet_t *pkt) { + int credits; + + // Wait till there is atleast 1 credit to send the write + do { + credits = hb_mc_platform_get_credits(); + } while (credits == 0); + + uint32_t *bp_to_mc_req_fifo_addr = (uint32_t *) (MC_BASE_ADDR + BP_TO_MC_REQ_FIFO_ADDR); + for(int i = 0; i < 4; i++) { + *bp_to_mc_req_fifo_addr = pkt->words[i]; + bp_to_mc_req_fifo_addr++; + } +} + +/* + * Reads the manycore bridge FIFOs in 32-bit chunks to form the 128-bit packet + * @param[in] pkt --> Pointer to the manycore packet + * @param[in] type --> Type of FIFO to read from + * @returns HB_MC_SUCCESS on success, HB_MC_FAIL if FIFO type is unknown + */ +int hb_mc_platform_read_from_manycore_bridge(hb_mc_packet_t *pkt, hb_mc_fifo_rx_t type) { + switch(type) { + case HB_MC_FIFO_RX_REQ: + { + // Check if the entries are full + uint32_t *mc_to_bp_req_entries_addr = (uint32_t *) (MC_BASE_ADDR + MC_TO_BP_REQ_ENTRIES_ADDR); + while(!(*mc_to_bp_req_entries_addr)) + ; + + // Read the value + uint32_t *mc_to_bp_req_fifo_addr = (uint32_t *) (MC_BASE_ADDR + MC_TO_BP_REQ_FIFO_ADDR); + uint32_t read_status = 0xFFFF; + for (int i = 0; i < 4; i++) { + pkt->words[i] = *mc_to_bp_req_fifo_addr; + read_status &= pkt->words[i]; + mc_to_bp_req_fifo_addr++; + } + + // If all packets are 0xFFFF --> there is something wrong + if (read_status == 0xFFFF) + return HB_MC_FAIL; + } + break; + case HB_MC_FIFO_RX_RSP: + { + // Check if the entries are full + uint32_t *mc_to_bp_resp_entries_addr = (uint32_t *) (MC_BASE_ADDR + MC_TO_BP_RESP_ENTRIES_ADDR); + while(!(*mc_to_bp_resp_entries_addr)) + ; + + // Read the value + uint32_t *mc_to_bp_resp_fifo_addr = (uint32_t *) (MC_BASE_ADDR + MC_TO_BP_RESP_FIFO_ADDR); + uint32_t read_status = 0xFFFF; + for (int i = 0; i < 4; i++) { + pkt->words[i] = *mc_to_bp_resp_fifo_addr; + read_status &= pkt->words[i]; + mc_to_bp_resp_fifo_addr++; + } + + // If all packets are 0xFFFF --> there is something wrong + if (read_status == 0xFFFF) + return HB_MC_FAIL; + } + break; + default: + { + bsg_pr_err("%s: Unknown packet type\n", __func__); + return HB_MC_FAIL; + } + break; + } + return HB_MC_SUCCESS; +} + +////////////////////////// Platform-Level API ////////////////////////// + +typedef struct hb_mc_platform_t +{ + hb_mc_manycore_id_t id; +} hb_mc_platform_t; + +static std::set active_ids; + +/** + * Clean up the runtime platform + * @param[in] mc A manycore to clean up + */ +void hb_mc_platform_cleanup(hb_mc_manycore_t *mc) { + hb_mc_platform_t *platform = reinterpret_cast(mc->platform); + + // Remove the key + auto key = active_ids.find(platform->id); + active_ids.erase(key); + + platform->id = 0; + + // Ideally, we would clean up each platform in + // platforms. However, we can't guarantee that someone won't + // call init again, so we'll live with the memory leak for + // now. It's a rare case, since few people call init/cleanup + // and then continue their program indefinitley. + + return; +} + +/** + * Initialize the runtime platform + * @param[in] mc A manycore to initialize + * @param[in] id ID which selects the physical hardware from which this manycore is configured + * @return HB_MC_FAIL if an error occured. HB_MC_SUCCESS otherwise. + */ +int hb_mc_platform_init(hb_mc_manycore_t *mc, hb_mc_manycore_id_t id) { + hb_mc_platform_t *platform = new hb_mc_platform_t; + + // check if mc is already initialized + if (mc->platform) + return HB_MC_INITIALIZED_TWICE; + + if (id != 0) + { + manycore_pr_err(mc, "Failed to init platform: invalid ID\n"); + return HB_MC_INVALID; + } + + // Check if the ID has already been initialized + if(active_ids.find(id) != active_ids.end()) + { + manycore_pr_err(mc, "Already initialized ID\n"); + return HB_MC_INVALID; + } + + active_ids.insert(id); + platform->id = id; + + mc->platform = reinterpret_cast(platform); + + return HB_MC_SUCCESS; +} + +/** + * Transmit a request packet to manycore hardware + * @param[in] mc A manycore instance initialized with hb_mc_manycore_init() + * @param[in] request A request packet to transmit to manycore hardware + * @param[in] timeout A timeout counter. Unused - set to -1 to wait forever. + * @return HB_MC_SUCCESS on success. Otherwise an error code defined in bsg_manycore_errno.h. + */ +int hb_mc_platform_transmit(hb_mc_manycore_t *mc, hb_mc_packet_t *packet, hb_mc_fifo_tx_t type, long timeout) { + hb_mc_platform_t *platform = reinterpret_cast(mc->platform); + const char *typestr = hb_mc_fifo_tx_to_string(type); + + // Timeout is unsupported + if (timeout != -1) + { + manycore_pr_err(mc, "%s: Only a timeout value of -1 is supported\n", __func__); + return HB_MC_INVALID; + } + + // Host doesn't send responses to the mamycore + if (type == HB_MC_FIFO_TX_RSP) + { + manycore_pr_err(mc, "TX Response Not Supported!\n"); + return HB_MC_NOIMPL; + } + + // Write packet to the manycore bridge + hb_mc_platform_write_to_manycore_bridge(packet); + + return HB_MC_SUCCESS; +} + +/** + * Receive a packet from manycore hardware + * @param[in] mc A manycore instance initialized with hb_mc_manycore_init() + * @param[in] response A packet into which data should be read + * @param[in] timeout A timeout counter. Unused - set to -1 to wait forever. + * @return HB_MC_SUCCESS on success. Otherwise an error code defined in bsg_manycore_errno.h. + */ +int hb_mc_platform_receive(hb_mc_manycore_t *mc, hb_mc_packet_t *packet, hb_mc_fifo_rx_t type, long timeout) { + hb_mc_platform_t *platform = reinterpret_cast(mc->platform); + + // Timeout is unsupported + if (timeout != -1) + { + manycore_pr_err(mc, "%s: Only a timeout value of -1 is supported\n", __func__); + return HB_MC_INVALID; + } + + int err = hb_mc_platform_read_from_manycore_bridge(packet, type); + + if (err != 0) + { + manycore_pr_err(mc, "%s: Failed to receive packet\n", __func__); + return HB_MC_INVALID; + } + + return HB_MC_SUCCESS; +} + +/** + * Read the configuration register at an index + * @param[in] mc A manycore instance initialized with hb_mc_manycore_init() + * @param[in] idx Configuration register index to access + * @param[out] config Configuration value at index + * @return HB_MC_SUCCESS on success. Otherwise an error code defined in bsg_manycore_errno.h. + */ +int hb_mc_platform_get_config_at(hb_mc_manycore_t *mc, unsigned int idx, hb_mc_config_raw_t *config) { + hb_mc_platform_t *platform = reinterpret_cast(mc->platform); + + if (idx < HB_MC_CONFIG_MAX) + { + // TODO: + // Read from an array in an autogenerated C/C++ header + return HB_MC_SUCCESS; + } + + return HB_MC_INVALID; +} + +/** + * Stall until the all requests (and responses) have reached their destination. + * @param[in] mc A manycore instance initialized with hb_mc_manycore_init() + * @param[in] timeout A timeout counter. Unused - set to -1 to wait forever. + * @return HB_MC_SUCCESS on success. Otherwise an error code defined in bsg_manycore_errno.h. + */ +int hb_mc_platform_fence(hb_mc_manycore_t *mc, long timeout) { + int credits, err; + bool isvacant; + uint32_t max_credits; + + const hb_mc_config_t *cfg = hb_mc_manycore_get_config(mc); + hb_mc_platform_t *platform = reinterpret_cast(mc->platform); + max_credits = hb_mc_config_get_io_endpoint_max_out_credits(cfg); + + if (timeout != -1) { + manycore_pr_err(mc, "%s: Only a timeout value of -1 is supported\n", __func__); + return HB_MC_NOIMPL; + } + + do + { + credits = hb_mc_platform_get_credits(); + } while (!(credits == (int)max_credits)); + + return HB_MC_SUCCESS; +} + +/** + * Signal the hardware to start a bulk transfer over the network + * @param[in] mc A manycore instance initialized with hb_mc_manycore_init() + * @return HB_MC_SUCCESS on success. Otherwise an error code defined in bsg_manycore_errno.h. + */ +int hb_mc_platform_start_bulk_transfer(hb_mc_manycore_t *mc) { + return HB_MC_SUCCESS; +} + +/** + * Signal the hardware to end a bulk transfer over the network + * @param[in] mc A manycore instance initialized with hb_mc_manycore_init() + * @return HB_MC_SUCCESS on success. Otherwise an error code defined in bsg_manycore_errno.h. + */ +int hb_mc_platform_finish_bulk_transfer(hb_mc_manycore_t *mc) { + return HB_MC_SUCCESS; +} + +/** + * Get the current cycle counter of the Manycore Platform + * @param[in] mc A manycore instance initialized with hb_mc_manycore_init() + * @param[out] time The current counter value. + * @return HB_MC_SUCCESS on success. Otherwise an error code defined in bsg_manycore_errno.h. + */ +int hb_mc_platform_get_cycle(hb_mc_manycore_t *mc, uint64_t *time) { + return HB_MC_NOIMPL; +} + +/** + * Get the number of instructions executed for a certain class of instructions + * @param[in] mc A manycore instance initialized with hb_mc_manycore_init() + * @param[in] itype An enum defining the class of instructions to query. + * @param[out] count The number of instructions executed in the queried class. + * @return HB_MC_SUCCESS on success. Otherwise an error code defined in bsg_manycore_errno.h. + */ +int hb_mc_platform_get_icount(hb_mc_manycore_t *mc, bsg_instr_type_e itype, int *count) { + return HB_MC_NOIMPL; +} + +/** + * Enable trace file generation (vanilla_operation_trace.csv) + * @param[in] mc A manycore instance initialized with hb_mc_manycore_init() + * @return HB_MC_SUCCESS on success. Otherwise an error code defined in bsg_manycore_errno.h. + */ +int hb_mc_platform_trace_enable(hb_mc_manycore_t *mc) { + return HB_MC_NOIMPL; +} + +/** + * Disable trace file generation (vanilla_operation_trace.csv) + * @param[in] mc A manycore instance initialized with hb_mc_manycore_init() + * @return HB_MC_SUCCESS on success. Otherwise an error code defined in bsg_manycore_errno.h. + */ +int hb_mc_platform_trace_disable(hb_mc_manycore_t *mc) { + return HB_MC_NOIMPL; +} + +/** + * Enable log file generation (vanilla.log) + * @param[in] mc A manycore instance initialized with hb_mc_manycore_init() + * @return HB_MC_SUCCESS on success. Otherwise an error code defined in bsg_manycore_errno.h. + */ +int hb_mc_platform_log_enable(hb_mc_manycore_t *mc) { + return HB_MC_NOIMPL; +} + +/** + * Disable log file generation (vanilla.log) + * @param[in] mc A manycore instance initialized with hb_mc_manycore_init() + * @return HB_MC_SUCCESS on success. Otherwise an error code defined in bsg_manycore_errno.h. + */ +int hb_mc_platform_log_disable(hb_mc_manycore_t *mc) { + return HB_MC_NOIMPL; +} + +/** + * Block until chip reset has completed. + * @param[in] mc A manycore instance initialized with hb_mc_manycore_init() + * @return HB_MC_SUCCESS on success. Otherwise an error code defined in bsg_manycore_errno.h. + */ +int hb_mc_platform_wait_reset_done(hb_mc_manycore_t *mc) { + // Reset is guaranteed to be complete before program starts by the simulation wrapper + return HB_MC_SUCCESS; +} From e26510e6cb8a78f00756009379a513b7fe668dd0 Mon Sep 17 00:00:00 2001 From: sripathi-muralitharan Date: Sun, 25 Apr 2021 12:09:00 -0700 Subject: [PATCH 08/70] bsg_manycore_simulator.cpp * This C++ file controls simulation for BlackParrot/Dromajo using VCS * It is also modelled as the x86 host that BlackParrot will communicate with * during execution --- .../dromajo-vcs/bsg_manycore_simulator.cpp | 315 ++++++++++++++++++ 1 file changed, 315 insertions(+) create mode 100644 libraries/platforms/dromajo-vcs/bsg_manycore_simulator.cpp diff --git a/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.cpp b/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.cpp new file mode 100644 index 000000000..ec350ae2a --- /dev/null +++ b/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.cpp @@ -0,0 +1,315 @@ +// Copyright (c) 2020, University of Washington All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// Redistributions of source code must retain the above copyright notice, this list +// of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above copyright notice, this +// list of conditions and the following disclaimer in the documentation and/or +// other materials provided with the distribution. +// +// Neither the name of the copyright holder nor the names of its contributors may +// be used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// This file implements the SimulatorWrapper object, which hides +// differences in simulators. + +#include +#include +#include +#include +#include + +#include +#include + +#include "dromajo_cosim.h" +#include "dromajo_manycore.h" + +#include +#include + +#include +// We use __m128i so that we can pass a 128-bit type between Verilog +// and C. +#include + +extern "C" { + void bsg_dpi_next(); +} + +// Dromajo specifics +dromajo_cosim_state_t *dromajo_state; +dromajo_cosim_state_t* dromajo_init(); +bool dromajo_step(); +void dromajo_transmit_packet(); +void dromajo_receive_packet(); +void dromajo_set_credits(); + +// DPI +bsg_nonsynth_dpi::dpi_manycore *dpi; + +SimulationWrapper::SimulationWrapper(){ + root = new std::string("replicant_tb_top"); + std::string mc_dpi = *root + ".mc_dpi"; + top = svGetScopeFromName(mc_dpi.c_str()); +} + +// Does nothing. Turning on/off assertions is only supported in +// Verilator. +void SimulationWrapper::assertOn(bool val){ + +} + +std::string SimulationWrapper::getRoot(){ + return *root; +} + +void SimulationWrapper::eval(){ + // Execute one instruction on Dromajo + if (!dromajo_step()) { + // Fixme: Dromajo could also terminate due to premature errors. + // Use the test outputs to detect PASS/FAIL + printf("Dromajo Execution Complete!\nExiting...\n"); + dromajo_cosim_fini(dromajo_state); + exit(0); + } + + // Poll for packets to be transmitted + dromajo_transmit_packet(); + // Poll for packets to be received + dromajo_receive_packet(); + // Update the credits in dromajo + dromajo_set_credits(); + + // Advance time 1 unit + svScope prev; + prev = svSetScope(top); + bsg_dpi_next(); + svSetScope(prev); +} + +SimulationWrapper::~SimulationWrapper(){ + this->top = nullptr; +} + +static int dpi_fifo_drain(bsg_nonsynth_dpi::dpi_manycore *dpi, hb_mc_fifo_rx_t type) { + __m128i *pkt; + + int err, drains = 0; + int cap = dpi->config[HB_MC_CONFIG_IO_REMOTE_LOAD_CAP]; + + do { + bsg_dpi_next(); + switch(type) { + case HB_MC_FIFO_RX_REQ: + err = dpi->rx_req(*pkt); + break; + case HB_MC_FIFO_RX_RSP: + err = dpi->rx_rsp(*pkt); + break; + default: + printf("Unknown FIFO type\n"); + return HB_MC_FAIL; + } + + if (err == BSG_NONSYNTH_DPI_SUCCESS) + drains++; + } while ((err == BSG_NONSYNTH_DPI_NOT_WINDOW | err == BSG_NONSYNTH_DPI_SUCCESS) + && drains <= cap); + + if (drains != cap) + printf("Failed to drain FIFO\n"); + return HB_MC_FAIL; + + return HB_MC_SUCCESS; +} + +static void dpi_clean(bsg_nonsynth_dpi::dpi_manycore *dpi) { + delete dpi; +} + +static int dpi_init(bsg_nonsynth_dpi::dpi_manycore *dpi, std::string hierarchy) { + bsg_dpi_next(); + + dpi = new bsg_nonsynth_dpi::dpi_manycore(hierarchy + ".mc_dpi"); + + int err; + err = dpi_fifo_drain(dpi, HB_MC_FIFO_RX_REQ); + if (err != HB_MC_SUCCESS) { + dpi_clean(dpi); + return err; + } + + err = dpi_fifo_drain(dpi, HB_MC_FIFO_RX_RSP); + if (err != HB_MC_SUCCESS) { + dpi_clean(dpi); + return err; + } + + return HB_MC_SUCCESS; +} + +static int dpi_wait_for_reset(bsg_nonsynth_dpi::dpi_manycore *dpi) { + bool done; + dpi->reset_is_done(done); + + while (!done) { + bsg_dpi_next(); + dpi->reset_is_done(done); + } + + return HB_MC_SUCCESS; +} + +dromajo_cosim_state_t* dromajo_init() { + dromajo_cosim_state_t *dromajo_state; + + char dromajo[50]; + sprintf(dromajo, "dromajo"); + + char host[50]; + sprintf(host, "--host"); + + char manycore[50]; + sprintf(manycore, "--manycore"); + + char progname[50]; + sprintf(progname, "test.elf"); + + char* argv[] = {dromajo, host, manycore, progname}; + dromajo_state = dromajo_cosim_init(4, argv); + + return dromajo_state; +} + +bool dromajo_step() { + // Execute dromajo with verbose mode on + int err = dromajo_cosim_step(dromajo_state, 0, 0, 0, 0, 0, false, true); + if (err != 0) + return false; + else + return true; +} + +void dromajo_transmit_packet() { + hb_mc_packet_t *packet; + int err; + __m128i *pkt; + + // Check if FIFO is full and hence ready to transmit + mc_fifo_type_t type = FIFO_HOST_TO_MC_REQ; + bool is_full = mc_is_fifo_full(type); + + if (is_full) { + // Read the FIFO head pointer for all 32-bit FIFOs + packet->words[0] = host_to_mc_req_fifo->fifo[0].front(); + packet->words[1] = host_to_mc_req_fifo->fifo[1].front(); + packet->words[2] = host_to_mc_req_fifo->fifo[2].front(); + packet->words[3] = host_to_mc_req_fifo->fifo[3].front(); + + pkt = reinterpret_cast<__m128i *>(packet); + + // Try to transmit until you actually can + err = dpi->tx_req(*pkt); + + // Drain the FIFO once transmitted + if (err == BSG_NONSYNTH_DPI_SUCCESS) { + for (int i = 0;i < 4; i++) + host_to_mc_req_fifo->fifo[i].pop(); + } + } +} + +void dromajo_receive_packet() { + hb_mc_packet_t *req_packet, *resp_packet; + int err; + __m128i *pkt; + + // Read from the manycore request FIFO + err = dpi->rx_req(*pkt); + req_packet = reinterpret_cast(pkt); + + // Push to host if valid and mark the FIFOs as full + if (err == BSG_NONSYNTH_DPI_SUCCESS) { + for (int i = 0; i < 4; i++) { + mc_to_host_req_fifo->fifo[i].push(req_packet->words[i]); + mc_to_host_req_fifo->full[i] = true; + } + } + + // Read from the manycore response FIFO + err = dpi->rx_rsp(*pkt); + resp_packet = reinterpret_cast(pkt); + + // Push to host if valid and mark the FIFOs as full + if (err == BSG_NONSYNTH_DPI_SUCCESS) { + for (int i = 0; i < 4; i++) { + mc_to_host_resp_fifo->fifo[i].push(resp_packet->words[i]); + mc_to_host_resp_fifo->full[i] = true; + } + } +} + +void dromajo_set_credits() { + int credits; + int res = dpi->get_credits(credits); + if (res == BSG_NONSYNTH_DPI_SUCCESS) { + if (credits < 0) + printf("Warning! Credit value is negative!\n"); + + host_to_mc_req_fifo->credits = credits; + } +} + +#ifdef VCS +int vcs_main(int argc, char **argv) { +#else +int main(int argc, char **argv) { +#endif + + // Initialize Dromajo + dromajo_state = dromajo_init(); + + // Create an object of the simulation wrapper + SimulationWrapper *sim = new SimulationWrapper(); + std::string hierarchy = sim->getRoot(); + + int err; + + // Initialize DPI + err = dpi_init(dpi, hierarchy); + if (err != HB_MC_SUCCESS) { + delete sim; + printf("Failed to initialize DPI!\nExiting...\n"); + return -1; + } + + // Wait for reset to be done + err = dpi_wait_for_reset(dpi); + if (err != HB_MC_SUCCESS) { + dpi_clean(dpi); + delete sim; + printf("Failed to wait for reset!\nExiting...\n"); + return -1; + } + + while(1) + sim->eval(); + + return 0; +} \ No newline at end of file From 01aa184cd435f921261ea7907479436f79dd2dbc Mon Sep 17 00:00:00 2001 From: sripathi-muralitharan Date: Sun, 25 Apr 2021 12:15:52 -0700 Subject: [PATCH 09/70] Adding a .gitignore file --- libraries/platforms/dromajo-vcs/.gitignore | 1 + 1 file changed, 1 insertion(+) create mode 100644 libraries/platforms/dromajo-vcs/.gitignore diff --git a/libraries/platforms/dromajo-vcs/.gitignore b/libraries/platforms/dromajo-vcs/.gitignore new file mode 100644 index 000000000..e9da60ba1 --- /dev/null +++ b/libraries/platforms/dromajo-vcs/.gitignore @@ -0,0 +1 @@ +msg_config \ No newline at end of file From d8d288b9e4fc57246cee3b7f2f158bdb046f434a Mon Sep 17 00:00:00 2001 From: sripathi-muralitharan Date: Sun, 25 Apr 2021 12:17:13 -0700 Subject: [PATCH 10/70] Adding a dummy features.h and endian.h header files to point to newlib-specific versions --- .../dromajo-vcs/software/include/endian.h | 45 +++++++++++++++++++ .../dromajo-vcs/software/include/features.h | 35 +++++++++++++++ 2 files changed, 80 insertions(+) create mode 100644 libraries/platforms/dromajo-vcs/software/include/endian.h create mode 100644 libraries/platforms/dromajo-vcs/software/include/features.h diff --git a/libraries/platforms/dromajo-vcs/software/include/endian.h b/libraries/platforms/dromajo-vcs/software/include/endian.h new file mode 100644 index 000000000..c788d2fee --- /dev/null +++ b/libraries/platforms/dromajo-vcs/software/include/endian.h @@ -0,0 +1,45 @@ +// Copyright (c) 2020, University of Washington All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// Redistributions of source code must retain the above copyright notice, this list +// of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above copyright notice, this +// list of conditions and the following disclaimer in the documentation and/or +// other materials provided with the distribution. +// +// Neither the name of the copyright holder nor the names of its contributors may +// be used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// A dummy header to interface with the endian.h header from the newlib toolchain + +#ifndef _ENDIAN_H +#define _ENDIAN_H + +#include + +#if defined(_DEFAULT_SOURCE) && (!defined(__ASSEMBLER__)) +// BlackParrot is Little Endian +#define le16toh(_x) ((__uint16_t)(_x)) +#define htole16(_x) ((__uint16_t)(_x)) +#define le32toh(_x) ((__uint32_t)(_x)) +#define htole32(_x) ((__uint32_t)(_x)) +#define le64toh(_x) ((__uint64_t)(_x)) +#define htole64(_x) ((__uint64_t)(_x)) +#endif + +#endif/* _ENDIAN_H__ */ diff --git a/libraries/platforms/dromajo-vcs/software/include/features.h b/libraries/platforms/dromajo-vcs/software/include/features.h new file mode 100644 index 000000000..352797c3d --- /dev/null +++ b/libraries/platforms/dromajo-vcs/software/include/features.h @@ -0,0 +1,35 @@ +// Copyright (c) 2020, University of Washington All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// Redistributions of source code must retain the above copyright notice, this list +// of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above copyright notice, this +// list of conditions and the following disclaimer in the documentation and/or +// other materials provided with the distribution. +// +// Neither the name of the copyright holder nor the names of its contributors may +// be used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// A dummy header to interface with the features.h header from the newlib toolchain + +#ifndef _FEATURES_H +#define _FEATURES_H + +#include + +#endif /* _FEATURES_H */ \ No newline at end of file From d63b464237ae9912974a27e3ce1e73145415f5ad Mon Sep 17 00:00:00 2001 From: sripathi-muralitharan Date: Sun, 25 Apr 2021 12:19:05 -0700 Subject: [PATCH 11/70] Include files for Dromajo * This currently contains only a config file of very low priority * Is there a better solution? Maybe ifdefs? --- .../platforms/dromajo-vcs/software/include/dromajo/config.h | 1 + 1 file changed, 1 insertion(+) create mode 100644 libraries/platforms/dromajo-vcs/software/include/dromajo/config.h diff --git a/libraries/platforms/dromajo-vcs/software/include/dromajo/config.h b/libraries/platforms/dromajo-vcs/software/include/dromajo/config.h new file mode 100644 index 000000000..b6a6a72fa --- /dev/null +++ b/libraries/platforms/dromajo-vcs/software/include/dromajo/config.h @@ -0,0 +1 @@ +#define CONFIG_VERSION "Dromajo-0.1" \ No newline at end of file From f078785c40c621e1f001a7a98cd0a4335283e3a7 Mon Sep 17 00:00:00 2001 From: sripathi-muralitharan Date: Sun, 25 Apr 2021 12:20:36 -0700 Subject: [PATCH 12/70] Implementations of file lock and unlock functions * The implementation is currently a no-op since BlackParrot is * single-thread --- .../dromajo-vcs/software/src/flockfile.c | 37 +++++++++++++++++++ .../dromajo-vcs/software/src/funlockfile.c | 37 +++++++++++++++++++ 2 files changed, 74 insertions(+) create mode 100644 libraries/platforms/dromajo-vcs/software/src/flockfile.c create mode 100644 libraries/platforms/dromajo-vcs/software/src/funlockfile.c diff --git a/libraries/platforms/dromajo-vcs/software/src/flockfile.c b/libraries/platforms/dromajo-vcs/software/src/flockfile.c new file mode 100644 index 000000000..2028dc4dd --- /dev/null +++ b/libraries/platforms/dromajo-vcs/software/src/flockfile.c @@ -0,0 +1,37 @@ +// Copyright (c) 2020, University of Washington All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// Redistributions of source code must retain the above copyright notice, this list +// of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above copyright notice, this +// list of conditions and the following disclaimer in the documentation and/or +// other materials provided with the distribution. +// +// Neither the name of the copyright holder nor the names of its contributors may +// be used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// RISC-V Newlib does not seem to define this function anywhere although +// it is declared in stdio.h. +// Since there is no threading library, implement this function as a no-op + +#include + +void flockfile(FILE *fp) +{ + // Do nothing +} \ No newline at end of file diff --git a/libraries/platforms/dromajo-vcs/software/src/funlockfile.c b/libraries/platforms/dromajo-vcs/software/src/funlockfile.c new file mode 100644 index 000000000..dfab8688a --- /dev/null +++ b/libraries/platforms/dromajo-vcs/software/src/funlockfile.c @@ -0,0 +1,37 @@ +// Copyright (c) 2020, University of Washington All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// Redistributions of source code must retain the above copyright notice, this list +// of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above copyright notice, this +// list of conditions and the following disclaimer in the documentation and/or +// other materials provided with the distribution. +// +// Neither the name of the copyright holder nor the names of its contributors may +// be used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// RISC-V Newlib does not seem to define this function anywhere although +// it is declared in stdio.h. +// Since there is no threading library, implement this function as a no-op + +#include + +void funlockfile(FILE *fp) +{ + // Do nothing +} \ No newline at end of file From 050b13814d151984458bc4312215feb47fa4e12b Mon Sep 17 00:00:00 2001 From: sripathi-muralitharan Date: Sun, 25 Apr 2021 12:25:08 -0700 Subject: [PATCH 13/70] Adding the argument parsing library * This copies the argument parsing library from RISC-V's linux-only newlib * There are small modifications to calls to * sleep() --> Implemented as a for loop (Replace later) * alloca() --> Implemented using malloc() and free() * Note: Explore better methods to recompile the toolchain with this library * to avoid including it in this folder --- .../software/include/argp-fmtstream.h | 297 +++ .../software/include/argp-namefrob.h | 92 + .../dromajo-vcs/software/include/argp.h | 578 +++++ .../dromajo-vcs/software/include/sysexits.h | 114 + .../dromajo-vcs/software/src/argp/argp-ba.c | 26 + .../software/src/argp/argp-eexst.c | 32 + .../software/src/argp/argp-fmtstream.c | 429 ++++ .../software/src/argp/argp-fs-xinl.c | 41 + .../dromajo-vcs/software/src/argp/argp-help.c | 1862 +++++++++++++++++ .../software/src/argp/argp-parse.c | 988 +++++++++ .../dromajo-vcs/software/src/argp/argp-pv.c | 25 + .../dromajo-vcs/software/src/argp/argp-pvh.c | 32 + .../dromajo-vcs/software/src/argp/argp-xinl.c | 42 + 13 files changed, 4558 insertions(+) create mode 100644 libraries/platforms/dromajo-vcs/software/include/argp-fmtstream.h create mode 100644 libraries/platforms/dromajo-vcs/software/include/argp-namefrob.h create mode 100644 libraries/platforms/dromajo-vcs/software/include/argp.h create mode 100644 libraries/platforms/dromajo-vcs/software/include/sysexits.h create mode 100644 libraries/platforms/dromajo-vcs/software/src/argp/argp-ba.c create mode 100644 libraries/platforms/dromajo-vcs/software/src/argp/argp-eexst.c create mode 100644 libraries/platforms/dromajo-vcs/software/src/argp/argp-fmtstream.c create mode 100644 libraries/platforms/dromajo-vcs/software/src/argp/argp-fs-xinl.c create mode 100644 libraries/platforms/dromajo-vcs/software/src/argp/argp-help.c create mode 100644 libraries/platforms/dromajo-vcs/software/src/argp/argp-parse.c create mode 100644 libraries/platforms/dromajo-vcs/software/src/argp/argp-pv.c create mode 100644 libraries/platforms/dromajo-vcs/software/src/argp/argp-pvh.c create mode 100644 libraries/platforms/dromajo-vcs/software/src/argp/argp-xinl.c diff --git a/libraries/platforms/dromajo-vcs/software/include/argp-fmtstream.h b/libraries/platforms/dromajo-vcs/software/include/argp-fmtstream.h new file mode 100644 index 000000000..7a291e28c --- /dev/null +++ b/libraries/platforms/dromajo-vcs/software/include/argp-fmtstream.h @@ -0,0 +1,297 @@ +/* Word-wrapping and line-truncating streams. + Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Written by Miles Bader . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This package emulates glibc `line_wrap_stream' semantics for systems that + don't have that. If the system does have it, it is just a wrapper for + that. This header file is only used internally while compiling argp, and + shouldn't be installed. */ + +#ifndef _ARGP_FMTSTREAM_H +#define _ARGP_FMTSTREAM_H + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#if (_LIBC - 0 && !defined (USE_IN_LIBIO)) \ + || (defined (__GNU_LIBRARY__) && defined (HAVE_LINEWRAP_H)) +/* line_wrap_stream is available, so use that. */ +#define ARGP_FMTSTREAM_USE_LINEWRAP +#endif + +#ifdef ARGP_FMTSTREAM_USE_LINEWRAP +/* Just be a simple wrapper for line_wrap_stream; the semantics are + *slightly* different, as line_wrap_stream doesn't actually make a new + object, it just modifies the given stream (reversibly) to do + line-wrapping. Since we control who uses this code, it doesn't matter. */ + +#include + +typedef FILE *argp_fmtstream_t; + +#define argp_make_fmtstream line_wrap_stream +#define __argp_make_fmtstream line_wrap_stream +#define argp_fmtstream_free line_unwrap_stream +#define __argp_fmtstream_free line_unwrap_stream + +#define __argp_fmtstream_putc(fs,ch) putc(ch,fs) +#define argp_fmtstream_putc(fs,ch) putc(ch,fs) +#define __argp_fmtstream_puts(fs,str) fputs(str,fs) +#define argp_fmtstream_puts(fs,str) fputs(str,fs) +#define __argp_fmtstream_write(fs,str,len) fwrite(str,1,len,fs) +#define argp_fmtstream_write(fs,str,len) fwrite(str,1,len,fs) +#define __argp_fmtstream_printf fprintf +#define argp_fmtstream_printf fprintf + +#define __argp_fmtstream_lmargin line_wrap_lmargin +#define argp_fmtstream_lmargin line_wrap_lmargin +#define __argp_fmtstream_set_lmargin line_wrap_set_lmargin +#define argp_fmtstream_set_lmargin line_wrap_set_lmargin +#define __argp_fmtstream_rmargin line_wrap_rmargin +#define argp_fmtstream_rmargin line_wrap_rmargin +#define __argp_fmtstream_set_rmargin line_wrap_set_rmargin +#define argp_fmtstream_set_rmargin line_wrap_set_rmargin +#define __argp_fmtstream_wmargin line_wrap_wmargin +#define argp_fmtstream_wmargin line_wrap_wmargin +#define __argp_fmtstream_set_wmargin line_wrap_set_wmargin +#define argp_fmtstream_set_wmargin line_wrap_set_wmargin +#define __argp_fmtstream_point line_wrap_point +#define argp_fmtstream_point line_wrap_point + +#else /* !ARGP_FMTSTREAM_USE_LINEWRAP */ +/* Guess we have to define our own version. */ + +#ifndef __const +#define __const const +#endif + +struct argp_fmtstream +{ + FILE *stream; /* The stream we're outputting to. */ + + size_t lmargin, rmargin; /* Left and right margins. */ + ssize_t wmargin; /* Margin to wrap to, or -1 to truncate. */ + + /* Point in buffer to which we've processed for wrapping, but not output. */ + size_t point_offs; + /* Output column at POINT_OFFS, or -1 meaning 0 but don't add lmargin. */ + ssize_t point_col; + + char *buf; /* Output buffer. */ + char *p; /* Current end of text in BUF. */ + char *end; /* Absolute end of BUF. */ +}; + +typedef struct argp_fmtstream *argp_fmtstream_t; + +/* Return an argp_fmtstream that outputs to STREAM, and which prefixes lines + written on it with LMARGIN spaces and limits them to RMARGIN columns + total. If WMARGIN >= 0, words that extend past RMARGIN are wrapped by + replacing the whitespace before them with a newline and WMARGIN spaces. + Otherwise, chars beyond RMARGIN are simply dropped until a newline. + Returns NULL if there was an error. */ +extern argp_fmtstream_t __argp_make_fmtstream (FILE *__stream, + size_t __lmargin, + size_t __rmargin, + ssize_t __wmargin); +extern argp_fmtstream_t argp_make_fmtstream (FILE *__stream, + size_t __lmargin, + size_t __rmargin, + ssize_t __wmargin); + +/* Flush __FS to its stream, and free it (but don't close the stream). */ +extern void __argp_fmtstream_free (argp_fmtstream_t __fs); +extern void argp_fmtstream_free (argp_fmtstream_t __fs); + +extern ssize_t __argp_fmtstream_printf (argp_fmtstream_t __fs, + __const char *__fmt, ...) + __attribute__ ((__format__ (printf, 2, 3))); +extern ssize_t argp_fmtstream_printf (argp_fmtstream_t __fs, + __const char *__fmt, ...) + __attribute__ ((__format__ (printf, 2, 3))); + +extern int __argp_fmtstream_putc (argp_fmtstream_t __fs, int __ch); +extern int argp_fmtstream_putc (argp_fmtstream_t __fs, int __ch); + +extern int __argp_fmtstream_puts (argp_fmtstream_t __fs, __const char *__str); +extern int argp_fmtstream_puts (argp_fmtstream_t __fs, __const char *__str); + +extern size_t __argp_fmtstream_write (argp_fmtstream_t __fs, + __const char *__str, size_t __len); +extern size_t argp_fmtstream_write (argp_fmtstream_t __fs, + __const char *__str, size_t __len); + +/* Access macros for various bits of state. */ +#define argp_fmtstream_lmargin(__fs) ((__fs)->lmargin) +#define argp_fmtstream_rmargin(__fs) ((__fs)->rmargin) +#define argp_fmtstream_wmargin(__fs) ((__fs)->wmargin) +#define __argp_fmtstream_lmargin argp_fmtstream_lmargin +#define __argp_fmtstream_rmargin argp_fmtstream_rmargin +#define __argp_fmtstream_wmargin argp_fmtstream_wmargin + +/* Set __FS's left margin to LMARGIN and return the old value. */ +extern size_t argp_fmtstream_set_lmargin (argp_fmtstream_t __fs, + size_t __lmargin); +extern size_t __argp_fmtstream_set_lmargin (argp_fmtstream_t __fs, + size_t __lmargin); + +/* Set __FS's right margin to __RMARGIN and return the old value. */ +extern size_t argp_fmtstream_set_rmargin (argp_fmtstream_t __fs, + size_t __rmargin); +extern size_t __argp_fmtstream_set_rmargin (argp_fmtstream_t __fs, + size_t __rmargin); + +/* Set __FS's wrap margin to __WMARGIN and return the old value. */ +extern size_t argp_fmtstream_set_wmargin (argp_fmtstream_t __fs, + size_t __wmargin); +extern size_t __argp_fmtstream_set_wmargin (argp_fmtstream_t __fs, + size_t __wmargin); + +/* Return the column number of the current output point in __FS. */ +extern size_t argp_fmtstream_point (argp_fmtstream_t __fs); +extern size_t __argp_fmtstream_point (argp_fmtstream_t __fs); + +/* Internal routines. */ +extern void _argp_fmtstream_update (argp_fmtstream_t __fs); +extern void __argp_fmtstream_update (argp_fmtstream_t __fs); +extern int _argp_fmtstream_ensure (argp_fmtstream_t __fs, size_t __amount); +extern int __argp_fmtstream_ensure (argp_fmtstream_t __fs, size_t __amount); + +#ifdef __OPTIMIZE__ +/* Inline versions of above routines. */ + +#if !_LIBC +#define __argp_fmtstream_putc argp_fmtstream_putc +#define __argp_fmtstream_puts argp_fmtstream_puts +#define __argp_fmtstream_write argp_fmtstream_write +#define __argp_fmtstream_set_lmargin argp_fmtstream_set_lmargin +#define __argp_fmtstream_set_rmargin argp_fmtstream_set_rmargin +#define __argp_fmtstream_set_wmargin argp_fmtstream_set_wmargin +#define __argp_fmtstream_point argp_fmtstream_point +#define __argp_fmtstream_update _argp_fmtstream_update +#define __argp_fmtstream_ensure _argp_fmtstream_ensure +#endif + +#ifndef ARGP_FS_EI +#define ARGP_FS_EI extern inline +#endif + +ARGP_FS_EI size_t +__argp_fmtstream_write (argp_fmtstream_t __fs, + __const char *__str, size_t __len) +{ + if (__fs->p + __len <= __fs->end || __argp_fmtstream_ensure (__fs, __len)) + { + memcpy (__fs->p, __str, __len); + __fs->p += __len; + return __len; + } + else + return 0; +} + +ARGP_FS_EI int +__argp_fmtstream_puts (argp_fmtstream_t __fs, __const char *__str) +{ + size_t __len = strlen (__str); + if (__len) + { + size_t __wrote = __argp_fmtstream_write (__fs, __str, __len); + return __wrote == __len ? 0 : -1; + } + else + return 0; +} + +ARGP_FS_EI int +__argp_fmtstream_putc (argp_fmtstream_t __fs, int __ch) +{ + if (__fs->p < __fs->end || __argp_fmtstream_ensure (__fs, 1)) + return *__fs->p++ = __ch; + else + return EOF; +} + +/* Set __FS's left margin to __LMARGIN and return the old value. */ +ARGP_FS_EI size_t +__argp_fmtstream_set_lmargin (argp_fmtstream_t __fs, size_t __lmargin) +{ + size_t __old; + if ((size_t) (__fs->p - __fs->buf) > __fs->point_offs) + __argp_fmtstream_update (__fs); + __old = __fs->lmargin; + __fs->lmargin = __lmargin; + return __old; +} + +/* Set __FS's right margin to __RMARGIN and return the old value. */ +ARGP_FS_EI size_t +__argp_fmtstream_set_rmargin (argp_fmtstream_t __fs, size_t __rmargin) +{ + size_t __old; + if ((size_t) (__fs->p - __fs->buf) > __fs->point_offs) + __argp_fmtstream_update (__fs); + __old = __fs->rmargin; + __fs->rmargin = __rmargin; + return __old; +} + +/* Set FS's wrap margin to __WMARGIN and return the old value. */ +ARGP_FS_EI size_t +__argp_fmtstream_set_wmargin (argp_fmtstream_t __fs, size_t __wmargin) +{ + size_t __old; + if ((size_t) (__fs->p - __fs->buf) > __fs->point_offs) + __argp_fmtstream_update (__fs); + __old = __fs->wmargin; + __fs->wmargin = __wmargin; + return __old; +} + +/* Return the column number of the current output point in __FS. */ +ARGP_FS_EI size_t +__argp_fmtstream_point (argp_fmtstream_t __fs) +{ + if ((size_t) (__fs->p - __fs->buf) > __fs->point_offs) + __argp_fmtstream_update (__fs); + return __fs->point_col >= 0 ? __fs->point_col : 0; +} + +#if !_LIBC +#undef __argp_fmtstream_putc +#undef __argp_fmtstream_puts +#undef __argp_fmtstream_write +#undef __argp_fmtstream_set_lmargin +#undef __argp_fmtstream_set_rmargin +#undef __argp_fmtstream_set_wmargin +#undef __argp_fmtstream_point +#undef __argp_fmtstream_update +#undef __argp_fmtstream_ensure +#endif + +#endif /* __OPTIMIZE__ */ + +#endif /* ARGP_FMTSTREAM_USE_LINEWRAP */ + +#endif /* argp-fmtstream.h */ diff --git a/libraries/platforms/dromajo-vcs/software/include/argp-namefrob.h b/libraries/platforms/dromajo-vcs/software/include/argp-namefrob.h new file mode 100644 index 000000000..668f35d0d --- /dev/null +++ b/libraries/platforms/dromajo-vcs/software/include/argp-namefrob.h @@ -0,0 +1,92 @@ +/* Name frobnication for compiling argp outside of glibc + Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Written by Miles Bader . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#if !_LIBC +/* This code is written for inclusion in gnu-libc, and uses names in the + namespace reserved for libc. If we're not compiling in libc, define those + names to be the normal ones instead. */ + +/* argp-parse functions */ +#undef __argp_parse +#define __argp_parse argp_parse +#undef __option_is_end +#define __option_is_end _option_is_end +#undef __option_is_short +#define __option_is_short _option_is_short +#undef __argp_input +#define __argp_input _argp_input + +/* argp-help functions */ +#undef __argp_help +#define __argp_help argp_help +#undef __argp_error +#define __argp_error argp_error +#undef __argp_failure +#define __argp_failure argp_failure +#undef __argp_state_help +#define __argp_state_help argp_state_help +#undef __argp_usage +#define __argp_usage argp_usage + +/* argp-fmtstream functions */ +#undef __argp_make_fmtstream +#define __argp_make_fmtstream argp_make_fmtstream +#undef __argp_fmtstream_free +#define __argp_fmtstream_free argp_fmtstream_free +#undef __argp_fmtstream_putc +#define __argp_fmtstream_putc argp_fmtstream_putc +#undef __argp_fmtstream_puts +#define __argp_fmtstream_puts argp_fmtstream_puts +#undef __argp_fmtstream_write +#define __argp_fmtstream_write argp_fmtstream_write +#undef __argp_fmtstream_printf +#define __argp_fmtstream_printf argp_fmtstream_printf +#undef __argp_fmtstream_set_lmargin +#define __argp_fmtstream_set_lmargin argp_fmtstream_set_lmargin +#undef __argp_fmtstream_set_rmargin +#define __argp_fmtstream_set_rmargin argp_fmtstream_set_rmargin +#undef __argp_fmtstream_set_wmargin +#define __argp_fmtstream_set_wmargin argp_fmtstream_set_wmargin +#undef __argp_fmtstream_point +#define __argp_fmtstream_point argp_fmtstream_point +#undef __argp_fmtstream_update +#define __argp_fmtstream_update _argp_fmtstream_update +#undef __argp_fmtstream_ensure +#define __argp_fmtstream_ensure _argp_fmtstream_ensure +#undef __argp_fmtstream_lmargin +#define __argp_fmtstream_lmargin argp_fmtstream_lmargin +#undef __argp_fmtstream_rmargin +#define __argp_fmtstream_rmargin argp_fmtstream_rmargin +#undef __argp_fmtstream_wmargin +#define __argp_fmtstream_wmargin argp_fmtstream_wmargin + +/* normal libc functions we call */ +#undef __sleep +#define __sleep sleep +#undef __strcasecmp +#define __strcasecmp strcasecmp +#undef __vsnprintf +#define __vsnprintf vsnprintf + +#endif /* !_LIBC */ + +#ifndef __set_errno +#define __set_errno(e) (errno = (e)) +#endif diff --git a/libraries/platforms/dromajo-vcs/software/include/argp.h b/libraries/platforms/dromajo-vcs/software/include/argp.h new file mode 100644 index 000000000..e63196cb1 --- /dev/null +++ b/libraries/platforms/dromajo-vcs/software/include/argp.h @@ -0,0 +1,578 @@ +/* Hierarchial argument parsing, layered over getopt. + Copyright (C) 1995, 1996, 1997, 1998, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Written by Miles Bader . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _ARGP_H +#define _ARGP_H + +#include +#include +#include + +#define __need_error_t +#include + +char *program_invocation_name; +char *program_invocation_short_name; + +#ifndef __const +# define __const const +#endif + +#ifndef __error_t_defined +typedef int error_t; +# define __error_t_defined +#endif + +#undef __THROW +#define __THROW + +#ifndef __NTH +# define __NTH(fct) fct __THROW +#endif + + +#ifdef __cplusplus +extern "C" { +#endif + +/* A description of a particular option. A pointer to an array of + these is passed in the OPTIONS field of an argp structure. Each option + entry can correspond to one long option and/or one short option; more + names for the same option can be added by following an entry in an option + array with options having the OPTION_ALIAS flag set. */ +struct argp_option +{ + /* The long option name. For more than one name for the same option, you + can use following options with the OPTION_ALIAS flag set. */ + __const char *name; + + /* What key is returned for this option. If > 0 and printable, then it's + also accepted as a short option. */ + int key; + + /* If non-NULL, this is the name of the argument associated with this + option, which is required unless the OPTION_ARG_OPTIONAL flag is set. */ + __const char *arg; + + /* OPTION_ flags. */ + int flags; + + /* The doc string for this option. If both NAME and KEY are 0, This string + will be printed outdented from the normal option column, making it + useful as a group header (it will be the first thing printed in its + group); in this usage, it's conventional to end the string with a `:'. */ + __const char *doc; + + /* The group this option is in. In a long help message, options are sorted + alphabetically within each group, and the groups presented in the order + 0, 1, 2, ..., n, -m, ..., -2, -1. Every entry in an options array with + if this field 0 will inherit the group number of the previous entry, or + zero if it's the first one, unless its a group header (NAME and KEY both + 0), in which case, the previous entry + 1 is the default. Automagic + options such as --help are put into group -1. */ + int group; +}; + +/* The argument associated with this option is optional. */ +#define OPTION_ARG_OPTIONAL 0x1 + +/* This option isn't displayed in any help messages. */ +#define OPTION_HIDDEN 0x2 + +/* This option is an alias for the closest previous non-alias option. This + means that it will be displayed in the same help entry, and will inherit + fields other than NAME and KEY from the aliased option. */ +#define OPTION_ALIAS 0x4 + +/* This option isn't actually an option (and so should be ignored by the + actual option parser), but rather an arbitrary piece of documentation that + should be displayed in much the same manner as the options. If this flag + is set, then the option NAME field is displayed unmodified (e.g., no `--' + prefix is added) at the left-margin (where a *short* option would normally + be displayed), and the documentation string in the normal place. For + purposes of sorting, any leading whitespace and puncuation is ignored, + except that if the first non-whitespace character is not `-', this entry + is displayed after all options (and OPTION_DOC entries with a leading `-') + in the same group. */ +#define OPTION_DOC 0x8 + +/* This option shouldn't be included in `long' usage messages (but is still + included in help messages). This is mainly intended for options that are + completely documented in an argp's ARGS_DOC field, in which case including + the option in the generic usage list would be redundant. For instance, + if ARGS_DOC is "FOO BAR\n-x BLAH", and the `-x' option's purpose is to + distinguish these two cases, -x should probably be marked + OPTION_NO_USAGE. */ +#define OPTION_NO_USAGE 0x10 + +struct argp; /* fwd declare this type */ +struct argp_state; /* " */ +struct argp_child; /* " */ + +/* The type of a pointer to an argp parsing function. */ +typedef error_t (*argp_parser_t) (int key, char *arg, + struct argp_state *state); + +/* What to return for unrecognized keys. For special ARGP_KEY_ keys, such + returns will simply be ignored. For user keys, this error will be turned + into EINVAL (if the call to argp_parse is such that errors are propagated + back to the user instead of exiting); returning EINVAL itself would result + in an immediate stop to parsing in *all* cases. */ +#define ARGP_ERR_UNKNOWN E2BIG /* Hurd should never need E2BIG. XXX */ + +/* Special values for the KEY argument to an argument parsing function. + ARGP_ERR_UNKNOWN should be returned if they aren't understood. + + The sequence of keys to a parsing function is either (where each + uppercased word should be prefixed by `ARGP_KEY_' and opt is a user key): + + INIT opt... NO_ARGS END SUCCESS -- No non-option arguments at all + or INIT (opt | ARG)... END SUCCESS -- All non-option args parsed + or INIT (opt | ARG)... SUCCESS -- Some non-option arg unrecognized + + The third case is where every parser returned ARGP_KEY_UNKNOWN for an + argument, in which case parsing stops at that argument (returning the + unparsed arguments to the caller of argp_parse if requested, or stopping + with an error message if not). + + If an error occurs (either detected by argp, or because the parsing + function returned an error value), then the parser is called with + ARGP_KEY_ERROR, and no further calls are made. */ + +/* This is not an option at all, but rather a command line argument. If a + parser receiving this key returns success, the fact is recorded, and the + ARGP_KEY_NO_ARGS case won't be used. HOWEVER, if while processing the + argument, a parser function decrements the NEXT field of the state it's + passed, the option won't be considered processed; this is to allow you to + actually modify the argument (perhaps into an option), and have it + processed again. */ +#define ARGP_KEY_ARG 0 +/* There are remaining arguments not parsed by any parser, which may be found + starting at (STATE->argv + STATE->next). If success is returned, but + STATE->next left untouched, it's assumed that all arguments were consume, + otherwise, the parser should adjust STATE->next to reflect any arguments + consumed. */ +#define ARGP_KEY_ARGS 0x1000006 +/* There are no more command line arguments at all. */ +#define ARGP_KEY_END 0x1000001 +/* Because it's common to want to do some special processing if there aren't + any non-option args, user parsers are called with this key if they didn't + successfully process any non-option arguments. Called just before + ARGP_KEY_END (where more general validity checks on previously parsed + arguments can take place). */ +#define ARGP_KEY_NO_ARGS 0x1000002 +/* Passed in before any parsing is done. Afterwards, the values of each + element of the CHILD_INPUT field, if any, in the state structure is + copied to each child's state to be the initial value of the INPUT field. */ +#define ARGP_KEY_INIT 0x1000003 +/* Use after all other keys, including SUCCESS & END. */ +#define ARGP_KEY_FINI 0x1000007 +/* Passed in when parsing has successfully been completed (even if there are + still arguments remaining). */ +#define ARGP_KEY_SUCCESS 0x1000004 +/* Passed in if an error occurs. */ +#define ARGP_KEY_ERROR 0x1000005 + +/* An argp structure contains a set of options declarations, a function to + deal with parsing one, documentation string, a possible vector of child + argp's, and perhaps a function to filter help output. When actually + parsing options, getopt is called with the union of all the argp + structures chained together through their CHILD pointers, with conflicts + being resolved in favor of the first occurrence in the chain. */ +struct argp +{ + /* An array of argp_option structures, terminated by an entry with both + NAME and KEY having a value of 0. */ + __const struct argp_option *options; + + /* What to do with an option from this structure. KEY is the key + associated with the option, and ARG is any associated argument (NULL if + none was supplied). If KEY isn't understood, ARGP_ERR_UNKNOWN should be + returned. If a non-zero, non-ARGP_ERR_UNKNOWN value is returned, then + parsing is stopped immediately, and that value is returned from + argp_parse(). For special (non-user-supplied) values of KEY, see the + ARGP_KEY_ definitions below. */ + argp_parser_t parser; + + /* A string describing what other arguments are wanted by this program. It + is only used by argp_usage to print the `Usage:' message. If it + contains newlines, the strings separated by them are considered + alternative usage patterns, and printed on separate lines (lines after + the first are prefix by ` or: ' instead of `Usage:'). */ + __const char *args_doc; + + /* If non-NULL, a string containing extra text to be printed before and + after the options in a long help message (separated by a vertical tab + `\v' character). */ + __const char *doc; + + /* A vector of argp_children structures, terminated by a member with a 0 + argp field, pointing to child argps should be parsed with this one. Any + conflicts are resolved in favor of this argp, or early argps in the + CHILDREN list. This field is useful if you use libraries that supply + their own argp structure, which you want to use in conjunction with your + own. */ + __const struct argp_child *children; + + /* If non-zero, this should be a function to filter the output of help + messages. KEY is either a key from an option, in which case TEXT is + that option's help text, or a special key from the ARGP_KEY_HELP_ + defines, below, describing which other help text TEXT is. The function + should return either TEXT, if it should be used as-is, a replacement + string, which should be malloced, and will be freed by argp, or NULL, + meaning `print nothing'. The value for TEXT is *after* any translation + has been done, so if any of the replacement text also needs translation, + that should be done by the filter function. INPUT is either the input + supplied to argp_parse, or NULL, if argp_help was called directly. */ + char *(*help_filter) (int __key, __const char *__text, void *__input); + + /* If non-zero the strings used in the argp library are translated using + the domain described by this string. Otherwise the currently installed + default domain is used. */ + const char *argp_domain; +}; + +/* Possible KEY arguments to a help filter function. */ +#define ARGP_KEY_HELP_PRE_DOC 0x2000001 /* Help text preceeding options. */ +#define ARGP_KEY_HELP_POST_DOC 0x2000002 /* Help text following options. */ +#define ARGP_KEY_HELP_HEADER 0x2000003 /* Option header string. */ +#define ARGP_KEY_HELP_EXTRA 0x2000004 /* After all other documentation; + TEXT is NULL for this key. */ +/* Explanatory note emitted when duplicate option arguments have been + suppressed. */ +#define ARGP_KEY_HELP_DUP_ARGS_NOTE 0x2000005 +#define ARGP_KEY_HELP_ARGS_DOC 0x2000006 /* Argument doc string. */ + +/* When an argp has a non-zero CHILDREN field, it should point to a vector of + argp_child structures, each of which describes a subsidiary argp. */ +struct argp_child +{ + /* The child parser. */ + __const struct argp *argp; + + /* Flags for this child. */ + int flags; + + /* If non-zero, an optional header to be printed in help output before the + child options. As a side-effect, a non-zero value forces the child + options to be grouped together; to achieve this effect without actually + printing a header string, use a value of "". */ + __const char *header; + + /* Where to group the child options relative to the other (`consolidated') + options in the parent argp; the values are the same as the GROUP field + in argp_option structs, but all child-groupings follow parent options at + a particular group level. If both this field and HEADER are zero, then + they aren't grouped at all, but rather merged with the parent options + (merging the child's grouping levels with the parents). */ + int group; +}; + +/* Parsing state. This is provided to parsing functions called by argp, + which may examine and, as noted, modify fields. */ +struct argp_state +{ + /* The top level ARGP being parsed. */ + __const struct argp *root_argp; + + /* The argument vector being parsed. May be modified. */ + int argc; + char **argv; + + /* The index in ARGV of the next arg that to be parsed. May be modified. */ + int next; + + /* The flags supplied to argp_parse. May be modified. */ + unsigned flags; + + /* While calling a parsing function with a key of ARGP_KEY_ARG, this is the + number of the current arg, starting at zero, and incremented after each + such call returns. At all other times, this is the number of such + arguments that have been processed. */ + unsigned arg_num; + + /* If non-zero, the index in ARGV of the first argument following a special + `--' argument (which prevents anything following being interpreted as an + option). Only set once argument parsing has proceeded past this point. */ + int quoted; + + /* An arbitrary pointer passed in from the user. */ + void *input; + /* Values to pass to child parsers. This vector will be the same length as + the number of children for the current parser. */ + void **child_inputs; + + /* For the parser's use. Initialized to 0. */ + void *hook; + + /* The name used when printing messages. This is initialized to ARGV[0], + or PROGRAM_INVOCATION_NAME if that is unavailable. */ + char *name; + + /* Streams used when argp prints something. */ + FILE *err_stream; /* For errors; initialized to stderr. */ + FILE *out_stream; /* For information; initialized to stdout. */ + + void *pstate; /* Private, for use by argp. */ +}; + +/* Flags for argp_parse (note that the defaults are those that are + convenient for program command line parsing): */ + +/* Don't ignore the first element of ARGV. Normally (and always unless + ARGP_NO_ERRS is set) the first element of the argument vector is + skipped for option parsing purposes, as it corresponds to the program name + in a command line. */ +#define ARGP_PARSE_ARGV0 0x01 + +/* Don't print error messages for unknown options to stderr; unless this flag + is set, ARGP_PARSE_ARGV0 is ignored, as ARGV[0] is used as the program + name in the error messages. This flag implies ARGP_NO_EXIT (on the + assumption that silent exiting upon errors is bad behaviour). */ +#define ARGP_NO_ERRS 0x02 + +/* Don't parse any non-option args. Normally non-option args are parsed by + calling the parse functions with a key of ARGP_KEY_ARG, and the actual arg + as the value. Since it's impossible to know which parse function wants to + handle it, each one is called in turn, until one returns 0 or an error + other than ARGP_ERR_UNKNOWN; if an argument is handled by no one, the + argp_parse returns prematurely (but with a return value of 0). If all + args have been parsed without error, all parsing functions are called one + last time with a key of ARGP_KEY_END. This flag needn't normally be set, + as the normal behavior is to stop parsing as soon as some argument can't + be handled. */ +#define ARGP_NO_ARGS 0x04 + +/* Parse options and arguments in the same order they occur on the command + line -- normally they're rearranged so that all options come first. */ +#define ARGP_IN_ORDER 0x08 + +/* Don't provide the standard long option --help, which causes usage and + option help information to be output to stdout, and exit (0) called. */ +#define ARGP_NO_HELP 0x10 + +/* Don't exit on errors (they may still result in error messages). */ +#define ARGP_NO_EXIT 0x20 + +/* Use the gnu getopt `long-only' rules for parsing arguments. */ +#define ARGP_LONG_ONLY 0x40 + +/* Turns off any message-printing/exiting options. */ +#define ARGP_SILENT (ARGP_NO_EXIT | ARGP_NO_ERRS | ARGP_NO_HELP) + +/* Parse the options strings in ARGC & ARGV according to the options in ARGP. + FLAGS is one of the ARGP_ flags above. If ARG_INDEX is non-NULL, the + index in ARGV of the first unparsed option is returned in it. If an + unknown option is present, ARGP_ERR_UNKNOWN is returned; if some parser + routine returned a non-zero value, it is returned; otherwise 0 is + returned. This function may also call exit unless the ARGP_NO_HELP flag + is set. INPUT is a pointer to a value to be passed in to the parser. */ +extern error_t argp_parse (__const struct argp *__restrict __argp, + int __argc, char **__restrict __argv, + unsigned __flags, int *__restrict __arg_index, + void *__restrict __input) __THROW; +extern error_t __argp_parse (__const struct argp *__restrict __argp, + int __argc, char **__restrict __argv, + unsigned __flags, int *__restrict __arg_index, + void *__restrict __input) __THROW; + +/* Global variables. */ + +/* If defined or set by the user program to a non-zero value, then a default + option --version is added (unless the ARGP_NO_HELP flag is used), which + will print this string followed by a newline and exit (unless the + ARGP_NO_EXIT flag is used). Overridden by ARGP_PROGRAM_VERSION_HOOK. */ +extern __const char *argp_program_version; + +/* If defined or set by the user program to a non-zero value, then a default + option --version is added (unless the ARGP_NO_HELP flag is used), which + calls this function with a stream to print the version to and a pointer to + the current parsing state, and then exits (unless the ARGP_NO_EXIT flag is + used). This variable takes precedent over ARGP_PROGRAM_VERSION. */ +extern void (*argp_program_version_hook) (FILE *__restrict __stream, + struct argp_state *__restrict + __state); + +/* If defined or set by the user program, it should point to string that is + the bug-reporting address for the program. It will be printed by + argp_help if the ARGP_HELP_BUG_ADDR flag is set (as it is by various + standard help messages), embedded in a sentence that says something like + `Report bugs to ADDR.'. */ +extern __const char *argp_program_bug_address; + +/* The exit status that argp will use when exiting due to a parsing error. + If not defined or set by the user program, this defaults to EX_USAGE from + . */ +extern error_t argp_err_exit_status; + +/* Flags for argp_help. */ +#define ARGP_HELP_USAGE 0x01 /* a Usage: message. */ +#define ARGP_HELP_SHORT_USAGE 0x02 /* " but don't actually print options. */ +#define ARGP_HELP_SEE 0x04 /* a `Try ... for more help' message. */ +#define ARGP_HELP_LONG 0x08 /* a long help message. */ +#define ARGP_HELP_PRE_DOC 0x10 /* doc string preceding long help. */ +#define ARGP_HELP_POST_DOC 0x20 /* doc string following long help. */ +#define ARGP_HELP_DOC (ARGP_HELP_PRE_DOC | ARGP_HELP_POST_DOC) +#define ARGP_HELP_BUG_ADDR 0x40 /* bug report address */ +#define ARGP_HELP_LONG_ONLY 0x80 /* modify output appropriately to + reflect ARGP_LONG_ONLY mode. */ + +/* These ARGP_HELP flags are only understood by argp_state_help. */ +#define ARGP_HELP_EXIT_ERR 0x100 /* Call exit(1) instead of returning. */ +#define ARGP_HELP_EXIT_OK 0x200 /* Call exit(0) instead of returning. */ + +/* The standard thing to do after a program command line parsing error, if an + error message has already been printed. */ +#define ARGP_HELP_STD_ERR \ + (ARGP_HELP_SEE | ARGP_HELP_EXIT_ERR) +/* The standard thing to do after a program command line parsing error, if no + more specific error message has been printed. */ +#define ARGP_HELP_STD_USAGE \ + (ARGP_HELP_SHORT_USAGE | ARGP_HELP_SEE | ARGP_HELP_EXIT_ERR) +/* The standard thing to do in response to a --help option. */ +#define ARGP_HELP_STD_HELP \ + (ARGP_HELP_SHORT_USAGE | ARGP_HELP_LONG | ARGP_HELP_EXIT_OK \ + | ARGP_HELP_DOC | ARGP_HELP_BUG_ADDR) + +/* Output a usage message for ARGP to STREAM. FLAGS are from the set + ARGP_HELP_*. */ +extern void argp_help (__const struct argp *__restrict __argp, + FILE *__restrict __stream, + unsigned __flags, char *__restrict __name) __THROW; +extern void __argp_help (__const struct argp *__restrict __argp, + FILE *__restrict __stream, unsigned __flags, + char *__name) __THROW; + +/* The following routines are intended to be called from within an argp + parsing routine (thus taking an argp_state structure as the first + argument). They may or may not print an error message and exit, depending + on the flags in STATE -- in any case, the caller should be prepared for + them *not* to exit, and should return an appropiate error after calling + them. [argp_usage & argp_error should probably be called argp_state_..., + but they're used often enough that they should be short] */ + +/* Output, if appropriate, a usage message for STATE to STREAM. FLAGS are + from the set ARGP_HELP_*. */ +extern void argp_state_help (__const struct argp_state *__restrict __state, + FILE *__restrict __stream, + unsigned int __flags) __THROW; +extern void __argp_state_help (__const struct argp_state *__restrict __state, + FILE *__restrict __stream, + unsigned int __flags) __THROW; + +/* Possibly output the standard usage message for ARGP to stderr and exit. */ +extern void argp_usage (__const struct argp_state *__state) __THROW; +extern void __argp_usage (__const struct argp_state *__state) __THROW; + +/* If appropriate, print the printf string FMT and following args, preceded + by the program name and `:', to stderr, and followed by a `Try ... --help' + message, then exit (1). */ +extern void argp_error (__const struct argp_state *__restrict __state, + __const char *__restrict __fmt, ...) __THROW + __attribute__ ((__format__ (__printf__, 2, 3))); +extern void __argp_error (__const struct argp_state *__restrict __state, + __const char *__restrict __fmt, ...) __THROW + __attribute__ ((__format__ (__printf__, 2, 3))); + +/* Similar to the standard gnu error-reporting function error(), but will + respect the ARGP_NO_EXIT and ARGP_NO_ERRS flags in STATE, and will print + to STATE->err_stream. This is useful for argument parsing code that is + shared between program startup (when exiting is desired) and runtime + option parsing (when typically an error code is returned instead). The + difference between this function and argp_error is that the latter is for + *parsing errors*, and the former is for other problems that occur during + parsing but don't reflect a (syntactic) problem with the input. */ +extern void argp_failure (__const struct argp_state *__restrict __state, + int __status, int __errnum, + __const char *__restrict __fmt, ...) __THROW + __attribute__ ((__format__ (__printf__, 4, 5))); +extern void __argp_failure (__const struct argp_state *__restrict __state, + int __status, int __errnum, + __const char *__restrict __fmt, ...) __THROW + __attribute__ ((__format__ (__printf__, 4, 5))); + +/* Returns true if the option OPT is a valid short option. */ +extern int _option_is_short (__const struct argp_option *__opt) __THROW; +extern int __option_is_short (__const struct argp_option *__opt) __THROW; + +/* Returns true if the option OPT is in fact the last (unused) entry in an + options array. */ +extern int _option_is_end (__const struct argp_option *__opt) __THROW; +extern int __option_is_end (__const struct argp_option *__opt) __THROW; + +/* Return the input field for ARGP in the parser corresponding to STATE; used + by the help routines. */ +extern void *_argp_input (__const struct argp *__restrict __argp, + __const struct argp_state *__restrict __state) + __THROW; +extern void *__argp_input (__const struct argp *__restrict __argp, + __const struct argp_state *__restrict __state) + __THROW; + +#ifdef __USE_EXTERN_INLINES + +# if !_LIBC +# define __argp_usage argp_usage +# define __argp_state_help argp_state_help +# define __option_is_short _option_is_short +# define __option_is_end _option_is_end +# endif + +# ifndef ARGP_EI +# define ARGP_EI extern __inline__ +# endif + +ARGP_EI void +__argp_usage (__const struct argp_state *__state) __THROW +{ + __argp_state_help (__state, stderr, ARGP_HELP_STD_USAGE); +} + +ARGP_EI int +__option_is_short (__const struct argp_option *__opt) __THROW +{ + if (__opt->flags & OPTION_DOC) + return 0; + else + { + int __key = __opt->key; + return __key > 0 && isprint (__key); + } +} + +ARGP_EI int +__option_is_end (__const struct argp_option *__opt) __THROW +{ + return !__opt->key && !__opt->name && !__opt->doc && !__opt->group; +} + +# if !_LIBC +# undef __argp_usage +# undef __argp_state_help +# undef __option_is_short +# undef __option_is_end +# endif +#endif /* Use extern inlines. */ + +#ifdef __cplusplus +} +#endif + +#endif /* argp.h */ diff --git a/libraries/platforms/dromajo-vcs/software/include/sysexits.h b/libraries/platforms/dromajo-vcs/software/include/sysexits.h new file mode 100644 index 000000000..37246b6e7 --- /dev/null +++ b/libraries/platforms/dromajo-vcs/software/include/sysexits.h @@ -0,0 +1,114 @@ +/* + * Copyright (c) 1987, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)sysexits.h 8.1 (Berkeley) 6/2/93 + */ + +#ifndef _SYSEXITS_H +#define _SYSEXITS_H 1 + +/* + * SYSEXITS.H -- Exit status codes for system programs. + * + * This include file attempts to categorize possible error + * exit statuses for system programs, notably delivermail + * and the Berkeley network. + * + * Error numbers begin at EX__BASE to reduce the possibility of + * clashing with other exit statuses that random programs may + * already return. The meaning of the codes is approximately + * as follows: + * + * EX_USAGE -- The command was used incorrectly, e.g., with + * the wrong number of arguments, a bad flag, a bad + * syntax in a parameter, or whatever. + * EX_DATAERR -- The input data was incorrect in some way. + * This should only be used for user's data & not + * system files. + * EX_NOINPUT -- An input file (not a system file) did not + * exist or was not readable. This could also include + * errors like "No message" to a mailer (if it cared + * to catch it). + * EX_NOUSER -- The user specified did not exist. This might + * be used for mail addresses or remote logins. + * EX_NOHOST -- The host specified did not exist. This is used + * in mail addresses or network requests. + * EX_UNAVAILABLE -- A service is unavailable. This can occur + * if a support program or file does not exist. This + * can also be used as a catchall message when something + * you wanted to do doesn't work, but you don't know + * why. + * EX_SOFTWARE -- An internal software error has been detected. + * This should be limited to non-operating system related + * errors as possible. + * EX_OSERR -- An operating system error has been detected. + * This is intended to be used for such things as "cannot + * fork", "cannot create pipe", or the like. It includes + * things like getuid returning a user that does not + * exist in the passwd file. + * EX_OSFILE -- Some system file (e.g., /etc/passwd, /etc/utmp, + * etc.) does not exist, cannot be opened, or has some + * sort of error (e.g., syntax error). + * EX_CANTCREAT -- A (user specified) output file cannot be + * created. + * EX_IOERR -- An error occurred while doing I/O on some file. + * EX_TEMPFAIL -- temporary failure, indicating something that + * is not really an error. In sendmail, this means + * that a mailer (e.g.) could not create a connection, + * and the request should be reattempted later. + * EX_PROTOCOL -- the remote system returned something that + * was "not possible" during a protocol exchange. + * EX_NOPERM -- You did not have sufficient permission to + * perform the operation. This is not intended for + * file system problems, which should use NOINPUT or + * CANTCREAT, but rather for higher level permissions. + */ + +#define EX_OK 0 /* successful termination */ + +#define EX__BASE 64 /* base value for error messages */ + +#define EX_USAGE 64 /* command line usage error */ +#define EX_DATAERR 65 /* data format error */ +#define EX_NOINPUT 66 /* cannot open input */ +#define EX_NOUSER 67 /* addressee unknown */ +#define EX_NOHOST 68 /* host name unknown */ +#define EX_UNAVAILABLE 69 /* service unavailable */ +#define EX_SOFTWARE 70 /* internal software error */ +#define EX_OSERR 71 /* system error (e.g., can't fork) */ +#define EX_OSFILE 72 /* critical OS file missing */ +#define EX_CANTCREAT 73 /* can't create (user) output file */ +#define EX_IOERR 74 /* input/output error */ +#define EX_TEMPFAIL 75 /* temp failure; user is invited to retry */ +#define EX_PROTOCOL 76 /* remote error in protocol */ +#define EX_NOPERM 77 /* permission denied */ +#define EX_CONFIG 78 /* configuration error */ + +#define EX__MAX 78 /* maximum listed value */ + +#endif /* sysexits.h */ diff --git a/libraries/platforms/dromajo-vcs/software/src/argp/argp-ba.c b/libraries/platforms/dromajo-vcs/software/src/argp/argp-ba.c new file mode 100644 index 000000000..f5270c88d --- /dev/null +++ b/libraries/platforms/dromajo-vcs/software/src/argp/argp-ba.c @@ -0,0 +1,26 @@ +/* Default definition for ARGP_PROGRAM_BUG_ADDRESS. + Copyright (C) 1996, 1997, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Written by Miles Bader . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* If set by the user program, it should point to string that is the + bug-reporting address for the program. It will be printed by argp_help if + the ARGP_HELP_BUG_ADDR flag is set (as it is by various standard help + messages), embedded in a sentence that says something like `Report bugs to + ADDR.'. */ +const char *argp_program_bug_address; diff --git a/libraries/platforms/dromajo-vcs/software/src/argp/argp-eexst.c b/libraries/platforms/dromajo-vcs/software/src/argp/argp-eexst.c new file mode 100644 index 000000000..a94c34674 --- /dev/null +++ b/libraries/platforms/dromajo-vcs/software/src/argp/argp-eexst.c @@ -0,0 +1,32 @@ +/* Default definition for ARGP_ERR_EXIT_STATUS + Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Written by Miles Bader . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include + +/* The exit status that argp will use when exiting due to a parsing error. + If not defined or set by the user program, this defaults to EX_USAGE from + . */ +error_t argp_err_exit_status = EX_USAGE; diff --git a/libraries/platforms/dromajo-vcs/software/src/argp/argp-fmtstream.c b/libraries/platforms/dromajo-vcs/software/src/argp/argp-fmtstream.c new file mode 100644 index 000000000..647ed985d --- /dev/null +++ b/libraries/platforms/dromajo-vcs/software/src/argp/argp-fmtstream.c @@ -0,0 +1,429 @@ +/* Word-wrapping and line-truncating streams + Copyright (C) 1997, 1998, 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Written by Miles Bader . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This package emulates glibc `line_wrap_stream' semantics for systems that + don't have that. */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include + +#include "argp-fmtstream.h" +#include "argp-namefrob.h" + +#ifndef ARGP_FMTSTREAM_USE_LINEWRAP + +#ifndef isblank +#define isblank(ch) ((ch)==' ' || (ch)=='\t') +#endif + +#if defined _LIBC && defined USE_IN_LIBIO +# include +# include +# define __vsnprintf(s, l, f, a) _IO_vsnprintf (s, l, f, a) +#endif + +#define INIT_BUF_SIZE 200 +#define PRINTF_SIZE_GUESS 150 + +/* Return an argp_fmtstream that outputs to STREAM, and which prefixes lines + written on it with LMARGIN spaces and limits them to RMARGIN columns + total. If WMARGIN >= 0, words that extend past RMARGIN are wrapped by + replacing the whitespace before them with a newline and WMARGIN spaces. + Otherwise, chars beyond RMARGIN are simply dropped until a newline. + Returns NULL if there was an error. */ +argp_fmtstream_t +__argp_make_fmtstream (FILE *stream, size_t lmargin, size_t rmargin, ssize_t wmargin) +{ + argp_fmtstream_t fs; + + fs = (struct argp_fmtstream *) malloc (sizeof (struct argp_fmtstream)); + if (fs != NULL) + { + fs->stream = stream; + + fs->lmargin = lmargin; + fs->rmargin = rmargin; + fs->wmargin = wmargin; + fs->point_col = 0; + fs->point_offs = 0; + + fs->buf = (char *) malloc (INIT_BUF_SIZE); + if (! fs->buf) + { + free (fs); + fs = 0; + } + else + { + fs->p = fs->buf; + fs->end = fs->buf + INIT_BUF_SIZE; + } + } + + return fs; +} +#ifdef weak_alias +weak_alias (__argp_make_fmtstream, argp_make_fmtstream) +#endif + +/* Flush FS to its stream, and free it (but don't close the stream). */ +void +__argp_fmtstream_free (argp_fmtstream_t fs) +{ + __argp_fmtstream_update (fs); + if (fs->p > fs->buf) + { +#ifdef USE_IN_LIBIO + if (_IO_fwide (fs->stream, 0) > 0) + __fwprintf (fs->stream, L"%.*s", (int) (fs->p - fs->buf), fs->buf); + else +#endif + fwrite (fs->buf, 1, fs->p - fs->buf, fs->stream); + } + free (fs->buf); + free (fs); +} +#ifdef weak_alias +weak_alias (__argp_fmtstream_free, argp_fmtstream_free) +#endif + +/* Process FS's buffer so that line wrapping is done from POINT_OFFS to the + end of its buffer. This code is mostly from glibc stdio/linewrap.c. */ +void +__argp_fmtstream_update (argp_fmtstream_t fs) +{ + char *buf, *nl; + size_t len; + + /* Scan the buffer for newlines. */ + buf = fs->buf + fs->point_offs; + while (buf < fs->p) + { + size_t r; + + if (fs->point_col == 0 && fs->lmargin != 0) + { + /* We are starting a new line. Print spaces to the left margin. */ + const size_t pad = fs->lmargin; + if (fs->p + pad < fs->end) + { + /* We can fit in them in the buffer by moving the + buffer text up and filling in the beginning. */ + memmove (buf + pad, buf, fs->p - buf); + fs->p += pad; /* Compensate for bigger buffer. */ + memset (buf, ' ', pad); /* Fill in the spaces. */ + buf += pad; /* Don't bother searching them. */ + } + else + { + /* No buffer space for spaces. Must flush. */ + size_t i; + for (i = 0; i < pad; i++) + { +#ifdef USE_IN_LIBIO + if (_IO_fwide (fs->stream, 0) > 0) + putwc_unlocked (L' ', fs->stream); + else +#endif + putc_unlocked (' ', fs->stream); + } + } + fs->point_col = pad; + } + + len = fs->p - buf; + nl = memchr (buf, '\n', len); + + if (fs->point_col < 0) + fs->point_col = 0; + + if (!nl) + { + /* The buffer ends in a partial line. */ + + if (fs->point_col + len < fs->rmargin) + { + /* The remaining buffer text is a partial line and fits + within the maximum line width. Advance point for the + characters to be written and stop scanning. */ + fs->point_col += len; + break; + } + else + /* Set the end-of-line pointer for the code below to + the end of the buffer. */ + nl = fs->p; + } + else if (fs->point_col + (nl - buf) < (ssize_t) fs->rmargin) + { + /* The buffer contains a full line that fits within the maximum + line width. Reset point and scan the next line. */ + fs->point_col = 0; + buf = nl + 1; + continue; + } + + /* This line is too long. */ + r = fs->rmargin - 1; + + if (fs->wmargin < 0) + { + /* Truncate the line by overwriting the excess with the + newline and anything after it in the buffer. */ + if (nl < fs->p) + { + memmove (buf + (r - fs->point_col), nl, fs->p - nl); + fs->p -= buf + (r - fs->point_col) - nl; + /* Reset point for the next line and start scanning it. */ + fs->point_col = 0; + buf += r + 1; /* Skip full line plus \n. */ + } + else + { + /* The buffer ends with a partial line that is beyond the + maximum line width. Advance point for the characters + written, and discard those past the max from the buffer. */ + fs->point_col += len; + fs->p -= fs->point_col - r; + break; + } + } + else + { + /* Do word wrap. Go to the column just past the maximum line + width and scan back for the beginning of the word there. + Then insert a line break. */ + + char *p, *nextline; + int i; + + p = buf + (r + 1 - fs->point_col); + while (p >= buf && !isblank (*p)) + --p; + nextline = p + 1; /* This will begin the next line. */ + + if (nextline > buf) + { + /* Swallow separating blanks. */ + if (p >= buf) + do + --p; + while (p >= buf && isblank (*p)); + nl = p + 1; /* The newline will replace the first blank. */ + } + else + { + /* A single word that is greater than the maximum line width. + Oh well. Put it on an overlong line by itself. */ + p = buf + (r + 1 - fs->point_col); + /* Find the end of the long word. */ + do + ++p; + while (p < nl && !isblank (*p)); + if (p == nl) + { + /* It already ends a line. No fussing required. */ + fs->point_col = 0; + buf = nl + 1; + continue; + } + /* We will move the newline to replace the first blank. */ + nl = p; + /* Swallow separating blanks. */ + do + ++p; + while (isblank (*p)); + /* The next line will start here. */ + nextline = p; + } + + /* Note: There are a bunch of tests below for + NEXTLINE == BUF + LEN + 1; this case is where NL happens to fall + at the end of the buffer, and NEXTLINE is in fact empty (and so + we need not be careful to maintain its contents). */ + + if (nextline == buf + len + 1 + ? fs->end - nl < fs->wmargin + 1 + : nextline - (nl + 1) < fs->wmargin) + { + /* The margin needs more blanks than we removed. */ + if (fs->end - fs->p > fs->wmargin + 1) + /* Make some space for them. */ + { + size_t mv = fs->p - nextline; + memmove (nl + 1 + fs->wmargin, nextline, mv); + nextline = nl + 1 + fs->wmargin; + len = nextline + mv - buf; + *nl++ = '\n'; + } + else + /* Output the first line so we can use the space. */ + { +#ifdef USE_IN_LIBIO + if (_IO_fwide (fs->stream, 0) > 0) + __fwprintf (fs->stream, L"%.*s\n", + (int) (nl - fs->buf), fs->buf); + else +#endif + { + if (nl > fs->buf) + fwrite (fs->buf, 1, nl - fs->buf, fs->stream); + putc_unlocked ('\n', fs->stream); + } + len += buf - fs->buf; + nl = buf = fs->buf; + } + } + else + /* We can fit the newline and blanks in before + the next word. */ + *nl++ = '\n'; + + if (nextline - nl >= fs->wmargin + || (nextline == buf + len + 1 && fs->end - nextline >= fs->wmargin)) + /* Add blanks up to the wrap margin column. */ + for (i = 0; i < fs->wmargin; ++i) + *nl++ = ' '; + else + for (i = 0; i < fs->wmargin; ++i) +#ifdef USE_IN_LIBIO + if (_IO_fwide (fs->stream, 0) > 0) + putwc_unlocked (L' ', fs->stream); + else +#endif + putc_unlocked (' ', fs->stream); + + /* Copy the tail of the original buffer into the current buffer + position. */ + if (nl < nextline) + memmove (nl, nextline, buf + len - nextline); + len -= nextline - buf; + + /* Continue the scan on the remaining lines in the buffer. */ + buf = nl; + + /* Restore bufp to include all the remaining text. */ + fs->p = nl + len; + + /* Reset the counter of what has been output this line. If wmargin + is 0, we want to avoid the lmargin getting added, so we set + point_col to a magic value of -1 in that case. */ + fs->point_col = fs->wmargin ? fs->wmargin : -1; + } + } + + /* Remember that we've scanned as far as the end of the buffer. */ + fs->point_offs = fs->p - fs->buf; +} + +/* Ensure that FS has space for AMOUNT more bytes in its buffer, either by + growing the buffer, or by flushing it. True is returned iff we succeed. */ +int +__argp_fmtstream_ensure (struct argp_fmtstream *fs, size_t amount) +{ + if ((size_t) (fs->end - fs->p) < amount) + { + ssize_t wrote; + + /* Flush FS's buffer. */ + __argp_fmtstream_update (fs); + +#ifdef USE_IN_LIBIO + if (_IO_fwide (fs->stream, 0) > 0) + { + __fwprintf (fs->stream, L"%.*s", (int) (fs->p - fs->buf), fs->buf); + wrote = fs->p - fs->buf; + } + else +#endif + wrote = fwrite (fs->buf, 1, fs->p - fs->buf, fs->stream); + if (wrote == fs->p - fs->buf) + { + fs->p = fs->buf; + fs->point_offs = 0; + } + else + { + fs->p -= wrote; + fs->point_offs -= wrote; + memmove (fs->buf, fs->buf + wrote, fs->p - fs->buf); + return 0; + } + + if ((size_t) (fs->end - fs->buf) < amount) + /* Gotta grow the buffer. */ + { + size_t new_size = fs->end - fs->buf + amount; + char *new_buf = realloc (fs->buf, new_size); + + if (! new_buf) + { + __set_errno (ENOMEM); + return 0; + } + + fs->buf = new_buf; + fs->end = new_buf + new_size; + fs->p = fs->buf; + } + } + + return 1; +} + +ssize_t +__argp_fmtstream_printf (struct argp_fmtstream *fs, const char *fmt, ...) +{ + int out; + size_t avail; + size_t size_guess = PRINTF_SIZE_GUESS; /* How much space to reserve. */ + + do + { + va_list args; + + if (! __argp_fmtstream_ensure (fs, size_guess)) + return -1; + + va_start (args, fmt); + avail = fs->end - fs->p; + out = __vsnprintf (fs->p, avail, fmt, args); + va_end (args); + if (out >= avail) + size_guess = out + 1; + } + while (out >= avail); + + fs->p += out; + + return out; +} +#ifdef weak_alias +weak_alias (__argp_fmtstream_printf, argp_fmtstream_printf) +#endif + +#endif /* !ARGP_FMTSTREAM_USE_LINEWRAP */ diff --git a/libraries/platforms/dromajo-vcs/software/src/argp/argp-fs-xinl.c b/libraries/platforms/dromajo-vcs/software/src/argp/argp-fs-xinl.c new file mode 100644 index 000000000..9b836d138 --- /dev/null +++ b/libraries/platforms/dromajo-vcs/software/src/argp/argp-fs-xinl.c @@ -0,0 +1,41 @@ +/* Real definitions for extern inline functions in argp-fmtstream.h + Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Written by Miles Bader . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#define ARGP_FS_EI +#undef __OPTIMIZE__ +#define __OPTIMIZE__ 1 +#include "argp-fmtstream.h" + +/* Add weak aliases. */ +#if _LIBC - 0 && !defined (ARGP_FMTSTREAM_USE_LINEWRAP) && defined (weak_alias) + +weak_alias (__argp_fmtstream_putc, argp_fmtstream_putc) +weak_alias (__argp_fmtstream_puts, argp_fmtstream_puts) +weak_alias (__argp_fmtstream_write, argp_fmtstream_write) +weak_alias (__argp_fmtstream_set_lmargin, argp_fmtstream_set_lmargin) +weak_alias (__argp_fmtstream_set_rmargin, argp_fmtstream_set_rmargin) +weak_alias (__argp_fmtstream_set_wmargin, argp_fmtstream_set_wmargin) +weak_alias (__argp_fmtstream_point, argp_fmtstream_point) + +#endif diff --git a/libraries/platforms/dromajo-vcs/software/src/argp/argp-help.c b/libraries/platforms/dromajo-vcs/software/src/argp/argp-help.c new file mode 100644 index 000000000..6b278065c --- /dev/null +++ b/libraries/platforms/dromajo-vcs/software/src/argp/argp-help.c @@ -0,0 +1,1862 @@ +/* Hierarchial argument parsing help output + Copyright (C) 1995-2000, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Written by Miles Bader . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _GNU_SOURCE +# define _GNU_SOURCE 1 +#endif + +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifndef alloca +# ifdef __GNUC__ +# define alloca __builtin_alloca +# define HAVE_ALLOCA 1 +# else +# if defined HAVE_ALLOCA_H || defined _LIBC +# include +# else +# ifdef _AIX + #pragma alloca +# else +# ifndef alloca +char *alloca (); +# endif +# endif +# endif +# endif +#endif + +#include +#include +#include +#include +#include +#include +#include +#ifdef USE_IN_LIBIO +# include +#endif + +#ifndef _ +/* This is for other GNU distributions with internationalized messages. */ +# if defined HAVE_LIBINTL_H || defined _LIBC +# include +# ifdef _LIBC +# undef dgettext +# define dgettext(domain, msgid) __dcgettext (domain, msgid, LC_MESSAGES) +# endif +# else +# define dgettext(domain, msgid) (msgid) +# endif +#endif + +#include +#include "argp-fmtstream.h" +#include "argp-namefrob.h" + +/* User-selectable (using an environment variable) formatting parameters. + + These may be specified in an environment variable called `ARGP_HELP_FMT', + with a contents like: VAR1=VAL1,VAR2=VAL2,BOOLVAR2,no-BOOLVAR2 + Where VALn must be a positive integer. The list of variables is in the + UPARAM_NAMES vector, below. */ + +/* Default parameters. */ +#define DUP_ARGS 0 /* True if option argument can be duplicated. */ +#define DUP_ARGS_NOTE 1 /* True to print a note about duplicate args. */ +#define SHORT_OPT_COL 2 /* column in which short options start */ +#define LONG_OPT_COL 6 /* column in which long options start */ +#define DOC_OPT_COL 2 /* column in which doc options start */ +#define OPT_DOC_COL 29 /* column in which option text starts */ +#define HEADER_COL 1 /* column in which group headers are printed */ +#define USAGE_INDENT 12 /* indentation of wrapped usage lines */ +#define RMARGIN 79 /* right margin used for wrapping */ + +/* User-selectable (using an environment variable) formatting parameters. + They must all be of type `int' for the parsing code to work. */ +struct uparams +{ + /* If true, arguments for an option are shown with both short and long + options, even when a given option has both, e.g. `-x ARG, --longx=ARG'. + If false, then if an option has both, the argument is only shown with + the long one, e.g., `-x, --longx=ARG', and a message indicating that + this really means both is printed below the options. */ + int dup_args; + + /* This is true if when DUP_ARGS is false, and some duplicate arguments have + been suppressed, an explanatory message should be printed. */ + int dup_args_note; + + /* Various output columns. */ + int short_opt_col; + int long_opt_col; + int doc_opt_col; + int opt_doc_col; + int header_col; + int usage_indent; + int rmargin; + + int valid; /* True when the values in here are valid. */ +}; + +/* This is a global variable, as user options are only ever read once. */ +static struct uparams uparams = { + DUP_ARGS, DUP_ARGS_NOTE, + SHORT_OPT_COL, LONG_OPT_COL, DOC_OPT_COL, OPT_DOC_COL, HEADER_COL, + USAGE_INDENT, RMARGIN, + 0 +}; + +/* A particular uparam, and what the user name is. */ +struct uparam_name +{ + const char *name; /* User name. */ + int is_bool; /* Whether it's `boolean'. */ + size_t uparams_offs; /* Location of the (int) field in UPARAMS. */ +}; + +/* The name-field mappings we know about. */ +static const struct uparam_name uparam_names[] = +{ + { "dup-args", 1, offsetof (struct uparams, dup_args) }, + { "dup-args-note", 1, offsetof (struct uparams, dup_args_note) }, + { "short-opt-col", 0, offsetof (struct uparams, short_opt_col) }, + { "long-opt-col", 0, offsetof (struct uparams, long_opt_col) }, + { "doc-opt-col", 0, offsetof (struct uparams, doc_opt_col) }, + { "opt-doc-col", 0, offsetof (struct uparams, opt_doc_col) }, + { "header-col", 0, offsetof (struct uparams, header_col) }, + { "usage-indent", 0, offsetof (struct uparams, usage_indent) }, + { "rmargin", 0, offsetof (struct uparams, rmargin) }, + { 0 } +}; + +/* Read user options from the environment, and fill in UPARAMS appropiately. */ +static void +fill_in_uparams (const struct argp_state *state) +{ + const char *var = getenv ("ARGP_HELP_FMT"); + +#define SKIPWS(p) do { while (isspace (*p)) p++; } while (0); + + if (var) + /* Parse var. */ + while (*var) + { + SKIPWS (var); + + if (isalpha (*var)) + { + size_t var_len; + const struct uparam_name *un; + int unspec = 0, val = 0; + const char *arg = var; + + while (isalnum (*arg) || *arg == '-' || *arg == '_') + arg++; + var_len = arg - var; + + SKIPWS (arg); + + if (*arg == '\0' || *arg == ',') + unspec = 1; + else if (*arg == '=') + { + arg++; + SKIPWS (arg); + } + + if (unspec) + { + if (var[0] == 'n' && var[1] == 'o' && var[2] == '-') + { + val = 0; + var += 3; + var_len -= 3; + } + else + val = 1; + } + else if (isdigit (*arg)) + { + val = atoi (arg); + while (isdigit (*arg)) + arg++; + SKIPWS (arg); + } + + for (un = uparam_names; un->name; un++) + if (strlen (un->name) == var_len + && strncmp (var, un->name, var_len) == 0) + { + if (unspec && !un->is_bool) + __argp_failure (state, 0, 0, + dgettext (state->root_argp->argp_domain, "\ + %.*s: ARGP_HELP_FMT parameter requires a value"), + (int) var_len, var); + else + *(int *)((char *)&uparams + un->uparams_offs) = val; + break; + } + if (! un->name) + __argp_failure (state, 0, 0, + dgettext (state->root_argp->argp_domain, "\ + %.*s: Unknown ARGP_HELP_FMT parameter"), + (int) var_len, var); + + var = arg; + if (*var == ',') + var++; + } + else if (*var) + { + __argp_failure (state, 0, 0, + dgettext (state->root_argp->argp_domain, + "Garbage in ARGP_HELP_FMT: %s"), var); + break; + } + } +} + +/* Returns true if OPT hasn't been marked invisible. Visibility only affects + whether OPT is displayed or used in sorting, not option shadowing. */ +#define ovisible(opt) (! ((opt)->flags & OPTION_HIDDEN)) + +/* Returns true if OPT is an alias for an earlier option. */ +#define oalias(opt) ((opt)->flags & OPTION_ALIAS) + +/* Returns true if OPT is an documentation-only entry. */ +#define odoc(opt) ((opt)->flags & OPTION_DOC) + +/* Returns true if OPT is the end-of-list marker for a list of options. */ +#define oend(opt) __option_is_end (opt) + +/* Returns true if OPT has a short option. */ +#define oshort(opt) __option_is_short (opt) + +/* + The help format for a particular option is like: + + -xARG, -yARG, --long1=ARG, --long2=ARG Documentation... + + Where ARG will be omitted if there's no argument, for this option, or + will be surrounded by "[" and "]" appropiately if the argument is + optional. The documentation string is word-wrapped appropiately, and if + the list of options is long enough, it will be started on a separate line. + If there are no short options for a given option, the first long option is + indented slighly in a way that's supposed to make most long options appear + to be in a separate column. + + For example, the following output (from ps): + + -p PID, --pid=PID List the process PID + --pgrp=PGRP List processes in the process group PGRP + -P, -x, --no-parent Include processes without parents + -Q, --all-fields Don't elide unusable fields (normally if there's + some reason ps can't print a field for any + process, it's removed from the output entirely) + -r, --reverse, --gratuitously-long-reverse-option + Reverse the order of any sort + --session[=SID] Add the processes from the session SID (which + defaults to the sid of the current process) + + Here are some more options: + -f ZOT, --foonly=ZOT Glork a foonly + -z, --zaza Snit a zar + + -?, --help Give this help list + --usage Give a short usage message + -V, --version Print program version + + The struct argp_option array for the above could look like: + + { + {"pid", 'p', "PID", 0, "List the process PID"}, + {"pgrp", OPT_PGRP, "PGRP", 0, "List processes in the process group PGRP"}, + {"no-parent", 'P', 0, 0, "Include processes without parents"}, + {0, 'x', 0, OPTION_ALIAS}, + {"all-fields",'Q', 0, 0, "Don't elide unusable fields (normally" + " if there's some reason ps can't" + " print a field for any process, it's" + " removed from the output entirely)" }, + {"reverse", 'r', 0, 0, "Reverse the order of any sort"}, + {"gratuitously-long-reverse-option", 0, 0, OPTION_ALIAS}, + {"session", OPT_SESS, "SID", OPTION_ARG_OPTIONAL, + "Add the processes from the session" + " SID (which defaults to the sid of" + " the current process)" }, + + {0,0,0,0, "Here are some more options:"}, + {"foonly", 'f', "ZOT", 0, "Glork a foonly"}, + {"zaza", 'z', 0, 0, "Snit a zar"}, + + {0} + } + + Note that the last three options are automatically supplied by argp_parse, + unless you tell it not to with ARGP_NO_HELP. + +*/ + +/* Returns true if CH occurs between BEG and END. */ +static int +find_char (char ch, char *beg, char *end) +{ + while (beg < end) + if (*beg == ch) + return 1; + else + beg++; + return 0; +} + +struct hol_cluster; /* fwd decl */ + +struct hol_entry +{ + /* First option. */ + const struct argp_option *opt; + /* Number of options (including aliases). */ + unsigned num; + + /* A pointers into the HOL's short_options field, to the first short option + letter for this entry. The order of the characters following this point + corresponds to the order of options pointed to by OPT, and there are at + most NUM. A short option recorded in a option following OPT is only + valid if it occurs in the right place in SHORT_OPTIONS (otherwise it's + probably been shadowed by some other entry). */ + char *short_options; + + /* Entries are sorted by their group first, in the order: + 1, 2, ..., n, 0, -m, ..., -2, -1 + and then alphabetically within each group. The default is 0. */ + int group; + + /* The cluster of options this entry belongs to, or 0 if none. */ + struct hol_cluster *cluster; + + /* The argp from which this option came. */ + const struct argp *argp; +}; + +/* A cluster of entries to reflect the argp tree structure. */ +struct hol_cluster +{ + /* A descriptive header printed before options in this cluster. */ + const char *header; + + /* Used to order clusters within the same group with the same parent, + according to the order in which they occurred in the parent argp's child + list. */ + int index; + + /* How to sort this cluster with respect to options and other clusters at the + same depth (clusters always follow options in the same group). */ + int group; + + /* The cluster to which this cluster belongs, or 0 if it's at the base + level. */ + struct hol_cluster *parent; + + /* The argp from which this cluster is (eventually) derived. */ + const struct argp *argp; + + /* The distance this cluster is from the root. */ + int depth; + + /* Clusters in a given hol are kept in a linked list, to make freeing them + possible. */ + struct hol_cluster *next; +}; + +/* A list of options for help. */ +struct hol +{ + /* An array of hol_entry's. */ + struct hol_entry *entries; + /* The number of entries in this hol. If this field is zero, the others + are undefined. */ + unsigned num_entries; + + /* A string containing all short options in this HOL. Each entry contains + pointers into this string, so the order can't be messed with blindly. */ + char *short_options; + + /* Clusters of entries in this hol. */ + struct hol_cluster *clusters; +}; + +/* Create a struct hol from the options in ARGP. CLUSTER is the + hol_cluster in which these entries occur, or 0, if at the root. */ +static struct hol * +make_hol (const struct argp *argp, struct hol_cluster *cluster) +{ + char *so; + const struct argp_option *o; + const struct argp_option *opts = argp->options; + struct hol_entry *entry; + unsigned num_short_options = 0; + struct hol *hol = malloc (sizeof (struct hol)); + + assert (hol); + + hol->num_entries = 0; + hol->clusters = 0; + + if (opts) + { + int cur_group = 0; + + /* The first option must not be an alias. */ + assert (! oalias (opts)); + + /* Calculate the space needed. */ + for (o = opts; ! oend (o); o++) + { + if (! oalias (o)) + hol->num_entries++; + if (oshort (o)) + num_short_options++; /* This is an upper bound. */ + } + + hol->entries = malloc (sizeof (struct hol_entry) * hol->num_entries); + hol->short_options = malloc (num_short_options + 1); + + assert (hol->entries && hol->short_options); + + /* Fill in the entries. */ + so = hol->short_options; + for (o = opts, entry = hol->entries; ! oend (o); entry++) + { + entry->opt = o; + entry->num = 0; + entry->short_options = so; + entry->group = cur_group = + o->group + ? o->group + : ((!o->name && !o->key) + ? cur_group + 1 + : cur_group); + entry->cluster = cluster; + entry->argp = argp; + + do + { + entry->num++; + if (oshort (o) && ! find_char (o->key, hol->short_options, so)) + /* O has a valid short option which hasn't already been used.*/ + *so++ = o->key; + o++; + } + while (! oend (o) && oalias (o)); + } + *so = '\0'; /* null terminated so we can find the length */ + } + + return hol; +} + +/* Add a new cluster to HOL, with the given GROUP and HEADER (taken from the + associated argp child list entry), INDEX, and PARENT, and return a pointer + to it. ARGP is the argp that this cluster results from. */ +static struct hol_cluster * +hol_add_cluster (struct hol *hol, int group, const char *header, int index, + struct hol_cluster *parent, const struct argp *argp) +{ + struct hol_cluster *cl = malloc (sizeof (struct hol_cluster)); + if (cl) + { + cl->group = group; + cl->header = header; + + cl->index = index; + cl->parent = parent; + cl->argp = argp; + cl->depth = parent ? parent->depth + 1 : 0; + + cl->next = hol->clusters; + hol->clusters = cl; + } + return cl; +} + +/* Free HOL and any resources it uses. */ +static void +hol_free (struct hol *hol) +{ + struct hol_cluster *cl = hol->clusters; + + while (cl) + { + struct hol_cluster *next = cl->next; + free (cl); + cl = next; + } + + if (hol->num_entries > 0) + { + free (hol->entries); + free (hol->short_options); + } + + free (hol); +} + +static inline int +hol_entry_short_iterate (const struct hol_entry *entry, + int (*func)(const struct argp_option *opt, + const struct argp_option *real, + const char *domain, void *cookie), + const char *domain, void *cookie) +{ + unsigned nopts; + int val = 0; + const struct argp_option *opt, *real = entry->opt; + char *so = entry->short_options; + + for (opt = real, nopts = entry->num; nopts > 0 && !val; opt++, nopts--) + if (oshort (opt) && *so == opt->key) + { + if (!oalias (opt)) + real = opt; + if (ovisible (opt)) + val = (*func)(opt, real, domain, cookie); + so++; + } + + return val; +} + +static inline int +hol_entry_long_iterate (const struct hol_entry *entry, + int (*func)(const struct argp_option *opt, + const struct argp_option *real, + const char *domain, void *cookie), + const char *domain, void *cookie) +{ + unsigned nopts; + int val = 0; + const struct argp_option *opt, *real = entry->opt; + + for (opt = real, nopts = entry->num; nopts > 0 && !val; opt++, nopts--) + if (opt->name) + { + if (!oalias (opt)) + real = opt; + if (ovisible (opt)) + val = (*func)(opt, real, domain, cookie); + } + + return val; +} + +/* Iterator that returns true for the first short option. */ +static inline int +until_short (const struct argp_option *opt, const struct argp_option *real, + const char *domain, void *cookie) +{ + return oshort (opt) ? opt->key : 0; +} + +/* Returns the first valid short option in ENTRY, or 0 if there is none. */ +static char +hol_entry_first_short (const struct hol_entry *entry) +{ + return hol_entry_short_iterate (entry, until_short, + entry->argp->argp_domain, 0); +} + +/* Returns the first valid long option in ENTRY, or 0 if there is none. */ +static const char * +hol_entry_first_long (const struct hol_entry *entry) +{ + const struct argp_option *opt; + unsigned num; + for (opt = entry->opt, num = entry->num; num > 0; opt++, num--) + if (opt->name && ovisible (opt)) + return opt->name; + return 0; +} + +/* Returns the entry in HOL with the long option name NAME, or 0 if there is + none. */ +static struct hol_entry * +hol_find_entry (struct hol *hol, const char *name) +{ + struct hol_entry *entry = hol->entries; + unsigned num_entries = hol->num_entries; + + while (num_entries-- > 0) + { + const struct argp_option *opt = entry->opt; + unsigned num_opts = entry->num; + + while (num_opts-- > 0) + if (opt->name && ovisible (opt) && strcmp (opt->name, name) == 0) + return entry; + else + opt++; + + entry++; + } + + return 0; +} + +/* If an entry with the long option NAME occurs in HOL, set it's special + sort position to GROUP. */ +static void +hol_set_group (struct hol *hol, const char *name, int group) +{ + struct hol_entry *entry = hol_find_entry (hol, name); + if (entry) + entry->group = group; +} + +/* Order by group: 0, 1, 2, ..., n, -m, ..., -2, -1. + EQ is what to return if GROUP1 and GROUP2 are the same. */ +static int +group_cmp (int group1, int group2, int eq) +{ + if (group1 == group2) + return eq; + else if ((group1 < 0 && group2 < 0) || (group1 >= 0 && group2 >= 0)) + return group1 - group2; + else + return group2 - group1; +} + +/* Compare clusters CL1 & CL2 by the order that they should appear in + output. */ +static int +hol_cluster_cmp (const struct hol_cluster *cl1, const struct hol_cluster *cl2) +{ + /* If one cluster is deeper than the other, use its ancestor at the same + level, so that finding the common ancestor is straightforward. */ + while (cl1->depth < cl2->depth) + cl1 = cl1->parent; + while (cl2->depth < cl1->depth) + cl2 = cl2->parent; + + /* Now reduce both clusters to their ancestors at the point where both have + a common parent; these can be directly compared. */ + while (cl1->parent != cl2->parent) + cl1 = cl1->parent, cl2 = cl2->parent; + + return group_cmp (cl1->group, cl2->group, cl2->index - cl1->index); +} + +/* Return the ancestor of CL that's just below the root (i.e., has a parent + of 0). */ +static struct hol_cluster * +hol_cluster_base (struct hol_cluster *cl) +{ + while (cl->parent) + cl = cl->parent; + return cl; +} + +/* Return true if CL1 is a child of CL2. */ +static int +hol_cluster_is_child (const struct hol_cluster *cl1, + const struct hol_cluster *cl2) +{ + while (cl1 && cl1 != cl2) + cl1 = cl1->parent; + return cl1 == cl2; +} + +/* Given the name of a OPTION_DOC option, modifies NAME to start at the tail + that should be used for comparisons, and returns true iff it should be + treated as a non-option. */ +static int +canon_doc_option (const char **name) +{ + int non_opt; + /* Skip initial whitespace. */ + while (isspace (**name)) + (*name)++; + /* Decide whether this looks like an option (leading `-') or not. */ + non_opt = (**name != '-'); + /* Skip until part of name used for sorting. */ + while (**name && !isalnum (**name)) + (*name)++; + return non_opt; +} + +/* Order ENTRY1 & ENTRY2 by the order which they should appear in a help + listing. */ +static int +hol_entry_cmp (const struct hol_entry *entry1, + const struct hol_entry *entry2) +{ + /* The group numbers by which the entries should be ordered; if either is + in a cluster, then this is just the group within the cluster. */ + int group1 = entry1->group, group2 = entry2->group; + + if (entry1->cluster != entry2->cluster) + { + /* The entries are not within the same cluster, so we can't compare them + directly, we have to use the appropiate clustering level too. */ + if (! entry1->cluster) + /* ENTRY1 is at the `base level', not in a cluster, so we have to + compare it's group number with that of the base cluster in which + ENTRY2 resides. Note that if they're in the same group, the + clustered option always comes laster. */ + return group_cmp (group1, hol_cluster_base (entry2->cluster)->group, -1); + else if (! entry2->cluster) + /* Likewise, but ENTRY2's not in a cluster. */ + return group_cmp (hol_cluster_base (entry1->cluster)->group, group2, 1); + else + /* Both entries are in clusters, we can just compare the clusters. */ + return hol_cluster_cmp (entry1->cluster, entry2->cluster); + } + else if (group1 == group2) + /* The entries are both in the same cluster and group, so compare them + alphabetically. */ + { + int short1 = hol_entry_first_short (entry1); + int short2 = hol_entry_first_short (entry2); + int doc1 = odoc (entry1->opt); + int doc2 = odoc (entry2->opt); + const char *long1 = hol_entry_first_long (entry1); + const char *long2 = hol_entry_first_long (entry2); + + if (doc1) + doc1 = canon_doc_option (&long1); + if (doc2) + doc2 = canon_doc_option (&long2); + + if (doc1 != doc2) + /* `documentation' options always follow normal options (or + documentation options that *look* like normal options). */ + return doc1 - doc2; + else if (!short1 && !short2 && long1 && long2) + /* Only long options. */ + return __strcasecmp (long1, long2); + else + /* Compare short/short, long/short, short/long, using the first + character of long options. Entries without *any* valid + options (such as options with OPTION_HIDDEN set) will be put + first, but as they're not displayed, it doesn't matter where + they are. */ + { + char first1 = short1 ? short1 : long1 ? *long1 : 0; + char first2 = short2 ? short2 : long2 ? *long2 : 0; +#ifdef _tolower + int lower_cmp = _tolower (first1) - _tolower (first2); +#else + int lower_cmp = tolower (first1) - tolower (first2); +#endif + /* Compare ignoring case, except when the options are both the + same letter, in which case lower-case always comes first. */ + return lower_cmp ? lower_cmp : first2 - first1; + } + } + else + /* Within the same cluster, but not the same group, so just compare + groups. */ + return group_cmp (group1, group2, 0); +} + +/* Version of hol_entry_cmp with correct signature for qsort. */ +static int +hol_entry_qcmp (const void *entry1_v, const void *entry2_v) +{ + return hol_entry_cmp (entry1_v, entry2_v); +} + +/* Sort HOL by group and alphabetically by option name (with short options + taking precedence over long). Since the sorting is for display purposes + only, the shadowing of options isn't effected. */ +static void +hol_sort (struct hol *hol) +{ + if (hol->num_entries > 0) + qsort (hol->entries, hol->num_entries, sizeof (struct hol_entry), + hol_entry_qcmp); +} + +/* Append MORE to HOL, destroying MORE in the process. Options in HOL shadow + any in MORE with the same name. */ +static void +hol_append (struct hol *hol, struct hol *more) +{ + struct hol_cluster **cl_end = &hol->clusters; + char *tmp; + + /* Steal MORE's cluster list, and add it to the end of HOL's. */ + while (*cl_end) + cl_end = &(*cl_end)->next; + *cl_end = more->clusters; + more->clusters = 0; + + /* Merge entries. */ + if (more->num_entries > 0) + { + if (hol->num_entries == 0) + { + hol->num_entries = more->num_entries; + hol->entries = more->entries; + hol->short_options = more->short_options; + more->num_entries = 0; /* Mark MORE's fields as invalid. */ + } + else + /* Append the entries in MORE to those in HOL, taking care to only add + non-shadowed SHORT_OPTIONS values. */ + { + unsigned left; + char *so, *more_so; + struct hol_entry *e; + unsigned num_entries = hol->num_entries + more->num_entries; + struct hol_entry *entries = + malloc (num_entries * sizeof (struct hol_entry)); + unsigned hol_so_len = strlen (hol->short_options); + char *short_options = + malloc (hol_so_len + strlen (more->short_options) + 1); + + tmp = memcpy (entries, hol->entries, + hol->num_entries * sizeof (struct hol_entry)); + tmp += hol->num_entries * sizeof (struct hol_entry); + memcpy (tmp, + more->entries, + more->num_entries * sizeof (struct hol_entry)); + + memcpy (short_options, hol->short_options, hol_so_len); + + /* Fix up the short options pointers from HOL. */ + for (e = entries, left = hol->num_entries; left > 0; e++, left--) + e->short_options += (short_options - hol->short_options); + + /* Now add the short options from MORE, fixing up its entries + too. */ + so = short_options + hol_so_len; + more_so = more->short_options; + for (left = more->num_entries; left > 0; e++, left--) + { + int opts_left; + const struct argp_option *opt; + + e->short_options = so; + + for (opts_left = e->num, opt = e->opt; opts_left; opt++, opts_left--) + { + int ch = *more_so; + if (oshort (opt) && ch == opt->key) + /* The next short option in MORE_SO, CH, is from OPT. */ + { + if (! find_char (ch, short_options, + short_options + hol_so_len)) + /* The short option CH isn't shadowed by HOL's options, + so add it to the sum. */ + *so++ = ch; + more_so++; + } + } + } + + *so = '\0'; + + free (hol->entries); + free (hol->short_options); + + hol->entries = entries; + hol->num_entries = num_entries; + hol->short_options = short_options; + } + } + + hol_free (more); +} + +/* Inserts enough spaces to make sure STREAM is at column COL. */ +static void +indent_to (argp_fmtstream_t stream, unsigned col) +{ + int needed = col - __argp_fmtstream_point (stream); + while (needed-- > 0) + __argp_fmtstream_putc (stream, ' '); +} + +/* Output to STREAM either a space, or a newline if there isn't room for at + least ENSURE characters before the right margin. */ +static void +space (argp_fmtstream_t stream, size_t ensure) +{ + if (__argp_fmtstream_point (stream) + ensure + >= __argp_fmtstream_rmargin (stream)) + __argp_fmtstream_putc (stream, '\n'); + else + __argp_fmtstream_putc (stream, ' '); +} + +/* If the option REAL has an argument, we print it in using the printf + format REQ_FMT or OPT_FMT depending on whether it's a required or + optional argument. */ +static void +arg (const struct argp_option *real, const char *req_fmt, const char *opt_fmt, + const char *domain, argp_fmtstream_t stream) +{ + if (real->arg) + { + if (real->flags & OPTION_ARG_OPTIONAL) + __argp_fmtstream_printf (stream, opt_fmt, + dgettext (domain, real->arg)); + else + __argp_fmtstream_printf (stream, req_fmt, + dgettext (domain, real->arg)); + } +} + +/* Helper functions for hol_entry_help. */ + +/* State used during the execution of hol_help. */ +struct hol_help_state +{ + /* PREV_ENTRY should contain the previous entry printed, or 0. */ + struct hol_entry *prev_entry; + + /* If an entry is in a different group from the previous one, and SEP_GROUPS + is true, then a blank line will be printed before any output. */ + int sep_groups; + + /* True if a duplicate option argument was suppressed (only ever set if + UPARAMS.dup_args is false). */ + int suppressed_dup_arg; +}; + +/* Some state used while printing a help entry (used to communicate with + helper functions). See the doc for hol_entry_help for more info, as most + of the fields are copied from its arguments. */ +struct pentry_state +{ + const struct hol_entry *entry; + argp_fmtstream_t stream; + struct hol_help_state *hhstate; + + /* True if nothing's been printed so far. */ + int first; + + /* If non-zero, the state that was used to print this help. */ + const struct argp_state *state; +}; + +/* If a user doc filter should be applied to DOC, do so. */ +static const char * +filter_doc (const char *doc, int key, const struct argp *argp, + const struct argp_state *state) +{ + if (argp->help_filter) + /* We must apply a user filter to this output. */ + { + void *input = __argp_input (argp, state); + return (*argp->help_filter) (key, doc, input); + } + else + /* No filter. */ + return doc; +} + +/* Prints STR as a header line, with the margin lines set appropiately, and + notes the fact that groups should be separated with a blank line. ARGP is + the argp that should dictate any user doc filtering to take place. Note + that the previous wrap margin isn't restored, but the left margin is reset + to 0. */ +static void +print_header (const char *str, const struct argp *argp, + struct pentry_state *pest) +{ + const char *tstr = dgettext (argp->argp_domain, str); + const char *fstr = filter_doc (tstr, ARGP_KEY_HELP_HEADER, argp, pest->state); + + if (fstr) + { + if (*fstr) + { + if (pest->hhstate->prev_entry) + /* Precede with a blank line. */ + __argp_fmtstream_putc (pest->stream, '\n'); + indent_to (pest->stream, uparams.header_col); + __argp_fmtstream_set_lmargin (pest->stream, uparams.header_col); + __argp_fmtstream_set_wmargin (pest->stream, uparams.header_col); + __argp_fmtstream_puts (pest->stream, fstr); + __argp_fmtstream_set_lmargin (pest->stream, 0); + __argp_fmtstream_putc (pest->stream, '\n'); + } + + pest->hhstate->sep_groups = 1; /* Separate subsequent groups. */ + } + + if (fstr != tstr) + free ((char *) fstr); +} + +/* Inserts a comma if this isn't the first item on the line, and then makes + sure we're at least to column COL. If this *is* the first item on a line, + prints any pending whitespace/headers that should precede this line. Also + clears FIRST. */ +static void +comma (unsigned col, struct pentry_state *pest) +{ + if (pest->first) + { + const struct hol_entry *pe = pest->hhstate->prev_entry; + const struct hol_cluster *cl = pest->entry->cluster; + + if (pest->hhstate->sep_groups && pe && pest->entry->group != pe->group) + __argp_fmtstream_putc (pest->stream, '\n'); + + if (cl && cl->header && *cl->header + && (!pe + || (pe->cluster != cl + && !hol_cluster_is_child (pe->cluster, cl)))) + /* If we're changing clusters, then this must be the start of the + ENTRY's cluster unless that is an ancestor of the previous one + (in which case we had just popped into a sub-cluster for a bit). + If so, then print the cluster's header line. */ + { + int old_wm = __argp_fmtstream_wmargin (pest->stream); + print_header (cl->header, cl->argp, pest); + __argp_fmtstream_set_wmargin (pest->stream, old_wm); + } + + pest->first = 0; + } + else + __argp_fmtstream_puts (pest->stream, ", "); + + indent_to (pest->stream, col); +} + +/* Print help for ENTRY to STREAM. */ +static void +hol_entry_help (struct hol_entry *entry, const struct argp_state *state, + argp_fmtstream_t stream, struct hol_help_state *hhstate) +{ + unsigned num; + const struct argp_option *real = entry->opt, *opt; + char *so = entry->short_options; + int have_long_opt = 0; /* We have any long options. */ + /* Saved margins. */ + int old_lm = __argp_fmtstream_set_lmargin (stream, 0); + int old_wm = __argp_fmtstream_wmargin (stream); + /* PEST is a state block holding some of our variables that we'd like to + share with helper functions. */ + struct pentry_state pest = { entry, stream, hhstate, 1, state }; + + if (! odoc (real)) + for (opt = real, num = entry->num; num > 0; opt++, num--) + if (opt->name && ovisible (opt)) + { + have_long_opt = 1; + break; + } + + /* First emit short options. */ + __argp_fmtstream_set_wmargin (stream, uparams.short_opt_col); /* For truly bizarre cases. */ + for (opt = real, num = entry->num; num > 0; opt++, num--) + if (oshort (opt) && opt->key == *so) + /* OPT has a valid (non shadowed) short option. */ + { + if (ovisible (opt)) + { + comma (uparams.short_opt_col, &pest); + __argp_fmtstream_putc (stream, '-'); + __argp_fmtstream_putc (stream, *so); + if (!have_long_opt || uparams.dup_args) + arg (real, " %s", "[%s]", state->root_argp->argp_domain, stream); + else if (real->arg) + hhstate->suppressed_dup_arg = 1; + } + so++; + } + + /* Now, long options. */ + if (odoc (real)) + /* A `documentation' option. */ + { + __argp_fmtstream_set_wmargin (stream, uparams.doc_opt_col); + for (opt = real, num = entry->num; num > 0; opt++, num--) + if (opt->name && ovisible (opt)) + { + comma (uparams.doc_opt_col, &pest); + /* Calling gettext here isn't quite right, since sorting will + have been done on the original; but documentation options + should be pretty rare anyway... */ + __argp_fmtstream_puts (stream, + dgettext (state->root_argp->argp_domain, + opt->name)); + } + } + else + /* A real long option. */ + { + int first_long_opt = 1; + + __argp_fmtstream_set_wmargin (stream, uparams.long_opt_col); + for (opt = real, num = entry->num; num > 0; opt++, num--) + if (opt->name && ovisible (opt)) + { + comma (uparams.long_opt_col, &pest); + __argp_fmtstream_printf (stream, "--%s", opt->name); + if (first_long_opt || uparams.dup_args) + arg (real, "=%s", "[=%s]", state->root_argp->argp_domain, stream); + else if (real->arg) + hhstate->suppressed_dup_arg = 1; + } + } + + /* Next, documentation strings. */ + __argp_fmtstream_set_lmargin (stream, 0); + + if (pest.first) + { + /* Didn't print any switches, what's up? */ + if (!oshort (real) && !real->name) + /* This is a group header, print it nicely. */ + print_header (real->doc, entry->argp, &pest); + else + /* Just a totally shadowed option or null header; print nothing. */ + goto cleanup; /* Just return, after cleaning up. */ + } + else + { + const char *tstr = real->doc ? dgettext (state->root_argp->argp_domain, + real->doc) : 0; + const char *fstr = filter_doc (tstr, real->key, entry->argp, state); + if (fstr && *fstr) + { + unsigned int col = __argp_fmtstream_point (stream); + + __argp_fmtstream_set_lmargin (stream, uparams.opt_doc_col); + __argp_fmtstream_set_wmargin (stream, uparams.opt_doc_col); + + if (col > (unsigned int) (uparams.opt_doc_col + 3)) + __argp_fmtstream_putc (stream, '\n'); + else if (col >= (unsigned int) uparams.opt_doc_col) + __argp_fmtstream_puts (stream, " "); + else + indent_to (stream, uparams.opt_doc_col); + + __argp_fmtstream_puts (stream, fstr); + } + if (fstr && fstr != tstr) + free ((char *) fstr); + + /* Reset the left margin. */ + __argp_fmtstream_set_lmargin (stream, 0); + __argp_fmtstream_putc (stream, '\n'); + } + + hhstate->prev_entry = entry; + +cleanup: + __argp_fmtstream_set_lmargin (stream, old_lm); + __argp_fmtstream_set_wmargin (stream, old_wm); +} + +/* Output a long help message about the options in HOL to STREAM. */ +static void +hol_help (struct hol *hol, const struct argp_state *state, + argp_fmtstream_t stream) +{ + unsigned num; + struct hol_entry *entry; + struct hol_help_state hhstate = { 0, 0, 0 }; + + for (entry = hol->entries, num = hol->num_entries; num > 0; entry++, num--) + hol_entry_help (entry, state, stream, &hhstate); + + if (hhstate.suppressed_dup_arg && uparams.dup_args_note) + { + const char *tstr = dgettext (state->root_argp->argp_domain, "\ + Mandatory or optional arguments to long options are also mandatory or \ + optional for any corresponding short options."); + const char *fstr = filter_doc (tstr, ARGP_KEY_HELP_DUP_ARGS_NOTE, + state ? state->root_argp : 0, state); + if (fstr && *fstr) + { + __argp_fmtstream_putc (stream, '\n'); + __argp_fmtstream_puts (stream, fstr); + __argp_fmtstream_putc (stream, '\n'); + } + if (fstr && fstr != tstr) + free ((char *) fstr); + } +} + +/* Helper functions for hol_usage. */ + +/* If OPT is a short option without an arg, append its key to the string + pointer pointer to by COOKIE, and advance the pointer. */ +static int +add_argless_short_opt (const struct argp_option *opt, + const struct argp_option *real, + const char *domain, void *cookie) +{ + char **snao_end = cookie; + if (!(opt->arg || real->arg) + && !((opt->flags | real->flags) & OPTION_NO_USAGE)) + *(*snao_end)++ = opt->key; + return 0; +} + +/* If OPT is a short option with an arg, output a usage entry for it to the + stream pointed at by COOKIE. */ +static int +usage_argful_short_opt (const struct argp_option *opt, + const struct argp_option *real, + const char *domain, void *cookie) +{ + argp_fmtstream_t stream = cookie; + const char *arg = opt->arg; + int flags = opt->flags | real->flags; + + if (! arg) + arg = real->arg; + + if (arg && !(flags & OPTION_NO_USAGE)) + { + arg = dgettext (domain, arg); + + if (flags & OPTION_ARG_OPTIONAL) + __argp_fmtstream_printf (stream, " [-%c[%s]]", opt->key, arg); + else + { + /* Manually do line wrapping so that it (probably) won't + get wrapped at the embedded space. */ + space (stream, 6 + strlen (arg)); + __argp_fmtstream_printf (stream, "[-%c %s]", opt->key, arg); + } + } + + return 0; +} + +/* Output a usage entry for the long option opt to the stream pointed at by + COOKIE. */ +static int +usage_long_opt (const struct argp_option *opt, + const struct argp_option *real, + const char *domain, void *cookie) +{ + argp_fmtstream_t stream = cookie; + const char *arg = opt->arg; + int flags = opt->flags | real->flags; + + if (! arg) + arg = real->arg; + + if (! (flags & OPTION_NO_USAGE)) + { + if (arg) + { + arg = dgettext (domain, arg); + if (flags & OPTION_ARG_OPTIONAL) + __argp_fmtstream_printf (stream, " [--%s[=%s]]", opt->name, arg); + else + __argp_fmtstream_printf (stream, " [--%s=%s]", opt->name, arg); + } + else + __argp_fmtstream_printf (stream, " [--%s]", opt->name); + } + + return 0; +} + +/* Print a short usage description for the arguments in HOL to STREAM. */ +static void +hol_usage (struct hol *hol, argp_fmtstream_t stream) +{ + if (hol->num_entries > 0) + { + unsigned nentries; + struct hol_entry *entry; + char *short_no_arg_opts = alloca (strlen (hol->short_options) + 1); + char *snao_end = short_no_arg_opts; + + /* First we put a list of short options without arguments. */ + for (entry = hol->entries, nentries = hol->num_entries + ; nentries > 0 + ; entry++, nentries--) + hol_entry_short_iterate (entry, add_argless_short_opt, + entry->argp->argp_domain, &snao_end); + if (snao_end > short_no_arg_opts) + { + *snao_end++ = 0; + __argp_fmtstream_printf (stream, " [-%s]", short_no_arg_opts); + } + + /* Now a list of short options *with* arguments. */ + for (entry = hol->entries, nentries = hol->num_entries + ; nentries > 0 + ; entry++, nentries--) + hol_entry_short_iterate (entry, usage_argful_short_opt, + entry->argp->argp_domain, stream); + + /* Finally, a list of long options (whew!). */ + for (entry = hol->entries, nentries = hol->num_entries + ; nentries > 0 + ; entry++, nentries--) + hol_entry_long_iterate (entry, usage_long_opt, + entry->argp->argp_domain, stream); + } +} + +/* Make a HOL containing all levels of options in ARGP. CLUSTER is the + cluster in which ARGP's entries should be clustered, or 0. */ +static struct hol * +argp_hol (const struct argp *argp, struct hol_cluster *cluster) +{ + const struct argp_child *child = argp->children; + struct hol *hol = make_hol (argp, cluster); + if (child) + while (child->argp) + { + struct hol_cluster *child_cluster = + ((child->group || child->header) + /* Put CHILD->argp within its own cluster. */ + ? hol_add_cluster (hol, child->group, child->header, + child - argp->children, cluster, argp) + /* Just merge it into the parent's cluster. */ + : cluster); + hol_append (hol, argp_hol (child->argp, child_cluster)) ; + child++; + } + return hol; +} + +/* Calculate how many different levels with alternative args strings exist in + ARGP. */ +static size_t +argp_args_levels (const struct argp *argp) +{ + size_t levels = 0; + const struct argp_child *child = argp->children; + + if (argp->args_doc && strchr (argp->args_doc, '\n')) + levels++; + + if (child) + while (child->argp) + levels += argp_args_levels ((child++)->argp); + + return levels; +} + +/* Print all the non-option args documented in ARGP to STREAM. Any output is + preceded by a space. LEVELS is a pointer to a byte vector the length + returned by argp_args_levels; it should be initialized to zero, and + updated by this routine for the next call if ADVANCE is true. True is + returned as long as there are more patterns to output. */ +static int +argp_args_usage (const struct argp *argp, const struct argp_state *state, + char **levels, int advance, argp_fmtstream_t stream) +{ + char *our_level = *levels; + int multiple = 0; + const struct argp_child *child = argp->children; + const char *tdoc = dgettext (argp->argp_domain, argp->args_doc), *nl = 0; + const char *fdoc = filter_doc (tdoc, ARGP_KEY_HELP_ARGS_DOC, argp, state); + + if (fdoc) + { + const char *cp = fdoc; + nl = strchr (cp, '\n'); + if (!nl) + { + nl = cp; + while (*nl != '\0') nl++; + } + + if (*nl != '\0') + /* This is a `multi-level' args doc; advance to the correct position + as determined by our state in LEVELS, and update LEVELS. */ + { + int i; + multiple = 1; + for (i = 0; i < *our_level; i++) + { + cp = nl + 1; + nl = strchr (cp, '\n'); + if (!nl) + { + nl = cp; + while (*nl != '\0') nl++; + } + } + (*levels)++; + } + + /* Manually do line wrapping so that it (probably) won't get wrapped at + any embedded spaces. */ + space (stream, 1 + nl - cp); + + __argp_fmtstream_write (stream, cp, nl - cp); + } + if (fdoc && fdoc != tdoc) + free ((char *)fdoc); /* Free user's modified doc string. */ + + if (child) + while (child->argp) + advance = !argp_args_usage ((child++)->argp, state, levels, advance, stream); + + if (advance && multiple) + { + /* Need to increment our level. */ + if (*nl) + /* There's more we can do here. */ + { + (*our_level)++; + advance = 0; /* Our parent shouldn't advance also. */ + } + else if (*our_level > 0) + /* We had multiple levels, but used them up; reset to zero. */ + *our_level = 0; + } + + return !advance; +} + +/* Print the documentation for ARGP to STREAM; if POST is false, then + everything preceeding a `\v' character in the documentation strings (or + the whole string, for those with none) is printed, otherwise, everything + following the `\v' character (nothing for strings without). Each separate + bit of documentation is separated a blank line, and if PRE_BLANK is true, + then the first is as well. If FIRST_ONLY is true, only the first + occurrence is output. Returns true if anything was output. */ +static int +argp_doc (const struct argp *argp, const struct argp_state *state, + int post, int pre_blank, int first_only, + argp_fmtstream_t stream) +{ + const char *text; + const char *inp_text; + char *tmp_text; + void *input = 0; + int anything = 0; + size_t inp_text_limit = 0; + const char *doc = dgettext (argp->argp_domain, argp->doc); + const struct argp_child *child = argp->children; + + if (doc) + { + char *vt = strchr (doc, '\v'); + inp_text = post ? (vt ? vt + 1 : 0) : doc; + inp_text_limit = (!post && vt) ? (vt - doc) : 0; + } + else + inp_text = 0; + + if (argp->help_filter) + /* We have to filter the doc strings. */ + { + if (inp_text_limit) + { + /* Copy INP_TEXT so that it's nul-terminated. */ + tmp_text = _malloc_r (_REENT, inp_text_limit); + strncpy (tmp_text, inp_text, inp_text_limit); + _free_r (_REENT, inp_text); + inp_text = tmp_text; + } + input = __argp_input (argp, state); + text = + (*argp->help_filter) (post + ? ARGP_KEY_HELP_POST_DOC + : ARGP_KEY_HELP_PRE_DOC, + inp_text, input); + } + else + text = (const char *) inp_text; + + if (text) + { + if (pre_blank) + __argp_fmtstream_putc (stream, '\n'); + + if (text == inp_text && inp_text_limit) + __argp_fmtstream_write (stream, inp_text, inp_text_limit); + else + __argp_fmtstream_puts (stream, text); + + if (__argp_fmtstream_point (stream) > __argp_fmtstream_lmargin (stream)) + __argp_fmtstream_putc (stream, '\n'); + + anything = 1; + } + + if (text && text != inp_text) + free ((char *) text); /* Free TEXT returned from the help filter. */ + if (inp_text && inp_text_limit && argp->help_filter) + free ((char *) inp_text); /* We copied INP_TEXT, so free it now. */ + + if (post && argp->help_filter) + /* Now see if we have to output a ARGP_KEY_HELP_EXTRA text. */ + { + text = (*argp->help_filter) (ARGP_KEY_HELP_EXTRA, 0, input); + if (text) + { + if (anything || pre_blank) + __argp_fmtstream_putc (stream, '\n'); + __argp_fmtstream_puts (stream, text); + free ((char *) text); + if (__argp_fmtstream_point (stream) + > __argp_fmtstream_lmargin (stream)) + __argp_fmtstream_putc (stream, '\n'); + anything = 1; + } + } + + if (child) + while (child->argp && !(first_only && anything)) + anything |= + argp_doc ((child++)->argp, state, + post, anything || pre_blank, first_only, + stream); + + return anything; +} + +/* Output a usage message for ARGP to STREAM. If called from + argp_state_help, STATE is the relevent parsing state. FLAGS are from the + set ARGP_HELP_*. NAME is what to use wherever a `program name' is + needed. */ +static void +_help (const struct argp *argp, const struct argp_state *state, FILE *stream, + unsigned flags, char *name) +{ + int anything = 0; /* Whether we've output anything. */ + struct hol *hol = 0; + argp_fmtstream_t fs; + + if (! stream) + return; + + _flockfile (stream); + + if (! uparams.valid) + fill_in_uparams (state); + + fs = __argp_make_fmtstream (stream, 0, uparams.rmargin, 0); + if (! fs) + { + _funlockfile (stream); + return; + } + + if (flags & (ARGP_HELP_USAGE | ARGP_HELP_SHORT_USAGE | ARGP_HELP_LONG)) + { + hol = argp_hol (argp, 0); + + /* If present, these options always come last. */ + hol_set_group (hol, "help", -1); + hol_set_group (hol, "version", -1); + + hol_sort (hol); + } + + if (flags & (ARGP_HELP_USAGE | ARGP_HELP_SHORT_USAGE)) + /* Print a short `Usage:' message. */ + { + int first_pattern = 1, more_patterns; + size_t num_pattern_levels = argp_args_levels (argp); + char *pattern_levels = alloca (num_pattern_levels); + + memset (pattern_levels, 0, num_pattern_levels); + + do + { + int old_lm; + int old_wm = __argp_fmtstream_set_wmargin (fs, uparams.usage_indent); + char *levels = pattern_levels; + + if (first_pattern) + __argp_fmtstream_printf (fs, "%s %s", + dgettext (argp->argp_domain, "Usage:"), + name); + else + __argp_fmtstream_printf (fs, "%s %s", + dgettext (argp->argp_domain, " or: "), + name); + + /* We set the lmargin as well as the wmargin, because hol_usage + manually wraps options with newline to avoid annoying breaks. */ + old_lm = __argp_fmtstream_set_lmargin (fs, uparams.usage_indent); + + if (flags & ARGP_HELP_SHORT_USAGE) + /* Just show where the options go. */ + { + if (hol->num_entries > 0) + __argp_fmtstream_puts (fs, dgettext (argp->argp_domain, + " [OPTION...]")); + } + else + /* Actually print the options. */ + { + hol_usage (hol, fs); + flags |= ARGP_HELP_SHORT_USAGE; /* But only do so once. */ + } + + more_patterns = argp_args_usage (argp, state, &levels, 1, fs); + + __argp_fmtstream_set_wmargin (fs, old_wm); + __argp_fmtstream_set_lmargin (fs, old_lm); + + __argp_fmtstream_putc (fs, '\n'); + anything = 1; + + first_pattern = 0; + } + while (more_patterns); + } + + if (flags & ARGP_HELP_PRE_DOC) + anything |= argp_doc (argp, state, 0, 0, 1, fs); + + if (flags & ARGP_HELP_SEE) + { + __argp_fmtstream_printf (fs, dgettext (argp->argp_domain, "\ + Try `%s --help' or `%s --usage' for more information.\n"), + name, name); + anything = 1; + } + + if (flags & ARGP_HELP_LONG) + /* Print a long, detailed help message. */ + { + /* Print info about all the options. */ + if (hol->num_entries > 0) + { + if (anything) + __argp_fmtstream_putc (fs, '\n'); + hol_help (hol, state, fs); + anything = 1; + } + } + + if (flags & ARGP_HELP_POST_DOC) + /* Print any documentation strings at the end. */ + anything |= argp_doc (argp, state, 1, anything, 0, fs); + + if ((flags & ARGP_HELP_BUG_ADDR) && argp_program_bug_address) + { + if (anything) + __argp_fmtstream_putc (fs, '\n'); + __argp_fmtstream_printf (fs, dgettext (argp->argp_domain, + "Report bugs to %s.\n"), + argp_program_bug_address); + anything = 1; + } + + _funlockfile (stream); + + if (hol) + hol_free (hol); + + __argp_fmtstream_free (fs); +} + +/* Output a usage message for ARGP to STREAM. FLAGS are from the set + ARGP_HELP_*. NAME is what to use wherever a `program name' is needed. */ +void __argp_help (const struct argp *argp, FILE *stream, + unsigned flags, char *name) +{ + _help (argp, 0, stream, flags, name); +} +#ifdef weak_alias +weak_alias (__argp_help, argp_help) +#endif + +/* Output, if appropriate, a usage message for STATE to STREAM. FLAGS are + from the set ARGP_HELP_*. */ +void +__argp_state_help (const struct argp_state *state, FILE *stream, unsigned flags) +{ + if ((!state || ! (state->flags & ARGP_NO_ERRS)) && stream) + { + if (state && (state->flags & ARGP_LONG_ONLY)) + flags |= ARGP_HELP_LONG_ONLY; + + _help (state ? state->root_argp : 0, state, stream, flags, + state ? state->name : program_invocation_short_name); + + if (!state || ! (state->flags & ARGP_NO_EXIT)) + { + if (flags & ARGP_HELP_EXIT_ERR) + exit (argp_err_exit_status); + if (flags & ARGP_HELP_EXIT_OK) + exit (0); + } + } +} +#ifdef weak_alias +weak_alias (__argp_state_help, argp_state_help) +#endif + +/* If appropriate, print the printf string FMT and following args, preceded + by the program name and `:', to stderr, and followed by a `Try ... --help' + message, then exit (1). */ +void +__argp_error (const struct argp_state *state, const char *fmt, ...) +{ + if (!state || !(state->flags & ARGP_NO_ERRS)) + { + FILE *stream = state ? state->err_stream : stderr; + + if (stream) + { + va_list ap; + + _flockfile (stream); + + va_start (ap, fmt); + +#ifdef USE_IN_LIBIO + if (_IO_fwide (stream, 0) > 0) + { + char *buf; + + __asprintf (&buf, fmt, ap); + + __fwprintf (stream, L"%s: %s\n", + state ? state->name : program_invocation_short_name, + buf); + + free (buf); + } + else +#endif + { + fputs (state + ? state->name : program_invocation_short_name, + stream); + putc_unlocked (':', stream); + putc_unlocked (' ', stream); + + vfprintf (stream, fmt, ap); + + putc_unlocked ('\n', stream); + } + + __argp_state_help (state, stream, ARGP_HELP_STD_ERR); + + va_end (ap); + + _funlockfile (stream); + } + } +} +#ifdef weak_alias +weak_alias (__argp_error, argp_error) +#endif + +/* Similar to the standard gnu error-reporting function error(), but will + respect the ARGP_NO_EXIT and ARGP_NO_ERRS flags in STATE, and will print + to STATE->err_stream. This is useful for argument parsing code that is + shared between program startup (when exiting is desired) and runtime + option parsing (when typically an error code is returned instead). The + difference between this function and argp_error is that the latter is for + *parsing errors*, and the former is for other problems that occur during + parsing but don't reflect a (syntactic) problem with the input. */ +void +__argp_failure (const struct argp_state *state, int status, int errnum, + const char *fmt, ...) +{ + if (!state || !(state->flags & ARGP_NO_ERRS)) + { + FILE *stream = state ? state->err_stream : stderr; + + if (stream) + { + _flockfile (stream); + +#ifdef USE_IN_LIBIO + if (_IO_fwide (stream, 0) > 0) + __fwprintf (stream, L"%s", + state ? state->name : program_invocation_short_name); + else +#endif + fputs (state + ? state->name : program_invocation_short_name, + stream); + + if (fmt) + { + va_list ap; + + va_start (ap, fmt); +#ifdef USE_IN_LIBIO + if (_IO_fwide (stream, 0) > 0) + { + char *buf; + + __asprintf (&buf, fmt, ap); + + __fwprintf (stream, L": %s", buf); + + free (buf); + } + else +#endif + { + putc_unlocked (':', stream); + putc_unlocked (' ', stream); + + vfprintf (stream, fmt, ap); + } + + va_end (ap); + } + + if (errnum) + { + char buf[200]; + +#ifdef USE_IN_LIBIO + if (_IO_fwide (stream, 0) > 0) + __fwprintf (stream, L": %s", + strerror_r (errnum, buf, sizeof (buf))); + else +#endif + { + putc_unlocked (':', stream); + putc_unlocked (' ', stream); + fputs (strerror_r (errnum, buf, sizeof (buf)), stream); + } + } + +#ifdef USE_IN_LIBIO + if (_IO_fwide (stream, 0) > 0) + putwc_unlocked (L'\n', stream); + else +#endif + putc_unlocked ('\n', stream); + + _funlockfile (stream); + + if (status && (!state || !(state->flags & ARGP_NO_EXIT))) + exit (status); + } + } +} +#ifdef weak_alias +weak_alias (__argp_failure, argp_failure) +#endif diff --git a/libraries/platforms/dromajo-vcs/software/src/argp/argp-parse.c b/libraries/platforms/dromajo-vcs/software/src/argp/argp-parse.c new file mode 100644 index 000000000..7d29edd98 --- /dev/null +++ b/libraries/platforms/dromajo-vcs/software/src/argp/argp-parse.c @@ -0,0 +1,988 @@ +/* Hierarchial argument parsing, layered over getopt + Copyright (C) 1995, 96, 97, 98, 99, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Written by Miles Bader . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include + +#ifndef _ +/* This is for other GNU distributions with internationalized messages. + When compiling libc, the _ macro is predefined. */ +# if defined HAVE_LIBINTL_H || defined _LIBC +# include +# ifdef _LIBC +# undef dgettext +# define dgettext(domain, msgid) __dcgettext (domain, msgid, LC_MESSAGES) +# endif +# else +# define dgettext(domain, msgid) (msgid) +# define gettext(msgid) (msgid) +# endif +#endif +#ifndef N_ +# define N_(msgid) (msgid) +#endif + +#if _LIBC - 0 +#include +#else +#ifdef HAVE_CTHREADS_H +#include +#endif +#endif /* _LIBC */ + +#include +#include "argp-namefrob.h" + +/* Getopt return values. */ +#define KEY_END (-1) /* The end of the options. */ +#define KEY_ARG 1 /* A non-option argument. */ +#define KEY_ERR '?' /* An error parsing the options. */ + +/* The meta-argument used to prevent any further arguments being interpreted + as options. */ +#define QUOTE "--" + +/* The number of bits we steal in a long-option value for our own use. */ +#define GROUP_BITS CHAR_BIT + +/* The number of bits available for the user value. */ +#define USER_BITS ((sizeof ((struct option *)0)->val * CHAR_BIT) - GROUP_BITS) +#define USER_MASK ((1 << USER_BITS) - 1) + +/* EZ alias for ARGP_ERR_UNKNOWN. */ +#define EBADKEY ARGP_ERR_UNKNOWN + +/* Default options. */ + +/* When argp is given the --HANG switch, _ARGP_HANG is set and argp will sleep + for one second intervals, decrementing _ARGP_HANG until it's zero. Thus + you can force the program to continue by attaching a debugger and setting + it to 0 yourself. */ +volatile int _argp_hang; + +#define OPT_PROGNAME -2 +#define OPT_USAGE -3 +#define OPT_HANG -4 + +static const struct argp_option argp_default_options[] = +{ + {"help", '?', 0, 0, N_("Give this help list"), -1}, + {"usage", OPT_USAGE, 0, 0, N_("Give a short usage message")}, + {"program-name",OPT_PROGNAME,"NAME", OPTION_HIDDEN, N_("Set the program name")}, + {"HANG", OPT_HANG, "SECS", OPTION_ARG_OPTIONAL | OPTION_HIDDEN, + N_("Hang for SECS seconds (default 3600)")}, + {0, 0} +}; + +static error_t +argp_default_parser (int key, char *arg, struct argp_state *state) +{ + switch (key) + { + case '?': + __argp_state_help (state, state->out_stream, ARGP_HELP_STD_HELP); + break; + case OPT_USAGE: + __argp_state_help (state, state->out_stream, + ARGP_HELP_USAGE | ARGP_HELP_EXIT_OK); + break; + + case OPT_PROGNAME: /* Set the program name. */ + program_invocation_name = arg; + + /* [Note that some systems only have PROGRAM_INVOCATION_SHORT_NAME (aka + __PROGNAME), in which case, PROGRAM_INVOCATION_NAME is just defined + to be that, so we have to be a bit careful here.] */ + arg = strrchr (arg, '/'); + if (arg) + program_invocation_short_name = arg + 1; + else + program_invocation_short_name = program_invocation_name; + + /* Update what we use for messages. */ + state->name = program_invocation_short_name; + + if ((state->flags & (ARGP_PARSE_ARGV0 | ARGP_NO_ERRS)) + == ARGP_PARSE_ARGV0) + /* Update what getopt uses too. */ + state->argv[0] = program_invocation_name; + + break; + + case OPT_HANG: + _argp_hang = atoi (arg ? arg : "3600"); + while (_argp_hang-- > 0) + // Use a for loop to hang the execution rather than sleep + // since it is not implemented + // This will consume power but we don't really care since we will + // run a full-featured linux in real use cases and this will not be a problem + // Also, this a single-thread execution and there is nothing to context switch to + // while sleeping, so it shouldn't matter anyways. + // Choosing an arbitrary number to sleep. This necessarily may not map to 1 second + for (int i = 0; i < 1000; i++) + for (int j = 0; j <= (1 << 31); j++) + // Use this to prevent the compiler from optimizing this piece of code out. + __asm__ __volatile__("" : "+g" (i), "+g" (j) : :); + break; + + default: + return EBADKEY; + } + return 0; +} + +static const struct argp argp_default_argp = + {argp_default_options, &argp_default_parser, NULL, NULL, NULL, NULL, "libc"}; + + +static const struct argp_option argp_version_options[] = +{ + {"version", 'V', 0, 0, N_("Print program version"), -1}, + {0, 0} +}; + +static error_t +argp_version_parser (int key, char *arg, struct argp_state *state) +{ + switch (key) + { + case 'V': + if (argp_program_version_hook) + (*argp_program_version_hook) (state->out_stream, state); + else if (argp_program_version) + fprintf (state->out_stream, "%s\n", argp_program_version); + else + __argp_error (state, dgettext (state->root_argp->argp_domain, + "(PROGRAM ERROR) No version known!?")); + if (! (state->flags & ARGP_NO_EXIT)) + exit (0); + break; + default: + return EBADKEY; + } + return 0; +} + +static const struct argp argp_version_argp = + {argp_version_options, &argp_version_parser, NULL, NULL, NULL, NULL, "libc"}; + +/* Returns the offset into the getopt long options array LONG_OPTIONS of a + long option with called NAME, or -1 if none is found. Passing NULL as + NAME will return the number of options. */ +static int +find_long_option (struct option *long_options, const char *name) +{ + struct option *l = long_options; + while (l->name != NULL) + if (name != NULL && strcmp (l->name, name) == 0) + return l - long_options; + else + l++; + if (name == NULL) + return l - long_options; + else + return -1; +} + +/* If we can, we regulate access to getopt, which is non-reentrant, with a + mutex. Since the case we're trying to guard against is two different + threads interfering, and it's possible that someone might want to call + argp_parse recursively (they're careful), we use a recursive lock if + possible. */ + +#if _LIBC - 0 + +__libc_lock_define_initialized_recursive (static, getopt_lock) +#define LOCK_GETOPT __libc_lock_lock_recursive (getopt_lock) +#define UNLOCK_GETOPT __libc_lock_unlock_recursive (getopt_lock) + +#else /* !_LIBC */ +#ifdef HAVE_CTHREADS_H + +static struct mutex getopt_lock = MUTEX_INITIALIZER; +#define LOCK_GETOPT mutex_lock (&getopt_lock) +#define UNLOCK_GETOPT mutex_unlock (&getopt_lock) + +#else /* !HAVE_CTHREADS_H */ + +#define LOCK_GETOPT (void)0 +#define UNLOCK_GETOPT (void)0 + +#endif /* HAVE_CTHREADS_H */ +#endif /* _LIBC */ + +/* This hack to allow programs that know what's going on to call argp + recursively. If someday argp is changed not to use the non-reentrant + getopt interface, we can get rid of this shit. XXX */ +void +_argp_unlock_xxx (void) +{ + UNLOCK_GETOPT; +} + +/* The state of a `group' during parsing. Each group corresponds to a + particular argp structure from the tree of such descending from the top + level argp passed to argp_parse. */ +struct group +{ + /* This group's parsing function. */ + argp_parser_t parser; + + /* Which argp this group is from. */ + const struct argp *argp; + + /* Points to the point in SHORT_OPTS corresponding to the end of the short + options for this group. We use it to determine from which group a + particular short options is from. */ + char *short_end; + + /* The number of non-option args sucessfully handled by this parser. */ + unsigned args_processed; + + /* This group's parser's parent's group. */ + struct group *parent; + unsigned parent_index; /* And the our position in the parent. */ + + /* These fields are swapped into and out of the state structure when + calling this group's parser. */ + void *input, **child_inputs; + void *hook; +}; + +/* Call GROUP's parser with KEY and ARG, swapping any group-specific info + from STATE before calling, and back into state afterwards. If GROUP has + no parser, EBADKEY is returned. */ +static error_t +group_parse (struct group *group, struct argp_state *state, int key, char *arg) +{ + if (group->parser) + { + error_t err; + state->hook = group->hook; + state->input = group->input; + state->child_inputs = group->child_inputs; + state->arg_num = group->args_processed; + err = (*group->parser)(key, arg, state); + group->hook = state->hook; + return err; + } + else + return EBADKEY; +} + +struct parser +{ + const struct argp *argp; + + /* SHORT_OPTS is the getopt short options string for the union of all the + groups of options. */ + char *short_opts; + /* LONG_OPTS is the array of getop long option structures for the union of + all the groups of options. */ + struct option *long_opts; + + /* States of the various parsing groups. */ + struct group *groups; + /* The end of the GROUPS array. */ + struct group *egroup; + /* An vector containing storage for the CHILD_INPUTS field in all groups. */ + void **child_inputs; + + /* True if we think using getopt is still useful; if false, then + remaining arguments are just passed verbatim with ARGP_KEY_ARG. This is + cleared whenever getopt returns KEY_END, but may be set again if the user + moves the next argument pointer backwards. */ + int try_getopt; + + /* State block supplied to parsing routines. */ + struct argp_state state; + + /* Memory used by this parser. */ + void *storage; +}; + +/* The next usable entries in the various parser tables being filled in by + convert_options. */ +struct parser_convert_state +{ + struct parser *parser; + char *short_end; + struct option *long_end; + void **child_inputs_end; +}; + +/* Converts all options in ARGP (which is put in GROUP) and ancestors + into getopt options stored in SHORT_OPTS and LONG_OPTS; SHORT_END and + CVT->LONG_END are the points at which new options are added. Returns the + next unused group entry. CVT holds state used during the conversion. */ +static struct group * +convert_options (const struct argp *argp, + struct group *parent, unsigned parent_index, + struct group *group, struct parser_convert_state *cvt) +{ + /* REAL is the most recent non-alias value of OPT. */ + const struct argp_option *real = argp->options; + const struct argp_child *children = argp->children; + + if (real || argp->parser) + { + const struct argp_option *opt; + + if (real) + for (opt = real; !__option_is_end (opt); opt++) + { + if (! (opt->flags & OPTION_ALIAS)) + /* OPT isn't an alias, so we can use values from it. */ + real = opt; + + if (! (real->flags & OPTION_DOC)) + /* A real option (not just documentation). */ + { + if (__option_is_short (opt)) + /* OPT can be used as a short option. */ + { + *cvt->short_end++ = opt->key; + if (real->arg) + { + *cvt->short_end++ = ':'; + if (real->flags & OPTION_ARG_OPTIONAL) + *cvt->short_end++ = ':'; + } + *cvt->short_end = '\0'; /* keep 0 terminated */ + } + + if (opt->name + && find_long_option (cvt->parser->long_opts, opt->name) < 0) + /* OPT can be used as a long option. */ + { + cvt->long_end->name = opt->name; + cvt->long_end->has_arg = + (real->arg + ? (real->flags & OPTION_ARG_OPTIONAL + ? optional_argument + : required_argument) + : no_argument); + cvt->long_end->flag = 0; + /* we add a disambiguating code to all the user's + values (which is removed before we actually call + the function to parse the value); this means that + the user loses use of the high 8 bits in all his + values (the sign of the lower bits is preserved + however)... */ + cvt->long_end->val = + ((opt->key | real->key) & USER_MASK) + + (((group - cvt->parser->groups) + 1) << USER_BITS); + + /* Keep the LONG_OPTS list terminated. */ + (++cvt->long_end)->name = NULL; + } + } + } + + group->parser = argp->parser; + group->argp = argp; + group->short_end = cvt->short_end; + group->args_processed = 0; + group->parent = parent; + group->parent_index = parent_index; + group->input = 0; + group->hook = 0; + group->child_inputs = 0; + + if (children) + /* Assign GROUP's CHILD_INPUTS field some space from + CVT->child_inputs_end.*/ + { + unsigned num_children = 0; + while (children[num_children].argp) + num_children++; + group->child_inputs = cvt->child_inputs_end; + cvt->child_inputs_end += num_children; + } + + parent = group++; + } + else + parent = 0; + + if (children) + { + unsigned index = 0; + while (children->argp) + group = + convert_options (children++->argp, parent, index++, group, cvt); + } + + return group; +} + +/* Find the merged set of getopt options, with keys appropiately prefixed. */ +static void +parser_convert (struct parser *parser, const struct argp *argp, int flags) +{ + struct parser_convert_state cvt; + + cvt.parser = parser; + cvt.short_end = parser->short_opts; + cvt.long_end = parser->long_opts; + cvt.child_inputs_end = parser->child_inputs; + + if (flags & ARGP_IN_ORDER) + *cvt.short_end++ = '-'; + else if (flags & ARGP_NO_ARGS) + *cvt.short_end++ = '+'; + *cvt.short_end = '\0'; + + cvt.long_end->name = NULL; + + parser->argp = argp; + + if (argp) + parser->egroup = convert_options (argp, 0, 0, parser->groups, &cvt); + else + parser->egroup = parser->groups; /* No parsers at all! */ +} + +/* Lengths of various parser fields which we will allocated. */ +struct parser_sizes +{ + size_t short_len; /* Getopt short options string. */ + size_t long_len; /* Getopt long options vector. */ + size_t num_groups; /* Group structures we allocate. */ + size_t num_child_inputs; /* Child input slots. */ +}; + +/* For ARGP, increments the NUM_GROUPS field in SZS by the total number of + argp structures descended from it, and the SHORT_LEN & LONG_LEN fields by + the maximum lengths of the resulting merged getopt short options string and + long-options array, respectively. */ +static void +calc_sizes (const struct argp *argp, struct parser_sizes *szs) +{ + const struct argp_child *child = argp->children; + const struct argp_option *opt = argp->options; + + if (opt || argp->parser) + { + szs->num_groups++; + if (opt) + { + int num_opts = 0; + while (!__option_is_end (opt++)) + num_opts++; + szs->short_len += num_opts * 3; /* opt + up to 2 `:'s */ + szs->long_len += num_opts; + } + } + + if (child) + while (child->argp) + { + calc_sizes ((child++)->argp, szs); + szs->num_child_inputs++; + } +} + +/* Initializes PARSER to parse ARGP in a manner described by FLAGS. */ +static error_t +parser_init (struct parser *parser, const struct argp *argp, + int argc, char **argv, int flags, void *input) +{ + error_t err = 0; + struct group *group; + struct parser_sizes szs; + + szs.short_len = (flags & ARGP_NO_ARGS) ? 0 : 1; + szs.long_len = 0; + szs.num_groups = 0; + szs.num_child_inputs = 0; + + if (argp) + calc_sizes (argp, &szs); + + /* Lengths of the various bits of storage used by PARSER. */ +#define GLEN (szs.num_groups + 1) * sizeof (struct group) +#define CLEN (szs.num_child_inputs * sizeof (void *)) +#define LLEN ((szs.long_len + 1) * sizeof (struct option)) +#define SLEN (szs.short_len + 1) + + parser->storage = malloc (GLEN + CLEN + LLEN + SLEN); + if (! parser->storage) + return ENOMEM; + + parser->groups = parser->storage; + parser->child_inputs = parser->storage + GLEN; + parser->long_opts = parser->storage + GLEN + CLEN; + parser->short_opts = parser->storage + GLEN + CLEN + LLEN; + + memset (parser->child_inputs, 0, szs.num_child_inputs * sizeof (void *)); + parser_convert (parser, argp, flags); + + memset (&parser->state, 0, sizeof (struct argp_state)); + parser->state.root_argp = parser->argp; + parser->state.argc = argc; + parser->state.argv = argv; + parser->state.flags = flags; + parser->state.err_stream = stderr; + parser->state.out_stream = stdout; + parser->state.next = 0; /* Tell getopt to initialize. */ + parser->state.pstate = parser; + + parser->try_getopt = 1; + + /* Call each parser for the first time, giving it a chance to propagate + values to child parsers. */ + if (parser->groups < parser->egroup) + parser->groups->input = input; + for (group = parser->groups; + group < parser->egroup && (!err || err == EBADKEY); + group++) + { + if (group->parent) + /* If a child parser, get the initial input value from the parent. */ + group->input = group->parent->child_inputs[group->parent_index]; + + if (!group->parser + && group->argp->children && group->argp->children->argp) + /* For the special case where no parsing function is supplied for an + argp, propagate its input to its first child, if any (this just + makes very simple wrapper argps more convenient). */ + group->child_inputs[0] = group->input; + + err = group_parse (group, &parser->state, ARGP_KEY_INIT, 0); + } + if (err == EBADKEY) + err = 0; /* Some parser didn't understand. */ + + if (err) + return err; + + /* Getopt is (currently) non-reentrant. */ + LOCK_GETOPT; + + if (parser->state.flags & ARGP_NO_ERRS) + { + opterr = 0; + if (parser->state.flags & ARGP_PARSE_ARGV0) + /* getopt always skips ARGV[0], so we have to fake it out. As long + as OPTERR is 0, then it shouldn't actually try to access it. */ + parser->state.argv--, parser->state.argc++; + } + else + opterr = 1; /* Print error messages. */ + + if (parser->state.argv == argv && argv[0]) + /* There's an argv[0]; use it for messages. */ + { + char *short_name = strrchr (argv[0], '/'); + parser->state.name = short_name ? short_name + 1 : argv[0]; + } + else + parser->state.name = program_invocation_short_name; + + return 0; +} + +/* Free any storage consumed by PARSER (but not PARSER itself). */ +static error_t +parser_finalize (struct parser *parser, + error_t err, int arg_ebadkey, int *end_index) +{ + struct group *group; + + UNLOCK_GETOPT; + + if (err == EBADKEY && arg_ebadkey) + /* Suppress errors generated by unparsed arguments. */ + err = 0; + + if (! err) + { + if (parser->state.next == parser->state.argc) + /* We successfully parsed all arguments! Call all the parsers again, + just a few more times... */ + { + for (group = parser->groups; + group < parser->egroup && (!err || err==EBADKEY); + group++) + if (group->args_processed == 0) + err = group_parse (group, &parser->state, ARGP_KEY_NO_ARGS, 0); + for (group = parser->egroup - 1; + group >= parser->groups && (!err || err==EBADKEY); + group--) + err = group_parse (group, &parser->state, ARGP_KEY_END, 0); + + if (err == EBADKEY) + err = 0; /* Some parser didn't understand. */ + + /* Tell the user that all arguments are parsed. */ + if (end_index) + *end_index = parser->state.next; + } + else if (end_index) + /* Return any remaining arguments to the user. */ + *end_index = parser->state.next; + else + /* No way to return the remaining arguments, they must be bogus. */ + { + if (!(parser->state.flags & ARGP_NO_ERRS) + && parser->state.err_stream) + fprintf (parser->state.err_stream, + dgettext (parser->argp->argp_domain, + "%s: Too many arguments\n"), + parser->state.name); + err = EBADKEY; + } + } + + /* Okay, we're all done, with either an error or success; call the parsers + to indicate which one. */ + + if (err) + { + /* Maybe print an error message. */ + if (err == EBADKEY) + /* An appropriate message describing what the error was should have + been printed earlier. */ + __argp_state_help (&parser->state, parser->state.err_stream, + ARGP_HELP_STD_ERR); + + /* Since we didn't exit, give each parser an error indication. */ + for (group = parser->groups; group < parser->egroup; group++) + group_parse (group, &parser->state, ARGP_KEY_ERROR, 0); + } + else + /* Notify parsers of success, and propagate back values from parsers. */ + { + /* We pass over the groups in reverse order so that child groups are + given a chance to do there processing before passing back a value to + the parent. */ + for (group = parser->egroup - 1 + ; group >= parser->groups && (!err || err == EBADKEY) + ; group--) + err = group_parse (group, &parser->state, ARGP_KEY_SUCCESS, 0); + if (err == EBADKEY) + err = 0; /* Some parser didn't understand. */ + } + + /* Call parsers once more, to do any final cleanup. Errors are ignored. */ + for (group = parser->egroup - 1; group >= parser->groups; group--) + group_parse (group, &parser->state, ARGP_KEY_FINI, 0); + + if (err == EBADKEY) + err = EINVAL; + + free (parser->storage); + + return err; +} + +/* Call the user parsers to parse the non-option argument VAL, at the current + position, returning any error. The state NEXT pointer is assumed to have + been adjusted (by getopt) to point after this argument; this function will + adjust it correctly to reflect however many args actually end up being + consumed. */ +static error_t +parser_parse_arg (struct parser *parser, char *val) +{ + /* Save the starting value of NEXT, first adjusting it so that the arg + we're parsing is again the front of the arg vector. */ + int index = --parser->state.next; + error_t err = EBADKEY; + struct group *group; + int key = 0; /* Which of ARGP_KEY_ARG[S] we used. */ + + /* Try to parse the argument in each parser. */ + for (group = parser->groups + ; group < parser->egroup && err == EBADKEY + ; group++) + { + parser->state.next++; /* For ARGP_KEY_ARG, consume the arg. */ + key = ARGP_KEY_ARG; + err = group_parse (group, &parser->state, key, val); + + if (err == EBADKEY) + /* This parser doesn't like ARGP_KEY_ARG; try ARGP_KEY_ARGS instead. */ + { + parser->state.next--; /* For ARGP_KEY_ARGS, put back the arg. */ + key = ARGP_KEY_ARGS; + err = group_parse (group, &parser->state, key, 0); + } + } + + if (! err) + { + if (key == ARGP_KEY_ARGS) + /* The default for ARGP_KEY_ARGS is to assume that if NEXT isn't + changed by the user, *all* arguments should be considered + consumed. */ + parser->state.next = parser->state.argc; + + if (parser->state.next > index) + /* Remember that we successfully processed a non-option + argument -- but only if the user hasn't gotten tricky and set + the clock back. */ + (--group)->args_processed += (parser->state.next - index); + else + /* The user wants to reparse some args, give getopt another try. */ + parser->try_getopt = 1; + } + + return err; +} + +/* Call the user parsers to parse the option OPT, with argument VAL, at the + current position, returning any error. */ +static error_t +parser_parse_opt (struct parser *parser, int opt, char *val) +{ + /* The group key encoded in the high bits; 0 for short opts or + group_number + 1 for long opts. */ + int group_key = opt >> USER_BITS; + error_t err = EBADKEY; + + if (group_key == 0) + /* A short option. By comparing OPT's position in SHORT_OPTS to the + various starting positions in each group's SHORT_END field, we can + determine which group OPT came from. */ + { + struct group *group; + char *short_index = strchr (parser->short_opts, opt); + + if (short_index) + for (group = parser->groups; group < parser->egroup; group++) + if (group->short_end > short_index) + { + err = group_parse (group, &parser->state, opt, optarg); + break; + } + } + else + /* A long option. We use shifts instead of masking for extracting + the user value in order to preserve the sign. */ + err = + group_parse (&parser->groups[group_key - 1], &parser->state, + (opt << GROUP_BITS) >> GROUP_BITS, optarg); + + if (err == EBADKEY) + /* At least currently, an option not recognized is an error in the + parser, because we pre-compute which parser is supposed to deal + with each option. */ + { + static const char bad_key_err[] = + N_("(PROGRAM ERROR) Option should have been recognized!?"); + if (group_key == 0) + __argp_error (&parser->state, "-%c: %s", opt, + dgettext (parser->argp->argp_domain, bad_key_err)); + else + { + struct option *long_opt = parser->long_opts; + while (long_opt->val != opt && long_opt->name) + long_opt++; + __argp_error (&parser->state, "--%s: %s", + long_opt->name ? long_opt->name : "???", + dgettext (parser->argp->argp_domain, bad_key_err)); + } + } + + return err; +} + +/* Parse the next argument in PARSER (as indicated by PARSER->state.next). + Any error from the parsers is returned, and *ARGP_EBADKEY indicates + whether a value of EBADKEY is due to an unrecognized argument (which is + generally not fatal). */ +static error_t +parser_parse_next (struct parser *parser, int *arg_ebadkey) +{ + int opt; + error_t err = 0; + + if (parser->state.quoted && parser->state.next < parser->state.quoted) + /* The next argument pointer has been moved to before the quoted + region, so pretend we never saw the quoting `--', and give getopt + another chance. If the user hasn't removed it, getopt will just + process it again. */ + parser->state.quoted = 0; + + if (parser->try_getopt && !parser->state.quoted) + /* Give getopt a chance to parse this. */ + { + optind = parser->state.next; /* Put it back in OPTIND for getopt. */ + optopt = KEY_END; /* Distinguish KEY_ERR from a real option. */ + if (parser->state.flags & ARGP_LONG_ONLY) + opt = getopt_long_only (parser->state.argc, parser->state.argv, + parser->short_opts, parser->long_opts, 0); + else + opt = getopt_long (parser->state.argc, parser->state.argv, + parser->short_opts, parser->long_opts, 0); + parser->state.next = optind; /* And see what getopt did. */ + + if (opt == KEY_END) + /* Getopt says there are no more options, so stop using + getopt; we'll continue if necessary on our own. */ + { + parser->try_getopt = 0; + if (parser->state.next > 1 + && strcmp (parser->state.argv[parser->state.next - 1], QUOTE) + == 0) + /* Not only is this the end of the options, but it's a + `quoted' region, which may have args that *look* like + options, so we definitely shouldn't try to use getopt past + here, whatever happens. */ + parser->state.quoted = parser->state.next; + } + else if (opt == KEY_ERR && optopt != KEY_END) + /* KEY_ERR can have the same value as a valid user short + option, but in the case of a real error, getopt sets OPTOPT + to the offending character, which can never be KEY_END. */ + { + *arg_ebadkey = 0; + return EBADKEY; + } + } + else + opt = KEY_END; + + if (opt == KEY_END) + { + /* We're past what getopt considers the options. */ + if (parser->state.next >= parser->state.argc + || (parser->state.flags & ARGP_NO_ARGS)) + /* Indicate that we're done. */ + { + *arg_ebadkey = 1; + return EBADKEY; + } + else + /* A non-option arg; simulate what getopt might have done. */ + { + opt = KEY_ARG; + optarg = parser->state.argv[parser->state.next++]; + } + } + + if (opt == KEY_ARG) + /* A non-option argument; try each parser in turn. */ + err = parser_parse_arg (parser, optarg); + else + err = parser_parse_opt (parser, opt, optarg); + + if (err == EBADKEY) + *arg_ebadkey = (opt == KEY_END || opt == KEY_ARG); + + return err; +} + +/* Parse the options strings in ARGC & ARGV according to the argp in ARGP. + FLAGS is one of the ARGP_ flags above. If END_INDEX is non-NULL, the + index in ARGV of the first unparsed option is returned in it. If an + unknown option is present, EINVAL is returned; if some parser routine + returned a non-zero value, it is returned; otherwise 0 is returned. */ +error_t +__argp_parse (const struct argp *argp, int argc, char **argv, unsigned flags, + int *end_index, void *input) +{ + error_t err; + struct parser parser; + + /* If true, then err == EBADKEY is a result of a non-option argument failing + to be parsed (which in some cases isn't actually an error). */ + int arg_ebadkey = 0; + + // Forward declare the struct pointers since malloc is being used instead of alloca + struct argp_child *child; + struct argp *top_argp; + if (! (flags & ARGP_NO_HELP)) + /* Add our own options. */ + { + // Originally alloca was used but since newlib does not implement that + // we are switching over to malloc which is a lot slower + child = (struct argp_child *) malloc (4 * sizeof (struct argp_child)); + top_argp = (struct argp *) malloc (sizeof (struct argp)); + + /* TOP_ARGP has no options, it just serves to group the user & default + argps. */ + memset (top_argp, 0, sizeof (*top_argp)); + top_argp->children = child; + + memset (child, 0, 4 * sizeof (struct argp_child)); + + if (argp) + (child++)->argp = argp; + (child++)->argp = &argp_default_argp; + if (argp_program_version || argp_program_version_hook) + (child++)->argp = &argp_version_argp; + child->argp = 0; + + argp = top_argp; + } + + /* Construct a parser for these arguments. */ + err = parser_init (&parser, argp, argc, argv, flags, input); + + if (! err) + /* Parse! */ + { + while (! err) + err = parser_parse_next (&parser, &arg_ebadkey); + err = parser_finalize (&parser, err, arg_ebadkey, end_index); + } + + // malloc was used to allocate space for the argp_child and argp structs + // alloca automatically freed the memory when the function returned + // but since we are using malloc, we need to explicitly free it to + // avoid memory leaks + free(child); + free(top_argp); + + return err; +} +#ifdef weak_alias +weak_alias (__argp_parse, argp_parse) +#endif + +/* Return the input field for ARGP in the parser corresponding to STATE; used + by the help routines. */ +void * +__argp_input (const struct argp *argp, const struct argp_state *state) +{ + if (state) + { + struct group *group; + struct parser *parser = state->pstate; + + for (group = parser->groups; group < parser->egroup; group++) + if (group->argp == argp) + return group->input; + } + + return 0; +} +#ifdef weak_alias +weak_alias (__argp_input, _argp_input) +#endif diff --git a/libraries/platforms/dromajo-vcs/software/src/argp/argp-pv.c b/libraries/platforms/dromajo-vcs/software/src/argp/argp-pv.c new file mode 100644 index 000000000..5987956a9 --- /dev/null +++ b/libraries/platforms/dromajo-vcs/software/src/argp/argp-pv.c @@ -0,0 +1,25 @@ +/* Default definition for ARGP_PROGRAM_VERSION. + Copyright (C) 1996, 1997, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Written by Miles Bader . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* If set by the user program to a non-zero value, then a default option + --version is added (unless the ARGP_NO_HELP flag is used), which will + print this this string followed by a newline and exit (unless the + ARGP_NO_EXIT flag is used). Overridden by ARGP_PROGRAM_VERSION_HOOK. */ +const char *argp_program_version; diff --git a/libraries/platforms/dromajo-vcs/software/src/argp/argp-pvh.c b/libraries/platforms/dromajo-vcs/software/src/argp/argp-pvh.c new file mode 100644 index 000000000..8a8fd309d --- /dev/null +++ b/libraries/platforms/dromajo-vcs/software/src/argp/argp-pvh.c @@ -0,0 +1,32 @@ +/* Default definition for ARGP_PROGRAM_VERSION_HOOK. + Copyright (C) 1996, 1997, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Written by Miles Bader . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +/* If set by the user program to a non-zero value, then a default option + --version is added (unless the ARGP_NO_HELP flag is used), which calls + this function with a stream to print the version to and a pointer to the + current parsing state, and then exits (unless the ARGP_NO_EXIT flag is + used). This variable takes precedent over ARGP_PROGRAM_VERSION. */ +void (*argp_program_version_hook) (FILE *stream, struct argp_state *state); diff --git a/libraries/platforms/dromajo-vcs/software/src/argp/argp-xinl.c b/libraries/platforms/dromajo-vcs/software/src/argp/argp-xinl.c new file mode 100644 index 000000000..644836d30 --- /dev/null +++ b/libraries/platforms/dromajo-vcs/software/src/argp/argp-xinl.c @@ -0,0 +1,42 @@ +/* Real definitions for extern inline functions in argp.h + Copyright (C) 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Written by Miles Bader . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#ifndef __USE_EXTERN_INLINES +# define __USE_EXTERN_INLINES 1 +#endif +#define ARGP_EI +#undef __OPTIMIZE__ +#define __OPTIMIZE__ 1 +#include + +/* Add weak aliases. */ +#if _LIBC - 0 && defined (weak_alias) + +weak_alias (__argp_usage, argp_usage) +weak_alias (__option_is_short, _option_is_short) +weak_alias (__option_is_end, _option_is_end) + +#endif From 03f70e6f4b6f25598c2ec8e98e5e900271e7536e Mon Sep 17 00:00:00 2001 From: sripathi-muralitharan Date: Sun, 25 Apr 2021 12:35:09 -0700 Subject: [PATCH 14/70] Adding BlackParrot specific files * Utilities can be later modified to meaningfully terminate a program * Start code will be modified to load the BlackParrot arguments --- .../dromajo-vcs/software/include/bp_utils.h | 38 +++++++++ .../dromajo-vcs/software/src/bp_utils.c | 63 ++++++++++++++ .../platforms/dromajo-vcs/software/src/crt0.S | 85 +++++++++++++++++++ 3 files changed, 186 insertions(+) create mode 100644 libraries/platforms/dromajo-vcs/software/include/bp_utils.h create mode 100644 libraries/platforms/dromajo-vcs/software/src/bp_utils.c create mode 100644 libraries/platforms/dromajo-vcs/software/src/crt0.S diff --git a/libraries/platforms/dromajo-vcs/software/include/bp_utils.h b/libraries/platforms/dromajo-vcs/software/include/bp_utils.h new file mode 100644 index 000000000..025d7b305 --- /dev/null +++ b/libraries/platforms/dromajo-vcs/software/include/bp_utils.h @@ -0,0 +1,38 @@ +// BlackParrot utilities header file +// Note: This file is included here instead of the existing code +// in the perch library in order to allow for easy changes to the finish code +// in the future + +#ifndef BP_UTILS_H +#define BP_UTILS_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include "bsg_newlib_intf.h" + +#define HOST_DEV_BASE_ADDR ((char *)(0x00100000)) +#define GETCHAR_BASE_ADDR ((char *)(HOST_DEV_BASE_ADDR+0x0000)) +#define PUTCHAR_BASE_ADDR ((char *)(HOST_DEV_BASE_ADDR+0x1000)) +#define FINISH_BASE_ADDR ((char *)(HOST_DEV_BASE_ADDR+0x2000)) + + +uint64_t bp_get_hart(); + +void bp_barrier_end(volatile uint64_t *barrier_address, uint64_t total_num_cores); + +void bp_hprint(uint8_t hex); + +void bp_cprint(uint8_t ch); + +void bp_finish(uint8_t code); + +#define BP_CFG_BASE_ADDR ((char *)(0x00200000)) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libraries/platforms/dromajo-vcs/software/src/bp_utils.c b/libraries/platforms/dromajo-vcs/software/src/bp_utils.c new file mode 100644 index 000000000..f6bd2601a --- /dev/null +++ b/libraries/platforms/dromajo-vcs/software/src/bp_utils.c @@ -0,0 +1,63 @@ +// BlackParrot utilities +// Note: This file is compiled instead of the existing code in the perch +// library in order to allow for easy changes to the finish code in the future + +#include +#include "bp_utils.h" + +uint64_t bp_get_hart() { + uint64_t core_id; + __asm__ volatile("csrr %0, mhartid": "=r"(core_id): :); + return core_id; +} + +void bp_barrier_end(volatile uint64_t * barrier_address, uint64_t total_num_cores) { + uint64_t core_id; + uint64_t atomic_inc = 1; + uint64_t atomic_result; + __asm__ volatile("csrr %0, mhartid": "=r"(core_id): :); + + /* if we're not core 0, increment the barrier and then just loop */ + if (core_id != 0) { + __asm__ volatile("amoadd.d %0, %2, (%1)": "=r"(atomic_result) + : "r"(barrier_address), "r"(atomic_inc) + :); + while (1) { } + } + /* + * if we're core 0, increment the barrier as well and then test if the + * barrier is equal to the total number of cores + */ + else { + uint64_t finish_value = 0; + __asm__ volatile("amoadd.d %0, %2, (%1)": "=r"(atomic_result) + : "r"(barrier_address), "r"(atomic_inc) + :); + while(*barrier_address < total_num_cores) { + + + } + bp_finish(0); + } +} + +void bp_finish(uint8_t code) { + uint64_t core_id; + + __asm__ volatile("csrr %0, mhartid": "=r"(core_id): :); + + *(FINISH_BASE_ADDR+core_id*8) = code; +} + +void bp_hprint(uint8_t hex) { + + *(PUTCHAR_BASE_ADDR) = ('0' + hex); +} + +void bp_cprint(uint8_t ch) { + + *(PUTCHAR_BASE_ADDR) = ch; +} + + + diff --git a/libraries/platforms/dromajo-vcs/software/src/crt0.S b/libraries/platforms/dromajo-vcs/software/src/crt0.S new file mode 100644 index 000000000..919ccbb41 --- /dev/null +++ b/libraries/platforms/dromajo-vcs/software/src/crt0.S @@ -0,0 +1,85 @@ +# Start code +# This assembly file mimics the BlackParrot perch library start.S +# with minor modifications to allow arguments to be loaded into the +# corresponding registers for main + +.section ".text.init" +.globl _start +.type _start, @function +_start: +# Setup the global pointer +.option push +.option norelax + la gp, _gp +.option pop + +# Setup stack pointers. Stacks start at 0x800F0000 +# We then subtract off 8K*coreID. The top 4K is for the core emulation stack +# the lower 4K is for the program TODO: Maybe larger stack value? + li sp, 0x800F0000 + csrr t0, mhartid + slli t0, t0, 13 + sub sp, sp, t0 + +# Save the stack pointer to mscratch, so it can be used on first trap entry + csrw mscratch, sp +# Get 4K and subtract it off to get the program stack pointer + li t0, 1 + slli t0, t0, 12 + sub sp, sp, t0 + +# Setup mtvec + la t0, bp_mtvec_handler + csrw mtvec, t0 + +# Enable FPU + li t0, 0x00006000 & (0x00006000 >> 1); + csrs mstatus, t0; + csrwi fcsr, 0 + +# 0 all registers except sp and gp + addi x1, x0, 0 + addi x4, x0, 0 + addi x5, x0, 0 + addi x6, x0, 0 + addi x7, x0, 0 + addi x8, x0, 0 + addi x9, x0, 0 + addi x10, x0, 0 + addi x11, x0, 0 + addi x12, x0, 0 + addi x13, x0, 0 + addi x14, x0, 0 + addi x15, x0, 0 + addi x16, x0, 0 + addi x17, x0, 0 + addi x18, x0, 0 + addi x19, x0, 0 + addi x20, x0, 0 + addi x21, x0, 0 + addi x22, x0, 0 + addi x23, x0, 0 + addi x24, x0, 0 + addi x25, x0, 0 + addi x26, x0, 0 + addi x27, x0, 0 + addi x28, x0, 0 + addi x29, x0, 0 + addi x30, x0, 0 + addi x31, x0, 0 + + la a0, __libc_fini_array # Register global termination functions + call atexit # to be called upon exit + call __libc_init_array # Run global initialization functions + +#ifdef _DRAMFS + call dramfs_init +#endif + + call main + tail bp_finish + +# Loop if we pass exit +loop: + nop + j loop From 0e49e39c14a6f1a1348a926809b2bd61a4c766e2 Mon Sep 17 00:00:00 2001 From: sripathi-muralitharan Date: Sun, 25 Apr 2021 12:38:01 -0700 Subject: [PATCH 15/70] libraries.mk * This file controls how the CUDA-lite library is compiled * For Dromajo/BlackParrot, the bsg_manycore_runtme library * compiles BlackParrot firmware * is a statically linked library * This library is linked with the test program to generate the final * binary that runs on Dromajo/BlackParrot --- libraries/libraries.mk | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/libraries/libraries.mk b/libraries/libraries.mk index ebc756fa3..0ecd0377f 100644 --- a/libraries/libraries.mk +++ b/libraries/libraries.mk @@ -129,15 +129,27 @@ $(LIB_STRICT_OBJECTS): CXXFLAGS += -Wno-unused-variable $(LIB_STRICT_OBJECTS): CXXFLAGS += -Wno-unused-function $(LIB_STRICT_OBJECTS): CXXFLAGS += -Wno-unused-but-set-variable +ifdef __NEWLIB +LIB_OBJECTS += $(patsubst %S,%o,$(LIB_SSOURCES)) +$(BSG_PLATFORM_PATH)/libbsg_manycore_runtime.so.1.0: $(LIB_OBJECTS) + $(RV_AR) -rcs $@ $^ +else $(BSG_PLATFORM_PATH)/libbsg_manycore_runtime.so.1.0: LD = $(CXX) $(BSG_PLATFORM_PATH)/libbsg_manycore_runtime.so.1.0: $(LIB_OBJECTS) $(LD) -shared -Wl,-soname,$(basename $(notdir $@)) -o $@ $^ $(LDFLAGS) +endif $(BSG_PLATFORM_PATH)/libbsgmc_cuda_legacy_pod_repl.so.1.0: LDFLAGS := $(BSG_PLATFORM_PATH)/libbsgmc_cuda_legacy_pod_repl.so.1.0: INCLUDES := + +ifdef __NEWLIB +$(BSG_PLATFORM_PATH)/libbsgmc_cuda_legacy_pod_repl.so.1.0: $(LIB_OBJECTS_CUDA_POD_REPL) + $(RV_AR) -rcs $@ $^ +else $(BSG_PLATFORM_PATH)/libbsgmc_cuda_legacy_pod_repl.so.1.0: LD = $(CXX) $(BSG_PLATFORM_PATH)/libbsgmc_cuda_legacy_pod_repl.so.1.0: $(LIB_OBJECTS_CUDA_POD_REPL) $(LD) -shared -Wl,-soname,$(basename $(notdir $@)) -o $@ $^ $(LDFLAGS) +endif $(BSG_PLATFORM_PATH)/libbsg_manycore_regression.so.1.0: LDFLAGS := $(BSG_PLATFORM_PATH)/libbsg_manycore_regression.so.1.0: INCLUDES := @@ -148,6 +160,7 @@ $(BSG_PLATFORM_PATH)/libbsg_manycore_regression.so.1.0: $(LIB_OBJECTS_REGRESSION .PHONY: libraries.clean libraries.clean: rm -f $(LIB_OBJECTS) + rm -f $(LIB_OBJECTS_CUDA_POD_REPL) rm -f $(BSG_PLATFORM_PATH)/libbsg_manycore_runtime.so.1.0 rm -f $(BSG_PLATFORM_PATH)/libbsgmc_cuda_legacy_pod_repl.so.1.0 rm -f $(BSG_PLATFORM_PATH)/libbsg_manycore_regression.so.1.0 From 0aa312bf038ad6a0271e61dbc647ad5ce4ab96a4 Mon Sep 17 00:00:00 2001 From: sripathi-muralitharan Date: Sun, 25 Apr 2021 16:34:16 -0700 Subject: [PATCH 16/70] Moving manycore read and write functions to bp_utils --- .../dromajo-vcs/bsg_manycore_platform.cpp | 114 +----------------- .../dromajo-vcs/software/include/bp_utils.h | 16 +++ .../dromajo-vcs/software/src/bp_utils.c | 91 +++++++++++++- 3 files changed, 110 insertions(+), 111 deletions(-) diff --git a/libraries/platforms/dromajo-vcs/bsg_manycore_platform.cpp b/libraries/platforms/dromajo-vcs/bsg_manycore_platform.cpp index 2f4669a8d..b7e5faee3 100644 --- a/libraries/platforms/dromajo-vcs/bsg_manycore_platform.cpp +++ b/libraries/platforms/dromajo-vcs/bsg_manycore_platform.cpp @@ -31,6 +31,7 @@ #include #include +#include /* these are convenience macros that are only good for one line prints */ #define manycore_pr_dbg(mc, fmt, ...) \ @@ -45,113 +46,6 @@ #define manycore_pr_info(mc, fmt, ...) \ bsg_pr_info("%s: " fmt, mc->name, ##__VA_ARGS__) -////////////////////////// RISC-V Host <--> Manycore API ////////////////////////// - -// Memory mapped addresses to interact with the manycore bridge -// BlackParrot writes to these addresses to interact with the manycore -// Manycore device base address -#define MC_BASE_ADDR 0x500000 -// BP --> Manycore Requests -#define BP_TO_MC_REQ_FIFO_ADDR 0x1000 -#define BP_TO_MC_REQ_CREDITS_ADDR 0x2000 -// Manycore --> BP Responses -#define MC_TO_BP_RESP_FIFO_ADDR 0x3000 -#define MC_TO_BP_RESP_ENTRIES_ADDR 0x4000 -// Manycore --> BP Requests -#define MC_TO_BP_REQ_FIFO_ADDR 0x5000 -#define MC_TO_BP_REQ_ENTRIES_ADDR 0x6000 - -/* - * Reads the manycore bridge for number of credits remaining in the endpoint - * @returns number of credits in the manycore bridge enddpoint - */ -int hb_mc_platform_get_credits() { - uint32_t *bp_to_mc_req_credits_addr = (uint32_t *) (MC_BASE_ADDR + BP_TO_MC_REQ_CREDITS_ADDR); - int credits = int(*bp_to_mc_req_credits_addr); - return credits; -} - -/* - * Writes a 128-bit manycore packet in 32-bit chunks to the manycore bridge FIFO - * @param[in] pkt --> Pointer to the manycore packet - */ -void hb_mc_platform_write_to_manycore_bridge(hb_mc_packet_t *pkt) { - int credits; - - // Wait till there is atleast 1 credit to send the write - do { - credits = hb_mc_platform_get_credits(); - } while (credits == 0); - - uint32_t *bp_to_mc_req_fifo_addr = (uint32_t *) (MC_BASE_ADDR + BP_TO_MC_REQ_FIFO_ADDR); - for(int i = 0; i < 4; i++) { - *bp_to_mc_req_fifo_addr = pkt->words[i]; - bp_to_mc_req_fifo_addr++; - } -} - -/* - * Reads the manycore bridge FIFOs in 32-bit chunks to form the 128-bit packet - * @param[in] pkt --> Pointer to the manycore packet - * @param[in] type --> Type of FIFO to read from - * @returns HB_MC_SUCCESS on success, HB_MC_FAIL if FIFO type is unknown - */ -int hb_mc_platform_read_from_manycore_bridge(hb_mc_packet_t *pkt, hb_mc_fifo_rx_t type) { - switch(type) { - case HB_MC_FIFO_RX_REQ: - { - // Check if the entries are full - uint32_t *mc_to_bp_req_entries_addr = (uint32_t *) (MC_BASE_ADDR + MC_TO_BP_REQ_ENTRIES_ADDR); - while(!(*mc_to_bp_req_entries_addr)) - ; - - // Read the value - uint32_t *mc_to_bp_req_fifo_addr = (uint32_t *) (MC_BASE_ADDR + MC_TO_BP_REQ_FIFO_ADDR); - uint32_t read_status = 0xFFFF; - for (int i = 0; i < 4; i++) { - pkt->words[i] = *mc_to_bp_req_fifo_addr; - read_status &= pkt->words[i]; - mc_to_bp_req_fifo_addr++; - } - - // If all packets are 0xFFFF --> there is something wrong - if (read_status == 0xFFFF) - return HB_MC_FAIL; - } - break; - case HB_MC_FIFO_RX_RSP: - { - // Check if the entries are full - uint32_t *mc_to_bp_resp_entries_addr = (uint32_t *) (MC_BASE_ADDR + MC_TO_BP_RESP_ENTRIES_ADDR); - while(!(*mc_to_bp_resp_entries_addr)) - ; - - // Read the value - uint32_t *mc_to_bp_resp_fifo_addr = (uint32_t *) (MC_BASE_ADDR + MC_TO_BP_RESP_FIFO_ADDR); - uint32_t read_status = 0xFFFF; - for (int i = 0; i < 4; i++) { - pkt->words[i] = *mc_to_bp_resp_fifo_addr; - read_status &= pkt->words[i]; - mc_to_bp_resp_fifo_addr++; - } - - // If all packets are 0xFFFF --> there is something wrong - if (read_status == 0xFFFF) - return HB_MC_FAIL; - } - break; - default: - { - bsg_pr_err("%s: Unknown packet type\n", __func__); - return HB_MC_FAIL; - } - break; - } - return HB_MC_SUCCESS; -} - -////////////////////////// Platform-Level API ////////////////////////// - typedef struct hb_mc_platform_t { hb_mc_manycore_id_t id; @@ -241,7 +135,7 @@ int hb_mc_platform_transmit(hb_mc_manycore_t *mc, hb_mc_packet_t *packet, hb_mc_ } // Write packet to the manycore bridge - hb_mc_platform_write_to_manycore_bridge(packet); + bp_hb_write_to_manycore_bridge(packet); return HB_MC_SUCCESS; } @@ -263,7 +157,7 @@ int hb_mc_platform_receive(hb_mc_manycore_t *mc, hb_mc_packet_t *packet, hb_mc_f return HB_MC_INVALID; } - int err = hb_mc_platform_read_from_manycore_bridge(packet, type); + int err = bp_hb_read_from_manycore_bridge(packet, type); if (err != 0) { @@ -316,7 +210,7 @@ int hb_mc_platform_fence(hb_mc_manycore_t *mc, long timeout) { do { - credits = hb_mc_platform_get_credits(); + credits = bp_hb_get_credits(); } while (!(credits == (int)max_credits)); return HB_MC_SUCCESS; diff --git a/libraries/platforms/dromajo-vcs/software/include/bp_utils.h b/libraries/platforms/dromajo-vcs/software/include/bp_utils.h index 025d7b305..24cb03381 100644 --- a/libraries/platforms/dromajo-vcs/software/include/bp_utils.h +++ b/libraries/platforms/dromajo-vcs/software/include/bp_utils.h @@ -12,12 +12,22 @@ extern "C" { #include #include "bsg_newlib_intf.h" +#include +// Memory mapped addresses to interact with the host #define HOST_DEV_BASE_ADDR ((char *)(0x00100000)) #define GETCHAR_BASE_ADDR ((char *)(HOST_DEV_BASE_ADDR+0x0000)) #define PUTCHAR_BASE_ADDR ((char *)(HOST_DEV_BASE_ADDR+0x1000)) #define FINISH_BASE_ADDR ((char *)(HOST_DEV_BASE_ADDR+0x2000)) +// Memory mapped addresses to interact with the manycore bridge +#define MC_BASE_ADDR 0x500000 +#define BP_TO_MC_REQ_FIFO_ADDR 0x1000 +#define BP_TO_MC_REQ_CREDITS_ADDR 0x2000 +#define MC_TO_BP_RESP_FIFO_ADDR 0x3000 +#define MC_TO_BP_RESP_ENTRIES_ADDR 0x4000 +#define MC_TO_BP_REQ_FIFO_ADDR 0x5000 +#define MC_TO_BP_REQ_ENTRIES_ADDR 0x6000 uint64_t bp_get_hart(); @@ -31,6 +41,12 @@ void bp_finish(uint8_t code); #define BP_CFG_BASE_ADDR ((char *)(0x00200000)) +int bp_hb_get_credits(); + +void bp_hb_write_to_manycore_bridge(hb_mc_packet_t *pkt); + +int bp_hb_read_from_manycore_bridge(hb_mc_packet_t *pkt, hb_mc_fifo_rx_t type); + #ifdef __cplusplus } #endif diff --git a/libraries/platforms/dromajo-vcs/software/src/bp_utils.c b/libraries/platforms/dromajo-vcs/software/src/bp_utils.c index f6bd2601a..54ea6219e 100644 --- a/libraries/platforms/dromajo-vcs/software/src/bp_utils.c +++ b/libraries/platforms/dromajo-vcs/software/src/bp_utils.c @@ -3,7 +3,9 @@ // library in order to allow for easy changes to the finish code in the future #include -#include "bp_utils.h" +#include +#include +#include uint64_t bp_get_hart() { uint64_t core_id; @@ -59,5 +61,92 @@ void bp_cprint(uint8_t ch) { *(PUTCHAR_BASE_ADDR) = ch; } +/* + * Reads the manycore bridge for number of credits remaining in the endpoint + * @returns number of credits in the manycore bridge enddpoint + */ +int bp_hb_get_credits() { + uint32_t *bp_to_mc_req_credits_addr = (uint32_t *) (MC_BASE_ADDR + BP_TO_MC_REQ_CREDITS_ADDR); + int credits = (int) *bp_to_mc_req_credits_addr; + return credits; +} + +/* + * Writes a 128-bit manycore packet in 32-bit chunks to the manycore bridge FIFO + * @param[in] pkt --> Pointer to the manycore packet + */ +void bp_hb_write_to_manycore_bridge(hb_mc_packet_t *pkt) { + int credits; + + // Wait till there is atleast 1 credit to send the write + do { + credits = bp_hb_get_credits(); + } while (credits == 0); + + uint32_t *bp_to_mc_req_fifo_addr = (uint32_t *) (MC_BASE_ADDR + BP_TO_MC_REQ_FIFO_ADDR); + for(int i = 0; i < 4; i++) { + *bp_to_mc_req_fifo_addr = pkt->words[i]; + bp_to_mc_req_fifo_addr++; + } +} +/* + * Reads the manycore bridge FIFOs in 32-bit chunks to form the 128-bit packet + * @param[in] pkt --> Pointer to the manycore packet + * @param[in] type --> Type of FIFO to read from + * @returns HB_MC_SUCCESS on success, HB_MC_FAIL if FIFO type is unknown + */ +int bp_hb_read_from_manycore_bridge(hb_mc_packet_t *pkt, hb_mc_fifo_rx_t type) { + switch(type) { + case HB_MC_FIFO_RX_REQ: + { + // Check if the entries are full + uint32_t *mc_to_bp_req_entries_addr = (uint32_t *) (MC_BASE_ADDR + MC_TO_BP_REQ_ENTRIES_ADDR); + while(!(*mc_to_bp_req_entries_addr)) + ; + + // Read the value + uint32_t *mc_to_bp_req_fifo_addr = (uint32_t *) (MC_BASE_ADDR + MC_TO_BP_REQ_FIFO_ADDR); + uint32_t read_status = 0xFFFF; + for (int i = 0; i < 4; i++) { + pkt->words[i] = *mc_to_bp_req_fifo_addr; + read_status &= pkt->words[i]; + mc_to_bp_req_fifo_addr++; + } + + // If all packets are 0xFFFF --> there is something wrong + if (read_status == 0xFFFF) + return HB_MC_FAIL; + } + break; + case HB_MC_FIFO_RX_RSP: + { + // Check if the entries are full + uint32_t *mc_to_bp_resp_entries_addr = (uint32_t *) (MC_BASE_ADDR + MC_TO_BP_RESP_ENTRIES_ADDR); + while(!(*mc_to_bp_resp_entries_addr)) + ; + + // Read the value + uint32_t *mc_to_bp_resp_fifo_addr = (uint32_t *) (MC_BASE_ADDR + MC_TO_BP_RESP_FIFO_ADDR); + uint32_t read_status = 0xFFFF; + for (int i = 0; i < 4; i++) { + pkt->words[i] = *mc_to_bp_resp_fifo_addr; + read_status &= pkt->words[i]; + mc_to_bp_resp_fifo_addr++; + } + + // If all packets are 0xFFFF --> there is something wrong + if (read_status == 0xFFFF) + return HB_MC_FAIL; + } + break; + default: + { + bsg_pr_err("%s: Unknown packet type\n", __func__); + return HB_MC_FAIL; + } + break; + } + return HB_MC_SUCCESS; +} From 9db8fd71196332b1095357a0786bb5b93f6a486f Mon Sep 17 00:00:00 2001 From: sripathi-muralitharan Date: Sun, 25 Apr 2021 16:35:02 -0700 Subject: [PATCH 17/70] Modifying start code to read arguments from the host --- libraries/platforms/dromajo-vcs/library.mk | 3 +- .../platforms/dromajo-vcs/software/src/args.c | 59 +++++++++++++++++++ .../platforms/dromajo-vcs/software/src/crt0.S | 6 ++ 3 files changed, 67 insertions(+), 1 deletion(-) create mode 100644 libraries/platforms/dromajo-vcs/software/src/args.c diff --git a/libraries/platforms/dromajo-vcs/library.mk b/libraries/platforms/dromajo-vcs/library.mk index 2b0aeddd6..759c1cff6 100644 --- a/libraries/platforms/dromajo-vcs/library.mk +++ b/libraries/platforms/dromajo-vcs/library.mk @@ -46,6 +46,7 @@ LIB_CSOURCES += $(BSG_PLATFORM_PATH)/software/src/argp/argp-pv.c LIB_CSOURCES += $(BSG_PLATFORM_PATH)/software/src/argp/argp-pvh.c LIB_CSOURCES += $(BSG_PLATFORM_PATH)/software/src/argp/argp-xinl.c LIB_CSOURCES += $(BSG_PLATFORM_PATH)/software/src/bp_utils.c +LIB_CSOURCES += $(BSG_PLATFORM_PATH)/software/src/args.c LIB_CSOURCES += $(BLACKPARROT_DIR)/sdk/perch/bsg_newlib_intf.c LIB_CSOURCES += $(BLACKPARROT_DIR)/sdk/perch/emulation.c @@ -139,6 +140,6 @@ platform.clean: rm -f $(BSG_PLATFORM_PATH)/libbsg_manycore_runtime.a.1 rm -f $(BSG_PLATFORM_PATH)/libbsgmc_cuda_legacy_pod_repl.a rm -f $(BSG_PLATFORM_PATH)/libbsgmc_cuda_legacy_pod_repl.a.1 - rm -f $(BSG_PLATFORM_PATH)/bsg_manycore_platform.so + rm -f $(BSG_PLATFORM_PATH)/libbsg_manycore_platform.so libraries.clean: platform.clean diff --git a/libraries/platforms/dromajo-vcs/software/src/args.c b/libraries/platforms/dromajo-vcs/software/src/args.c new file mode 100644 index 000000000..b9a6f73ed --- /dev/null +++ b/libraries/platforms/dromajo-vcs/software/src/args.c @@ -0,0 +1,59 @@ +/* + * args.c + * This file includes routines that queries the arguments from the x86 host and + * loads them into corresponding registers so that BlackParrot can access them + * The chain of events are: + * 1. VCS gets arguments from the +c_args options + * 2. The x86 simulator/host (bsg_manycore_simulator.cpp) accesses them via vcs_main() + * 3. A subset of these arguments are stored as arrays in the host + * 4. BlackParrot sends packets to load from this array and stores it in a global array + * 5. BlackParrot's start code loads the corresponding registers with the arguments + */ + +#include +#include +#include +#include + +int _argc; +char* _argv[10]; + +void __init_args(void) { + hb_mc_packet_t req_pkt; + hb_mc_packet_t *resp_pkt; + int count = 0; + + // Create a packet for the x86 host + // Host is at (0, 0) + req_pkt.request.x_dst = 0; + req_pkt.request.y_dst = 0; + // BlackParrot FIFOs are at (0, 1) + req_pkt.request.x_src = 0; + req_pkt.request.y_src = 1; + // Use addr 0 and upwards (in increments of 4 bytes) + // to talk to the x86 host for addresses + req_pkt.request.addr = 0; + req_pkt.request.op_v2 = HB_MC_PACKET_OP_REMOTE_LOAD; + req_pkt.request.payload = 0; + req_pkt.request.reg_id = 0; + + while(1) { + // Send packet + bp_hb_write_to_manycore_bridge(&req_pkt); + + // Wait for response + int err = bp_hb_read_from_manycore_bridge(resp_pkt, HB_MC_FIFO_RX_RSP); + if (err != 0) { + bp_finish(1); + } + + if (resp_pkt->response.data == 0xFFFFFFFF) + break; + else { + sprintf(_argv[count], "%d", resp_pkt->response.data); + count++; + } + req_pkt.request.addr += 4; + } + _argc = count; +} diff --git a/libraries/platforms/dromajo-vcs/software/src/crt0.S b/libraries/platforms/dromajo-vcs/software/src/crt0.S index 919ccbb41..1273e7edb 100644 --- a/libraries/platforms/dromajo-vcs/software/src/crt0.S +++ b/libraries/platforms/dromajo-vcs/software/src/crt0.S @@ -76,6 +76,12 @@ _start: call dramfs_init #endif +# Initialize the arguments + call __init_args + la a0, _argc + ld a0, 0(a0) + la a1, _argv + call main tail bp_finish From 23e958b358ce9f348a8467f5365442ca6b0ab5ff Mon Sep 17 00:00:00 2001 From: sripathi-muralitharan Date: Wed, 28 Apr 2021 18:09:10 -0700 Subject: [PATCH 18/70] Recompiling dromajo with -fPIC --- libraries/platforms/dromajo-vcs/library.mk | 5 +++-- libraries/platforms/dromajo-vcs/link.mk | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/libraries/platforms/dromajo-vcs/library.mk b/libraries/platforms/dromajo-vcs/library.mk index 759c1cff6..b45f2a5e2 100644 --- a/libraries/platforms/dromajo-vcs/library.mk +++ b/libraries/platforms/dromajo-vcs/library.mk @@ -96,16 +96,17 @@ DROMAJO_OBJECTS += $(patsubst %cpp,%o,$(DROMAJO_CXXSOURCES)) $(DROMAJO_OBJECTS): INCLUDES := -I$(DROMAJO_DIR)/include $(DROMAJO_OBJECTS): INCLUDES += -I$(BSG_PLATFORM_PATH)/software/include/dromajo -$(DROMAJO_OBJECTS): CXXFLAGS := -std=c++11 -fPIC -Wall -Wno-parentheses -MMD -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_GNU_SOURCE -D__STDC_FORMAT_MACROS -std=gnu++11 +$(DROMAJO_OBJECTS): CXXFLAGS := -std=c++11 -fPIC -Wall -Wno-parentheses -MMD -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_GNU_SOURCE -D__STDC_FORMAT_MACROS -DFIFO_MAX_ELEMENTS=$(BSG_MACHINE_IO_EP_CREDITS) -std=gnu++11 $(DROMAJO_OBJECTS): LDFLAGS := -fPIC +$(DROMAJO_OBJECTS): RV_CXX = $(CXX) PLATFORM_CXXSOURCES += $(BSG_PLATFORM_PATH)/bsg_manycore_simulator.cpp PLATFORM_OBJECTS += $(patsubst %cpp,%o,$(PLATFORM_CXXSOURCES)) PLATFORM_OBJECTS += $(patsubst %c,%o,$(PLATFORM_CSOURCES)) -$(PLATFORM_OBJECTS): $(DROMAJO_OBJECTS) $(PLATFORM_OBJECTS): INCLUDES := -I$(LIBRARIES_PATH) +$(PLATFORM_OBJECTS): INCLUDES += -I$(EXAMPLES_PATH) $(PLATFORM_OBJECTS): INCLUDES += -I$(LIBRARIES_PATH)/platforms/dpi-verilator $(PLATFORM_OBJECTS): INCLUDES += -I$(BSG_MACHINE_PATH)/notrace/ $(PLATFORM_OBJECTS): INCLUDES += -I$(BSG_PLATFORM_PATH) diff --git a/libraries/platforms/dromajo-vcs/link.mk b/libraries/platforms/dromajo-vcs/link.mk index e9d698c9d..a67e9dfff 100644 --- a/libraries/platforms/dromajo-vcs/link.mk +++ b/libraries/platforms/dromajo-vcs/link.mk @@ -117,6 +117,7 @@ $(BSG_PLATFORM_PATH)/test.riscv: LDFLAGS := -T$(BLACKPARROT_DIR)/sdk/linker/risc $(BSG_PLATFORM_PATH)/test.riscv: $(RV_CXX) -D_DRAMFS -o $@ $(BSG_PLATFORM_PATH)/software/src/crt0.o $(BSG_PLATFORM_PATH)/lfs.o $< $(LDFLAGS) +$(BSG_PLATFORM_PATH)/libbsg_manycore_platform.so: $(DROMAJO_OBJECTS) $(BSG_PLATFORM_PATH)/libbsg_manycore_platform.so: $(PLATFORM_OBJECTS) $(BSG_PLATFORM_PATH)/libbsg_manycore_platform.so: LDFLAGS := -fPIC $(BSG_PLATFORM_PATH)/libbsg_manycore_platform.so: From 0a8998ae6e0d4f3d5f61d8354f3fa7ae1dd73d5c Mon Sep 17 00:00:00 2001 From: sripathi-muralitharan Date: Wed, 28 Apr 2021 18:10:47 -0700 Subject: [PATCH 19/70] Updates to argument parsing, accounting for increased FIFO elements, fixing potential bugs --- .../dromajo-vcs/bsg_manycore_simulator.cpp | 94 +++++++++++++++---- .../platforms/dromajo-vcs/software/src/args.c | 72 ++++++++++---- 2 files changed, 130 insertions(+), 36 deletions(-) diff --git a/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.cpp b/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.cpp index ec350ae2a..32a170d55 100644 --- a/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.cpp +++ b/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.cpp @@ -36,6 +36,7 @@ #include #include +#include #include "dromajo_cosim.h" #include "dromajo_manycore.h" @@ -60,6 +61,12 @@ void dromajo_transmit_packet(); void dromajo_receive_packet(); void dromajo_set_credits(); +// Global variables to store arguments +int _argc; +char **_argv; +static int char_index = 0; +int idx = 0; + // DPI bsg_nonsynth_dpi::dpi_manycore *dpi; @@ -123,7 +130,7 @@ static int dpi_fifo_drain(bsg_nonsynth_dpi::dpi_manycore *dpi, err = dpi->rx_rsp(*pkt); break; default: - printf("Unknown FIFO type\n"); + printf("[BSG_ERROR] Unknown FIFO type\n"); return HB_MC_FAIL; } @@ -133,7 +140,7 @@ static int dpi_fifo_drain(bsg_nonsynth_dpi::dpi_manycore *dpi, && drains <= cap); if (drains != cap) - printf("Failed to drain FIFO\n"); + printf("[BSG_ERROR] Failed to drain FIFO\n"); return HB_MC_FAIL; return HB_MC_SUCCESS; @@ -207,7 +214,7 @@ bool dromajo_step() { } void dromajo_transmit_packet() { - hb_mc_packet_t *packet; + hb_mc_packet_t *packet, *host_resp_packet; int err; __m128i *pkt; @@ -222,15 +229,67 @@ void dromajo_transmit_packet() { packet->words[2] = host_to_mc_req_fifo->fifo[2].front(); packet->words[3] = host_to_mc_req_fifo->fifo[3].front(); - pkt = reinterpret_cast<__m128i *>(packet); + // Intercept packets that are for the host and generate appropriate responses + if ((packet->request.x_dst == 0) && (packet->request.y_dst == 0)) { + host_resp_packet->response.x_dst = packet->request.x_src; + host_resp_packet->response.y_dst = packet->request.y_src; + host_resp_packet->response.load_id = 0; + // If EPA maps to reading arguments + if (packet->request.op_v2 == HB_MC_PACKET_OP_REMOTE_LOAD) { + host_resp_packet->response.op = packet->request.op_v2; + idx = packet->request.addr; + uint32_t data = 0; + if (packet->request.addr >= 0 && packet->request.addr <= 0xFF) { + // Copy 4 bytes of the arguments + int num_characters = 0; + // If all arguments have been read, send this finish code + if (idx == _argc) { + data = 0xFFFFFFFF; + } + else { + for(int i = 0; i < 4; i++) { + if (_argv[idx][char_index] != '\0') { + data = (data << 8) | _argv[idx][char_index]; + num_characters++; + char_index++; + } + else { + data = (data << (4 - num_characters) * 8); + char_index = 0; + } + } + } + } + // Dromajo/BlackParrot wants to read the config + else if (packet->request.addr >= 0x100 && packet->request.addr <= 0x1FF) { + idx = packet->request.addr; + data = dpi->config[idx]; + } + else + printf("[BSG_ERROR] Host EPA not mapped\n"); + + host_resp_packet->response.data = data; + // Inject the response packet into manycore response FIFO + // Pop the request FIFO + for(int j = 0; j < 4; j++) { + mc_to_host_resp_fifo->fifo[j].push(host_resp_packet->words[j]); + host_to_mc_req_fifo->fifo[j].pop(); + } + } + else + printf("[BSG_ERROR] Operations other than loads are not implemented for the host\n"); + } + else { + pkt = reinterpret_cast<__m128i *>(packet); - // Try to transmit until you actually can - err = dpi->tx_req(*pkt); + // Try to transmit until you actually can + err = dpi->tx_req(*pkt); - // Drain the FIFO once transmitted - if (err == BSG_NONSYNTH_DPI_SUCCESS) { - for (int i = 0;i < 4; i++) - host_to_mc_req_fifo->fifo[i].pop(); + // Pop the FIFO once transmitted + if (err == BSG_NONSYNTH_DPI_SUCCESS) { + for (int i = 0;i < 4; i++) + host_to_mc_req_fifo->fifo[i].pop(); + } } } } @@ -244,11 +303,10 @@ void dromajo_receive_packet() { err = dpi->rx_req(*pkt); req_packet = reinterpret_cast(pkt); - // Push to host if valid and mark the FIFOs as full + // Push to host FIFO if valid if (err == BSG_NONSYNTH_DPI_SUCCESS) { for (int i = 0; i < 4; i++) { mc_to_host_req_fifo->fifo[i].push(req_packet->words[i]); - mc_to_host_req_fifo->full[i] = true; } } @@ -256,11 +314,10 @@ void dromajo_receive_packet() { err = dpi->rx_rsp(*pkt); resp_packet = reinterpret_cast(pkt); - // Push to host if valid and mark the FIFOs as full + // Push to host FIFO if valid if (err == BSG_NONSYNTH_DPI_SUCCESS) { for (int i = 0; i < 4; i++) { mc_to_host_resp_fifo->fifo[i].push(resp_packet->words[i]); - mc_to_host_resp_fifo->full[i] = true; } } } @@ -270,7 +327,7 @@ void dromajo_set_credits() { int res = dpi->get_credits(credits); if (res == BSG_NONSYNTH_DPI_SUCCESS) { if (credits < 0) - printf("Warning! Credit value is negative!\n"); + printf("[BSG_WARN] Warning! Credit value is negative!\n"); host_to_mc_req_fifo->credits = credits; } @@ -281,6 +338,9 @@ int vcs_main(int argc, char **argv) { #else int main(int argc, char **argv) { #endif + // Push command-line arguments into global variables + _argc = argc; + _argv = argv; // Initialize Dromajo dromajo_state = dromajo_init(); @@ -295,7 +355,7 @@ int main(int argc, char **argv) { err = dpi_init(dpi, hierarchy); if (err != HB_MC_SUCCESS) { delete sim; - printf("Failed to initialize DPI!\nExiting...\n"); + printf("[BSG_ERROR] Failed to initialize DPI!\nExiting...\n"); return -1; } @@ -304,7 +364,7 @@ int main(int argc, char **argv) { if (err != HB_MC_SUCCESS) { dpi_clean(dpi); delete sim; - printf("Failed to wait for reset!\nExiting...\n"); + printf("[BSG_ERROR] Failed to wait for reset!\nExiting...\n"); return -1; } diff --git a/libraries/platforms/dromajo-vcs/software/src/args.c b/libraries/platforms/dromajo-vcs/software/src/args.c index b9a6f73ed..b67437b2e 100644 --- a/libraries/platforms/dromajo-vcs/software/src/args.c +++ b/libraries/platforms/dromajo-vcs/software/src/args.c @@ -2,58 +2,92 @@ * args.c * This file includes routines that queries the arguments from the x86 host and * loads them into corresponding registers so that BlackParrot can access them - * The chain of events are: - * 1. VCS gets arguments from the +c_args options - * 2. The x86 simulator/host (bsg_manycore_simulator.cpp) accesses them via vcs_main() - * 3. A subset of these arguments are stored as arrays in the host - * 4. BlackParrot sends packets to load from this array and stores it in a global array - * 5. BlackParrot's start code loads the corresponding registers with the arguments */ #include #include #include +#include #include +// For now keep a limit on the number of arguments and the length of the argument +// string. +// TODO: Make this a pointer to a location on the stack int _argc; -char* _argv[10]; +char **_argv; +static int arg_index = 0; +static int char_index = -1; void __init_args(void) { - hb_mc_packet_t req_pkt; - hb_mc_packet_t *resp_pkt; - int count = 0; + hb_mc_packet_t req_pkt, resp_pkt; + + // Flat buffer to capture all the arguments contiguously + char buffer[3000]; + char *bufptr = buffer; // Create a packet for the x86 host // Host is at (0, 0) + // BlackParrot FIFOs are at (0, 1) req_pkt.request.x_dst = 0; req_pkt.request.y_dst = 0; - // BlackParrot FIFOs are at (0, 1) req_pkt.request.x_src = 0; req_pkt.request.y_src = 1; - // Use addr 0 and upwards (in increments of 4 bytes) - // to talk to the x86 host for addresses - req_pkt.request.addr = 0; req_pkt.request.op_v2 = HB_MC_PACKET_OP_REMOTE_LOAD; req_pkt.request.payload = 0; req_pkt.request.reg_id = 0; while(1) { + // Word address 0x00 to 0xFF tell the host to retrieve arguments + req_pkt.request.addr = arg_index; + // Send packet bp_hb_write_to_manycore_bridge(&req_pkt); // Wait for response - int err = bp_hb_read_from_manycore_bridge(resp_pkt, HB_MC_FIFO_RX_RSP); + int err = bp_hb_read_from_manycore_bridge(&resp_pkt, HB_MC_FIFO_RX_RSP); if (err != 0) { bp_finish(1); } - if (resp_pkt->response.data == 0xFFFFFFFF) + uint32_t data = resp_pkt.response.data; + if (data == 0xFFFFFFFF) { + bsg_pr_info("Argument retrieval complete!\n"); break; + } else { - sprintf(_argv[count], "%d", resp_pkt->response.data); + uint32_t mask = 0xFF000000; + uint8_t byte; + for(int i = 0; i < 4; i++) { + byte = data & mask; + if (byte != 0x0) { + buffer[char_index] = byte; + char_index++; + } + else { + buffer[char_index] = '\0'; + arg_index++; + char_index++; + break; + } + mask = mask >> 8; + } + } + } + _argc = arg_index; + + // Convert a flat buffer into a 2-D array of pointers as argparse + // expects it to be + char *args[_argc]; + char c = '\0'; + int count = 0; + while (count != _argc) { + if ((c == '\0') && (c != *bufptr)) { + args[count] = bufptr; count++; } - req_pkt.request.addr += 4; + c = *bufptr; + bufptr++; } - _argc = count; + _argv = args; + } From 2016fe72b89589104c49aa79b10b343838837b3a Mon Sep 17 00:00:00 2001 From: sripathi-muralitharan Date: Fri, 30 Apr 2021 09:44:12 -0700 Subject: [PATCH 20/70] Adds manycore regression platform header, VCS C argument parser and makefile updates --- libraries/libraries.mk | 7 + .../bsg_manycore_regression_platform.h | 39 ++ .../dromajo-vcs/bsg_manycore_simulator.cpp | 653 +++++++++++------- .../platforms/dromajo-vcs/compilation.mk | 1 + libraries/platforms/dromajo-vcs/library.mk | 16 +- libraries/platforms/dromajo-vcs/link.mk | 22 +- 6 files changed, 478 insertions(+), 260 deletions(-) create mode 100644 libraries/platforms/dromajo-vcs/bsg_manycore_regression_platform.h diff --git a/libraries/libraries.mk b/libraries/libraries.mk index 0ecd0377f..57ae73359 100644 --- a/libraries/libraries.mk +++ b/libraries/libraries.mk @@ -153,14 +153,21 @@ endif $(BSG_PLATFORM_PATH)/libbsg_manycore_regression.so.1.0: LDFLAGS := $(BSG_PLATFORM_PATH)/libbsg_manycore_regression.so.1.0: INCLUDES := + +ifdef __NEWLIB +$(BSG_PLATFORM_PATH)/libbsg_manycore_regression.so.1.0: $(LIB_OBJECTS_REGRESSION) + $(RV_AR) -rcs $@ $^ +else $(BSG_PLATFORM_PATH)/libbsg_manycore_regression.so.1.0: LD = $(CXX) $(BSG_PLATFORM_PATH)/libbsg_manycore_regression.so.1.0: $(LIB_OBJECTS_REGRESSION) $(LD) -shared -Wl,-soname,$(basename $(notdir $@)) -o $@ $^ $(LDFLAGS) +endif .PHONY: libraries.clean libraries.clean: rm -f $(LIB_OBJECTS) rm -f $(LIB_OBJECTS_CUDA_POD_REPL) + rm -f $(LIB_OBJECTS_REGRESSION) rm -f $(BSG_PLATFORM_PATH)/libbsg_manycore_runtime.so.1.0 rm -f $(BSG_PLATFORM_PATH)/libbsgmc_cuda_legacy_pod_repl.so.1.0 rm -f $(BSG_PLATFORM_PATH)/libbsg_manycore_regression.so.1.0 diff --git a/libraries/platforms/dromajo-vcs/bsg_manycore_regression_platform.h b/libraries/platforms/dromajo-vcs/bsg_manycore_regression_platform.h new file mode 100644 index 000000000..1c51de2f4 --- /dev/null +++ b/libraries/platforms/dromajo-vcs/bsg_manycore_regression_platform.h @@ -0,0 +1,39 @@ +#pragma once +#ifdef __cplusplus +extern "C" { +#endif + +// To make your program HammerBlade cross-platform compatible, +// define a function with the signature of "main", and then +// use this macro to mark it as the entry point of your program +// +// Example: +// +// int MyMain(int argc, char *argv[]) { +// /* your code here */ +// } +// declare_program_main("The name of your test", MyMain) +// +#define declare_program_main(test_name, name) \ + int main(int argc, char *argv[]) { \ + bsg_pr_test_info("Regression Test: %s\n", test_name); \ + int rc = name(argc, argv); \ + bsg_pr_test_pass_fail(rc == HB_MC_SUCCESS); \ + return rc; \ + } + +#ifdef __cplusplus +} +#endif + +// Some library functions need to be compiled in both RISC-V +// and x86. Makefile scripts don't recompile a target that was already +// executed even if the file does not exist. Therefore such functions +// are defined as macros here which are included in +// bsg_manycore_simulator.cpp +#define declare_hb_mc_get_bits \ + uint32_t hb_mc_get_bits (uint32_t val, uint32_t start, uint32_t size) { \ + uint32_t mask = ((1 << size) - 1) << start; \ + return ((val & mask) >> start); \ + } \ + diff --git a/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.cpp b/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.cpp index 32a170d55..0bf63616a 100644 --- a/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.cpp +++ b/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.cpp @@ -36,19 +36,22 @@ #include #include -#include -#include "dromajo_cosim.h" -#include "dromajo_manycore.h" +#include +#include #include #include +#include +#include +#include #include // We use __m128i so that we can pass a 128-bit type between Verilog // and C. #include +// DPI function to advance time extern "C" { void bsg_dpi_next(); } @@ -67,13 +70,18 @@ char **_argv; static int char_index = 0; int idx = 0; -// DPI +// DPI object bsg_nonsynth_dpi::dpi_manycore *dpi; +// Define invisible library functions +declare_hb_mc_get_bits + +////////////////////////////// SimulationWrapper functions ////////////////////////////// + SimulationWrapper::SimulationWrapper(){ - root = new std::string("replicant_tb_top"); - std::string mc_dpi = *root + ".mc_dpi"; - top = svGetScopeFromName(mc_dpi.c_str()); + root = new std::string("replicant_tb_top"); + std::string mc_dpi = *root + ".mc_dpi"; + top = svGetScopeFromName(mc_dpi.c_str()); } // Does nothing. Turning on/off assertions is only supported in @@ -87,289 +95,434 @@ std::string SimulationWrapper::getRoot(){ } void SimulationWrapper::eval(){ - // Execute one instruction on Dromajo - if (!dromajo_step()) { - // Fixme: Dromajo could also terminate due to premature errors. - // Use the test outputs to detect PASS/FAIL - printf("Dromajo Execution Complete!\nExiting...\n"); - dromajo_cosim_fini(dromajo_state); - exit(0); - } - - // Poll for packets to be transmitted - dromajo_transmit_packet(); - // Poll for packets to be received - dromajo_receive_packet(); - // Update the credits in dromajo - dromajo_set_credits(); - - // Advance time 1 unit - svScope prev; - prev = svSetScope(top); - bsg_dpi_next(); - svSetScope(prev); + // Execute one instruction on Dromajo + if (!dromajo_step()) { + // Fixme: Dromajo could also terminate due to premature errors. + // Use the test outputs to detect PASS/FAIL + printf("Dromajo Execution Complete!\nExiting...\n"); + dromajo_cosim_fini(dromajo_state); + exit(0); + } + + // Poll for packets to be transmitted + dromajo_transmit_packet(); + // Poll for packets to be received + dromajo_receive_packet(); + // Update the credits in dromajo + dromajo_set_credits(); + + // Advance time 1 unit + svScope prev; + prev = svSetScope(top); + bsg_dpi_next(); + svSetScope(prev); } SimulationWrapper::~SimulationWrapper(){ - this->top = nullptr; + this->top = nullptr; } +////////////////////////////// DPI helper functions ////////////////////////////// + +/* + * dpi_fifo_drain + * Drains all DPI fifos. This function is used during initialization and does not push packets + * to the FIFOs in Dromajo + * @param[in] dpi - Pointer to the manycore DPI object + * @param[in] type - Manycore FIFO type + * @returns success if all the FIFOs were drained correctly + */ static int dpi_fifo_drain(bsg_nonsynth_dpi::dpi_manycore *dpi, hb_mc_fifo_rx_t type) { - __m128i *pkt; - - int err, drains = 0; - int cap = dpi->config[HB_MC_CONFIG_IO_REMOTE_LOAD_CAP]; - - do { - bsg_dpi_next(); - switch(type) { - case HB_MC_FIFO_RX_REQ: - err = dpi->rx_req(*pkt); - break; - case HB_MC_FIFO_RX_RSP: - err = dpi->rx_rsp(*pkt); - break; - default: - printf("[BSG_ERROR] Unknown FIFO type\n"); - return HB_MC_FAIL; - } - - if (err == BSG_NONSYNTH_DPI_SUCCESS) - drains++; - } while ((err == BSG_NONSYNTH_DPI_NOT_WINDOW | err == BSG_NONSYNTH_DPI_SUCCESS) - && drains <= cap); - - if (drains != cap) - printf("[BSG_ERROR] Failed to drain FIFO\n"); - return HB_MC_FAIL; - - return HB_MC_SUCCESS; + __m128i *pkt; + + int err, drains = 0; + int cap = dpi->config[HB_MC_CONFIG_IO_REMOTE_LOAD_CAP]; + + do { + bsg_dpi_next(); + switch(type) { + case HB_MC_FIFO_RX_REQ: + err = dpi->rx_req(*pkt); + break; + case HB_MC_FIFO_RX_RSP: + err = dpi->rx_rsp(*pkt); + break; + default: + printf("[BSG_ERROR] Unknown FIFO type\n"); + return HB_MC_FAIL; + } + + if (err == BSG_NONSYNTH_DPI_SUCCESS) + drains++; + } while ((err == BSG_NONSYNTH_DPI_NOT_WINDOW | err == BSG_NONSYNTH_DPI_SUCCESS) + && drains <= cap); + + if (drains != cap) + printf("[BSG_ERROR] Failed to drain FIFO\n"); + return HB_MC_FAIL; + + return HB_MC_SUCCESS; } +/* + * dpi_clean + * Destroys the pointer to the manycore DPI object + * @params[in] dpi - Pointer to the manycore DPI object + */ static void dpi_clean(bsg_nonsynth_dpi::dpi_manycore *dpi) { - delete dpi; + delete dpi; } +/* + * dpi_init + * Initializes the DPI between the manycore and Dromajo + * @params[in] dpi - Pointer to the manycore DPI object + * @params[in] hierarchy - A C++ string that holds the manycore hierarchy + * @returns success if initialized correctly + */ static int dpi_init(bsg_nonsynth_dpi::dpi_manycore *dpi, std::string hierarchy) { - bsg_dpi_next(); + bsg_dpi_next(); - dpi = new bsg_nonsynth_dpi::dpi_manycore(hierarchy + ".mc_dpi"); + dpi = new bsg_nonsynth_dpi::dpi_manycore(hierarchy + ".mc_dpi"); - int err; - err = dpi_fifo_drain(dpi, HB_MC_FIFO_RX_REQ); - if (err != HB_MC_SUCCESS) { - dpi_clean(dpi); - return err; - } + int err; + err = dpi_fifo_drain(dpi, HB_MC_FIFO_RX_REQ); + if (err != HB_MC_SUCCESS) { + dpi_clean(dpi); + return err; + } - err = dpi_fifo_drain(dpi, HB_MC_FIFO_RX_RSP); - if (err != HB_MC_SUCCESS) { - dpi_clean(dpi); - return err; - } + err = dpi_fifo_drain(dpi, HB_MC_FIFO_RX_RSP); + if (err != HB_MC_SUCCESS) { + dpi_clean(dpi); + return err; + } - return HB_MC_SUCCESS; + return HB_MC_SUCCESS; } +/* + * dpi_wait_for_reset + * Ensures that the manycore hardware is reset + * @params[in] dpi - Pointer to the manycore DPI object + */ static int dpi_wait_for_reset(bsg_nonsynth_dpi::dpi_manycore *dpi) { - bool done; - dpi->reset_is_done(done); + bool done; + dpi->reset_is_done(done); - while (!done) { - bsg_dpi_next(); - dpi->reset_is_done(done); - } + while (!done) { + bsg_dpi_next(); + dpi->reset_is_done(done); + } - return HB_MC_SUCCESS; + return HB_MC_SUCCESS; } +////////////////////////////// Dromajo helper functions ////////////////////////////// + +/* + * dromajo_init + * Initializes dromajo with the correct command-line arguments + * @returns a pointer to a dromajo_cosim_state_t object + */ dromajo_cosim_state_t* dromajo_init() { - dromajo_cosim_state_t *dromajo_state; - - char dromajo[50]; - sprintf(dromajo, "dromajo"); + dromajo_cosim_state_t *dromajo_state; + + char dromajo[50]; + sprintf(dromajo, "dromajo"); + + char host[50]; + sprintf(host, "--host"); - char host[50]; - sprintf(host, "--host"); - - char manycore[50]; - sprintf(manycore, "--manycore"); + char manycore[50]; + sprintf(manycore, "--manycore"); - char progname[50]; - sprintf(progname, "test.elf"); + char progname[50]; + sprintf(progname, "test.elf"); - char* argv[] = {dromajo, host, manycore, progname}; - dromajo_state = dromajo_cosim_init(4, argv); + char* argv[] = {dromajo, host, manycore, progname}; + dromajo_state = dromajo_cosim_init(4, argv); - return dromajo_state; + return dromajo_state; } +/* + * dromajo_step + * Executes 1 instruction in Dromajo + * @returns true if execution is incomplete and/or without errors + */ bool dromajo_step() { - // Execute dromajo with verbose mode on - int err = dromajo_cosim_step(dromajo_state, 0, 0, 0, 0, 0, false, true); - if (err != 0) - return false; - else - return true; + // Execute dromajo with verbose mode on + int err = dromajo_cosim_step(dromajo_state, 0, 0, 0, 0, 0, false, true); + if (err != 0) + return false; + else + return true; } +/* + * dromajo_transmit_packet + * Fetches data from the Dromajo->Manycore FIFO and pushes it into the DPI FIFO + * to send packets to the manycore + */ void dromajo_transmit_packet() { - hb_mc_packet_t *packet, *host_resp_packet; - int err; - __m128i *pkt; - - // Check if FIFO is full and hence ready to transmit - mc_fifo_type_t type = FIFO_HOST_TO_MC_REQ; - bool is_full = mc_is_fifo_full(type); - - if (is_full) { - // Read the FIFO head pointer for all 32-bit FIFOs - packet->words[0] = host_to_mc_req_fifo->fifo[0].front(); - packet->words[1] = host_to_mc_req_fifo->fifo[1].front(); - packet->words[2] = host_to_mc_req_fifo->fifo[2].front(); - packet->words[3] = host_to_mc_req_fifo->fifo[3].front(); - - // Intercept packets that are for the host and generate appropriate responses - if ((packet->request.x_dst == 0) && (packet->request.y_dst == 0)) { - host_resp_packet->response.x_dst = packet->request.x_src; - host_resp_packet->response.y_dst = packet->request.y_src; - host_resp_packet->response.load_id = 0; - // If EPA maps to reading arguments - if (packet->request.op_v2 == HB_MC_PACKET_OP_REMOTE_LOAD) { - host_resp_packet->response.op = packet->request.op_v2; - idx = packet->request.addr; - uint32_t data = 0; - if (packet->request.addr >= 0 && packet->request.addr <= 0xFF) { - // Copy 4 bytes of the arguments - int num_characters = 0; - // If all arguments have been read, send this finish code - if (idx == _argc) { - data = 0xFFFFFFFF; - } - else { - for(int i = 0; i < 4; i++) { - if (_argv[idx][char_index] != '\0') { - data = (data << 8) | _argv[idx][char_index]; - num_characters++; - char_index++; - } - else { - data = (data << (4 - num_characters) * 8); - char_index = 0; - } - } - } - } - // Dromajo/BlackParrot wants to read the config - else if (packet->request.addr >= 0x100 && packet->request.addr <= 0x1FF) { - idx = packet->request.addr; - data = dpi->config[idx]; - } - else - printf("[BSG_ERROR] Host EPA not mapped\n"); - - host_resp_packet->response.data = data; - // Inject the response packet into manycore response FIFO - // Pop the request FIFO - for(int j = 0; j < 4; j++) { - mc_to_host_resp_fifo->fifo[j].push(host_resp_packet->words[j]); - host_to_mc_req_fifo->fifo[j].pop(); - } - } - else - printf("[BSG_ERROR] Operations other than loads are not implemented for the host\n"); - } - else { - pkt = reinterpret_cast<__m128i *>(packet); - - // Try to transmit until you actually can - err = dpi->tx_req(*pkt); - - // Pop the FIFO once transmitted - if (err == BSG_NONSYNTH_DPI_SUCCESS) { - for (int i = 0;i < 4; i++) - host_to_mc_req_fifo->fifo[i].pop(); - } - } - } + hb_mc_packet_t packet, host_resp_packet; + int err; + __m128i *pkt; + + // Check if FIFO is full and hence ready to transmit + mc_fifo_type_t type = FIFO_HOST_TO_MC_REQ; + bool is_full = mc_is_fifo_full(type); + + if (is_full) { + // Read the FIFO head pointer for all 32-bit FIFOs + packet.words[0] = host_to_mc_req_fifo->fifo[0].front(); + packet.words[1] = host_to_mc_req_fifo->fifo[1].front(); + packet.words[2] = host_to_mc_req_fifo->fifo[2].front(); + packet.words[3] = host_to_mc_req_fifo->fifo[3].front(); + + // Intercept packets that are for the host and generate appropriate responses + if ((packet.request.x_dst == 0) && (packet.request.y_dst == 0)) { + host_resp_packet.response.x_dst = packet.request.x_src; + host_resp_packet.response.y_dst = packet.request.y_src; + host_resp_packet.response.load_id = 0; + if (packet.request.op_v2 == HB_MC_PACKET_OP_REMOTE_LOAD) { + host_resp_packet.response.op = packet.request.op_v2; + idx = packet.request.addr; + uint32_t data = 0; + // If EPA maps to reading arguments + if (packet.request.addr >= 0 && packet.request.addr <= 0xFF) { + int num_characters = 0; + // If all arguments have been read, send this finish code + if (idx == _argc) { + data = 0xFFFFFFFF; + } + else { + // Copy 4 bytes of the arguments + for(int i = 0; i < 4; i++) { + if (_argv[idx][char_index] != '\0') { + data = (data << 8) | _argv[idx][char_index]; + num_characters++; + char_index++; + } + else { + data = (data << (4 - num_characters) * 8); + char_index = 0; + } + } + } + } + // Dromajo/BlackParrot wants to read the config + else if (packet.request.addr >= 0x100 && packet.request.addr <= 0x1FF) { + idx = packet.request.addr; + data = dpi->config[idx]; + } + else + printf("[BSG_ERROR] Host EPA not mapped\n"); + + host_resp_packet.response.data = data; + // Inject the response packet into manycore response FIFO + // Pop the request FIFO + for(int j = 0; j < 4; j++) { + mc_to_host_resp_fifo->fifo[j].push(host_resp_packet.words[j]); + host_to_mc_req_fifo->fifo[j].pop(); + } + } + else + printf("[BSG_ERROR] Operations other than loads are not implemented for the host\n"); + } + else { + pkt = reinterpret_cast<__m128i *>(&packet); + + // Try to transmit until you actually can + err = dpi->tx_req(*pkt); + + // Pop the FIFO once transmitted + if (err == BSG_NONSYNTH_DPI_SUCCESS) { + for (int i = 0;i < 4; i++) + host_to_mc_req_fifo->fifo[i].pop(); + } + } + } } +/* + * dromajo_receive_packet + * Receives packets from the DPI FIFOs and pushes the data into the + * manycore request and response FIFOs in Dromajo + */ void dromajo_receive_packet() { - hb_mc_packet_t *req_packet, *resp_packet; - int err; - __m128i *pkt; - - // Read from the manycore request FIFO - err = dpi->rx_req(*pkt); - req_packet = reinterpret_cast(pkt); - - // Push to host FIFO if valid - if (err == BSG_NONSYNTH_DPI_SUCCESS) { - for (int i = 0; i < 4; i++) { - mc_to_host_req_fifo->fifo[i].push(req_packet->words[i]); - } - } - - // Read from the manycore response FIFO - err = dpi->rx_rsp(*pkt); - resp_packet = reinterpret_cast(pkt); - - // Push to host FIFO if valid - if (err == BSG_NONSYNTH_DPI_SUCCESS) { - for (int i = 0; i < 4; i++) { - mc_to_host_resp_fifo->fifo[i].push(resp_packet->words[i]); - } - } + hb_mc_packet_t *req_packet, *resp_packet; + int err; + __m128i *pkt; + + // Read from the manycore request FIFO + err = dpi->rx_req(*pkt); + req_packet = reinterpret_cast(pkt); + + // Push to host FIFO if valid + if (err == BSG_NONSYNTH_DPI_SUCCESS) { + for (int i = 0; i < 4; i++) { + mc_to_host_req_fifo->fifo[i].push(req_packet->words[i]); + } + } + + // Read from the manycore response FIFO + err = dpi->rx_rsp(*pkt); + resp_packet = reinterpret_cast(pkt); + + // Push to host FIFO if valid + if (err == BSG_NONSYNTH_DPI_SUCCESS) { + for (int i = 0; i < 4; i++) { + mc_to_host_resp_fifo->fifo[i].push(resp_packet->words[i]); + } + } } +/* + * dromajo_set_credits + * Polls the hardware for credit information and sets the credits info + * for the Dromajo->Manycore request FIFO in dromajo + */ void dromajo_set_credits() { - int credits; - int res = dpi->get_credits(credits); - if (res == BSG_NONSYNTH_DPI_SUCCESS) { - if (credits < 0) - printf("[BSG_WARN] Warning! Credit value is negative!\n"); - - host_to_mc_req_fifo->credits = credits; - } + int credits; + int res = dpi->get_credits(credits); + if (res == BSG_NONSYNTH_DPI_SUCCESS) { + if (credits < 0) + printf("[BSG_WARN] Warning! Credit value is negative!\n"); + + host_to_mc_req_fifo->credits = credits; + } } -#ifdef VCS +////////////////////////////// Interacting with VCS ////////////////////////////// + +/* + * get_argc + * Given a string, determine the number of space-separated arguments + * @params[in] args - Pointer to a character array that holds the arguments + * @returns the number of arguments + */ +int get_argc(char * args){ + char *cur = args, prev=' '; + int count = 1; + while(*cur != '\0'){ + if((prev == ' ') && (prev != *cur)){ + count ++; + } + prev = *cur; + ++cur; + } + return count; +} + +/* + * get_argv + * Given a string, retrieves the space-separated arguments + * @params[in] args - Pointer to a character array that holds the arguments + * @params[in] argc - Number of arguments + * @params[in] argv - Pointer to an array of strings that will hold the different + * arguments + */ +static +void get_argv(char * args, int argc, char **argv){ + int count = 0; + char *cur = args, prev=' '; + + // First parse the path name. This is not in the argument string because + // VCS doesn't provide it to us. Instead, we "hack" around it by reading + // the path from 'proc/self/exe'. The maximum path-name length is 1024, + // with an extra null character for safety + static char path[1025] = {'\0'}; + + readlink("/proc/self/exe", path, sizeof(path) - 1); + argv[0] = path; + count ++; + + // Then we parse the remaining arguments. Arguments are separated by N + // >= 1 spaces. We only register an argument when the previous character + // was a space, and the current character is not (so that multiple + // spaces don't count as multiple arguments). We replace spaces with + // null characters (\0) so that each argument appears to be an + // individual string and can be used later, by argparse (and other + // libraries) + while(*cur != '\0'){ + if((prev == ' ') && (prev != *cur)){ + argv[count] = cur; + count++; + } + prev = *cur; + if(*cur == ' ') + *cur = '\0'; + cur++; + } +} + +/* + * vcs_main + * The main function for the x86 host. It initializes all devices and controls + * the time in simulation. It handles all DPI calls and passes packets to and from + * Dromajo during execution + * @params[in] argc - Number of arguments + * @params[in] argv - Pointer to an array of string arguments + * @returns + */ int vcs_main(int argc, char **argv) { -#else -int main(int argc, char **argv) { -#endif - // Push command-line arguments into global variables - _argc = argc; - _argv = argv; - - // Initialize Dromajo - dromajo_state = dromajo_init(); - - // Create an object of the simulation wrapper - SimulationWrapper *sim = new SimulationWrapper(); - std::string hierarchy = sim->getRoot(); - - int err; - - // Initialize DPI - err = dpi_init(dpi, hierarchy); - if (err != HB_MC_SUCCESS) { - delete sim; - printf("[BSG_ERROR] Failed to initialize DPI!\nExiting...\n"); - return -1; - } - - // Wait for reset to be done - err = dpi_wait_for_reset(dpi); - if (err != HB_MC_SUCCESS) { - dpi_clean(dpi); - delete sim; - printf("[BSG_ERROR] Failed to wait for reset!\nExiting...\n"); - return -1; - } - - while(1) - sim->eval(); - - return 0; -} \ No newline at end of file + // Push command-line arguments into global variables + _argc = argc; + _argv = argv; + + + // Initialize Dromajo + dromajo_state = dromajo_init(); + + // Create an object of the simulation wrapper + SimulationWrapper *sim = new SimulationWrapper(); + std::string hierarchy = sim->getRoot(); + + int err; + + // Initialize DPI + err = dpi_init(dpi, hierarchy); + if (err != HB_MC_SUCCESS) { + delete sim; + printf("[BSG_ERROR] Failed to initialize DPI!\nExiting...\n"); + return HB_MC_FAIL; + } + + // Wait for reset to be done + err = dpi_wait_for_reset(dpi); + if (err != HB_MC_SUCCESS) { + dpi_clean(dpi); + delete sim; + printf("[BSG_ERROR] Failed to wait for reset!\nExiting...\n"); + return HB_MC_FAIL; + } + + while(1) + sim->eval(); + + return HB_MC_SUCCESS; +} + +/* + * cosim_main + * This function is the VCS hook for cosimulation + * @params[in] exit_code - A pointer to an integer that holds the exit code + * @params[in] args - A character array that holds the space-separated + * arguments to the function + */ +void cosim_main(uint32_t *exit_code, char *args) { + // We aren't passed command line arguments directly so we parse them + // from *args. args is a string from VCS - to pass a string of arguments + // to args, pass c_args to VCS as follows: +c_args="" + int argc = get_argc(args); + char *argv[argc]; + get_argv(args, argc, argv); + + int rc = vcs_main(argc, argv); + *exit_code = rc; + bsg_pr_test_pass_fail(rc == HB_MC_SUCCESS); + return; +} diff --git a/libraries/platforms/dromajo-vcs/compilation.mk b/libraries/platforms/dromajo-vcs/compilation.mk index e40788fe8..0f20ff015 100644 --- a/libraries/platforms/dromajo-vcs/compilation.mk +++ b/libraries/platforms/dromajo-vcs/compilation.mk @@ -38,6 +38,7 @@ NC=\033[0m DEFINES += -UVCS -D_DRAMFS INCLUDES += -I$(LIBRARIES_PATH) INCLUDES += -I$(BSG_PLATFORM_PATH)/software/include +INCLUDES += -I$(BSG_PLATFORM_PATH) INCLUDES += -I$(BLACKPARROT_DIR)/sdk/perch CXXFLAGS += $(DEFINES) -march=rv64imafd -mabi=lp64 -mcmodel=medany diff --git a/libraries/platforms/dromajo-vcs/library.mk b/libraries/platforms/dromajo-vcs/library.mk index b45f2a5e2..dea858f31 100644 --- a/libraries/platforms/dromajo-vcs/library.mk +++ b/libraries/platforms/dromajo-vcs/library.mk @@ -63,8 +63,8 @@ $(DMA_FEATURE_OBJECTS): CFLAGS += -march=rv64imafd -mcmodel=medany -mabi=lp64 -D $(DMA_FEATURE_OBJECTS): CXXFLAGS += -march=rv64imafd -mcmodel=medany -mabi=lp64 -D_BSD_SOURCE -D_XOPEN_SOURCE=500 # Add the riscv-newlib specific includes for the library -$(LIB_OBJECTS) $(LIB_OBJECTS_CUDA_POD_REPL): INCLUDES := -I$(BSG_PLATFORM_PATH)/software/include -$(LIB_OBJECTS) $(LIB_OBJECTS_CUDA_POD_REPL): INCLUDES += -I$(BLACKPARROT_DIR)/sdk/perch +$(LIB_OBJECTS) $(LIB_OBJECTS_CUDA_POD_REPL) $(LIB_OBJECTS_REGRESSION): INCLUDES := -I$(BSG_PLATFORM_PATH)/software/include +$(LIB_OBJECTS) $(LIB_OBJECTS_CUDA_POD_REPL) $(LIB_OBJECTS_REGRESSSION): INCLUDES += -I$(BLACKPARROT_DIR)/sdk/perch # Make the litteFS file system $(BSG_PLATFORM_PATH)/lfs.o: @@ -72,8 +72,8 @@ $(BSG_PLATFORM_PATH)/lfs.o: $(RV_CXX) $(BLACKPARROT_DIR)/sdk/bp-tests/lfs.cpp -c -o $@ $(CXXFLAGS) $(INCLUDES) # Compile the feature libraries with the manycore runtime -$(LIB_OBJECTS) $(LIB_OBJECTS_CUDA_POD_REPL): INCLUDES += -I$(LIBRARIES_PATH)/features/profiler -$(LIB_OBJECTS) $(LIB_OBJECTS_CUDA_POD_REPL): INCLUDES += -I$(LIBRARIES_PATH)/features/tracer +$(LIB_OBJECTS) $(LIB_OBJECTS_CUDA_POD_REPL) $(LIB_OBJECTS_REGRESSION): INCLUDES += -I$(LIBRARIES_PATH)/features/profiler +$(LIB_OBJECTS) $(LIB_OBJECTS_CUDA_POD_REPL) $(LIB_OBJECTS_REGRESSION): INCLUDES += -I$(LIBRARIES_PATH)/features/tracer DROMAJO_CXXSOURCES += $(DROMAJO_DIR)/src/cutils.cpp DROMAJO_CXXSOURCES += $(DROMAJO_DIR)/src/dromajo_cosim.cpp @@ -127,12 +127,18 @@ $(BSG_PLATFORM_PATH)/libbsg_manycore_runtime.a.1: %.a.1: %.so.1.0 $(BSG_PLATFORM_PATH)/libbsgmc_cuda_legacy_pod_repl.a.1: %.a.1: %.so.1.0 ln -sf $(basename $(basename $@)).so.1.0 $@ +$(BSG_PLATFORM_PATH)/libbsg_manycore_regression.a.1: %.a.1: %.so.1.0 + ln -sf $(basename $(basename $@)).so.1.0 $@ + $(BSG_PLATFORM_PATH)/libbsg_manycore_runtime.a: %: %.1 ln -sf $@.1 $@ $(BSG_PLATFORM_PATH)/libbsgmc_cuda_legacy_pod_repl.a: %: %.1 ln -sf $@.1 $@ +$(BSG_PLATFORM_PATH)/libbsg_manycore_regression.a: %: %.1 + ln -sf $@.1 $@ + platform.clean: rm -f $(PLATFORM_OBJECTS) rm -f $(DROMAJO_OBJECTS) @@ -141,6 +147,8 @@ platform.clean: rm -f $(BSG_PLATFORM_PATH)/libbsg_manycore_runtime.a.1 rm -f $(BSG_PLATFORM_PATH)/libbsgmc_cuda_legacy_pod_repl.a rm -f $(BSG_PLATFORM_PATH)/libbsgmc_cuda_legacy_pod_repl.a.1 + rm -f $(BSG_PLATFORM_PATH)/libbsg_manycore_regression.a + rm -f $(BSG_PLATFORM_PATH)/libbsg_manycore_regression.a.1 rm -f $(BSG_PLATFORM_PATH)/libbsg_manycore_platform.so libraries.clean: platform.clean diff --git a/libraries/platforms/dromajo-vcs/link.mk b/libraries/platforms/dromajo-vcs/link.mk index a67e9dfff..19805f254 100644 --- a/libraries/platforms/dromajo-vcs/link.mk +++ b/libraries/platforms/dromajo-vcs/link.mk @@ -93,8 +93,8 @@ $(BSG_MACHINE_PATH)/$(BSG_PLATFORM)/vcs_simlibs/replicant_tb_top_exec/AN.DB: $(B SYNOPSYS_SIM_SETUP=$< vlogan -work replicant_tb_top $(VLOGAN_FLAGS) -l $(BSG_MACHINE_PATH)/$(BSG_PLATFORM)/vlogan.exec.log # libbsg_manycore_platform will be compiled in $(BSG_PLATFORM_PATH) -LDFLAGS += -lbsg_manycore_platform -lm LDFLAGS += -L$(BSG_PLATFORM_PATH) -Wl,-rpath=$(BSG_PLATFORM_PATH) +LDFLAGS += -lbsg_manycore_platform -lm VCS_LDFLAGS += $(foreach def,$(LDFLAGS),-LDFLAGS "$(def)") VCS_VFLAGS += -M -L -ntb_opts tb_timescale=1ps/1ps -lca @@ -113,16 +113,24 @@ $(BSG_PLATFORM_PATH)/test.riscv: $(TEST_OBJECTS) $(BSG_PLATFORM_PATH)/test.riscv: $(BSG_PLATFORM_PATH)/lfs.o $(BSG_PLATFORM_PATH)/test.riscv: $(BSG_PLATFORM_PATH)/libbsg_manycore_runtime.a $(BSG_PLATFORM_PATH)/test.riscv: $(BSG_PLATFORM_PATH)/libbsgmc_cuda_legacy_pod_repl.a -$(BSG_PLATFORM_PATH)/test.riscv: LDFLAGS := -T$(BLACKPARROT_DIR)/sdk/linker/riscv.ld -L$(BSG_PLATFORM_PATH) -static -nostartfiles -lstdc++ -lbsg_manycore_runtime +$(BSG_PLATFORM_PATH)/test.riscv: $(BSG_PLATFORM_PATH)/libbsg_manycore_regression.a +$(BSG_PLATFORM_PATH)/test.riscv: LDFLAGS := -T$(BLACKPARROT_DIR)/sdk/linker/riscv.ld -L$(BSG_PLATFORM_PATH) -static -nostartfiles -lstdc++ -lbsg_manycore_runtime -lbsg_manycore_regression $(BSG_PLATFORM_PATH)/test.riscv: $(RV_CXX) -D_DRAMFS -o $@ $(BSG_PLATFORM_PATH)/software/src/crt0.o $(BSG_PLATFORM_PATH)/lfs.o $< $(LDFLAGS) + cp $@ $(subst riscv,elf,$(notdir $@)) -$(BSG_PLATFORM_PATH)/libbsg_manycore_platform.so: $(DROMAJO_OBJECTS) -$(BSG_PLATFORM_PATH)/libbsg_manycore_platform.so: $(PLATFORM_OBJECTS) -$(BSG_PLATFORM_PATH)/libbsg_manycore_platform.so: LDFLAGS := -fPIC -$(BSG_PLATFORM_PATH)/libbsg_manycore_platform.so: +$(BSG_PLATFORM_PATH)/libbsg_manycore_platform.so.1.0: $(DROMAJO_OBJECTS) +$(BSG_PLATFORM_PATH)/libbsg_manycore_platform.so.1.0: $(PLATFORM_OBJECTS) +$(BSG_PLATFORM_PATH)/libbsg_manycore_platform.so.1.0: LDFLAGS := -fPIC +$(BSG_PLATFORM_PATH)/libbsg_manycore_platform.so.1.0: $(CXX) -shared -Wl,-soname,$(basename $(notdir $@)) -o $@ $^ $(LDFLAGS) +$(BSG_PLATFORM_PATH)/libbsg_manycore_platform.so.1: %: %.0 + ln -sf $@.0 $@ + +$(BSG_PLATFORM_PATH)/libbsg_manycore_platform.so: %: %.1 + ln -sf $@.1 $@ + # VCS Generates an executable file by linking the TEST_OBJECTS with # the the VCS work libraries for the design, and the runtime shared # libraries @@ -154,6 +162,8 @@ REGRESSION_PREBUILD += $(BSG_MACHINE_PATH)/$(BSG_PLATFORM)/vcs_simlibs/replicant REGRESSION_PREBUILD += $(BSG_MACHINE_PATH)/$(BSG_PLATFORM)/vcs_simlibs/replicant_tb_top_saifgen/AN.DB REGRESSION_PREBUILD += $(BSG_PLATFORM_PATH)/libbsgmc_cuda_legacy_pod_repl.a REGRESSION_PREBUILD += $(BSG_PLATFORM_PATH)/libbsg_manycore_runtime.a +REGRESSION_PREBUILD += $(BSG_PLATFORM_PATH)/libbsg_manycore_regression.a +REGRESSION_PREBUILD += $(BSG_PLATFORM_PATH)/libbsg_manycore_platform.so .PHONY: platform.link.clean platform.link.clean: From f7b456e675e2c006924816c3473e42302b8b761f Mon Sep 17 00:00:00 2001 From: sripathi-muralitharan Date: Fri, 30 Apr 2021 09:44:48 -0700 Subject: [PATCH 21/70] Gitignore updates --- examples/.gitignore | 2 ++ libraries/.gitignore | 6 +++++- machines/.gitignore | 1 + 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/examples/.gitignore b/examples/.gitignore index 2c55a9bd9..f6f502536 100644 --- a/examples/.gitignore +++ b/examples/.gitignore @@ -24,3 +24,5 @@ ucli.key *.saifgen *.json dramsim3.txt +*.riscv + diff --git a/libraries/.gitignore b/libraries/.gitignore index 8b447aa5d..437ff9063 100644 --- a/libraries/.gitignore +++ b/libraries/.gitignore @@ -1,4 +1,8 @@ *.o *.so *.so.1 -*.so.1.0 \ No newline at end of file +*.so.1.0 +*.riscv +*.a +*.a.1 +*.a.1.0 diff --git a/machines/.gitignore b/machines/.gitignore index cedb46588..33747ae50 100644 --- a/machines/.gitignore +++ b/machines/.gitignore @@ -16,3 +16,4 @@ bigblade-vcs bsg_tag_boot_rom.v bsg_tag_boot_rom.tr tapeout-vcs +dromajo-vcs From 7d53d461c8df0756747eb484424965d6ef28b795 Mon Sep 17 00:00:00 2001 From: sripathi-muralitharan Date: Fri, 30 Apr 2021 10:03:25 -0700 Subject: [PATCH 22/70] Aesthestics and adding cleans to target; Completing platform-level API to get config --- .../dromajo-vcs/bsg_manycore_platform.cpp | 119 ++++++++++-------- libraries/platforms/dromajo-vcs/library.mk | 1 + 2 files changed, 67 insertions(+), 53 deletions(-) diff --git a/libraries/platforms/dromajo-vcs/bsg_manycore_platform.cpp b/libraries/platforms/dromajo-vcs/bsg_manycore_platform.cpp index b7e5faee3..d25c8855b 100644 --- a/libraries/platforms/dromajo-vcs/bsg_manycore_platform.cpp +++ b/libraries/platforms/dromajo-vcs/bsg_manycore_platform.cpp @@ -89,14 +89,14 @@ int hb_mc_platform_init(hb_mc_manycore_t *mc, hb_mc_manycore_id_t id) { return HB_MC_INITIALIZED_TWICE; if (id != 0) - { - manycore_pr_err(mc, "Failed to init platform: invalid ID\n"); - return HB_MC_INVALID; + { + manycore_pr_err(mc, "Failed to init platform: invalid ID\n"); + return HB_MC_INVALID; } // Check if the ID has already been initialized if(active_ids.find(id) != active_ids.end()) - { + { manycore_pr_err(mc, "Already initialized ID\n"); return HB_MC_INVALID; } @@ -120,24 +120,24 @@ int hb_mc_platform_transmit(hb_mc_manycore_t *mc, hb_mc_packet_t *packet, hb_mc_ hb_mc_platform_t *platform = reinterpret_cast(mc->platform); const char *typestr = hb_mc_fifo_tx_to_string(type); - // Timeout is unsupported - if (timeout != -1) - { + // Timeout is unsupported + if (timeout != -1) + { manycore_pr_err(mc, "%s: Only a timeout value of -1 is supported\n", __func__); return HB_MC_INVALID; } - // Host doesn't send responses to the mamycore - if (type == HB_MC_FIFO_TX_RSP) - { + // Host doesn't send responses to the mamycore + if (type == HB_MC_FIFO_TX_RSP) + { manycore_pr_err(mc, "TX Response Not Supported!\n"); return HB_MC_NOIMPL; } - // Write packet to the manycore bridge - bp_hb_write_to_manycore_bridge(packet); + // Write packet to the manycore bridge + bp_hb_write_to_manycore_bridge(packet); - return HB_MC_SUCCESS; + return HB_MC_SUCCESS; } /** @@ -148,24 +148,24 @@ int hb_mc_platform_transmit(hb_mc_manycore_t *mc, hb_mc_packet_t *packet, hb_mc_ * @return HB_MC_SUCCESS on success. Otherwise an error code defined in bsg_manycore_errno.h. */ int hb_mc_platform_receive(hb_mc_manycore_t *mc, hb_mc_packet_t *packet, hb_mc_fifo_rx_t type, long timeout) { - hb_mc_platform_t *platform = reinterpret_cast(mc->platform); + hb_mc_platform_t *platform = reinterpret_cast(mc->platform); - // Timeout is unsupported - if (timeout != -1) - { + // Timeout is unsupported + if (timeout != -1) + { manycore_pr_err(mc, "%s: Only a timeout value of -1 is supported\n", __func__); return HB_MC_INVALID; } - int err = bp_hb_read_from_manycore_bridge(packet, type); + int err = bp_hb_read_from_manycore_bridge(packet, type); - if (err != 0) - { - manycore_pr_err(mc, "%s: Failed to receive packet\n", __func__); + if (err != 0) + { + manycore_pr_err(mc, "%s: Failed to receive packet\n", __func__); return HB_MC_INVALID; - } + } - return HB_MC_SUCCESS; + return HB_MC_SUCCESS; } /** @@ -176,16 +176,29 @@ int hb_mc_platform_receive(hb_mc_manycore_t *mc, hb_mc_packet_t *packet, hb_mc_f * @return HB_MC_SUCCESS on success. Otherwise an error code defined in bsg_manycore_errno.h. */ int hb_mc_platform_get_config_at(hb_mc_manycore_t *mc, unsigned int idx, hb_mc_config_raw_t *config) { - hb_mc_platform_t *platform = reinterpret_cast(mc->platform); - - if (idx < HB_MC_CONFIG_MAX) - { - // TODO: - // Read from an array in an autogenerated C/C++ header - return HB_MC_SUCCESS; - } + hb_mc_platform_t *platform = reinterpret_cast(mc->platform); + hb_mc_packet_t req_pkt, resp_pkt; + + if (idx < HB_MC_CONFIG_MAX) + { + req_pkt.request.x_dst = 0; + req_pkt.request.y_dst = 0; + req_pkt.request.x_src = 0; + req_pkt.request.y_src = 1; + req_pkt.request.op_v2 = HB_MC_PACKET_OP_REMOTE_LOAD; + req_pkt.request.payload = 0; + req_pkt.request.reg_id = 0; + req_pkt.request.addr = 0x100 + idx; + bp_hb_write_to_manycore_bridge(&req_pkt); + int err = bp_hb_read_from_manycore_bridge(&resp_pkt, HB_MC_FIFO_RX_RSP); + if (err != 0) + return HB_MC_FAIL; + *config = resp_pkt.response.data; + + return HB_MC_SUCCESS; + } - return HB_MC_INVALID; + return HB_MC_INVALID; } /** @@ -195,25 +208,25 @@ int hb_mc_platform_get_config_at(hb_mc_manycore_t *mc, unsigned int idx, hb_mc_c * @return HB_MC_SUCCESS on success. Otherwise an error code defined in bsg_manycore_errno.h. */ int hb_mc_platform_fence(hb_mc_manycore_t *mc, long timeout) { - int credits, err; + int credits, err; bool isvacant; uint32_t max_credits; const hb_mc_config_t *cfg = hb_mc_manycore_get_config(mc); hb_mc_platform_t *platform = reinterpret_cast(mc->platform); - max_credits = hb_mc_config_get_io_endpoint_max_out_credits(cfg); + max_credits = hb_mc_config_get_io_endpoint_max_out_credits(cfg); - if (timeout != -1) { - manycore_pr_err(mc, "%s: Only a timeout value of -1 is supported\n", __func__); - return HB_MC_NOIMPL; - } + if (timeout != -1) { + manycore_pr_err(mc, "%s: Only a timeout value of -1 is supported\n", __func__); + return HB_MC_NOIMPL; + } - do - { - credits = bp_hb_get_credits(); - } while (!(credits == (int)max_credits)); + do + { + credits = bp_hb_get_credits(); + } while (!(credits == (int)max_credits)); - return HB_MC_SUCCESS; + return HB_MC_SUCCESS; } /** @@ -222,7 +235,7 @@ int hb_mc_platform_fence(hb_mc_manycore_t *mc, long timeout) { * @return HB_MC_SUCCESS on success. Otherwise an error code defined in bsg_manycore_errno.h. */ int hb_mc_platform_start_bulk_transfer(hb_mc_manycore_t *mc) { - return HB_MC_SUCCESS; + return HB_MC_SUCCESS; } /** @@ -231,7 +244,7 @@ int hb_mc_platform_start_bulk_transfer(hb_mc_manycore_t *mc) { * @return HB_MC_SUCCESS on success. Otherwise an error code defined in bsg_manycore_errno.h. */ int hb_mc_platform_finish_bulk_transfer(hb_mc_manycore_t *mc) { - return HB_MC_SUCCESS; + return HB_MC_SUCCESS; } /** @@ -241,7 +254,7 @@ int hb_mc_platform_finish_bulk_transfer(hb_mc_manycore_t *mc) { * @return HB_MC_SUCCESS on success. Otherwise an error code defined in bsg_manycore_errno.h. */ int hb_mc_platform_get_cycle(hb_mc_manycore_t *mc, uint64_t *time) { - return HB_MC_NOIMPL; + return HB_MC_NOIMPL; } /** @@ -252,7 +265,7 @@ int hb_mc_platform_get_cycle(hb_mc_manycore_t *mc, uint64_t *time) { * @return HB_MC_SUCCESS on success. Otherwise an error code defined in bsg_manycore_errno.h. */ int hb_mc_platform_get_icount(hb_mc_manycore_t *mc, bsg_instr_type_e itype, int *count) { - return HB_MC_NOIMPL; + return HB_MC_NOIMPL; } /** @@ -261,7 +274,7 @@ int hb_mc_platform_get_icount(hb_mc_manycore_t *mc, bsg_instr_type_e itype, int * @return HB_MC_SUCCESS on success. Otherwise an error code defined in bsg_manycore_errno.h. */ int hb_mc_platform_trace_enable(hb_mc_manycore_t *mc) { - return HB_MC_NOIMPL; + return HB_MC_NOIMPL; } /** @@ -270,7 +283,7 @@ int hb_mc_platform_trace_enable(hb_mc_manycore_t *mc) { * @return HB_MC_SUCCESS on success. Otherwise an error code defined in bsg_manycore_errno.h. */ int hb_mc_platform_trace_disable(hb_mc_manycore_t *mc) { - return HB_MC_NOIMPL; + return HB_MC_NOIMPL; } /** @@ -279,7 +292,7 @@ int hb_mc_platform_trace_disable(hb_mc_manycore_t *mc) { * @return HB_MC_SUCCESS on success. Otherwise an error code defined in bsg_manycore_errno.h. */ int hb_mc_platform_log_enable(hb_mc_manycore_t *mc) { - return HB_MC_NOIMPL; + return HB_MC_NOIMPL; } /** @@ -288,7 +301,7 @@ int hb_mc_platform_log_enable(hb_mc_manycore_t *mc) { * @return HB_MC_SUCCESS on success. Otherwise an error code defined in bsg_manycore_errno.h. */ int hb_mc_platform_log_disable(hb_mc_manycore_t *mc) { - return HB_MC_NOIMPL; + return HB_MC_NOIMPL; } /** @@ -297,6 +310,6 @@ int hb_mc_platform_log_disable(hb_mc_manycore_t *mc) { * @return HB_MC_SUCCESS on success. Otherwise an error code defined in bsg_manycore_errno.h. */ int hb_mc_platform_wait_reset_done(hb_mc_manycore_t *mc) { - // Reset is guaranteed to be complete before program starts by the simulation wrapper - return HB_MC_SUCCESS; + // Reset is guaranteed to be complete before program starts by the simulation wrapper + return HB_MC_SUCCESS; } diff --git a/libraries/platforms/dromajo-vcs/library.mk b/libraries/platforms/dromajo-vcs/library.mk index dea858f31..8e94ef221 100644 --- a/libraries/platforms/dromajo-vcs/library.mk +++ b/libraries/platforms/dromajo-vcs/library.mk @@ -150,5 +150,6 @@ platform.clean: rm -f $(BSG_PLATFORM_PATH)/libbsg_manycore_regression.a rm -f $(BSG_PLATFORM_PATH)/libbsg_manycore_regression.a.1 rm -f $(BSG_PLATFORM_PATH)/libbsg_manycore_platform.so + rm -f $(BSG_PLATFORM_PATH)/libbsg_manycore_platform.so.1 libraries.clean: platform.clean From 6e33293eefb526219f8907ba7315381b64a37d32 Mon Sep 17 00:00:00 2001 From: sripathi-muralitharan Date: Fri, 30 Apr 2021 11:06:16 -0700 Subject: [PATCH 23/70] Compiling DRAMSim3 and DMA memory libraries with the x86 simulator --- libraries/platforms/dromajo-vcs/compilation.mk | 2 +- libraries/platforms/dromajo-vcs/library.mk | 15 +++++++++++++-- libraries/platforms/dromajo-vcs/link.mk | 8 +++++++- 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/libraries/platforms/dromajo-vcs/compilation.mk b/libraries/platforms/dromajo-vcs/compilation.mk index 0f20ff015..fe2b90b2f 100644 --- a/libraries/platforms/dromajo-vcs/compilation.mk +++ b/libraries/platforms/dromajo-vcs/compilation.mk @@ -35,7 +35,7 @@ NC=\033[0m # This file REQUIRES several variables to be set. They are typically # set by the Makefile that includes this makefile.. # -DEFINES += -UVCS -D_DRAMFS +DEFINES += -D_DRAMFS INCLUDES += -I$(LIBRARIES_PATH) INCLUDES += -I$(BSG_PLATFORM_PATH)/software/include INCLUDES += -I$(BSG_PLATFORM_PATH) diff --git a/libraries/platforms/dromajo-vcs/library.mk b/libraries/platforms/dromajo-vcs/library.mk index 8e94ef221..7f5446513 100644 --- a/libraries/platforms/dromajo-vcs/library.mk +++ b/libraries/platforms/dromajo-vcs/library.mk @@ -100,6 +100,17 @@ $(DROMAJO_OBJECTS): CXXFLAGS := -std=c++11 -fPIC -Wall -Wno-parentheses -MMD -D_ $(DROMAJO_OBJECTS): LDFLAGS := -fPIC $(DROMAJO_OBJECTS): RV_CXX = $(CXX) +include $(LIBRARIES_PATH)/features/dma/simulation/dramsim3.mk +include $(LIBRARIES_PATH)/features/dma/simulation/libdmamem.mk + +$(LIBRARIES_PATH)/features/dma/simulation/libdmamem.so: CXXFLAGS := $(filter-out -march=%,$(CXXFLAGS)) +$(LIBRARIES_PATH)/features/dma/simulation/libdmamem.so: CXXFLAGS := $(filter-out -mabi=%,$(CXXFLAGS)) +$(LIBRARIES_PATH)/features/dma/simulation/libdmamem.so: CXXFLAGS := $(filter-out -mcmodel=%,$(CXXFLAGS)) +$(LIBRARIES_PATH)/features/dma/simulation/libdmamem.so: CXXFLAGS := $(filter-out -D_DRAMFS,$(CXXFLAGS)) +$(LIBRARIES_PATH)/features/dma/simulation/libdmamem.so: INCLUDES := + +$(LIBRARIES_PATH)/features/dma/simulation/libdramsim3.so: INCLUDES := + PLATFORM_CXXSOURCES += $(BSG_PLATFORM_PATH)/bsg_manycore_simulator.cpp PLATFORM_OBJECTS += $(patsubst %cpp,%o,$(PLATFORM_CXXSOURCES)) @@ -114,8 +125,8 @@ $(PLATFORM_OBJECTS): INCLUDES += -I$(VCS_HOME)/linux64/lib/ $(PLATFORM_OBJECTS): INCLUDES += -I$(BSG_MANYCORE_DIR)/testbenches/dpi/ $(PLATFORM_OBJECTS): INCLUDES += -I$(BASEJUMP_STL_DIR)/bsg_test/ $(PLATFORM_OBJECTS): INCLUDES += -I$(BLACKPARROT_DIR)/sdk/dromajo/include -$(PLATFORM_OBJECTS): CFLAGS := -std=c11 -fPIC -DVCS -D_GNU_SOURCE -DVERILATOR -D_BSD_SOURCE -D_XOPEN_SOURCE=500 $(INCLUDES) -$(PLATFORM_OBJECTS): CXXFLAGS := -std=c++11 -fPIC -DVCS -D_GNU_SOURCE -DVERILATOR -D_BSD_SOURCE -D_XOPEN_SOURCE=500 $(INCLUDES) +$(PLATFORM_OBJECTS): CFLAGS := -std=c11 -fPIC -DVCS -D_GNU_SOURCE -DVERILATOR -D_BSD_SOURCE -D_XOPEN_SOURCE=500 +$(PLATFORM_OBJECTS): CXXFLAGS := -std=c++11 -fPIC -DVCS -D_GNU_SOURCE -DVERILATOR -D_BSD_SOURCE -D_XOPEN_SOURCE=500 $(PLATFORM_OBJECTS): LDFLAGS := -fPIC $(PLATFORM_OBJECTS): RV_CXX = $(CXX) diff --git a/libraries/platforms/dromajo-vcs/link.mk b/libraries/platforms/dromajo-vcs/link.mk index 19805f254..2b804eea8 100644 --- a/libraries/platforms/dromajo-vcs/link.mk +++ b/libraries/platforms/dromajo-vcs/link.mk @@ -122,8 +122,12 @@ $(BSG_PLATFORM_PATH)/test.riscv: $(BSG_PLATFORM_PATH)/libbsg_manycore_platform.so.1.0: $(DROMAJO_OBJECTS) $(BSG_PLATFORM_PATH)/libbsg_manycore_platform.so.1.0: $(PLATFORM_OBJECTS) $(BSG_PLATFORM_PATH)/libbsg_manycore_platform.so.1.0: LDFLAGS := -fPIC +$(BSG_PLATFORM_PATH)/libbsg_manycore_platform.so.1.0: LDFLAGS += -L$(LIBRARIES_PATH)/features/dma/simulation -Wl,-rpath=$(LIBRARIES_PATH)/features/dma/simulation -ldmamem +$(BSG_PLATFORM_PATH)/libbsg_manycore_platform.so.1.0: $(LIBRARIES_PATH)/features/dma/simulation/libdmamem.so +$(BSG_PLATFORM_PATH)/libbsg_manycore_platform.so.1.0: LDFLAGS += -L$(LIBRARIES_PATH)/features/dma/simulation -Wl,-rpath=$(LIBRARIES_PATH)/features/dma/simulation -ldramsim3 +$(BSG_PLATFORM_PATH)/libbsg_manycore_platform.so.1.0: $(LIBRARIES_PATH)/features/dma/simulation/libdramsim3.so $(BSG_PLATFORM_PATH)/libbsg_manycore_platform.so.1.0: - $(CXX) -shared -Wl,-soname,$(basename $(notdir $@)) -o $@ $^ $(LDFLAGS) + $(CXX) -shared -Wl,-soname,$(basename $(notdir $@)) -o $@ $(DROMAJO_OBJECTS) $(PLATFORM_OBJECTS) $(LDFLAGS) $(BSG_PLATFORM_PATH)/libbsg_manycore_platform.so.1: %: %.0 ln -sf $@.0 $@ @@ -176,6 +180,8 @@ platform.link.clean: rm -rf *.vcs.log rm -rf vc_hdrs.h rm -rf *.debug *.profile *.saifgen *.exec + rm -rf *.elf + rm -rf $(BSG_PLATFORM_PATH)/*.riscv link.clean: platform.link.clean ; From b7f2542657713422ac809c10b9391800bc741992 Mon Sep 17 00:00:00 2001 From: sripathi-muralitharan Date: Mon, 3 May 2021 11:20:06 -0700 Subject: [PATCH 24/70] Various fixes * Adding another host EPA to check if reset is done * Wrapping bsg_dpi_next in advance_time for global access * Making cosim_main visible to VCS --- .../dromajo-vcs/bsg_manycore_simulator.cpp | 92 +++++++++---------- 1 file changed, 43 insertions(+), 49 deletions(-) diff --git a/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.cpp b/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.cpp index 0bf63616a..303c1dc3e 100644 --- a/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.cpp +++ b/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.cpp @@ -76,10 +76,21 @@ bsg_nonsynth_dpi::dpi_manycore *dpi; // Define invisible library functions declare_hb_mc_get_bits +// Advance time +void advance_time() { + std::string mc_dpi = "replicant_tb_top.mc_dpi"; + void *top = svGetScopeFromName(mc_dpi.c_str()); + svScope prev; + prev = svSetScope(top); + bsg_dpi_next(); + svSetScope(prev); +} + ////////////////////////////// SimulationWrapper functions ////////////////////////////// SimulationWrapper::SimulationWrapper(){ root = new std::string("replicant_tb_top"); + // These are not used since we need them globally std::string mc_dpi = *root + ".mc_dpi"; top = svGetScopeFromName(mc_dpi.c_str()); } @@ -112,10 +123,7 @@ void SimulationWrapper::eval(){ dromajo_set_credits(); // Advance time 1 unit - svScope prev; - prev = svSetScope(top); - bsg_dpi_next(); - svSetScope(prev); + advance_time(); } SimulationWrapper::~SimulationWrapper(){ @@ -139,7 +147,7 @@ static int dpi_fifo_drain(bsg_nonsynth_dpi::dpi_manycore *dpi, int cap = dpi->config[HB_MC_CONFIG_IO_REMOTE_LOAD_CAP]; do { - bsg_dpi_next(); + advance_time(); switch(type) { case HB_MC_FIFO_RX_REQ: err = dpi->rx_req(*pkt); @@ -154,12 +162,13 @@ static int dpi_fifo_drain(bsg_nonsynth_dpi::dpi_manycore *dpi, if (err == BSG_NONSYNTH_DPI_SUCCESS) drains++; - } while ((err == BSG_NONSYNTH_DPI_NOT_WINDOW | err == BSG_NONSYNTH_DPI_SUCCESS) + } while ((err == BSG_NONSYNTH_DPI_NOT_WINDOW || err == BSG_NONSYNTH_DPI_SUCCESS) && drains <= cap); - if (drains != cap) + if (drains == cap) { printf("[BSG_ERROR] Failed to drain FIFO\n"); return HB_MC_FAIL; + } return HB_MC_SUCCESS; } @@ -181,7 +190,7 @@ static void dpi_clean(bsg_nonsynth_dpi::dpi_manycore *dpi) { * @returns success if initialized correctly */ static int dpi_init(bsg_nonsynth_dpi::dpi_manycore *dpi, std::string hierarchy) { - bsg_dpi_next(); + advance_time(); dpi = new bsg_nonsynth_dpi::dpi_manycore(hierarchy + ".mc_dpi"); @@ -201,23 +210,6 @@ static int dpi_init(bsg_nonsynth_dpi::dpi_manycore *dpi, std:: return HB_MC_SUCCESS; } -/* - * dpi_wait_for_reset - * Ensures that the manycore hardware is reset - * @params[in] dpi - Pointer to the manycore DPI object - */ -static int dpi_wait_for_reset(bsg_nonsynth_dpi::dpi_manycore *dpi) { - bool done; - dpi->reset_is_done(done); - - while (!done) { - bsg_dpi_next(); - dpi->reset_is_done(done); - } - - return HB_MC_SUCCESS; -} - ////////////////////////////// Dromajo helper functions ////////////////////////////// /* @@ -317,6 +309,14 @@ void dromajo_transmit_packet() { idx = packet.request.addr; data = dpi->config[idx]; } + else if (packet.request.addr == 0x200) { + bool done; + dpi->reset_is_done(done); + if (done) + data = 1; + else + data = 0; + } else printf("[BSG_ERROR] Host EPA not mapped\n"); @@ -403,7 +403,7 @@ void dromajo_set_credits() { * @params[in] args - Pointer to a character array that holds the arguments * @returns the number of arguments */ -int get_argc(char * args){ +static int get_argc(char * args){ char *cur = args, prev=' '; int count = 1; while(*cur != '\0'){ @@ -424,8 +424,7 @@ int get_argc(char * args){ * @params[in] argv - Pointer to an array of strings that will hold the different * arguments */ -static -void get_argv(char * args, int argc, char **argv){ +static void get_argv(char * args, int argc, char **argv){ int count = 0; char *cur = args, prev=' '; @@ -490,14 +489,7 @@ int vcs_main(int argc, char **argv) { return HB_MC_FAIL; } - // Wait for reset to be done - err = dpi_wait_for_reset(dpi); - if (err != HB_MC_SUCCESS) { - dpi_clean(dpi); - delete sim; - printf("[BSG_ERROR] Failed to wait for reset!\nExiting...\n"); - return HB_MC_FAIL; - } + printf("[BSG_INFO] DPI Initialized!\n"); while(1) sim->eval(); @@ -512,17 +504,19 @@ int vcs_main(int argc, char **argv) { * @params[in] args - A character array that holds the space-separated * arguments to the function */ -void cosim_main(uint32_t *exit_code, char *args) { - // We aren't passed command line arguments directly so we parse them - // from *args. args is a string from VCS - to pass a string of arguments - // to args, pass c_args to VCS as follows: +c_args="" - int argc = get_argc(args); - char *argv[argc]; - get_argv(args, argc, argv); - - int rc = vcs_main(argc, argv); - *exit_code = rc; - bsg_pr_test_pass_fail(rc == HB_MC_SUCCESS); - return; +extern "C" { + void cosim_main(uint32_t *exit_code, char *args) { + // We aren't passed command line arguments directly so we parse them + // from *args. args is a string from VCS - to pass a string of arguments + // to args, pass c_args to VCS as follows: +c_args="" + int argc = get_argc(args); + char *argv[argc]; + get_argv(args, argc, argv); + + int rc = vcs_main(argc, argv); + *exit_code = rc; + bsg_pr_test_pass_fail(rc == HB_MC_SUCCESS); + return; + } } From f12564b8c279e915f0700f5c1d1d105cb4383ed3 Mon Sep 17 00:00:00 2001 From: sripathi-muralitharan Date: Mon, 3 May 2021 11:21:50 -0700 Subject: [PATCH 25/70] Implementing wait for reset platform call --- .../dromajo-vcs/bsg_manycore_platform.cpp | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/libraries/platforms/dromajo-vcs/bsg_manycore_platform.cpp b/libraries/platforms/dromajo-vcs/bsg_manycore_platform.cpp index d25c8855b..2ad7117e4 100644 --- a/libraries/platforms/dromajo-vcs/bsg_manycore_platform.cpp +++ b/libraries/platforms/dromajo-vcs/bsg_manycore_platform.cpp @@ -310,6 +310,20 @@ int hb_mc_platform_log_disable(hb_mc_manycore_t *mc) { * @return HB_MC_SUCCESS on success. Otherwise an error code defined in bsg_manycore_errno.h. */ int hb_mc_platform_wait_reset_done(hb_mc_manycore_t *mc) { - // Reset is guaranteed to be complete before program starts by the simulation wrapper - return HB_MC_SUCCESS; + hb_mc_packet_t req_pkt, resp_pkt; + int err; + + req_pkt.request.x_src = 0; + req_pkt.request.y_src = 1; + req_pkt.request.x_dst = 0; + req_pkt.request.y_dst = 0; + req_pkt.request.op_v2 = HB_MC_PACKET_OP_REMOTE_LOAD; + req_pkt.request.payload = 0; + req_pkt.request.reg_id = 0; + req_pkt.request.addr = 0x200; + + do { + bp_hb_write_to_manycore_bridge(&req_pkt); + err = bp_hb_read_from_manycore_bridge(&resp_pkt, HB_MC_FIFO_RX_RSP); + } while((err != HB_MC_SUCCESS) && (resp_pkt.response.data == 1)); } From 401a9a76f14c55fdd01a893604c810fb9c2ce914 Mon Sep 17 00:00:00 2001 From: sripathi-muralitharan Date: Mon, 3 May 2021 11:22:37 -0700 Subject: [PATCH 26/70] Using dpi_top.sv from dromajo-vcs instead of bigblade-vcs --- libraries/platforms/dromajo-vcs/hardware.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/platforms/dromajo-vcs/hardware.mk b/libraries/platforms/dromajo-vcs/hardware.mk index 17db5eca2..e411de4dd 100644 --- a/libraries/platforms/dromajo-vcs/hardware.mk +++ b/libraries/platforms/dromajo-vcs/hardware.mk @@ -143,7 +143,7 @@ VSOURCES += $(BASEJUMP_STL_DIR)/bsg_test/bsg_nonsynth_dpi_cycle_counter.v # Top-level module name BSG_DESIGN_TOP := replicant_tb_top -VSOURCES += $(LIBRARIES_PATH)/platforms/bigblade-vcs/hardware/dpi_top.sv +VSOURCES += $(LIBRARIES_PATH)/platforms/dromajo-vcs/hardware/dpi_top.sv VINCLUDES += $(BSG_PLATFORM_PATH)/hardware VINCLUDES += $(BSG_PLATFORM_PATH) From 2de2c408501f5e4b7921b03ff834c9a3be0fb70f Mon Sep 17 00:00:00 2001 From: sripathi-muralitharan Date: Thu, 6 May 2021 13:39:41 -0700 Subject: [PATCH 27/70] Specifies objects explicitly to link * Using the makefile prerequisite variables spuriously includes objects from the simulation features for DMA that are required for the hardware but not implemented as a feature for the RISC-V host --- libraries/libraries.mk | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/libraries/libraries.mk b/libraries/libraries.mk index 57ae73359..c935a9f15 100644 --- a/libraries/libraries.mk +++ b/libraries/libraries.mk @@ -131,8 +131,9 @@ $(LIB_STRICT_OBJECTS): CXXFLAGS += -Wno-unused-but-set-variable ifdef __NEWLIB LIB_OBJECTS += $(patsubst %S,%o,$(LIB_SSOURCES)) +$(BSG_PLATFORM_PATH)/libbsg_manycore_runtime.so.1.0: LDFLAGS := $(BSG_PLATFORM_PATH)/libbsg_manycore_runtime.so.1.0: $(LIB_OBJECTS) - $(RV_AR) -rcs $@ $^ + $(RV_AR) -rcs $@ $(LIB_OBJECTS) $(DMA_FEATURE_OBJECTS) else $(BSG_PLATFORM_PATH)/libbsg_manycore_runtime.so.1.0: LD = $(CXX) $(BSG_PLATFORM_PATH)/libbsg_manycore_runtime.so.1.0: $(LIB_OBJECTS) @@ -143,8 +144,9 @@ $(BSG_PLATFORM_PATH)/libbsgmc_cuda_legacy_pod_repl.so.1.0: LDFLAGS := $(BSG_PLATFORM_PATH)/libbsgmc_cuda_legacy_pod_repl.so.1.0: INCLUDES := ifdef __NEWLIB +$(BSG_PLATFORM_PATH)/libbsgmc_cuda_legacy_pod_repl.so.1.0: LDFLAGS := $(BSG_PLATFORM_PATH)/libbsgmc_cuda_legacy_pod_repl.so.1.0: $(LIB_OBJECTS_CUDA_POD_REPL) - $(RV_AR) -rcs $@ $^ + $(RV_AR) -rcs $@ $(LIB_OBJECTS_CUDA_POD_REPL) else $(BSG_PLATFORM_PATH)/libbsgmc_cuda_legacy_pod_repl.so.1.0: LD = $(CXX) $(BSG_PLATFORM_PATH)/libbsgmc_cuda_legacy_pod_repl.so.1.0: $(LIB_OBJECTS_CUDA_POD_REPL) @@ -155,8 +157,9 @@ $(BSG_PLATFORM_PATH)/libbsg_manycore_regression.so.1.0: LDFLAGS := $(BSG_PLATFORM_PATH)/libbsg_manycore_regression.so.1.0: INCLUDES := ifdef __NEWLIB +$(BSG_PLATFORM_PATH)/libbsg_manycore_regression.so.1.0: LDFLAGS := $(BSG_PLATFORM_PATH)/libbsg_manycore_regression.so.1.0: $(LIB_OBJECTS_REGRESSION) - $(RV_AR) -rcs $@ $^ + $(RV_AR) -rcs $@ $(LIB_OBJECTS_REGRESSION) else $(BSG_PLATFORM_PATH)/libbsg_manycore_regression.so.1.0: LD = $(CXX) $(BSG_PLATFORM_PATH)/libbsg_manycore_regression.so.1.0: $(LIB_OBJECTS_REGRESSION) From 3922ee0c737d282773dacf2ab71c0cacd3497f60 Mon Sep 17 00:00:00 2001 From: sripathi-muralitharan Date: Thu, 6 May 2021 13:49:25 -0700 Subject: [PATCH 28/70] Multiple fixes * Refactors the simulation wrapper * Multiple bug fixes to the platform calls and argument retrieval * test_coordinate and test_get_cycle works --- .../dromajo-vcs/bsg_manycore_platform.cpp | 16 +- .../bsg_manycore_regression_platform.h | 92 +++++ .../dromajo-vcs/bsg_manycore_simulator.cpp | 389 ++++++++++-------- .../dromajo-vcs/bsg_manycore_simulator.hpp | 107 +++++ libraries/platforms/dromajo-vcs/library.mk | 1 - .../platforms/dromajo-vcs/software/src/args.c | 18 +- .../dromajo-vcs/software/src/bp_utils.c | 12 +- 7 files changed, 440 insertions(+), 195 deletions(-) create mode 100644 libraries/platforms/dromajo-vcs/bsg_manycore_simulator.hpp diff --git a/libraries/platforms/dromajo-vcs/bsg_manycore_platform.cpp b/libraries/platforms/dromajo-vcs/bsg_manycore_platform.cpp index 2ad7117e4..de457f28d 100644 --- a/libraries/platforms/dromajo-vcs/bsg_manycore_platform.cpp +++ b/libraries/platforms/dromajo-vcs/bsg_manycore_platform.cpp @@ -193,7 +193,12 @@ int hb_mc_platform_get_config_at(hb_mc_manycore_t *mc, unsigned int idx, hb_mc_c int err = bp_hb_read_from_manycore_bridge(&resp_pkt, HB_MC_FIFO_RX_RSP); if (err != 0) return HB_MC_FAIL; - *config = resp_pkt.response.data; + + uint32_t data = resp_pkt.response.data; + if (data != 0xFFFFFFFF) + *config = data; + else + *config = 0; return HB_MC_SUCCESS; } @@ -312,6 +317,7 @@ int hb_mc_platform_log_disable(hb_mc_manycore_t *mc) { int hb_mc_platform_wait_reset_done(hb_mc_manycore_t *mc) { hb_mc_packet_t req_pkt, resp_pkt; int err; + uint32_t data; req_pkt.request.x_src = 0; req_pkt.request.y_src = 1; @@ -325,5 +331,11 @@ int hb_mc_platform_wait_reset_done(hb_mc_manycore_t *mc) { do { bp_hb_write_to_manycore_bridge(&req_pkt); err = bp_hb_read_from_manycore_bridge(&resp_pkt, HB_MC_FIFO_RX_RSP); - } while((err != HB_MC_SUCCESS) && (resp_pkt.response.data == 1)); + data = resp_pkt.response.data; + } while((err != HB_MC_SUCCESS) && (data != 1)); + + if (data == 0) + return HB_MC_FAIL; + + return HB_MC_SUCCESS; } diff --git a/libraries/platforms/dromajo-vcs/bsg_manycore_regression_platform.h b/libraries/platforms/dromajo-vcs/bsg_manycore_regression_platform.h index 1c51de2f4..28fb35e3b 100644 --- a/libraries/platforms/dromajo-vcs/bsg_manycore_regression_platform.h +++ b/libraries/platforms/dromajo-vcs/bsg_manycore_regression_platform.h @@ -37,3 +37,95 @@ extern "C" { return ((val & mask) >> start); \ } \ +#define declare_bsg_printing \ + typedef struct prefix_info { \ + FILE *file; \ + bool newline; \ + void (*newline_hook)(struct prefix_info *info, const char *prefix); \ +} prefix_info_t; \ + \ +/* inserts the time into the prefix */ \ +static void insert_time(prefix_info_t *info, const char *prefix) \ +{ \ + fprintf(info->file, "%s @ (%llu): ", prefix, bsg_utc()); \ + return; \ +} \ + \ +typedef std::map prefix_map; \ + \ +static prefix_map fmap = { \ + {BSG_PRINT_PREFIX_DEBUG, {BSG_PRINT_STREAM_DEBUG, true, insert_time}}, \ + {BSG_PRINT_PREFIX_ERROR, {BSG_PRINT_STREAM_ERROR, true, 0}}, \ + {BSG_PRINT_PREFIX_WARN, {BSG_PRINT_STREAM_WARN, true, 0}}, \ + {BSG_PRINT_PREFIX_INFO, {BSG_PRINT_STREAM_INFO, true, 0}}, \ +}; \ + \ +int bsg_pr_prefix(const char *prefix, const char *fmt, ...) \ +{ \ + std::string prefix_string(prefix); \ + std::string fmt_string(fmt); \ + prefix_info_t *info; \ + va_list ap; \ + int r = -1, count = 0; \ + bool newline; \ + \ + auto it = fmap.find(prefix_string); \ + if (it != fmap.end()) { \ + info = &it->second; \ + } else { \ + return r; \ + } \ + \ + /* lock our file to make our print atomic */ \ + flockfile(info->file); \ + va_start(ap, fmt); \ + newline = info->newline; \ + \ + std::string::size_type cl_start = 0, cl_end; \ + do { /* for each line in fmt */ \ + /* find end of line */ \ + cl_end = fmt_string.find('\n', cl_start); \ + cl_end = (cl_end == std::string::npos ? fmt_string.size() : cl_end); \ + \ + /* print prefix if this is the start of a new line */ \ + if (newline) { \ + if (info->newline_hook) { \ + info->newline_hook(info, prefix); \ + } else { \ + fprintf(info->file, "%s", prefix); \ + } \ + } \ + \ + /* print to the end of the line */ \ + std::string lfmt = fmt_string.substr(cl_start, cl_end-cl_start); \ + \ + count += vfprintf(info->file, lfmt.c_str(), ap); \ + \ + /* move cl_start forward */ \ + cl_start = cl_end; \ + \ + /* decide on newline */ \ + if (cl_end != fmt_string.size()) { \ + /* print the newline character and set 'newline' to true */ \ + count += fprintf(info->file, "\n"); \ + cl_start++; /* advance one so we don't print the 'newline' twice */ \ + newline = true; \ + } else { \ + /* this was the last line printed */ \ + /* if it was an empty line just set newline to false */ \ + newline = lfmt.empty() ? true : false; \ + } \ + \ + /* until we've reached the end of our format string */ \ + } while (cl_start < fmt_string.size()); \ + \ + /* success */ \ + r = count; \ + \ + exit_func: \ + /* setup for the next call */ \ + info->newline = newline; \ + va_end(ap); \ + funlockfile(info->file); \ + return r; \ +} \ diff --git a/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.cpp b/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.cpp index 303c1dc3e..b97fd68c3 100644 --- a/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.cpp +++ b/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.cpp @@ -29,23 +29,6 @@ // differences in simulators. #include -#include -#include -#include -#include - -#include -#include - -#include -#include - -#include -#include -#include -#include -#include - #include // We use __m128i so that we can pass a 128-bit type between Verilog // and C. @@ -56,43 +39,43 @@ extern "C" { void bsg_dpi_next(); } -// Dromajo specifics -dromajo_cosim_state_t *dromajo_state; -dromajo_cosim_state_t* dromajo_init(); -bool dromajo_step(); -void dromajo_transmit_packet(); -void dromajo_receive_packet(); -void dromajo_set_credits(); - // Global variables to store arguments int _argc; char **_argv; static int char_index = 0; int idx = 0; -// DPI object -bsg_nonsynth_dpi::dpi_manycore *dpi; - -// Define invisible library functions -declare_hb_mc_get_bits - -// Advance time -void advance_time() { - std::string mc_dpi = "replicant_tb_top.mc_dpi"; - void *top = svGetScopeFromName(mc_dpi.c_str()); - svScope prev; - prev = svSetScope(top); - bsg_dpi_next(); - svSetScope(prev); -} - ////////////////////////////// SimulationWrapper functions ////////////////////////////// +// Constructor SimulationWrapper::SimulationWrapper(){ root = new std::string("replicant_tb_top"); - // These are not used since we need them globally std::string mc_dpi = *root + ".mc_dpi"; top = svGetScopeFromName(mc_dpi.c_str()); + dpi = new bsg_nonsynth_dpi::dpi_manycore(mc_dpi); + + // Initialize DPI and Dromajo + dromajo_init(); + dpi_init(); + + if ((!dromajo) || (!dpi)) { + bsg_pr_err("Failed to initialize DPI pointer\n"); + } +} + +// Destructor +SimulationWrapper::~SimulationWrapper(){ + dpi_cleanup(); + dromajo_cosim_fini(dromajo); + this->top = nullptr; +} + +// Causes time to proceed by 1 unit +void SimulationWrapper::advance_time() { + svScope prev; + prev = svSetScope(top); + bsg_dpi_next(); + svSetScope(prev); } // Does nothing. Turning on/off assertions is only supported in @@ -105,33 +88,15 @@ std::string SimulationWrapper::getRoot(){ return *root; } -void SimulationWrapper::eval(){ - // Execute one instruction on Dromajo - if (!dromajo_step()) { - // Fixme: Dromajo could also terminate due to premature errors. - // Use the test outputs to detect PASS/FAIL - printf("Dromajo Execution Complete!\nExiting...\n"); - dromajo_cosim_fini(dromajo_state); - exit(0); - } - - // Poll for packets to be transmitted - dromajo_transmit_packet(); - // Poll for packets to be received - dromajo_receive_packet(); - // Update the credits in dromajo - dromajo_set_credits(); - - // Advance time 1 unit - advance_time(); -} - -SimulationWrapper::~SimulationWrapper(){ - this->top = nullptr; +/* + * dpi_cleanup + * Destroys the pointer to the manycore DPI object + * @params[in] dpi - Pointer to the manycore DPI object + */ +void SimulationWrapper::dpi_cleanup() { + delete dpi; } -////////////////////////////// DPI helper functions ////////////////////////////// - /* * dpi_fifo_drain * Drains all DPI fifos. This function is used during initialization and does not push packets @@ -140,7 +105,7 @@ SimulationWrapper::~SimulationWrapper(){ * @param[in] type - Manycore FIFO type * @returns success if all the FIFOs were drained correctly */ -static int dpi_fifo_drain(bsg_nonsynth_dpi::dpi_manycore *dpi, hb_mc_fifo_rx_t type) { +int SimulationWrapper::dpi_fifo_drain(hb_mc_fifo_rx_t type) { __m128i *pkt; int err, drains = 0; @@ -148,6 +113,7 @@ static int dpi_fifo_drain(bsg_nonsynth_dpi::dpi_manycore *dpi, do { advance_time(); + switch(type) { case HB_MC_FIFO_RX_REQ: err = dpi->rx_req(*pkt); @@ -156,7 +122,7 @@ static int dpi_fifo_drain(bsg_nonsynth_dpi::dpi_manycore *dpi, err = dpi->rx_rsp(*pkt); break; default: - printf("[BSG_ERROR] Unknown FIFO type\n"); + bsg_pr_err("Unknown FIFO type\n"); return HB_MC_FAIL; } @@ -166,22 +132,13 @@ static int dpi_fifo_drain(bsg_nonsynth_dpi::dpi_manycore *dpi, && drains <= cap); if (drains == cap) { - printf("[BSG_ERROR] Failed to drain FIFO\n"); + bsg_pr_err("Failed to drain FIFO\n"); return HB_MC_FAIL; } return HB_MC_SUCCESS; } -/* - * dpi_clean - * Destroys the pointer to the manycore DPI object - * @params[in] dpi - Pointer to the manycore DPI object - */ -static void dpi_clean(bsg_nonsynth_dpi::dpi_manycore *dpi) { - delete dpi; -} - /* * dpi_init * Initializes the DPI between the manycore and Dromajo @@ -189,53 +146,49 @@ static void dpi_clean(bsg_nonsynth_dpi::dpi_manycore *dpi) { * @params[in] hierarchy - A C++ string that holds the manycore hierarchy * @returns success if initialized correctly */ -static int dpi_init(bsg_nonsynth_dpi::dpi_manycore *dpi, std::string hierarchy) { +int SimulationWrapper::dpi_init() { advance_time(); - dpi = new bsg_nonsynth_dpi::dpi_manycore(hierarchy + ".mc_dpi"); - int err; - err = dpi_fifo_drain(dpi, HB_MC_FIFO_RX_REQ); + + err = dpi_fifo_drain(HB_MC_FIFO_RX_REQ); if (err != HB_MC_SUCCESS) { - dpi_clean(dpi); + dpi_cleanup(); return err; } - err = dpi_fifo_drain(dpi, HB_MC_FIFO_RX_RSP); + err = dpi_fifo_drain(HB_MC_FIFO_RX_RSP); if (err != HB_MC_SUCCESS) { - dpi_clean(dpi); + dpi_cleanup(); return err; } return HB_MC_SUCCESS; } -////////////////////////////// Dromajo helper functions ////////////////////////////// - /* * dromajo_init * Initializes dromajo with the correct command-line arguments * @returns a pointer to a dromajo_cosim_state_t object */ -dromajo_cosim_state_t* dromajo_init() { - dromajo_cosim_state_t *dromajo_state; - - char dromajo[50]; - sprintf(dromajo, "dromajo"); - - char host[50]; - sprintf(host, "--host"); - - char manycore[50]; - sprintf(manycore, "--manycore"); - - char progname[50]; - sprintf(progname, "test.elf"); - - char* argv[] = {dromajo, host, manycore, progname}; - dromajo_state = dromajo_cosim_init(4, argv); - - return dromajo_state; +int SimulationWrapper::dromajo_init() { + char dromajo_str[50]; + char host_str[50]; + char manycore_str[50]; + char prog_str[50]; + + sprintf(dromajo_str, "dromajo"); + sprintf(host_str, "--host"); + sprintf(manycore_str, "--manycore"); + sprintf(prog_str, "test.elf"); + + char* argv[] = {dromajo_str, host_str, manycore_str, prog_str}; + dromajo = dromajo_cosim_init(4, argv); + if (!dromajo) { + bsg_pr_err("Failed to initialize Dromajo!\n"); + return HB_MC_FAIL; + } + return HB_MC_SUCCESS; } /* @@ -243,9 +196,9 @@ dromajo_cosim_state_t* dromajo_init() { * Executes 1 instruction in Dromajo * @returns true if execution is incomplete and/or without errors */ -bool dromajo_step() { +bool SimulationWrapper::dromajo_step() { // Execute dromajo with verbose mode on - int err = dromajo_cosim_step(dromajo_state, 0, 0, 0, 0, 0, false, true); + int err = dromajo_cosim_step(dromajo, 0, 0, 0, 0, 0, false, false); if (err != 0) return false; else @@ -256,37 +209,41 @@ bool dromajo_step() { * dromajo_transmit_packet * Fetches data from the Dromajo->Manycore FIFO and pushes it into the DPI FIFO * to send packets to the manycore + * @returns success on succesful transmission */ -void dromajo_transmit_packet() { - hb_mc_packet_t packet, host_resp_packet; +int SimulationWrapper::dromajo_transmit_packet() { + hb_mc_packet_t dromajo_to_mc_packet, host_to_dromajo_packet; int err; __m128i *pkt; - // Check if FIFO is full and hence ready to transmit + // Check if FIFO has an element and hence ready to transmit mc_fifo_type_t type = FIFO_HOST_TO_MC_REQ; - bool is_full = mc_is_fifo_full(type); + bool is_empty = mc_is_fifo_empty(type); - if (is_full) { + if (!is_empty) { // Read the FIFO head pointer for all 32-bit FIFOs - packet.words[0] = host_to_mc_req_fifo->fifo[0].front(); - packet.words[1] = host_to_mc_req_fifo->fifo[1].front(); - packet.words[2] = host_to_mc_req_fifo->fifo[2].front(); - packet.words[3] = host_to_mc_req_fifo->fifo[3].front(); + dromajo_to_mc_packet.words[0] = host_to_mc_req_fifo->fifo[0].front(); + dromajo_to_mc_packet.words[1] = host_to_mc_req_fifo->fifo[1].front(); + dromajo_to_mc_packet.words[2] = host_to_mc_req_fifo->fifo[2].front(); + dromajo_to_mc_packet.words[3] = host_to_mc_req_fifo->fifo[3].front(); // Intercept packets that are for the host and generate appropriate responses - if ((packet.request.x_dst == 0) && (packet.request.y_dst == 0)) { - host_resp_packet.response.x_dst = packet.request.x_src; - host_resp_packet.response.y_dst = packet.request.y_src; - host_resp_packet.response.load_id = 0; - if (packet.request.op_v2 == HB_MC_PACKET_OP_REMOTE_LOAD) { - host_resp_packet.response.op = packet.request.op_v2; - idx = packet.request.addr; + if ((dromajo_to_mc_packet.request.x_dst == 0) && (dromajo_to_mc_packet.request.y_dst == 0)) { + host_to_dromajo_packet.response.x_dst = dromajo_to_mc_packet.request.x_src; + host_to_dromajo_packet.response.y_dst = dromajo_to_mc_packet.request.y_src; + host_to_dromajo_packet.response.load_id = 0; + + if (dromajo_to_mc_packet.request.op_v2 == HB_MC_PACKET_OP_REMOTE_LOAD) { + host_to_dromajo_packet.response.op = dromajo_to_mc_packet.request.op_v2; + uint32_t idx = dromajo_to_mc_packet.request.addr; uint32_t data = 0; + // If EPA maps to reading arguments - if (packet.request.addr >= 0 && packet.request.addr <= 0xFF) { + if (dromajo_to_mc_packet.request.addr >= 0 && dromajo_to_mc_packet.request.addr <= 0xFF) { int num_characters = 0; - // If all arguments have been read, send this finish code - if (idx == _argc) { + // If all arguments have been read or there are no arguments to read + // send a finish code + if ((idx == _argc) || (_argc == 0)) { data = 0xFFFFFFFF; } else { @@ -304,12 +261,17 @@ void dromajo_transmit_packet() { } } } + // Dromajo/BlackParrot wants to read the config - else if (packet.request.addr >= 0x100 && packet.request.addr <= 0x1FF) { - idx = packet.request.addr; - data = dpi->config[idx]; + else if (dromajo_to_mc_packet.request.addr >= 0x100 && dromajo_to_mc_packet.request.addr <= 0x1FF) { + idx = dromajo_to_mc_packet.request.addr - 0x100; + if (idx <= HB_MC_CONFIG_MAX) + data = dpi->config[idx]; + else + data = 0xFFFFFFFF; } - else if (packet.request.addr == 0x200) { + + else if (dromajo_to_mc_packet.request.addr == 0x200) { bool done; dpi->reset_is_done(done); if (done) @@ -317,33 +279,56 @@ void dromajo_transmit_packet() { else data = 0; } - else - printf("[BSG_ERROR] Host EPA not mapped\n"); - host_resp_packet.response.data = data; + else { + bsg_pr_err("Host EPA not mapped\n"); + return HB_MC_FAIL; + } + + host_to_dromajo_packet.response.data = data; // Inject the response packet into manycore response FIFO // Pop the request FIFO for(int j = 0; j < 4; j++) { - mc_to_host_resp_fifo->fifo[j].push(host_resp_packet.words[j]); + mc_to_host_resp_fifo->fifo[j].push(host_to_dromajo_packet.words[j]); host_to_mc_req_fifo->fifo[j].pop(); } } - else - printf("[BSG_ERROR] Operations other than loads are not implemented for the host\n"); + else { + bsg_pr_err("Operations other than loads are not implemented for the host\n"); + return HB_MC_FAIL; + } } else { - pkt = reinterpret_cast<__m128i *>(&packet); - - // Try to transmit until you actually can - err = dpi->tx_req(*pkt); + pkt = reinterpret_cast<__m128i *>(&dromajo_to_mc_packet); + + // Attempt packet transmission + // Since we trigger a call to the transmit FIFOs only when the Dromajo + // FIFOs are full, we need to wait until the DPI FIFOs are ready to receive + // before advancing to the next operation. This can prevent filling up of the + // FIFOs. However, not doing this can help in identifying situations that might + // create backpressure in actual hardware and provision for it. + do { + advance_time(); + err = dpi->tx_req(*pkt); + } while (err != BSG_NONSYNTH_DPI_SUCCESS && + (err == BSG_NONSYNTH_DPI_NO_CREDITS || + err == BSG_NONSYNTH_DPI_NOT_WINDOW || + err == BSG_NONSYNTH_DPI_BUSY || + err == BSG_NONSYNTH_DPI_NOT_READY)); // Pop the FIFO once transmitted if (err == BSG_NONSYNTH_DPI_SUCCESS) { for (int i = 0;i < 4; i++) host_to_mc_req_fifo->fifo[i].pop(); } + else { + bsg_pr_err("Packet transmission failed\n"); + return HB_MC_FAIL; + } } } + + return HB_MC_SUCCESS; } /* @@ -351,32 +336,53 @@ void dromajo_transmit_packet() { * Receives packets from the DPI FIFOs and pushes the data into the * manycore request and response FIFOs in Dromajo */ -void dromajo_receive_packet() { - hb_mc_packet_t *req_packet, *resp_packet; +int SimulationWrapper::dromajo_receive_packet() { + hb_mc_packet_t *mc_to_dromajo_req_packet, *mc_to_dromajo_resp_packet; int err; - __m128i *pkt; + __m128i pkt; // Read from the manycore request FIFO - err = dpi->rx_req(*pkt); - req_packet = reinterpret_cast(pkt); + // At every time step we are polling the request FIFO to see if there + // is a packet. If there is no packet (i.e err == BSG_NONSYNTH_NOT_VALID) + // we must move on + do { + advance_time(); + err = dpi->rx_req(pkt); + } while (err != BSG_NONSYNTH_DPI_SUCCESS && + (err == BSG_NONSYNTH_DPI_NOT_WINDOW || + err == BSG_NONSYNTH_DPI_BUSY )); - // Push to host FIFO if valid if (err == BSG_NONSYNTH_DPI_SUCCESS) { + mc_to_dromajo_req_packet = reinterpret_cast(&pkt); for (int i = 0; i < 4; i++) { - mc_to_host_req_fifo->fifo[i].push(req_packet->words[i]); + mc_to_host_req_fifo->fifo[i].push(mc_to_dromajo_req_packet->words[i]); } } + else if (err != BSG_NONSYNTH_DPI_NOT_VALID){ + bsg_pr_err("Failed to receive manycore request packet"); + return HB_MC_FAIL; + } // Read from the manycore response FIFO - err = dpi->rx_rsp(*pkt); - resp_packet = reinterpret_cast(pkt); + do { + advance_time(); + err = dpi->rx_rsp(pkt); + } while (err != BSG_NONSYNTH_DPI_SUCCESS && + (err == BSG_NONSYNTH_DPI_NOT_WINDOW || + err == BSG_NONSYNTH_DPI_BUSY )); - // Push to host FIFO if valid if (err == BSG_NONSYNTH_DPI_SUCCESS) { + mc_to_dromajo_resp_packet = reinterpret_cast(&pkt); for (int i = 0; i < 4; i++) { - mc_to_host_resp_fifo->fifo[i].push(resp_packet->words[i]); + mc_to_host_resp_fifo->fifo[i].push(mc_to_dromajo_resp_packet->words[i]); } } + else if (err != BSG_NONSYNTH_DPI_NOT_VALID) { + bsg_pr_err("Failed to receive manycore response packet"); + return HB_MC_FAIL; + } + + return HB_MC_SUCCESS; } /* @@ -384,15 +390,55 @@ void dromajo_receive_packet() { * Polls the hardware for credit information and sets the credits info * for the Dromajo->Manycore request FIFO in dromajo */ -void dromajo_set_credits() { +int SimulationWrapper::dromajo_set_credits() { int credits; - int res = dpi->get_credits(credits); - if (res == BSG_NONSYNTH_DPI_SUCCESS) { + int err = dpi->get_credits(credits); + if (err == BSG_NONSYNTH_DPI_SUCCESS) { if (credits < 0) - printf("[BSG_WARN] Warning! Credit value is negative!\n"); + bsg_pr_warn("Credit value is negative!\n"); host_to_mc_req_fifo->credits = credits; } + else { + bsg_pr_err(bsg_nonsynth_dpi_strerror(err)); + return HB_MC_FAIL; + } + + return HB_MC_SUCCESS; +} + +int SimulationWrapper::eval(){ + // Execute one instruction on Dromajo + if (!dromajo_step()) { + // Fixme: Dromajo could also terminate due to premature errors. + // Use the test outputs to detect PASS/FAIL + bsg_pr_info("Dromajo Execution Complete!\nExiting...\n"); + dromajo_cosim_fini(dromajo); + return HB_MC_SUCCESS; + } + + int err; + // Poll for packets to be transmitted + bsg_pr_dbg("Checking for packets to transmit\n"); + err = dromajo_transmit_packet(); + if (err != HB_MC_SUCCESS) + return err; + + // Poll for packets to be received + bsg_pr_dbg("Checking for packets to receive\n"); + err = dromajo_receive_packet(); + if (err != HB_MC_SUCCESS) + return err; + + // Update the credits in dromajo + bsg_pr_dbg("Checking for credits\n"); + err = dromajo_set_credits(); + if (err != HB_MC_SUCCESS) + return err; + + // Advance time 1 unit + advance_time(); + return HB_MC_SUCCESS; } ////////////////////////////// Interacting with VCS ////////////////////////////// @@ -471,30 +517,19 @@ int vcs_main(int argc, char **argv) { _argc = argc; _argv = argv; - - // Initialize Dromajo - dromajo_state = dromajo_init(); - - // Create an object of the simulation wrapper - SimulationWrapper *sim = new SimulationWrapper(); - std::string hierarchy = sim->getRoot(); - - int err; - - // Initialize DPI - err = dpi_init(dpi, hierarchy); - if (err != HB_MC_SUCCESS) { - delete sim; - printf("[BSG_ERROR] Failed to initialize DPI!\nExiting...\n"); + // Initialize Host + SimulationWrapper *host = new SimulationWrapper(); + if (!host) { + bsg_pr_err("Could not initialize host!\n"); return HB_MC_FAIL; } - printf("[BSG_INFO] DPI Initialized!\n"); - - while(1) - sim->eval(); + int err; + do { + err = host->eval(); + } while (err == HB_MC_SUCCESS); - return HB_MC_SUCCESS; + return err; } /* diff --git a/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.hpp b/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.hpp new file mode 100644 index 000000000..9d3f42a6d --- /dev/null +++ b/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.hpp @@ -0,0 +1,107 @@ +// Copyright (c) 2019, University of Washington All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// Redistributions of source code must retain the above copyright notice, this list +// of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above copyright notice, this +// list of conditions and the following disclaimer in the documentation and/or +// other materials provided with the distribution. +// +// Neither the name of the copyright holder nor the names of its contributors may +// be used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// This file implements the SimulationWrapper object. + +#ifndef __BSG_MANYCORE_SIMULATOR_HPP +#define __BSG_MANYCORE_SIMULATOR_HPP + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include + +// Define invisible library functions +declare_hb_mc_get_bits +declare_bsg_printing + +class SimulationWrapper{ + // This is the generic pointer for implementation-specific + // simulator details. In Verilator, this is + // Vmanycore_tb_top. In VCS this is the scope + // for DPI. + void *top = nullptr; + std::string *root; + // Pointer to the dromajo instance + dromajo_cosim_state_t *dromajo; + // Pointer to the manycore DPI controller + bsg_nonsynth_dpi::dpi_manycore *dpi; + +public: + SimulationWrapper(); + ~SimulationWrapper(); + + // Change the assertion state. + + // When Verilator simulation starts, we want to disable + // assertion because it is a two-state simulator and the lack + // of z/x may cause erroneous assertions. + // + // This does not need to be implemented in 4-state simulators + // like VCS + void assertOn(bool val); + + std::string getRoot(); + + // Causes time to proceed by 1 unit + void advance_time(); + + // DPI functions + int dpi_fifo_drain(hb_mc_fifo_rx_t); + void dpi_cleanup(); + int dpi_init(); + + // Dromajo functions + int dromajo_init(); + bool dromajo_step(); + int dromajo_transmit_packet(); + int dromajo_receive_packet(); + int dromajo_set_credits(); + + // Evaluates one instruction in RISC-V + // and forwards packets between Dromajo and the manycore + int eval(); +}; +#endif // __BSG_MANYCORE_SIMULATOR_HPP \ No newline at end of file diff --git a/libraries/platforms/dromajo-vcs/library.mk b/libraries/platforms/dromajo-vcs/library.mk index 7f5446513..029eab3af 100644 --- a/libraries/platforms/dromajo-vcs/library.mk +++ b/libraries/platforms/dromajo-vcs/library.mk @@ -118,7 +118,6 @@ PLATFORM_OBJECTS += $(patsubst %c,%o,$(PLATFORM_CSOURCES)) $(PLATFORM_OBJECTS): INCLUDES := -I$(LIBRARIES_PATH) $(PLATFORM_OBJECTS): INCLUDES += -I$(EXAMPLES_PATH) -$(PLATFORM_OBJECTS): INCLUDES += -I$(LIBRARIES_PATH)/platforms/dpi-verilator $(PLATFORM_OBJECTS): INCLUDES += -I$(BSG_MACHINE_PATH)/notrace/ $(PLATFORM_OBJECTS): INCLUDES += -I$(BSG_PLATFORM_PATH) $(PLATFORM_OBJECTS): INCLUDES += -I$(VCS_HOME)/linux64/lib/ diff --git a/libraries/platforms/dromajo-vcs/software/src/args.c b/libraries/platforms/dromajo-vcs/software/src/args.c index b67437b2e..d7d10f8d7 100644 --- a/libraries/platforms/dromajo-vcs/software/src/args.c +++ b/libraries/platforms/dromajo-vcs/software/src/args.c @@ -51,7 +51,6 @@ void __init_args(void) { uint32_t data = resp_pkt.response.data; if (data == 0xFFFFFFFF) { - bsg_pr_info("Argument retrieval complete!\n"); break; } else { @@ -80,14 +79,15 @@ void __init_args(void) { char *args[_argc]; char c = '\0'; int count = 0; - while (count != _argc) { - if ((c == '\0') && (c != *bufptr)) { - args[count] = bufptr; - count++; + if (_argc != 0) { + while (count != _argc) { + if ((c == '\0') && (c != *bufptr)) { + args[count] = bufptr; + count++; + } + c = *bufptr; + bufptr++; } - c = *bufptr; - bufptr++; - } _argv = args; - + } } diff --git a/libraries/platforms/dromajo-vcs/software/src/bp_utils.c b/libraries/platforms/dromajo-vcs/software/src/bp_utils.c index 54ea6219e..f8749b384 100644 --- a/libraries/platforms/dromajo-vcs/software/src/bp_utils.c +++ b/libraries/platforms/dromajo-vcs/software/src/bp_utils.c @@ -107,15 +107,15 @@ int bp_hb_read_from_manycore_bridge(hb_mc_packet_t *pkt, hb_mc_fifo_rx_t type) { // Read the value uint32_t *mc_to_bp_req_fifo_addr = (uint32_t *) (MC_BASE_ADDR + MC_TO_BP_REQ_FIFO_ADDR); - uint32_t read_status = 0xFFFF; + uint32_t read_status = 0xFFFFFFFF; for (int i = 0; i < 4; i++) { pkt->words[i] = *mc_to_bp_req_fifo_addr; read_status &= pkt->words[i]; mc_to_bp_req_fifo_addr++; } - // If all packets are 0xFFFF --> there is something wrong - if (read_status == 0xFFFF) + // If all packets are 0xFFFFFFFF --> there is something wrong + if (read_status == 0xFFFFFFFF) return HB_MC_FAIL; } break; @@ -128,15 +128,15 @@ int bp_hb_read_from_manycore_bridge(hb_mc_packet_t *pkt, hb_mc_fifo_rx_t type) { // Read the value uint32_t *mc_to_bp_resp_fifo_addr = (uint32_t *) (MC_BASE_ADDR + MC_TO_BP_RESP_FIFO_ADDR); - uint32_t read_status = 0xFFFF; + uint32_t read_status = 0xFFFFFFFF; for (int i = 0; i < 4; i++) { pkt->words[i] = *mc_to_bp_resp_fifo_addr; read_status &= pkt->words[i]; mc_to_bp_resp_fifo_addr++; } - // If all packets are 0xFFFF --> there is something wrong - if (read_status == 0xFFFF) + // If all packets are 0xFFFFFFFF --> there is something wrong + if (read_status == 0xFFFFFFFF) return HB_MC_FAIL; } break; From cc1708ef6361d026f84f24bbda42688cf49facf4 Mon Sep 17 00:00:00 2001 From: sripathi-muralitharan Date: Thu, 6 May 2021 14:37:56 -0700 Subject: [PATCH 29/70] Fixing review comments --- libraries/platforms/dromajo-vcs/.gitignore | 1 - .../platforms/dromajo-vcs/compilation.mk | 15 +- libraries/platforms/dromajo-vcs/hardware.mk | 4 +- .../platforms/dromajo-vcs/hardware/dpi_top.sv | 357 ------------------ libraries/platforms/dromajo-vcs/library.mk | 4 +- 5 files changed, 12 insertions(+), 369 deletions(-) delete mode 100644 libraries/platforms/dromajo-vcs/.gitignore delete mode 100644 libraries/platforms/dromajo-vcs/hardware/dpi_top.sv diff --git a/libraries/platforms/dromajo-vcs/.gitignore b/libraries/platforms/dromajo-vcs/.gitignore deleted file mode 100644 index e9da60ba1..000000000 --- a/libraries/platforms/dromajo-vcs/.gitignore +++ /dev/null @@ -1 +0,0 @@ -msg_config \ No newline at end of file diff --git a/libraries/platforms/dromajo-vcs/compilation.mk b/libraries/platforms/dromajo-vcs/compilation.mk index fe2b90b2f..8bb140329 100644 --- a/libraries/platforms/dromajo-vcs/compilation.mk +++ b/libraries/platforms/dromajo-vcs/compilation.mk @@ -45,23 +45,24 @@ CXXFLAGS += $(DEFINES) -march=rv64imafd -mabi=lp64 -mcmodel=medany CFLAGS += $(DEFINES) -march=rv64imafd -mabi=lp64 -mcmodel=medany SFLAGS += $(DEFINES) -march=rv64imafd -mabi=lp64 -mcmodel=medany -export RV_CC = $(BLACKPARROT_DIR)/sdk/install/bin/riscv64-unknown-elf-dramfs-gcc -export RV_CXX = $(BLACKPARROT_DIR)/sdk/install/bin/riscv64-unknown-elf-dramfs-g++ -export RV_LD = $(RV_CXX) +RV_CC = $(BLACKPARROT_DIR)/sdk/install/bin/riscv64-unknown-elf-dramfs-gcc +RV_CXX = $(BLACKPARROT_DIR)/sdk/install/bin/riscv64-unknown-elf-dramfs-g++ export RV_AR = $(BLACKPARROT_DIR)/sdk/install/bin/riscv64-unknown-elf-dramfs-ar -export RV_RANLIB = $(BLACKPARROT_DIR)/sdk/install/bin/riscv64-unknown-elf-dramfs-ranlib # each regression target needs to build its .o from a .c and .h of the # same name +%.o: CC = $(RV_CC) %.o: %.c - $(RV_CC) -c -o $@ $< $(INCLUDES) $(CFLAGS) $(CDEFINES) + $(CC) -c -o $@ $< $(INCLUDES) $(CFLAGS) $(CDEFINES) # ... or a .cpp and .hpp of the same name +%.o: CXX = $(RV_CXX) %.o: %.cpp - $(RV_CXX) -c -o $@ $< $(INCLUDES) $(CXXFLAGS) $(CXXDEFINES) + $(CXX) -c -o $@ $< $(INCLUDES) $(CXXFLAGS) $(CXXDEFINES) +%.o: CC = $(RV_CC) %.o: %.S - $(RV_CC) -c -o $@ $< $(INCLUDES) $(SFLAGS) + $(CC) -c -o $@ $< $(INCLUDES) $(SFLAGS) .PRECIOUS: %.o diff --git a/libraries/platforms/dromajo-vcs/hardware.mk b/libraries/platforms/dromajo-vcs/hardware.mk index e411de4dd..0d304c7bd 100644 --- a/libraries/platforms/dromajo-vcs/hardware.mk +++ b/libraries/platforms/dromajo-vcs/hardware.mk @@ -143,9 +143,9 @@ VSOURCES += $(BASEJUMP_STL_DIR)/bsg_test/bsg_nonsynth_dpi_cycle_counter.v # Top-level module name BSG_DESIGN_TOP := replicant_tb_top -VSOURCES += $(LIBRARIES_PATH)/platforms/dromajo-vcs/hardware/dpi_top.sv +VSOURCES += $(LIBRARIES_PATH)/platforms/bigblade-vcs/hardware/dpi_top.sv -VINCLUDES += $(BSG_PLATFORM_PATH)/hardware +VINCLUDES += $(LIBRARIES_PATH)/platforms/bigblade-vcs/hardware VINCLUDES += $(BSG_PLATFORM_PATH) diff --git a/libraries/platforms/dromajo-vcs/hardware/dpi_top.sv b/libraries/platforms/dromajo-vcs/hardware/dpi_top.sv deleted file mode 100644 index 1d8cdf339..000000000 --- a/libraries/platforms/dromajo-vcs/hardware/dpi_top.sv +++ /dev/null @@ -1,357 +0,0 @@ -module replicant_tb_top - import bsg_manycore_pkg::*; - import bsg_bladerunner_pkg::*; - (); - - // Uncomment this to enable VCD Dumping - /* - initial begin - $display("[%0t] Tracing to vlt_dump.vcd...\n", $time); - $dumpfile("dump.vcd"); - $dumpvars(); - end - */ - initial begin - #0; - - $display("==================== BSG MACHINE SETTINGS: ===================="); - - $display("[INFO][TESTBENCH] bsg_machine_pods_x_gp = %d", bsg_machine_pods_x_gp); - $display("[INFO][TESTBENCH] bsg_machine_pods_y_gp = %d", bsg_machine_pods_y_gp); - - $display("[INFO][TESTBENCH] bsg_machine_pod_tiles_x_gp = %d", bsg_machine_pod_tiles_x_gp); - $display("[INFO][TESTBENCH] bsg_machine_pod_tiles_y_gp = %d", bsg_machine_pod_tiles_y_gp); - $display("[INFO][TESTBENCH] bsg_machine_pod_tiles_subarray_x_gp = %d", bsg_machine_pod_tiles_subarray_x_gp); - $display("[INFO][TESTBENCH] bsg_machine_pod_tiles_subarray_y_gp = %d", bsg_machine_pod_tiles_subarray_y_gp); - $display("[INFO][TESTBENCH] bsg_machine_pod_llcache_rows_gp = %d", bsg_machine_pod_llcache_rows_gp); - - $display("[INFO][TESTBENCH] bsg_machine_noc_cfg_gp = %s", bsg_machine_noc_cfg_gp.name()); - $display("[INFO][TESTBENCH] bsg_machine_noc_ruche_factor_X_gp = %d", bsg_machine_noc_ruche_factor_X_gp); - - $display("[INFO][TESTBENCH] bsg_machine_noc_epa_width_gp = %d", bsg_machine_noc_epa_width_gp); - $display("[INFO][TESTBENCH] bsg_machine_noc_data_width_gp = %d", bsg_machine_noc_data_width_gp); - $display("[INFO][TESTBENCH] bsg_machine_noc_coord_x_width_gp = %d", bsg_machine_noc_coord_x_width_gp); - $display("[INFO][TESTBENCH] bsg_machine_noc_coord_y_width_gp = %d", bsg_machine_noc_coord_y_width_gp); - $display("[INFO][TESTBENCH] bsg_machine_noc_pod_coord_x_width_gp = %d", bsg_machine_noc_pod_coord_x_width_gp); - $display("[INFO][TESTBENCH] bsg_machine_noc_pod_coord_y_width_gp = %d", bsg_machine_noc_pod_coord_y_width_gp); - - $display("[INFO][TESTBENCH] bsg_machine_llcache_sets_gp = %d", bsg_machine_llcache_sets_gp); - $display("[INFO][TESTBENCH] bsg_machine_llcache_ways_gp = %d", bsg_machine_llcache_ways_gp); - $display("[INFO][TESTBENCH] bsg_machine_llcache_line_words_gp = %d", bsg_machine_llcache_line_words_gp); - $display("[INFO][TESTBENCH] bsg_machine_llcache_words_gp = %d", bsg_machine_llcache_words_gp); - $display("[INFO][TESTBENCH] bsg_machine_llcache_miss_fifo_els_gp = %d", bsg_machine_llcache_miss_fifo_els_gp); - $display("[INFO][TESTBENCH] bsg_machine_llcache_channel_width_gp = %d", bsg_machine_llcache_channel_width_gp); - $display("[INFO][TESTBENCH] bsg_machine_llcache_dram_channel_ratio_gp = %d", bsg_machine_llcache_dram_channel_ratio_gp); - - $display("[INFO][TESTBENCH] bsg_machine_dram_bank_words_gp = %d", bsg_machine_dram_bank_words_gp); - $display("[INFO][TESTBENCH] bsg_machine_dram_channels_gp = %d", bsg_machine_dram_channels_gp); - $display("[INFO][TESTBENCH] bsg_machine_dram_words_gp = %d", bsg_machine_dram_words_gp); - $display("[INFO][TESTBENCH] bsg_machine_dram_cfg_gp = %s", bsg_machine_dram_cfg_gp.name()); - - $display("[INFO][TESTBENCH] bsg_machine_io_coord_x_gp = %d", bsg_machine_io_coord_x_gp); - $display("[INFO][TESTBENCH] bsg_machine_io_coord_y_gp = %d", bsg_machine_io_coord_y_gp); - - $display("[INFO][TESTBENCH] bsg_machine_enable_vcore_profiling_lp = %d", bsg_machine_enable_vcore_profiling_lp); - $display("[INFO][TESTBENCH] bsg_machine_enable_router_profiling_lp= %d", bsg_machine_enable_router_profiling_lp); - $display("[INFO][TESTBENCH] bsg_machine_enable_cache_profiling_lp = %d", bsg_machine_enable_cache_profiling_lp); - - $display("[INFO][TESTBENCH] bsg_machine_name_gp = %s", bsg_machine_name_gp); - end - - localparam bsg_machine_llcache_data_width_lp = bsg_machine_noc_data_width_gp; - localparam bsg_machine_llcache_addr_width_lp=(bsg_machine_noc_epa_width_gp-1+`BSG_SAFE_CLOG2(bsg_machine_noc_data_width_gp>>3)); - - localparam bsg_machine_wh_flit_width_lp = bsg_machine_llcache_channel_width_gp; - localparam bsg_machine_wh_ruche_factor_lp = 2; - localparam bsg_machine_wh_cid_width_lp = `BSG_SAFE_CLOG2(bsg_machine_wh_ruche_factor_lp*2); - localparam bsg_machine_wh_len_width_lp = `BSG_SAFE_CLOG2(1 + ((bsg_machine_llcache_line_words_gp * bsg_machine_llcache_data_width_lp) / bsg_machine_llcache_channel_width_gp)); - localparam bsg_machine_wh_coord_width_lp = bsg_machine_noc_coord_x_width_gp; - -// These are macros... for reasons. -`ifndef BSG_MACHINE_DISABLE_VCORE_PROFILING - localparam bsg_machine_enable_vcore_profiling_lp = 1; -`else - localparam bsg_machine_enable_vcore_profiling_lp = 0; -`endif - -`ifndef BSG_MACHINE_DISABLE_ROUTER_PROFILING - localparam bsg_machine_enable_router_profiling_lp = 1; -`else - localparam bsg_machine_enable_router_profiling_lp = 0; -`endif - -`ifndef BSG_MACHINE_DISABLE_CACHE_PROFILING - localparam bsg_machine_enable_cache_profiling_lp = 1; -`else - localparam bsg_machine_enable_cache_profiling_lp = 0; -`endif - - // Clock generator period - localparam lc_cycle_time_ps_lp = 1000; - - // Reset generator depth - localparam reset_depth_lp = 3; - - // Global Counter for Profilers, Tracing, Debugging - localparam global_counter_width_lp = 64; - logic [global_counter_width_lp-1:0] global_ctr; - - logic host_clk; - logic host_reset; - - // bsg_nonsynth_clock_gen and bsg_nonsynth_reset_gen BOTH have bit - // inputs and outputs (they're non-synthesizable). Casting between - // logic and bit can produce unexpected edges as logic types switch - // from X to 0/1 at Time 0 in simulation. This means that the input - // and outputs of both modules must have type bit, AND the wires - // between them. Therefore, we use bit_clk and bit_reset for the - // inputs/outputs of these modules to avoid unexpected - // negative/positive edges and other modules can choose between bit - // version (for non-synthesizable modules) and the logic version - // (otherwise). - bit bit_clk; - bit bit_reset; - logic core_clk; - logic core_reset; - - // reset_done is deasserted when tag programming is done. - logic core_reset_done_lo, core_reset_done_r; - - logic mem_clk; - logic mem_reset; - - logic cache_clk; - logic cache_reset; - - // Snoop wires for Print Stat - logic print_stat_v; - logic [bsg_machine_noc_data_width_gp-1:0] print_stat_tag; - - logic [bsg_machine_noc_coord_x_width_gp-1:0] host_x_coord_li = (bsg_machine_noc_coord_x_width_gp)'(bsg_machine_io_coord_x_gp); - logic [bsg_machine_noc_coord_y_width_gp-1:0] host_y_coord_li = (bsg_machine_noc_coord_y_width_gp)'(bsg_machine_io_coord_y_gp); - - `declare_bsg_manycore_link_sif_s(bsg_machine_noc_epa_width_gp, bsg_machine_noc_data_width_gp, bsg_machine_noc_coord_x_width_gp, bsg_machine_noc_coord_y_width_gp); - - bsg_manycore_link_sif_s host_link_sif_li; - bsg_manycore_link_sif_s host_link_sif_lo; - - // Trace Enable wire for runtime argument to enable tracing (+trace) - logic trace_en; - logic log_en; - logic dpi_trace_en; - logic dpi_log_en; - logic tag_done_lo; - assign trace_en = dpi_trace_en; - assign log_en = dpi_log_en; - - // -Verilator uses a clock generator that is controlled by C/C++ - // (bsg_nonsynth_dpi_clock_gen), whereas VCS uses the normal - // nonsynthesizable clock generator (bsg_nonsynth_clock_gen) -`ifdef VERILATOR - bsg_nonsynth_dpi_clock_gen -`else - bsg_nonsynth_clock_gen -`endif - #(.cycle_time_p(lc_cycle_time_ps_lp)) - core_clk_gen - (.o(bit_clk)); - assign core_clk = bit_clk; - - bsg_nonsynth_reset_gen - #( - .num_clocks_p(1) - ,.reset_cycles_lo_p(0) - ,.reset_cycles_hi_p(16) - ) - reset_gen - ( - .clk_i(bit_clk) - ,.async_reset_o(bit_reset) - ); - assign core_reset = bit_reset; - - bsg_nonsynth_manycore_testbench - #( - .num_pods_x_p(bsg_machine_pods_x_gp) - ,.num_pods_y_p(bsg_machine_pods_y_gp) - ,.pod_x_cord_width_p(bsg_machine_noc_pod_coord_x_width_gp) - ,.pod_y_cord_width_p(bsg_machine_noc_pod_coord_y_width_gp) - - ,.num_tiles_x_p(bsg_machine_pod_tiles_x_gp) - ,.num_tiles_y_p(bsg_machine_pod_tiles_y_gp) - ,.num_subarray_x_p(bsg_machine_pod_tiles_subarray_x_gp) - ,.num_subarray_y_p(bsg_machine_pod_tiles_subarray_y_gp) - - ,.x_cord_width_p(bsg_machine_noc_coord_x_width_gp) - ,.y_cord_width_p(bsg_machine_noc_coord_y_width_gp) - - ,.addr_width_p(bsg_machine_noc_epa_width_gp) - ,.data_width_p(bsg_machine_noc_data_width_gp) - ,.dmem_size_p(bsg_machine_core_dmem_words_gp) - ,.icache_entries_p(bsg_machine_core_icache_entries_gp) - ,.icache_tag_width_p(bsg_machine_core_icache_tag_width_gp) - - ,.ruche_factor_X_p(bsg_machine_noc_ruche_factor_X_gp) - - ,.num_vcache_rows_p(bsg_machine_pod_llcache_rows_gp) - ,.num_vcaches_per_channel_p(bsg_machine_llcache_dram_channel_ratio_gp) - ,.vcache_data_width_p(bsg_machine_llcache_data_width_lp) - ,.vcache_addr_width_p(bsg_machine_llcache_addr_width_lp) - ,.vcache_size_p(bsg_machine_llcache_words_gp) - ,.vcache_sets_p(bsg_machine_llcache_sets_gp) - ,.vcache_ways_p(bsg_machine_llcache_ways_gp) - ,.vcache_block_size_in_words_p(bsg_machine_llcache_line_words_gp) - ,.vcache_dma_data_width_p(bsg_machine_llcache_channel_width_gp) - - ,.wh_flit_width_p(bsg_machine_wh_flit_width_lp) - ,.wh_ruche_factor_p(bsg_machine_wh_ruche_factor_lp) - ,.wh_cid_width_p(bsg_machine_wh_cid_width_lp) - ,.wh_len_width_p(bsg_machine_wh_len_width_lp) - ,.wh_cord_width_p(bsg_machine_wh_coord_width_lp) - - ,.bsg_manycore_mem_cfg_p(bsg_machine_dram_cfg_gp) - ,.bsg_dram_size_p(bsg_machine_dram_words_gp) - - ,.enable_vcore_profiling_p(bsg_machine_enable_vcore_profiling_lp) - ,.enable_router_profiling_p(bsg_machine_enable_router_profiling_lp) - ,.enable_cache_profiling_p(bsg_machine_enable_cache_profiling_lp) - ,.hetero_type_vec_p(bsg_machine_hetero_type_vec_gp) - - ,.reset_depth_p(reset_depth_lp) - ) - testbench - ( - .clk_i(core_clk) - ,.reset_i(core_reset) - - ,.io_link_sif_i(host_link_sif_li) - ,.io_link_sif_o(host_link_sif_lo) - - ,.tag_done_o(core_reset_done_lo) - ); - - bsg_nonsynth_dpi_gpio - #( - .width_p(2) - ,.init_o_p('0) - ,.use_output_p('1) - ,.debug_p('1) - ) - trace_control - (.gpio_o({dpi_log_en, dpi_trace_en}) - ,.gpio_i('0) - ); - - // -------------------------------------------------------------------------- - // IO Complex - // -------------------------------------------------------------------------- - localparam dpi_fifo_width_lp = (1 << $clog2(`bsg_manycore_packet_width(bsg_machine_noc_epa_width_gp,bsg_machine_noc_data_width_gp,bsg_machine_noc_coord_x_width_gp,bsg_machine_noc_coord_y_width_gp))); - localparam ep_fifo_els_lp = 4; - assign host_clk = core_clk; - assign host_reset = core_reset; - - bsg_nonsynth_dpi_manycore - #( - .x_cord_width_p(bsg_machine_noc_coord_x_width_gp) - ,.y_cord_width_p(bsg_machine_noc_coord_y_width_gp) - ,.addr_width_p(bsg_machine_noc_epa_width_gp) - ,.data_width_p(bsg_machine_noc_data_width_gp) - ,.ep_fifo_els_p(ep_fifo_els_lp) - ,.dpi_fifo_els_p(bsg_machine_dpi_fifo_els_gp) - ,.fifo_width_p(128) // It would be better to read this from somewhere - ,.rom_els_p(bsg_machine_rom_els_gp) - ,.rom_width_p(bsg_machine_rom_width_gp) - ,.rom_arr_p(bsg_machine_rom_arr_gp) - ,.max_out_credits_p(bsg_machine_io_credits_max_gp) - ) - mc_dpi - ( - .clk_i(host_clk) - // DR: I don't particularly like this, but we'll leave it for now - ,.reset_i(host_reset | (~core_reset_done_r)) - ,.reset_done_i(core_reset_done_lo) - - // manycore link - ,.link_sif_i(host_link_sif_lo) - ,.link_sif_o(host_link_sif_li) - ,.my_x_i(host_x_coord_li) - ,.my_y_i(host_y_coord_li) - ); - - bsg_dff_chain - #( - .width_p(1) - ,.num_stages_p(reset_depth_lp) - ) - reset_dff - ( - .clk_i(core_clk) - ,.data_i(core_reset_done_lo) - ,.data_o(core_reset_done_r) - ); - - bsg_nonsynth_dpi_cycle_counter - #(.width_p(global_counter_width_lp)) - ctr - ( - .clk_i(core_clk) - ,.reset_i(core_reset) - ,.ctr_r_o(global_ctr) - ); - - bsg_print_stat_snoop - #( - .data_width_p(bsg_machine_noc_data_width_gp) - ,.addr_width_p(bsg_machine_noc_epa_width_gp) - ,.x_cord_width_p(bsg_machine_noc_coord_x_width_gp) - ,.y_cord_width_p(bsg_machine_noc_coord_y_width_gp) - ) - print_stat_snoop - ( - .loader_link_sif_in_i(host_link_sif_lo) // output from manycore - ,.loader_link_sif_out_i(host_link_sif_li) // output from host - - ,.print_stat_v_o(print_stat_v) - ,.print_stat_tag_o(print_stat_tag) - ); - - // In VCS, the C/C++ testbench is controlled by the - // simulator. Therefore, we need to "call into" the C/C++ program - // using the cosim_main function, during the initial block. - // - // DPI Calls in cosim_main will cause simulator time to progress. - // - // This mirrors the DPI functions in aws simulation -`ifndef VERILATOR - import "DPI-C" context task cosim_main(output int unsigned exit_code, input string args); - initial begin - int exit_code; - string args; - longint t; - $value$plusargs("c_args=%s", args); - replicant_tb_top.cosim_main(exit_code, args); - if(exit_code < 0) begin - $display("BSG COSIM FAIL: Test failed with exit code: %d", exit_code); - $fatal; - end else begin - $display("BSG COSIM PASS: Test passed!"); - $finish; - end - end - -`endif - -`ifdef BSG_MACHINE_ENABLE_SAIF - wor saif_en = 0; - - bind vanilla_core vanilla_core_saif_dumper - #( - ) - saif_dumper - ( - .* - ,.saif_en_i($root.`HOST_MODULE_PATH.saif_en) - ,.saif_en_o($root.`HOST_MODULE_PATH.saif_en) - ); -`endif -endmodule diff --git a/libraries/platforms/dromajo-vcs/library.mk b/libraries/platforms/dromajo-vcs/library.mk index 029eab3af..1a5e32658 100644 --- a/libraries/platforms/dromajo-vcs/library.mk +++ b/libraries/platforms/dromajo-vcs/library.mk @@ -98,7 +98,7 @@ $(DROMAJO_OBJECTS): INCLUDES := -I$(DROMAJO_DIR)/include $(DROMAJO_OBJECTS): INCLUDES += -I$(BSG_PLATFORM_PATH)/software/include/dromajo $(DROMAJO_OBJECTS): CXXFLAGS := -std=c++11 -fPIC -Wall -Wno-parentheses -MMD -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_GNU_SOURCE -D__STDC_FORMAT_MACROS -DFIFO_MAX_ELEMENTS=$(BSG_MACHINE_IO_EP_CREDITS) -std=gnu++11 $(DROMAJO_OBJECTS): LDFLAGS := -fPIC -$(DROMAJO_OBJECTS): RV_CXX = $(CXX) +$(DROMAJO_OBJECTS): CXX = g++ include $(LIBRARIES_PATH)/features/dma/simulation/dramsim3.mk include $(LIBRARIES_PATH)/features/dma/simulation/libdmamem.mk @@ -127,7 +127,7 @@ $(PLATFORM_OBJECTS): INCLUDES += -I$(BLACKPARROT_DIR)/sdk/dromajo/include $(PLATFORM_OBJECTS): CFLAGS := -std=c11 -fPIC -DVCS -D_GNU_SOURCE -DVERILATOR -D_BSD_SOURCE -D_XOPEN_SOURCE=500 $(PLATFORM_OBJECTS): CXXFLAGS := -std=c++11 -fPIC -DVCS -D_GNU_SOURCE -DVERILATOR -D_BSD_SOURCE -D_XOPEN_SOURCE=500 $(PLATFORM_OBJECTS): LDFLAGS := -fPIC -$(PLATFORM_OBJECTS): RV_CXX = $(CXX) +$(PLATFORM_OBJECTS): CXX = g++ # Mirror the extensions linux installation in /usr/lib provides so # that we can use -lbsg_manycore_runtime From de49f3d470fa9959f74059b1e96c35ca0a17527c Mon Sep 17 00:00:00 2001 From: sripathi-muralitharan Date: Mon, 17 May 2021 10:34:36 -0700 Subject: [PATCH 30/70] Updates to the simulation flow --- libraries/features/dma/noimpl/feature.mk | 2 + libraries/features/dma/simulation/feature.mk | 1 + .../features/dma/simulation/libdmamem.mk | 2 +- libraries/libraries.mk | 39 +++++----- .../platforms/dromajo-vcs/compilation.mk | 11 +-- libraries/platforms/dromajo-vcs/hardware.mk | 6 +- libraries/platforms/dromajo-vcs/library.mk | 78 +++++++++---------- libraries/platforms/dromajo-vcs/link.mk | 21 +---- 8 files changed, 68 insertions(+), 92 deletions(-) diff --git a/libraries/features/dma/noimpl/feature.mk b/libraries/features/dma/noimpl/feature.mk index 84aa9b7b3..9117e4436 100644 --- a/libraries/features/dma/noimpl/feature.mk +++ b/libraries/features/dma/noimpl/feature.mk @@ -40,6 +40,8 @@ $(DMA_FEATURE_OBJECTS): CXXFLAGS := -std=c++11 -fPIC -D_GNU_SOURCE -D_DEFAULT_SO $(BSG_PLATFORM_PATH)/libbsg_manycore_runtime.so.1.0: $(DMA_FEATURE_OBJECTS) +$(BSG_PLATFORM_PATH)/libbsg_manycore_runtime.a: $(DMA_FEATURE_OBJECTS) + .PHONY: dma_feature.clean dma_feature.clean: rm -f $(DMA_FEATURE_OBJECTS) diff --git a/libraries/features/dma/simulation/feature.mk b/libraries/features/dma/simulation/feature.mk index 07829f913..a4f851a26 100644 --- a/libraries/features/dma/simulation/feature.mk +++ b/libraries/features/dma/simulation/feature.mk @@ -46,6 +46,7 @@ $(DMA_FEATURE_OBJECTS): CXXFLAGS := -std=c++11 -fPIC $(INCLUDES) -D_GNU_SOURCE - $(BSG_PLATFORM_PATH)/libbsg_manycore_runtime.so.1.0: $(DMA_FEATURE_OBJECTS) +$(BSG_PLATFORM_PATH)/libbsg_manycore_runtime.a: $(DMA_FEATURE_OBJECTS) .PHONY: dma_feature.clean dma_feature.clean: diff --git a/libraries/features/dma/simulation/libdmamem.mk b/libraries/features/dma/simulation/libdmamem.mk index 149d5da17..9d545fc9a 100644 --- a/libraries/features/dma/simulation/libdmamem.mk +++ b/libraries/features/dma/simulation/libdmamem.mk @@ -60,7 +60,7 @@ dmamem.clean: libraries.clean: dmamem.clean # Rules for building Simulation "DMA library" -$(LIBRARIES_PATH)/features/dma/simulation/libdmamem.so: CXXFLAGS += -std=c++11 -D_GNU_SOURCE -D_DEFAULT_SOURCE -Wall -fPIC -shared +$(LIBRARIES_PATH)/features/dma/simulation/libdmamem.so: CXXFLAGS := -std=c++11 -D_GNU_SOURCE -D_DEFAULT_SOURCE -Wall -fPIC -shared $(LIBRARIES_PATH)/features/dma/simulation/libdmamem.so: CXXFLAGS += -I$(BASEJUMP_STL_DIR)/bsg_mem $(LIBRARIES_PATH)/features/dma/simulation/libdmamem.so: CXXFLAGS += -DBASEJUMP_STL_DIR="$(BASEJUMP_STL_DIR)" $(LIBRARIES_PATH)/features/dma/simulation/libdmamem.so: CXX=g++ diff --git a/libraries/libraries.mk b/libraries/libraries.mk index c935a9f15..efeca9d9e 100644 --- a/libraries/libraries.mk +++ b/libraries/libraries.mk @@ -28,6 +28,7 @@ ifndef __BSG_LIBRARIES_MK __BSG_LIBRARIES_MK := 1 +LIB_SSOURCES += LIB_CSOURCES += LIB_CSOURCES += $(LIBRARIES_PATH)/bsg_manycore_config_id_to_string.c LIB_CSOURCES += $(LIBRARIES_PATH)/bsg_manycore_memsys.c @@ -99,6 +100,7 @@ LIB_DEBUG_OBJECTS += LIB_OBJECTS += $(patsubst %cpp,%o,$(LIB_CXXSOURCES)) LIB_OBJECTS += $(patsubst %c,%o,$(LIB_CSOURCES)) +LIB_OBJECTS += $(patsubst %S,%o,$(LIB_SSOURCES)) LIB_OBJECTS_CUDA_POD_REPL += $(patsubst %cpp,%o,$(LIB_CXXSOURCES_CUDA_POD_REPL)) LIB_OBJECTS_REGRESSION += $(patsubst %cpp,%o,$(LIB_CXXSOURCES_REGRESSION)) @@ -114,10 +116,16 @@ $(LIB_OBJECTS) $(LIB_OBJECTS_CUDA_POD_REPL) $(LIB_OBJECTS_REGRESSION): INCLUDES $(LIB_OBJECTS) $(LIB_OBJECTS_CUDA_POD_REPL) $(LIB_OBJECTS_REGRESSION): INCLUDES += -I$(LIBRARIES_PATH)/xcl $(LIB_OBJECTS) $(LIB_OBJECTS_CUDA_POD_REPL) $(LIB_OBJECTS_REGRESSION): INCLUDES += -I$(LIBRARIES_PATH)/features/dma $(LIB_OBJECTS) $(LIB_OBJECTS_CUDA_POD_REPL) $(LIB_OBJECTS_REGRESSION): INCLUDES += -I$(LIBRARIES_PATH)/features/profiler +$(LIB_OBJECTS) $(LIB_OBJECTS_CUDA_POD_REPL) $(LIB_OBJECTS_REGRESSION): INCLUDES += -I$(LIBRARIES_PATH)/features/tracer $(LIB_OBJECTS) $(LIB_OBJECTS_CUDA_POD_REPL) $(LIB_OBJECTS_REGRESSION): INCLUDES += -I$(BSG_PLATFORM_PATH) +$(LIB_OBJECTS) $(LIB_OBJECTS_CUDA_POD_REPL) $(LIB_OBJECTS_REGRESSION): INCLUDES += $(LIB_PLATFORM_INCLUDES) $(LIB_OBJECTS) $(LIB_OBJECTS_CUDA_POD_REPL) $(LIB_OBJECTS_REGRESSION): CFLAGS += -std=c11 -fPIC $(INCLUDES) -D_GNU_SOURCE -D_BSD_SOURCE -D_DEFAULT_SOURCE $(LIB_OBJECTS) $(LIB_OBJECTS_CUDA_POD_REPL) $(LIB_OBJECTS_REGRESSION): CXXFLAGS += -std=c++11 -fPIC $(INCLUDES) -D_GNU_SOURCE -D_BSD_SOURCE -D_DEFAULT_SOURCE +# We should move this from AWS (and keep the license) +$(LIB_OBJECTS) $(LIB_OBJECTS_CUDA_POD_REPL) $(LIB_OBJECTS_REGRESSION): INCLUDES += -I$(AWS_FPGA_REPO_DIR)/SDAccel/userspace/include +$(LIB_OBJECTS) $(LIB_OBJECTS_CUDA_POD_REPL) $(LIB_OBJECTS_REGRESSION): CFLAGS += -O3 -std=c11 -fPIC -D_GNU_SOURCE -D_BSD_SOURCE -D_DEFAULT_SOURCE +$(LIB_OBJECTS) $(LIB_OBJECTS_CUDA_POD_REPL) $(LIB_OBJECTS_REGRESSION): CXXFLAGS += -O3 -std=c++11 -fPIC -D_GNU_SOURCE -D_BSD_SOURCE -D_DEFAULT_SOURCE # Need to move this, eventually #$(LIB_OBJECTS) $(PLATFORM_OBJECTS): $(BSG_MACHINE_PATH)/bsg_manycore_machine.h @@ -129,42 +137,32 @@ $(LIB_STRICT_OBJECTS): CXXFLAGS += -Wno-unused-variable $(LIB_STRICT_OBJECTS): CXXFLAGS += -Wno-unused-function $(LIB_STRICT_OBJECTS): CXXFLAGS += -Wno-unused-but-set-variable -ifdef __NEWLIB -LIB_OBJECTS += $(patsubst %S,%o,$(LIB_SSOURCES)) -$(BSG_PLATFORM_PATH)/libbsg_manycore_runtime.so.1.0: LDFLAGS := -$(BSG_PLATFORM_PATH)/libbsg_manycore_runtime.so.1.0: $(LIB_OBJECTS) - $(RV_AR) -rcs $@ $(LIB_OBJECTS) $(DMA_FEATURE_OBJECTS) -else $(BSG_PLATFORM_PATH)/libbsg_manycore_runtime.so.1.0: LD = $(CXX) $(BSG_PLATFORM_PATH)/libbsg_manycore_runtime.so.1.0: $(LIB_OBJECTS) $(LD) -shared -Wl,-soname,$(basename $(notdir $@)) -o $@ $^ $(LDFLAGS) -endif $(BSG_PLATFORM_PATH)/libbsgmc_cuda_legacy_pod_repl.so.1.0: LDFLAGS := $(BSG_PLATFORM_PATH)/libbsgmc_cuda_legacy_pod_repl.so.1.0: INCLUDES := -ifdef __NEWLIB -$(BSG_PLATFORM_PATH)/libbsgmc_cuda_legacy_pod_repl.so.1.0: LDFLAGS := -$(BSG_PLATFORM_PATH)/libbsgmc_cuda_legacy_pod_repl.so.1.0: $(LIB_OBJECTS_CUDA_POD_REPL) - $(RV_AR) -rcs $@ $(LIB_OBJECTS_CUDA_POD_REPL) -else $(BSG_PLATFORM_PATH)/libbsgmc_cuda_legacy_pod_repl.so.1.0: LD = $(CXX) $(BSG_PLATFORM_PATH)/libbsgmc_cuda_legacy_pod_repl.so.1.0: $(LIB_OBJECTS_CUDA_POD_REPL) $(LD) -shared -Wl,-soname,$(basename $(notdir $@)) -o $@ $^ $(LDFLAGS) -endif $(BSG_PLATFORM_PATH)/libbsg_manycore_regression.so.1.0: LDFLAGS := $(BSG_PLATFORM_PATH)/libbsg_manycore_regression.so.1.0: INCLUDES := -ifdef __NEWLIB -$(BSG_PLATFORM_PATH)/libbsg_manycore_regression.so.1.0: LDFLAGS := -$(BSG_PLATFORM_PATH)/libbsg_manycore_regression.so.1.0: $(LIB_OBJECTS_REGRESSION) - $(RV_AR) -rcs $@ $(LIB_OBJECTS_REGRESSION) -else $(BSG_PLATFORM_PATH)/libbsg_manycore_regression.so.1.0: LD = $(CXX) $(BSG_PLATFORM_PATH)/libbsg_manycore_regression.so.1.0: $(LIB_OBJECTS_REGRESSION) $(LD) -shared -Wl,-soname,$(basename $(notdir $@)) -o $@ $^ $(LDFLAGS) -endif + +$(BSG_PLATFORM_PATH)/libbsg_manycore_runtime.a: $(LIB_OBJECTS) + $(AR) -rcs $@ $^ + +$(BSG_PLATFORM_PATH)/libbsgmc_cuda_legacy_pod_repl.a: $(LIB_OBJECTS_CUDA_POD_REPL) + $(AR) -rcs $@ $^ + +$(BSG_PLATFORM_PATH)/libbsg_manycore_regression.a: $(LIB_OBJECTS_REGRESSION) + $(AR) -rcs $@ $^ .PHONY: libraries.clean libraries.clean: @@ -174,5 +172,8 @@ libraries.clean: rm -f $(BSG_PLATFORM_PATH)/libbsg_manycore_runtime.so.1.0 rm -f $(BSG_PLATFORM_PATH)/libbsgmc_cuda_legacy_pod_repl.so.1.0 rm -f $(BSG_PLATFORM_PATH)/libbsg_manycore_regression.so.1.0 + rm -f $(BSG_PLATFORM_PATH)/libbsg_manycore_runtime.a + rm -f $(BSG_PLATFORM_PATH)/libbsgmc_cuda_legacy_pod_repl.a + rm -f $(BSG_PLATFORM_PATH)/libbsg_manycore_regression.a endif diff --git a/libraries/platforms/dromajo-vcs/compilation.mk b/libraries/platforms/dromajo-vcs/compilation.mk index 8bb140329..710e432ff 100644 --- a/libraries/platforms/dromajo-vcs/compilation.mk +++ b/libraries/platforms/dromajo-vcs/compilation.mk @@ -37,30 +37,23 @@ NC=\033[0m # DEFINES += -D_DRAMFS INCLUDES += -I$(LIBRARIES_PATH) -INCLUDES += -I$(BSG_PLATFORM_PATH)/software/include INCLUDES += -I$(BSG_PLATFORM_PATH) +INCLUDES += -I$(BSG_PLATFORM_PATH)/software/include INCLUDES += -I$(BLACKPARROT_DIR)/sdk/perch CXXFLAGS += $(DEFINES) -march=rv64imafd -mabi=lp64 -mcmodel=medany CFLAGS += $(DEFINES) -march=rv64imafd -mabi=lp64 -mcmodel=medany -SFLAGS += $(DEFINES) -march=rv64imafd -mabi=lp64 -mcmodel=medany - -RV_CC = $(BLACKPARROT_DIR)/sdk/install/bin/riscv64-unknown-elf-dramfs-gcc -RV_CXX = $(BLACKPARROT_DIR)/sdk/install/bin/riscv64-unknown-elf-dramfs-g++ -export RV_AR = $(BLACKPARROT_DIR)/sdk/install/bin/riscv64-unknown-elf-dramfs-ar +SFLAGS += $(DEFINES) -march=rv64imafd -mabi=lp64 -mcmodel=medany # each regression target needs to build its .o from a .c and .h of the # same name -%.o: CC = $(RV_CC) %.o: %.c $(CC) -c -o $@ $< $(INCLUDES) $(CFLAGS) $(CDEFINES) # ... or a .cpp and .hpp of the same name -%.o: CXX = $(RV_CXX) %.o: %.cpp $(CXX) -c -o $@ $< $(INCLUDES) $(CXXFLAGS) $(CXXDEFINES) -%.o: CC = $(RV_CC) %.o: %.S $(CC) -c -o $@ $< $(INCLUDES) $(SFLAGS) diff --git a/libraries/platforms/dromajo-vcs/hardware.mk b/libraries/platforms/dromajo-vcs/hardware.mk index 0d304c7bd..5189f2ee1 100644 --- a/libraries/platforms/dromajo-vcs/hardware.mk +++ b/libraries/platforms/dromajo-vcs/hardware.mk @@ -120,8 +120,8 @@ VSOURCES += $(BASEJUMP_STL_DIR)/bsg_dataflow/bsg_serial_in_parallel_out_full.v VSOURCES += $(BASEJUMP_STL_DIR)/bsg_dataflow/bsg_round_robin_1_to_n.v VSOURCES += $(BASEJUMP_STL_DIR)/bsg_dataflow/bsg_one_fifo.v -VSOURCES += $(LIBRARIES_PATH)/platforms/aws-fpga/hardware/bsg_manycore_endpoint_to_fifos_pkg.v -VSOURCES += $(LIBRARIES_PATH)/platforms/aws-fpga/hardware/bsg_manycore_endpoint_to_fifos.v +VSOURCES += $(HARDWARE_PATH)/bsg_manycore_endpoint_to_fifos_pkg.v +VSOURCES += $(HARDWARE_PATH)/bsg_manycore_endpoint_to_fifos.v VSOURCES += $(BSG_MANYCORE_DIR)/testbenches/common/v/vanilla_core_saif_dumper.v @@ -145,7 +145,7 @@ BSG_DESIGN_TOP := replicant_tb_top VSOURCES += $(LIBRARIES_PATH)/platforms/bigblade-vcs/hardware/dpi_top.sv -VINCLUDES += $(LIBRARIES_PATH)/platforms/bigblade-vcs/hardware +VINCLUDES += $(BSG_PLATFORM_PATH)/hardware VINCLUDES += $(BSG_PLATFORM_PATH) diff --git a/libraries/platforms/dromajo-vcs/library.mk b/libraries/platforms/dromajo-vcs/library.mk index 1a5e32658..67a50fffc 100644 --- a/libraries/platforms/dromajo-vcs/library.mk +++ b/libraries/platforms/dromajo-vcs/library.mk @@ -25,11 +25,13 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# Dromajo/BlackParrot uses riscv-newlib for compilation -__NEWLIB = 1 +# RISC-V tools +RV_CC = $(BLACKPARROT_DIR)/sdk/install/bin/riscv64-unknown-elf-dramfs-gcc +RV_CXX = $(BLACKPARROT_DIR)/sdk/install/bin/riscv64-unknown-elf-dramfs-g++ +RV_AR = $(BLACKPARROT_DIR)/sdk/install/bin/riscv64-unknown-elf-dramfs-ar + DROMAJO_DIR = $(BLACKPARROT_DIR)/sdk/dromajo -# Compile the platform-level code and features with the library LIB_CXXSOURCES += $(LIBRARIES_PATH)/features/tracer/noimpl/bsg_manycore_tracer.cpp LIB_CXXSOURCES += $(LIBRARIES_PATH)/features/profiler/noimpl/bsg_manycore_profiler.cpp LIB_CXXSOURCES += $(BSG_PLATFORM_PATH)/bsg_manycore_platform.cpp @@ -63,17 +65,26 @@ $(DMA_FEATURE_OBJECTS): CFLAGS += -march=rv64imafd -mcmodel=medany -mabi=lp64 -D $(DMA_FEATURE_OBJECTS): CXXFLAGS += -march=rv64imafd -mcmodel=medany -mabi=lp64 -D_BSD_SOURCE -D_XOPEN_SOURCE=500 # Add the riscv-newlib specific includes for the library -$(LIB_OBJECTS) $(LIB_OBJECTS_CUDA_POD_REPL) $(LIB_OBJECTS_REGRESSION): INCLUDES := -I$(BSG_PLATFORM_PATH)/software/include -$(LIB_OBJECTS) $(LIB_OBJECTS_CUDA_POD_REPL) $(LIB_OBJECTS_REGRESSSION): INCLUDES += -I$(BLACKPARROT_DIR)/sdk/perch +LIB_PLATFORM_INCLUDES = -I$(BSG_PLATFORM_PATH)/software/include +LIB_PLATFORM_INCLUDES += -I$(BLACKPARROT_DIR)/sdk/perch + +$(LIB_OBJECTS) $(LIB_OBJECTS_CUDA_POD_REPL) $(LIB_OBJECTS_REGRESSION): CC = $(RV_CC) +$(LIB_OBJECTS) $(LIB_OBJECTS_CUDA_POD_REPL) $(LIB_OBJECTS_REGRESSION): CXX = $(RV_CXX) + +$(BSG_PLATFORM_PATH)/libbsg_manycore_runtime.a: AR = $(RV_AR) +$(BSG_PLATFORM_PATH)/libbsgmc_cuda_legacy_pod_repl.a: AR = $(RV_AR) +$(BSG_PLATFORM_PATH)/libbsg_manycore_regression.a: AR = $(RV_AR) # Make the litteFS file system $(BSG_PLATFORM_PATH)/lfs.o: $(MAKE) -C $(BLACKPARROT_DIR)/sdk/bp-tests lfs.cpp - $(RV_CXX) $(BLACKPARROT_DIR)/sdk/bp-tests/lfs.cpp -c -o $@ $(CXXFLAGS) $(INCLUDES) + $(CXX) $(BLACKPARROT_DIR)/sdk/bp-tests/lfs.cpp -c -o $@ $(CXXFLAGS) $(INCLUDES) -# Compile the feature libraries with the manycore runtime -$(LIB_OBJECTS) $(LIB_OBJECTS_CUDA_POD_REPL) $(LIB_OBJECTS_REGRESSION): INCLUDES += -I$(LIBRARIES_PATH)/features/profiler -$(LIB_OBJECTS) $(LIB_OBJECTS_CUDA_POD_REPL) $(LIB_OBJECTS_REGRESSION): INCLUDES += -I$(LIBRARIES_PATH)/features/tracer +include $(LIBRARIES_PATH)/features/dma/simulation/dramsim3.mk +include $(LIBRARIES_PATH)/features/dma/simulation/libdmamem.mk + +$(LIBRARIES_PATH)/features/dma/simulation/libdmamem.so: INCLUDES := +$(LIBRARIES_PATH)/features/dma/simulation/libdramsim3.so: INCLUDES := DROMAJO_CXXSOURCES += $(DROMAJO_DIR)/src/cutils.cpp DROMAJO_CXXSOURCES += $(DROMAJO_DIR)/src/dromajo_cosim.cpp @@ -100,17 +111,6 @@ $(DROMAJO_OBJECTS): CXXFLAGS := -std=c++11 -fPIC -Wall -Wno-parentheses -MMD -D_ $(DROMAJO_OBJECTS): LDFLAGS := -fPIC $(DROMAJO_OBJECTS): CXX = g++ -include $(LIBRARIES_PATH)/features/dma/simulation/dramsim3.mk -include $(LIBRARIES_PATH)/features/dma/simulation/libdmamem.mk - -$(LIBRARIES_PATH)/features/dma/simulation/libdmamem.so: CXXFLAGS := $(filter-out -march=%,$(CXXFLAGS)) -$(LIBRARIES_PATH)/features/dma/simulation/libdmamem.so: CXXFLAGS := $(filter-out -mabi=%,$(CXXFLAGS)) -$(LIBRARIES_PATH)/features/dma/simulation/libdmamem.so: CXXFLAGS := $(filter-out -mcmodel=%,$(CXXFLAGS)) -$(LIBRARIES_PATH)/features/dma/simulation/libdmamem.so: CXXFLAGS := $(filter-out -D_DRAMFS,$(CXXFLAGS)) -$(LIBRARIES_PATH)/features/dma/simulation/libdmamem.so: INCLUDES := - -$(LIBRARIES_PATH)/features/dma/simulation/libdramsim3.so: INCLUDES := - PLATFORM_CXXSOURCES += $(BSG_PLATFORM_PATH)/bsg_manycore_simulator.cpp PLATFORM_OBJECTS += $(patsubst %cpp,%o,$(PLATFORM_CXXSOURCES)) @@ -129,24 +129,21 @@ $(PLATFORM_OBJECTS): CXXFLAGS := -std=c++11 -fPIC -DVCS -D_GNU_SOURCE -DVERILATO $(PLATFORM_OBJECTS): LDFLAGS := -fPIC $(PLATFORM_OBJECTS): CXX = g++ -# Mirror the extensions linux installation in /usr/lib provides so -# that we can use -lbsg_manycore_runtime -$(BSG_PLATFORM_PATH)/libbsg_manycore_runtime.a.1: %.a.1: %.so.1.0 - ln -sf $(basename $(basename $@)).so.1.0 $@ - -$(BSG_PLATFORM_PATH)/libbsgmc_cuda_legacy_pod_repl.a.1: %.a.1: %.so.1.0 - ln -sf $(basename $(basename $@)).so.1.0 $@ - -$(BSG_PLATFORM_PATH)/libbsg_manycore_regression.a.1: %.a.1: %.so.1.0 - ln -sf $(basename $(basename $@)).so.1.0 $@ - -$(BSG_PLATFORM_PATH)/libbsg_manycore_runtime.a: %: %.1 - ln -sf $@.1 $@ - -$(BSG_PLATFORM_PATH)/libbsgmc_cuda_legacy_pod_repl.a: %: %.1 - ln -sf $@.1 $@ - -$(BSG_PLATFORM_PATH)/libbsg_manycore_regression.a: %: %.1 +$(BSG_PLATFORM_PATH)/libbsg_manycore_platform.so.1.0: $(DROMAJO_OBJECTS) +$(BSG_PLATFORM_PATH)/libbsg_manycore_platform.so.1.0: $(PLATFORM_OBJECTS) +$(BSG_PLATFORM_PATH)/libbsg_manycore_platform.so.1.0: $(LIBRARIES_PATH)/features/dma/simulation/libdmamem.so +$(BSG_PLATFORM_PATH)/libbsg_manycore_platform.so.1.0: $(LIBRARIES_PATH)/features/dma/simulation/libdramsim3.so +$(BSG_PLATFORM_PATH)/libbsg_manycore_platform.so.1.0: LDFLAGS := -fPIC +$(BSG_PLATFORM_PATH)/libbsg_manycore_platform.so.1.0: LDFLAGS += -L$(LIBRARIES_PATH)/features/dma/simulation -Wl,-rpath=$(LIBRARIES_PATH)/features/dma/simulation -ldmamem +$(BSG_PLATFORM_PATH)/libbsg_manycore_platform.so.1.0: LDFLAGS += -L$(LIBRARIES_PATH)/features/dma/simulation -Wl,-rpath=$(LIBRARIES_PATH)/features/dma/simulation -ldramsim3 +$(BSG_PLATFORM_PATH)/libbsg_manycore_platform.so.1.0: LD = $(CXX) +$(BSG_PLATFORM_PATH)/libbsg_manycore_platform.so.1.0: + $(LD) -shared -Wl,-soname,$(basename $(notdir $@)) -o $@ $(DROMAJO_OBJECTS) $(PLATFORM_OBJECTS) $(LDFLAGS) + +$(BSG_PLATFORM_PATH)/libbsg_manycore_platform.so.1: %: %.0 + ln -sf $@.0 $@ + +$(BSG_PLATFORM_PATH)/libbsg_manycore_platform.so: %: %.1 ln -sf $@.1 $@ platform.clean: @@ -154,12 +151,7 @@ platform.clean: rm -f $(DROMAJO_OBJECTS) rm -f $(BSG_PLATFORM_PATH)/lfs.o rm -f $(BSG_PLATFORM_PATH)/libbsg_manycore_runtime.a - rm -f $(BSG_PLATFORM_PATH)/libbsg_manycore_runtime.a.1 rm -f $(BSG_PLATFORM_PATH)/libbsgmc_cuda_legacy_pod_repl.a - rm -f $(BSG_PLATFORM_PATH)/libbsgmc_cuda_legacy_pod_repl.a.1 rm -f $(BSG_PLATFORM_PATH)/libbsg_manycore_regression.a - rm -f $(BSG_PLATFORM_PATH)/libbsg_manycore_regression.a.1 - rm -f $(BSG_PLATFORM_PATH)/libbsg_manycore_platform.so - rm -f $(BSG_PLATFORM_PATH)/libbsg_manycore_platform.so.1 libraries.clean: platform.clean diff --git a/libraries/platforms/dromajo-vcs/link.mk b/libraries/platforms/dromajo-vcs/link.mk index 2b804eea8..5d44f97f6 100644 --- a/libraries/platforms/dromajo-vcs/link.mk +++ b/libraries/platforms/dromajo-vcs/link.mk @@ -109,32 +109,19 @@ TEST_CXXSOURCES += $(filter %.cpp,$(TEST_SOURCES)) TEST_OBJECTS += $(TEST_CXXSOURCES:.cpp=.o) TEST_OBJECTS += $(TEST_CSOURCES:.c=.o) +$(BSG_PLATFORM_PATH)/test.riscv: CC = $(RV_CC) +$(BSG_PLATFORM_PATH)/test.riscv: CXX = $(RV_CXX) $(BSG_PLATFORM_PATH)/test.riscv: $(TEST_OBJECTS) $(BSG_PLATFORM_PATH)/test.riscv: $(BSG_PLATFORM_PATH)/lfs.o $(BSG_PLATFORM_PATH)/test.riscv: $(BSG_PLATFORM_PATH)/libbsg_manycore_runtime.a $(BSG_PLATFORM_PATH)/test.riscv: $(BSG_PLATFORM_PATH)/libbsgmc_cuda_legacy_pod_repl.a $(BSG_PLATFORM_PATH)/test.riscv: $(BSG_PLATFORM_PATH)/libbsg_manycore_regression.a $(BSG_PLATFORM_PATH)/test.riscv: LDFLAGS := -T$(BLACKPARROT_DIR)/sdk/linker/riscv.ld -L$(BSG_PLATFORM_PATH) -static -nostartfiles -lstdc++ -lbsg_manycore_runtime -lbsg_manycore_regression +$(BSG_PLATFORM_PATH)/test.riscv: LD = $(CXX) $(BSG_PLATFORM_PATH)/test.riscv: - $(RV_CXX) -D_DRAMFS -o $@ $(BSG_PLATFORM_PATH)/software/src/crt0.o $(BSG_PLATFORM_PATH)/lfs.o $< $(LDFLAGS) + $(LD) -D_DRAMFS -o $@ $(BSG_PLATFORM_PATH)/software/src/crt0.o $(BSG_PLATFORM_PATH)/lfs.o $< $(LDFLAGS) cp $@ $(subst riscv,elf,$(notdir $@)) -$(BSG_PLATFORM_PATH)/libbsg_manycore_platform.so.1.0: $(DROMAJO_OBJECTS) -$(BSG_PLATFORM_PATH)/libbsg_manycore_platform.so.1.0: $(PLATFORM_OBJECTS) -$(BSG_PLATFORM_PATH)/libbsg_manycore_platform.so.1.0: LDFLAGS := -fPIC -$(BSG_PLATFORM_PATH)/libbsg_manycore_platform.so.1.0: LDFLAGS += -L$(LIBRARIES_PATH)/features/dma/simulation -Wl,-rpath=$(LIBRARIES_PATH)/features/dma/simulation -ldmamem -$(BSG_PLATFORM_PATH)/libbsg_manycore_platform.so.1.0: $(LIBRARIES_PATH)/features/dma/simulation/libdmamem.so -$(BSG_PLATFORM_PATH)/libbsg_manycore_platform.so.1.0: LDFLAGS += -L$(LIBRARIES_PATH)/features/dma/simulation -Wl,-rpath=$(LIBRARIES_PATH)/features/dma/simulation -ldramsim3 -$(BSG_PLATFORM_PATH)/libbsg_manycore_platform.so.1.0: $(LIBRARIES_PATH)/features/dma/simulation/libdramsim3.so -$(BSG_PLATFORM_PATH)/libbsg_manycore_platform.so.1.0: - $(CXX) -shared -Wl,-soname,$(basename $(notdir $@)) -o $@ $(DROMAJO_OBJECTS) $(PLATFORM_OBJECTS) $(LDFLAGS) - -$(BSG_PLATFORM_PATH)/libbsg_manycore_platform.so.1: %: %.0 - ln -sf $@.0 $@ - -$(BSG_PLATFORM_PATH)/libbsg_manycore_platform.so: %: %.1 - ln -sf $@.1 $@ - # VCS Generates an executable file by linking the TEST_OBJECTS with # the the VCS work libraries for the design, and the runtime shared # libraries From e8e37d45d296f2fbe9d90f4d3fac7b3fdd4e720a Mon Sep 17 00:00:00 2001 From: sripathi-muralitharan Date: Mon, 17 May 2021 10:40:13 -0700 Subject: [PATCH 31/70] Credit refactor --- .../dromajo-vcs/bsg_manycore_platform.cpp | 24 ++++++++-- .../dromajo-vcs/bsg_manycore_simulator.cpp | 44 +++++++++++++++---- 2 files changed, 56 insertions(+), 12 deletions(-) diff --git a/libraries/platforms/dromajo-vcs/bsg_manycore_platform.cpp b/libraries/platforms/dromajo-vcs/bsg_manycore_platform.cpp index de457f28d..e236c3d6d 100644 --- a/libraries/platforms/dromajo-vcs/bsg_manycore_platform.cpp +++ b/libraries/platforms/dromajo-vcs/bsg_manycore_platform.cpp @@ -191,8 +191,10 @@ int hb_mc_platform_get_config_at(hb_mc_manycore_t *mc, unsigned int idx, hb_mc_c req_pkt.request.addr = 0x100 + idx; bp_hb_write_to_manycore_bridge(&req_pkt); int err = bp_hb_read_from_manycore_bridge(&resp_pkt, HB_MC_FIFO_RX_RSP); - if (err != 0) + if (err != HB_MC_SUCCESS) { + bsg_pr_err("Config read failed\n"); return HB_MC_FAIL; + } uint32_t data = resp_pkt.response.data; if (data != 0xFFFFFFFF) @@ -214,8 +216,9 @@ int hb_mc_platform_get_config_at(hb_mc_manycore_t *mc, unsigned int idx, hb_mc_c */ int hb_mc_platform_fence(hb_mc_manycore_t *mc, long timeout) { int credits, err; - bool isvacant; uint32_t max_credits; + int is_vacant; + hb_mc_packet_t req_pkt, resp_pkt; const hb_mc_config_t *cfg = hb_mc_manycore_get_config(mc); hb_mc_platform_t *platform = reinterpret_cast(mc->platform); @@ -226,12 +229,25 @@ int hb_mc_platform_fence(hb_mc_manycore_t *mc, long timeout) { return HB_MC_NOIMPL; } + // Prepare host packet to query TX vacancy + req_pkt.request.x_dst = 0; + req_pkt.request.y_dst = 0; + req_pkt.request.x_src = 0; + req_pkt.request.y_src = 1; + req_pkt.request.op_v2 = HB_MC_PACKET_OP_REMOTE_LOAD; + req_pkt.request.payload = 0; + req_pkt.request.reg_id = 0; + req_pkt.request.addr = 0x300; // x86 Host address to poll tx vacancy + do { credits = bp_hb_get_credits(); - } while (!(credits == (int)max_credits)); + bp_hb_write_to_manycore_bridge(&req_pkt); + err = bp_hb_read_from_manycore_bridge(&resp_pkt, HB_MC_FIFO_RX_RSP); + is_vacant = resp_pkt.response.data; + } while ((err == HB_MC_SUCCESS) && !(credits == max_credits) && (is_vacant == 1)); - return HB_MC_SUCCESS; + return err; } /** diff --git a/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.cpp b/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.cpp index b97fd68c3..18021d87d 100644 --- a/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.cpp +++ b/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.cpp @@ -271,6 +271,7 @@ int SimulationWrapper::dromajo_transmit_packet() { data = 0xFFFFFFFF; } + // Dromajo/BlackParrot wants to know if reset is done else if (dromajo_to_mc_packet.request.addr == 0x200) { bool done; dpi->reset_is_done(done); @@ -280,6 +281,16 @@ int SimulationWrapper::dromajo_transmit_packet() { data = 0; } + // Dromajo/BlackParrot wants to know if the TX FIFO is vacant + else if (dromajo_to_mc_packet.request.addr == 0x300) { + bool is_vacant; + dpi->tx_is_vacant(is_vacant); + if (is_vacant) + data = 1; + else + data = 0; + } + else { bsg_pr_err("Host EPA not mapped\n"); return HB_MC_FAIL; @@ -301,6 +312,12 @@ int SimulationWrapper::dromajo_transmit_packet() { else { pkt = reinterpret_cast<__m128i *>(&dromajo_to_mc_packet); + // Allows the DPI interface to track response FIFO capacity + bool expect_response = + (dromajo_to_mc_packet.request.op_v2 != HB_MC_PACKET_OP_REMOTE_STORE) && + (dromajo_to_mc_packet.request.op_v2 != HB_MC_PACKET_OP_REMOTE_SW) && + (dromajo_to_mc_packet.request.op_v2 != HB_MC_PACKET_OP_CACHE_OP); + // Attempt packet transmission // Since we trigger a call to the transmit FIFOs only when the Dromajo // FIFOs are full, we need to wait until the DPI FIFOs are ready to receive @@ -309,9 +326,10 @@ int SimulationWrapper::dromajo_transmit_packet() { // create backpressure in actual hardware and provision for it. do { advance_time(); - err = dpi->tx_req(*pkt); + err = dpi->tx_req(*pkt, expect_response); } while (err != BSG_NONSYNTH_DPI_SUCCESS && (err == BSG_NONSYNTH_DPI_NO_CREDITS || + err == BSG_NONSYNTH_DPI_NO_CAPACITY || err == BSG_NONSYNTH_DPI_NOT_WINDOW || err == BSG_NONSYNTH_DPI_BUSY || err == BSG_NONSYNTH_DPI_NOT_READY)); @@ -350,7 +368,8 @@ int SimulationWrapper::dromajo_receive_packet() { err = dpi->rx_req(pkt); } while (err != BSG_NONSYNTH_DPI_SUCCESS && (err == BSG_NONSYNTH_DPI_NOT_WINDOW || - err == BSG_NONSYNTH_DPI_BUSY )); + err == BSG_NONSYNTH_DPI_BUSY || + err == BSG_NONSYNTH_DPI_INVALID)); if (err == BSG_NONSYNTH_DPI_SUCCESS) { mc_to_dromajo_req_packet = reinterpret_cast(&pkt); @@ -369,7 +388,8 @@ int SimulationWrapper::dromajo_receive_packet() { err = dpi->rx_rsp(pkt); } while (err != BSG_NONSYNTH_DPI_SUCCESS && (err == BSG_NONSYNTH_DPI_NOT_WINDOW || - err == BSG_NONSYNTH_DPI_BUSY )); + err == BSG_NONSYNTH_DPI_BUSY || + err == BSG_NONSYNTH_DPI_INVALID)); if (err == BSG_NONSYNTH_DPI_SUCCESS) { mc_to_dromajo_resp_packet = reinterpret_cast(&pkt); @@ -391,17 +411,25 @@ int SimulationWrapper::dromajo_receive_packet() { * for the Dromajo->Manycore request FIFO in dromajo */ int SimulationWrapper::dromajo_set_credits() { - int credits; - int err = dpi->get_credits(credits); + int credits, credits_used, max_credits; + int err; + + err = dpi->get_credits_used(credits_used); + if (err != BSG_NONSYNTH_DPI_SUCCESS) { + bsg_pr_err(bsg_nonsynth_dpi_strerror(err)); + return HB_MC_FAIL; + } + + err = dpi->get_credits_max(max_credits); if (err == BSG_NONSYNTH_DPI_SUCCESS) { + credits = max_credits - credits_used; if (credits < 0) - bsg_pr_warn("Credit value is negative!\n"); - + bsg_pr_err("Credit value is < 0. Must be non-negative\n"); host_to_mc_req_fifo->credits = credits; } else { bsg_pr_err(bsg_nonsynth_dpi_strerror(err)); - return HB_MC_FAIL; + return err; } return HB_MC_SUCCESS; From 3cc0e00cd3e1bd48235f5de16222c7dcd336d131 Mon Sep 17 00:00:00 2001 From: sripathi-muralitharan Date: Mon, 21 Jun 2021 17:13:37 -0700 Subject: [PATCH 32/70] Add comments --- libraries/platforms/dromajo-vcs/software/src/flockfile.c | 4 ++++ libraries/platforms/dromajo-vcs/software/src/funlockfile.c | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/libraries/platforms/dromajo-vcs/software/src/flockfile.c b/libraries/platforms/dromajo-vcs/software/src/flockfile.c index 2028dc4dd..315c8e33a 100644 --- a/libraries/platforms/dromajo-vcs/software/src/flockfile.c +++ b/libraries/platforms/dromajo-vcs/software/src/flockfile.c @@ -31,6 +31,10 @@ #include +/** + * Lock a file. This function is currently a no-op since CUDA-lite is not thread-safe. + * @param[in] fp A FILE object pointer + */ void flockfile(FILE *fp) { // Do nothing diff --git a/libraries/platforms/dromajo-vcs/software/src/funlockfile.c b/libraries/platforms/dromajo-vcs/software/src/funlockfile.c index dfab8688a..dee9ef05a 100644 --- a/libraries/platforms/dromajo-vcs/software/src/funlockfile.c +++ b/libraries/platforms/dromajo-vcs/software/src/funlockfile.c @@ -31,6 +31,10 @@ #include +/** + * Unlock a file. This function is currently a no-op since CUDA-lite is not thread-safe. + * @param[in] fp A FILE object pointer + */ void funlockfile(FILE *fp) { // Do nothing From df98c717b8bd4040f02686974211677ab337f0b2 Mon Sep 17 00:00:00 2001 From: sripathi-muralitharan Date: Mon, 21 Jun 2021 17:31:08 -0700 Subject: [PATCH 33/70] Refactoring a lot of stuff * More comments, fixme's and TODOs - might be helpful for future * Adding more features to BP's host -> program termination and printing * Hopefully this is easier to maintain --- examples/.gitignore | 1 + .../dromajo-vcs/bsg_manycore_platform.cpp | 147 +++++---- .../dromajo-vcs/bsg_manycore_simulator.cpp | 245 ++++++++------- .../dromajo-vcs/bsg_manycore_simulator.hpp | 17 ++ .../dromajo-vcs/software/include/bp_utils.h | 85 +++++- .../platforms/dromajo-vcs/software/src/args.c | 67 +++-- .../dromajo-vcs/software/src/bp_utils.c | 278 ++++++++++++------ 7 files changed, 539 insertions(+), 301 deletions(-) diff --git a/examples/.gitignore b/examples/.gitignore index f6f502536..1b61de35f 100644 --- a/examples/.gitignore +++ b/examples/.gitignore @@ -25,4 +25,5 @@ ucli.key *.json dramsim3.txt *.riscv +*.elf diff --git a/libraries/platforms/dromajo-vcs/bsg_manycore_platform.cpp b/libraries/platforms/dromajo-vcs/bsg_manycore_platform.cpp index e236c3d6d..b84919277 100644 --- a/libraries/platforms/dromajo-vcs/bsg_manycore_platform.cpp +++ b/libraries/platforms/dromajo-vcs/bsg_manycore_platform.cpp @@ -119,6 +119,9 @@ int hb_mc_platform_init(hb_mc_manycore_t *mc, hb_mc_manycore_id_t id) { int hb_mc_platform_transmit(hb_mc_manycore_t *mc, hb_mc_packet_t *packet, hb_mc_fifo_tx_t type, long timeout) { hb_mc_platform_t *platform = reinterpret_cast(mc->platform); const char *typestr = hb_mc_fifo_tx_to_string(type); + const hb_mc_config_t *cfg = hb_mc_manycore_get_config(mc); + uint32_t max_credits = hb_mc_config_get_io_endpoint_max_out_credits(cfg); + int err; // Timeout is unsupported if (timeout != -1) @@ -134,8 +137,16 @@ int hb_mc_platform_transmit(hb_mc_manycore_t *mc, hb_mc_packet_t *packet, hb_mc_ return HB_MC_NOIMPL; } - // Write packet to the manycore bridge - bp_hb_write_to_manycore_bridge(packet); + int credits_used; + do { + err = bp_hb_get_credits_used(&credits_used); + } while ((err != HB_MC_SUCCESS) || (max_credits - credits_used <= 0)); + + err = bp_hb_write_to_mc_bridge(packet); + if (err != HB_MC_SUCCESS) { + bsg_pr_err("Write to the host request FIFO failed!"); + return err; + } return HB_MC_SUCCESS; } @@ -149,6 +160,7 @@ int hb_mc_platform_transmit(hb_mc_manycore_t *mc, hb_mc_packet_t *packet, hb_mc_ */ int hb_mc_platform_receive(hb_mc_manycore_t *mc, hb_mc_packet_t *packet, hb_mc_fifo_rx_t type, long timeout) { hb_mc_platform_t *platform = reinterpret_cast(mc->platform); + const char *typestr = hb_mc_fifo_rx_to_string(type); // Timeout is unsupported if (timeout != -1) @@ -157,11 +169,18 @@ int hb_mc_platform_receive(hb_mc_manycore_t *mc, hb_mc_packet_t *packet, hb_mc_f return HB_MC_INVALID; } - int err = bp_hb_read_from_manycore_bridge(packet, type); + int err; + int num_entries; + do { + err = bp_hb_get_fifo_entries(&num_entries, type); + } while (num_entries == 0 || err != HB_MC_SUCCESS); - if (err != 0) - { - manycore_pr_err(mc, "%s: Failed to receive packet\n", __func__); + if (err != HB_MC_SUCCESS) + return err; + + err = bp_hb_read_from_mc_bridge(packet, type); + if (err != HB_MC_SUCCESS) { + bsg_pr_err("Read from the %s FIFO did not succeed", typestr); return HB_MC_INVALID; } @@ -177,30 +196,41 @@ int hb_mc_platform_receive(hb_mc_manycore_t *mc, hb_mc_packet_t *packet, hb_mc_f */ int hb_mc_platform_get_config_at(hb_mc_manycore_t *mc, unsigned int idx, hb_mc_config_raw_t *config) { hb_mc_platform_t *platform = reinterpret_cast(mc->platform); - hb_mc_packet_t req_pkt, resp_pkt; + hb_mc_packet_t config_req_pkt, config_resp_pkt; + int num_entries, err; if (idx < HB_MC_CONFIG_MAX) { - req_pkt.request.x_dst = 0; - req_pkt.request.y_dst = 0; - req_pkt.request.x_src = 0; - req_pkt.request.y_src = 1; - req_pkt.request.op_v2 = HB_MC_PACKET_OP_REMOTE_LOAD; - req_pkt.request.payload = 0; - req_pkt.request.reg_id = 0; - req_pkt.request.addr = 0x100 + idx; - bp_hb_write_to_manycore_bridge(&req_pkt); - int err = bp_hb_read_from_manycore_bridge(&resp_pkt, HB_MC_FIFO_RX_RSP); + config_req_pkt.request.x_dst = (0 << 4) | 0; + config_req_pkt.request.y_dst = (1 << 3) | 0; + config_req_pkt.request.x_src = (0 << 4) | 0; + config_req_pkt.request.y_src = (1 << 3) | 1; + config_req_pkt.request.op_v2 = HB_MC_PACKET_OP_REMOTE_LOAD; + config_req_pkt.request.payload = 0; + config_req_pkt.request.reg_id = 0; + config_req_pkt.request.addr = MC_CONFIG_START_EPA_ADDR + idx; + + // Note: Potentially dangerous to write to the FIFO without checking for credits + // We get back credits used and not credits remaining and without the configuration + // there is no way to know the credits remaining. + err = bp_hb_write_to_mc_bridge(&config_req_pkt); + if (err != HB_MC_SUCCESS) { + bsg_pr_err("Write to the host request FIFO failed!"); + return err; + } + + do { + err = bp_hb_get_fifo_entries(&num_entries, HB_MC_FIFO_RX_RSP); + } while (num_entries == 0 || err != HB_MC_SUCCESS); + + err = bp_hb_read_from_mc_bridge(&config_resp_pkt, HB_MC_FIFO_RX_RSP); if (err != HB_MC_SUCCESS) { bsg_pr_err("Config read failed\n"); return HB_MC_FAIL; } - uint32_t data = resp_pkt.response.data; - if (data != 0xFFFFFFFF) - *config = data; - else - *config = 0; + uint32_t data = config_resp_pkt.response.data; + *config = (data != MC_HOST_OP_FINISH_CODE) ? data : 0; return HB_MC_SUCCESS; } @@ -215,14 +245,11 @@ int hb_mc_platform_get_config_at(hb_mc_manycore_t *mc, unsigned int idx, hb_mc_c * @return HB_MC_SUCCESS on success. Otherwise an error code defined in bsg_manycore_errno.h. */ int hb_mc_platform_fence(hb_mc_manycore_t *mc, long timeout) { - int credits, err; + int credits_used, is_vacant, num_entries, err; uint32_t max_credits; - int is_vacant; - hb_mc_packet_t req_pkt, resp_pkt; + hb_mc_packet_t fence_req_pkt, fence_resp_pkt; - const hb_mc_config_t *cfg = hb_mc_manycore_get_config(mc); hb_mc_platform_t *platform = reinterpret_cast(mc->platform); - max_credits = hb_mc_config_get_io_endpoint_max_out_credits(cfg); if (timeout != -1) { manycore_pr_err(mc, "%s: Only a timeout value of -1 is supported\n", __func__); @@ -230,22 +257,30 @@ int hb_mc_platform_fence(hb_mc_manycore_t *mc, long timeout) { } // Prepare host packet to query TX vacancy - req_pkt.request.x_dst = 0; - req_pkt.request.y_dst = 0; - req_pkt.request.x_src = 0; - req_pkt.request.y_src = 1; - req_pkt.request.op_v2 = HB_MC_PACKET_OP_REMOTE_LOAD; - req_pkt.request.payload = 0; - req_pkt.request.reg_id = 0; - req_pkt.request.addr = 0x300; // x86 Host address to poll tx vacancy + fence_req_pkt.request.x_dst = (0 << 4) | 0; + fence_req_pkt.request.y_dst = (1 << 3) | 0; + fence_req_pkt.request.x_src = (0 << 4) | 0; + fence_req_pkt.request.y_src = (1 << 3) | 1; + fence_req_pkt.request.op_v2 = HB_MC_PACKET_OP_REMOTE_LOAD; + fence_req_pkt.request.payload = 0; + fence_req_pkt.request.reg_id = 0; + fence_req_pkt.request.addr = MC_TX_VACANT_EPA_ADDR; // x86 Host address to poll tx vacancy do { - credits = bp_hb_get_credits(); - bp_hb_write_to_manycore_bridge(&req_pkt); - err = bp_hb_read_from_manycore_bridge(&resp_pkt, HB_MC_FIFO_RX_RSP); - is_vacant = resp_pkt.response.data; - } while ((err == HB_MC_SUCCESS) && !(credits == max_credits) && (is_vacant == 1)); + err = bp_hb_get_credits_used(&credits_used); + // In a real system, this function call makes no sense since we will be sending packets to the + // host on the network and are trying to check for credits to be zero and complete the fence. + // It is fine here because of the system setup. + err |= bp_hb_write_to_mc_bridge(&fence_req_pkt); + + do { + err = bp_hb_get_fifo_entries(&num_entries, HB_MC_FIFO_RX_RSP); + } while (num_entries == 0 || err != HB_MC_SUCCESS); + err |= bp_hb_read_from_mc_bridge(&fence_resp_pkt, HB_MC_FIFO_RX_RSP); + + is_vacant = fence_resp_pkt.response.data; + } while ((err != HB_MC_SUCCESS) || (credits_used != 0) || (is_vacant != 1)); return err; } @@ -331,27 +366,27 @@ int hb_mc_platform_log_disable(hb_mc_manycore_t *mc) { * @return HB_MC_SUCCESS on success. Otherwise an error code defined in bsg_manycore_errno.h. */ int hb_mc_platform_wait_reset_done(hb_mc_manycore_t *mc) { - hb_mc_packet_t req_pkt, resp_pkt; - int err; + hb_mc_packet_t reset_req_pkt, reset_resp_pkt; + int err, credits_used; uint32_t data; - req_pkt.request.x_src = 0; - req_pkt.request.y_src = 1; - req_pkt.request.x_dst = 0; - req_pkt.request.y_dst = 0; - req_pkt.request.op_v2 = HB_MC_PACKET_OP_REMOTE_LOAD; - req_pkt.request.payload = 0; - req_pkt.request.reg_id = 0; - req_pkt.request.addr = 0x200; + reset_req_pkt.request.x_dst = (0 << 4) | 0; + reset_req_pkt.request.y_dst = (1 << 3) | 0; + reset_req_pkt.request.x_src = (0 << 4) | 0; + reset_req_pkt.request.y_src = (1 << 3) | 1; + reset_req_pkt.request.op_v2 = HB_MC_PACKET_OP_REMOTE_LOAD; + reset_req_pkt.request.payload = 0; + reset_req_pkt.request.reg_id = 0; + reset_req_pkt.request.addr = MC_RESET_DONE_EPA_ADDR; do { - bp_hb_write_to_manycore_bridge(&req_pkt); - err = bp_hb_read_from_manycore_bridge(&resp_pkt, HB_MC_FIFO_RX_RSP); - data = resp_pkt.response.data; - } while((err != HB_MC_SUCCESS) && (data != 1)); + // The platform setup ensures that this packet will not go over the network so + // we don't need to check for credits. + err = bp_hb_write_to_mc_bridge(&reset_req_pkt); + err |= bp_hb_read_from_mc_bridge(&reset_resp_pkt, HB_MC_FIFO_RX_RSP); - if (data == 0) - return HB_MC_FAIL; + data = reset_resp_pkt.response.data; + } while((err != HB_MC_SUCCESS) || (data == 0)); return HB_MC_SUCCESS; } diff --git a/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.cpp b/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.cpp index 18021d87d..ef1f9ac1e 100644 --- a/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.cpp +++ b/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.cpp @@ -43,7 +43,6 @@ extern "C" { int _argc; char **_argv; static int char_index = 0; -int idx = 0; ////////////////////////////// SimulationWrapper functions ////////////////////////////// @@ -59,7 +58,7 @@ SimulationWrapper::SimulationWrapper(){ dpi_init(); if ((!dromajo) || (!dpi)) { - bsg_pr_err("Failed to initialize DPI pointer\n"); + bsg_pr_err("Failed to initialize DPI or Dromajo pointer\n"); } } @@ -199,10 +198,7 @@ int SimulationWrapper::dromajo_init() { bool SimulationWrapper::dromajo_step() { // Execute dromajo with verbose mode on int err = dromajo_cosim_step(dromajo, 0, 0, 0, 0, 0, false, false); - if (err != 0) - return false; - else - return true; + return (err != 0) ? false : true; } /* @@ -228,85 +224,125 @@ int SimulationWrapper::dromajo_transmit_packet() { dromajo_to_mc_packet.words[3] = host_to_mc_req_fifo->fifo[3].front(); // Intercept packets that are for the host and generate appropriate responses - if ((dromajo_to_mc_packet.request.x_dst == 0) && (dromajo_to_mc_packet.request.y_dst == 0)) { + if ((dromajo_to_mc_packet.request.x_dst == ((0 << 4) | 0)) && (dromajo_to_mc_packet.request.y_dst == ((1 << 3) | 0))) { host_to_dromajo_packet.response.x_dst = dromajo_to_mc_packet.request.x_src; host_to_dromajo_packet.response.y_dst = dromajo_to_mc_packet.request.y_src; host_to_dromajo_packet.response.load_id = 0; - if (dromajo_to_mc_packet.request.op_v2 == HB_MC_PACKET_OP_REMOTE_LOAD) { - host_to_dromajo_packet.response.op = dromajo_to_mc_packet.request.op_v2; - uint32_t idx = dromajo_to_mc_packet.request.addr; - uint32_t data = 0; - - // If EPA maps to reading arguments - if (dromajo_to_mc_packet.request.addr >= 0 && dromajo_to_mc_packet.request.addr <= 0xFF) { - int num_characters = 0; - // If all arguments have been read or there are no arguments to read - // send a finish code - if ((idx == _argc) || (_argc == 0)) { - data = 0xFFFFFFFF; - } - else { - // Copy 4 bytes of the arguments - for(int i = 0; i < 4; i++) { - if (_argv[idx][char_index] != '\0') { - data = (data << 8) | _argv[idx][char_index]; - num_characters++; - char_index++; - } - else { - data = (data << (4 - num_characters) * 8); - char_index = 0; + uint32_t data = 0; + switch (dromajo_to_mc_packet.request.op_v2) { + case HB_MC_PACKET_OP_REMOTE_LOAD: + { + // Fixme: Is there no struct for response opcode like in the manycore hardware + host_to_dromajo_packet.response.op = dromajo_to_mc_packet.request.op_v2; + switch (dromajo_to_mc_packet.request.addr) { + case MC_ARGS_START_EPA_ADDR ... MC_ARGS_FINISH_EPA_ADDR: + { + uint32_t idx = dromajo_to_mc_packet.request.addr - MC_ARGS_START_EPA_ADDR; + int num_characters = 0; + // If all arguments have been read or there are no arguments to read + // send a finish code + if ((idx != _argc) && (_argc != 0)) { + // Copy 4 bytes of the arguments + for(int i = 0; i < 4; i++) { + if (_argv[idx][char_index] != '\0') { + data = (data << 8) | _argv[idx][char_index]; + num_characters++; + char_index++; + } + else { + data = (data << (4 - num_characters) * 8); + char_index = 0; + } + } } + else + data = MC_HOST_OP_FINISH_CODE; + } + break; + case MC_CONFIG_START_EPA_ADDR ... MC_CONFIG_FINISH_EPA_ADDR: + { + uint32_t idx = dromajo_to_mc_packet.request.addr - MC_CONFIG_START_EPA_ADDR; + data = (idx <= HB_MC_CONFIG_MAX) ? dpi->config[idx] : MC_HOST_OP_FINISH_CODE; + } + break; + case MC_RESET_DONE_EPA_ADDR: + { + bool done; + dpi->reset_is_done(done); + data = done ? 1 : 0; + } + break; + case MC_TX_VACANT_EPA_ADDR: + { + bool is_vacant; + dpi->tx_is_vacant(is_vacant); + data = is_vacant ? 1 : 0; + } + break; + default: + { + bsg_pr_err("Invalid address for host load operation\n"); + return HB_MC_FAIL; } - } - } - - // Dromajo/BlackParrot wants to read the config - else if (dromajo_to_mc_packet.request.addr >= 0x100 && dromajo_to_mc_packet.request.addr <= 0x1FF) { - idx = dromajo_to_mc_packet.request.addr - 0x100; - if (idx <= HB_MC_CONFIG_MAX) - data = dpi->config[idx]; - else - data = 0xFFFFFFFF; - } - // Dromajo/BlackParrot wants to know if reset is done - else if (dromajo_to_mc_packet.request.addr == 0x200) { - bool done; - dpi->reset_is_done(done); - if (done) - data = 1; - else - data = 0; + } + host_to_dromajo_packet.response.data = data; + for(int j = 0; j < 4; j++) { + mc_to_host_resp_fifo->fifo[j].push(host_to_dromajo_packet.words[j]); + host_to_mc_req_fifo->fifo[j].pop(); + } } - - // Dromajo/BlackParrot wants to know if the TX FIFO is vacant - else if (dromajo_to_mc_packet.request.addr == 0x300) { - bool is_vacant; - dpi->tx_is_vacant(is_vacant); - if (is_vacant) - data = 1; - else - data = 0; + break; + case HB_MC_PACKET_OP_REMOTE_SW: + { + switch (dromajo_to_mc_packet.request.addr) { + case MC_STDOUT_EPA_ADDR: + case MC_STDERR_EPA_ADDR: + printf("%c", (uint8_t) dromajo_to_mc_packet.request.payload); + break; + case MC_FINISH_EPA_ADDR: + { + int16_t core_id = dromajo_to_mc_packet.request.payload >> 16; + // Success error codes in BP is 0, but 0 is already used by the manycore. Any positive number indicates + // success, therefore, add 1. + int err = (0x0000FFFF & dromajo_to_mc_packet.request.payload) + 1; + bsg_pr_info("Core %d successfully terminated\n", core_id); + // De-allocate all pointers prior to termination + dpi_cleanup(); + dromajo_cosim_fini(dromajo); + return err; + } + break; + case MC_FAIL_EPA_ADDR: + { + int16_t core_id = dromajo_to_mc_packet.request.payload >> 16; + int16_t err = 0x0000FFFF & dromajo_to_mc_packet.request.payload; + bsg_pr_err("Core %d terminated with code %d\n", core_id, err); + // De-allocate all pointers prior to termination + dpi_cleanup(); + dromajo_cosim_fini(dromajo); + return err; + } + break; + default: + { + bsg_pr_err("Invalid address for host store operation\n"); + return HB_MC_FAIL; + } + } + // Store requests don't have responses so only pop the host to MC fifo + for(int j = 0; j < 4; j++) { + host_to_mc_req_fifo->fifo[j].pop(); + } } - - else { - bsg_pr_err("Host EPA not mapped\n"); + break; + default: + { + bsg_pr_err("Operations other than loads and store words are not implemented for the host\n"); return HB_MC_FAIL; } - - host_to_dromajo_packet.response.data = data; - // Inject the response packet into manycore response FIFO - // Pop the request FIFO - for(int j = 0; j < 4; j++) { - mc_to_host_resp_fifo->fifo[j].push(host_to_dromajo_packet.words[j]); - host_to_mc_req_fifo->fifo[j].pop(); - } - } - else { - bsg_pr_err("Operations other than loads are not implemented for the host\n"); - return HB_MC_FAIL; + break; } } else { @@ -334,7 +370,6 @@ int SimulationWrapper::dromajo_transmit_packet() { err == BSG_NONSYNTH_DPI_BUSY || err == BSG_NONSYNTH_DPI_NOT_READY)); - // Pop the FIFO once transmitted if (err == BSG_NONSYNTH_DPI_SUCCESS) { for (int i = 0;i < 4; i++) host_to_mc_req_fifo->fifo[i].pop(); @@ -343,6 +378,12 @@ int SimulationWrapper::dromajo_transmit_packet() { bsg_pr_err("Packet transmission failed\n"); return HB_MC_FAIL; } + + // Update the credits in dromajo + bsg_pr_dbg("Checking for credits\n"); + err = dromajo_set_credits(); + if (err != HB_MC_SUCCESS) + return err; } } @@ -436,33 +477,29 @@ int SimulationWrapper::dromajo_set_credits() { } int SimulationWrapper::eval(){ - // Execute one instruction on Dromajo - if (!dromajo_step()) { - // Fixme: Dromajo could also terminate due to premature errors. - // Use the test outputs to detect PASS/FAIL - bsg_pr_info("Dromajo Execution Complete!\nExiting...\n"); - dromajo_cosim_fini(dromajo); - return HB_MC_SUCCESS; - } - - int err; - // Poll for packets to be transmitted - bsg_pr_dbg("Checking for packets to transmit\n"); - err = dromajo_transmit_packet(); - if (err != HB_MC_SUCCESS) - return err; - - // Poll for packets to be received - bsg_pr_dbg("Checking for packets to receive\n"); - err = dromajo_receive_packet(); - if (err != HB_MC_SUCCESS) - return err; + // Execute 100 instructions on Dromajo + for(int i = 0; i < NUM_DROMAJO_INSTR_PER_TICK; i++) { + if (!dromajo_step()) { + // Fixme: Dromajo could also terminate due to premature errors. + // Use the test outputs to detect PASS/FAIL + bsg_pr_info("Dromajo Execution Complete!\nExiting...\n"); + dromajo_cosim_fini(dromajo); + return HB_MC_SUCCESS; + } - // Update the credits in dromajo - bsg_pr_dbg("Checking for credits\n"); - err = dromajo_set_credits(); - if (err != HB_MC_SUCCESS) - return err; + int err; + // Poll for packets to be transmitted + bsg_pr_dbg("Checking for packets to transmit\n"); + err = dromajo_transmit_packet(); + if (err != HB_MC_SUCCESS) + return err; + + // Poll for packets to be received + bsg_pr_dbg("Checking for packets to receive\n"); + err = dromajo_receive_packet(); + if (err != HB_MC_SUCCESS) + return err; + } // Advance time 1 unit advance_time(); @@ -555,7 +592,9 @@ int vcs_main(int argc, char **argv) { int err; do { err = host->eval(); - } while (err == HB_MC_SUCCESS); + // Codes greater than 0 can be used to terminate a program + if (err > 0) break; + } while (err >= 0); return err; } @@ -579,7 +618,7 @@ extern "C" { int rc = vcs_main(argc, argv); *exit_code = rc; - bsg_pr_test_pass_fail(rc == HB_MC_SUCCESS); + bsg_pr_test_pass_fail(rc >= HB_MC_SUCCESS); return; } } diff --git a/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.hpp b/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.hpp index 9d3f42a6d..3194f8d61 100644 --- a/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.hpp +++ b/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.hpp @@ -57,6 +57,23 @@ declare_hb_mc_get_bits declare_bsg_printing +#define NUM_DROMAJO_INSTR_PER_TICK 1000 + +#define MC_ARGS_START_EPA_ADDR 0x0000 +#define MC_ARGS_FINISH_EPA_ADDR 0x00FF +#define MC_CONFIG_START_EPA_ADDR 0x0100 +#define MC_CONFIG_FINISH_EPA_ADDR 0x01FF +#define MC_RESET_DONE_EPA_ADDR 0x0200 +#define MC_TX_VACANT_EPA_ADDR 0x0300 +#define MC_FINISH_EPA_ADDR 0xEAD0 +#define MC_TIME_EPA_ADDR 0xEAD4 +#define MC_FAIL_EPA_ADDR 0xEAD8 +#define MC_STDOUT_EPA_ADDR 0xEADC +#define MC_STDERR_EPA_ADDR 0xEAE0 +#define MC_BRANCH_TRACE_EPA_ADDR 0xEAE4 +#define MC_PRINT_STAT_EPA_ADDR 0xEA0C +#define MC_HOST_OP_FINISH_CODE 0xFFFFFFFF + class SimulationWrapper{ // This is the generic pointer for implementation-specific // simulator details. In Verilator, this is diff --git a/libraries/platforms/dromajo-vcs/software/include/bp_utils.h b/libraries/platforms/dromajo-vcs/software/include/bp_utils.h index 24cb03381..509f6fa85 100644 --- a/libraries/platforms/dromajo-vcs/software/include/bp_utils.h +++ b/libraries/platforms/dromajo-vcs/software/include/bp_utils.h @@ -15,12 +15,26 @@ extern "C" { #include // Memory mapped addresses to interact with the host -#define HOST_DEV_BASE_ADDR ((char *)(0x00100000)) -#define GETCHAR_BASE_ADDR ((char *)(HOST_DEV_BASE_ADDR+0x0000)) -#define PUTCHAR_BASE_ADDR ((char *)(HOST_DEV_BASE_ADDR+0x1000)) -#define FINISH_BASE_ADDR ((char *)(HOST_DEV_BASE_ADDR+0x2000)) +#define MC_ARGS_START_EPA_ADDR 0x0000 +#define MC_ARGS_FINISH_EPA_ADDR 0x00FF +#define MC_CONFIG_START_EPA_ADDR 0x0100 +#define MC_CONFIG_FINISH_EPA_ADDR 0x01FF +#define MC_RESET_DONE_EPA_ADDR 0x0200 +#define MC_TX_VACANT_EPA_ADDR 0x0300 +#define MC_FINISH_EPA_ADDR 0xEAD0 +#define MC_TIME_EPA_ADDR 0xEAD4 +#define MC_FAIL_EPA_ADDR 0xEAD8 +#define MC_STDOUT_EPA_ADDR 0xEADC +#define MC_STDERR_EPA_ADDR 0xEAE0 +#define MC_BRANCH_TRACE_EPA_ADDR 0xEAE4 +#define MC_PRINT_STAT_EPA_ADDR 0xEA0C + +#define MC_HOST_OP_FINISH_CODE 0xFFFFFFFF +#define DROMAJO_RW_FAIL_CODE 0xFFFFFFFF // Memory mapped addresses to interact with the manycore bridge +// BlackParrot actually sets the MSB of its address to 1 to commnicate with the manycore +// Dromajo however is setup to identify the manycore as a device #define MC_BASE_ADDR 0x500000 #define BP_TO_MC_REQ_FIFO_ADDR 0x1000 #define BP_TO_MC_REQ_CREDITS_ADDR 0x2000 @@ -29,23 +43,68 @@ extern "C" { #define MC_TO_BP_REQ_FIFO_ADDR 0x5000 #define MC_TO_BP_REQ_ENTRIES_ADDR 0x6000 +#define BP_CFG_BASE_ADDR 0x00200000 + +// Manycore Bridge helper functions +/* + * Reads the manycore bridge for number of credits used in the endpoint + * @returns number of credits in the manycore bridge enddpoint + */ +int bp_hb_get_credits_used(int *credits_used); + +/* + * Writes a 128-bit manycore packet in 32-bit chunks to the manycore bridge FIFO + * @param[in] pkt --> Pointer to the manycore packet + */ +int bp_hb_write_to_mc_bridge(hb_mc_packet_t *pkt); + +/* + * Checks if the MC to BP FIFO contains any entries + * @param[in] type --> Type of FIFO to read from + * @returns number of entries in the MC to BP FIFO + */ +int bp_hb_get_fifo_entries(int *entries, hb_mc_fifo_rx_t type); + +/* + * Reads the manycore bridge FIFOs in 32-bit chunks to form the 128-bit packet + * @param[in] pkt --> Pointer to the manycore packet + * @param[in] type --> Type of FIFO to read from + * @returns HB_MC_SUCCESS on success, HB_MC_FAIL if FIFO type is unknown + */ +int bp_hb_read_from_mc_bridge(hb_mc_packet_t *pkt, hb_mc_fifo_rx_t type); + +// BlackParrot helper functions +/* + * Get hardware thread ID + * @returns result of reading the mhartid register + */ uint64_t bp_get_hart(); + +/* + * Checks to see if a barrier is finished + * @param[in] barrier_address --> An address in memory that all cores to write to after hitting the barrier + * @param[in] total_num_cores --> Number of cores + */ void bp_barrier_end(volatile uint64_t *barrier_address, uint64_t total_num_cores); +/* + * Sends a hex digit to the host to print + * @param[in] hex --> Hex digit to print + */ void bp_hprint(uint8_t hex); +/* + * Sends a character to the host to print + * @param[in] ch --> Character to print + */ void bp_cprint(uint8_t ch); -void bp_finish(uint8_t code); - -#define BP_CFG_BASE_ADDR ((char *)(0x00200000)) - -int bp_hb_get_credits(); - -void bp_hb_write_to_manycore_bridge(hb_mc_packet_t *pkt); - -int bp_hb_read_from_manycore_bridge(hb_mc_packet_t *pkt, hb_mc_fifo_rx_t type); +/* + * Sends a finish packet to the host + * @param[in] code --> Finish code + */ +void bp_finish(int16_t code); #ifdef __cplusplus } diff --git a/libraries/platforms/dromajo-vcs/software/src/args.c b/libraries/platforms/dromajo-vcs/software/src/args.c index d7d10f8d7..f1821bfc6 100644 --- a/libraries/platforms/dromajo-vcs/software/src/args.c +++ b/libraries/platforms/dromajo-vcs/software/src/args.c @@ -10,67 +10,66 @@ #include #include -// For now keep a limit on the number of arguments and the length of the argument -// string. -// TODO: Make this a pointer to a location on the stack +// Number of arguments that can be retrieved is currently based on the size of the buffer. +// Other ideas (TODO): +// 1. Create pointers to locations of arguments on the stack (traditional, preferred method) +// 2. Flush the argument buffer periodically int _argc; char **_argv; static int arg_index = 0; -static int char_index = -1; +static int char_index = 0; +/** + * Retrieve arguments from the manycore host + */ void __init_args(void) { - hb_mc_packet_t req_pkt, resp_pkt; + int err; + hb_mc_packet_t args_req_pkt, args_resp_pkt; // Flat buffer to capture all the arguments contiguously char buffer[3000]; char *bufptr = buffer; // Create a packet for the x86 host - // Host is at (0, 0) - // BlackParrot FIFOs are at (0, 1) - req_pkt.request.x_dst = 0; - req_pkt.request.y_dst = 0; - req_pkt.request.x_src = 0; - req_pkt.request.y_src = 1; - req_pkt.request.op_v2 = HB_MC_PACKET_OP_REMOTE_LOAD; - req_pkt.request.payload = 0; - req_pkt.request.reg_id = 0; + // Host is at POD (X, Y) = (0, 1), SUBCOORD (X, Y) = (0, 0) + // BlackParrot FIFO interface is at POD (X, Y) = (0, 1), SUBCOORD (X, Y) = (0, 1) + args_req_pkt.request.x_dst = (0 << 4) | 0; + args_req_pkt.request.y_dst = (1 << 3) | 0; + args_req_pkt.request.x_src = (0 << 4) | 0; + args_req_pkt.request.y_src = (1 << 3) | 1; + args_req_pkt.request.op_v2 = HB_MC_PACKET_OP_REMOTE_LOAD; + args_req_pkt.request.payload = 0; + args_req_pkt.request.reg_id = 0; while(1) { - // Word address 0x00 to 0xFF tell the host to retrieve arguments - req_pkt.request.addr = arg_index; - - // Send packet - bp_hb_write_to_manycore_bridge(&req_pkt); - - // Wait for response - int err = bp_hb_read_from_manycore_bridge(&resp_pkt, HB_MC_FIFO_RX_RSP); - if (err != 0) { - bp_finish(1); - } + // The platform setup in simulation ensures that this packet will not go over the network so + // we don't need to check for credits. Also, this code is executed before the CUDA-lite + // program starts. + args_req_pkt.request.addr = MC_ARGS_START_EPA_ADDR + arg_index; + err = bp_hb_write_to_mc_bridge(&args_req_pkt); + err = bp_hb_read_from_mc_bridge(&args_resp_pkt, HB_MC_FIFO_RX_RSP); + if (err != HB_MC_SUCCESS) + bp_finish(err); - uint32_t data = resp_pkt.response.data; - if (data == 0xFFFFFFFF) { - break; - } - else { + uint32_t data = args_resp_pkt.response.data; + if (data != MC_HOST_OP_FINISH_CODE) { uint32_t mask = 0xFF000000; uint8_t byte; for(int i = 0; i < 4; i++) { byte = data & mask; - if (byte != 0x0) { + if (byte != (uint8_t)'\0') buffer[char_index] = byte; - char_index++; - } else { buffer[char_index] = '\0'; arg_index++; - char_index++; break; } + char_index++; mask = mask >> 8; } } + else + break; } _argc = arg_index; diff --git a/libraries/platforms/dromajo-vcs/software/src/bp_utils.c b/libraries/platforms/dromajo-vcs/software/src/bp_utils.c index f8749b384..63859794b 100644 --- a/libraries/platforms/dromajo-vcs/software/src/bp_utils.c +++ b/libraries/platforms/dromajo-vcs/software/src/bp_utils.c @@ -1,18 +1,143 @@ // BlackParrot utilities -// Note: This file is compiled instead of the existing code in the perch -// library in order to allow for easy changes to the finish code in the future +// Compile this file instead of the existing one in the BlackParrot firmware #include #include #include #include +/* + * Reads the manycore bridge for number of credits used in the endpoint + * @param[in] credits_used --> Pointer to a location in memory that will hold the number of credits used + * @returns HB_MC_SUCCESS + */ +int bp_hb_get_credits_used(int *credits_used) { + uint32_t *bp_to_mc_req_credits_addr = (uint32_t *) (MC_BASE_ADDR + BP_TO_MC_REQ_CREDITS_ADDR); + if ((*credits_used = (int) *bp_to_mc_req_credits_addr) < 0) { + bsg_pr_err("Credits used cannot be negative. Credits = %d", *credits_used); + return HB_MC_FAIL; + } + return HB_MC_SUCCESS; +} + +/* + * Writes a 128-bit manycore packet in 32-bit chunks to the manycore bridge FIFO + * @param[in] pkt --> Pointer to the manycore packet + * @returns HB_MC_SUCCESS + * TODO: Implement error checking (Requires some modifications in Dromajo) + */ +int bp_hb_write_to_mc_bridge(hb_mc_packet_t *pkt) { + uint32_t *bp_to_mc_req_fifo_addr = (uint32_t *) (MC_BASE_ADDR + BP_TO_MC_REQ_FIFO_ADDR); + for(int i = 0; i < 4; i++) { + *bp_to_mc_req_fifo_addr = pkt->words[i]; + bp_to_mc_req_fifo_addr++; + } + return HB_MC_SUCCESS; +} + +/* + * Checks if the MC to BP FIFO contains any valid elements to be read + * @param[in] entries --> Pointer to a location in memory that will hold the number of entries + * @param[in] type --> Type of FIFO to read from + * @returns HB_MC_SUCCESS on success or HB_MC_FAIL on fail + */ +int bp_hb_get_fifo_entries(int *entries, hb_mc_fifo_rx_t type) { + switch (type) { + case HB_MC_FIFO_RX_REQ: + { + uint32_t *mc_to_bp_req_fifo_entries_addr = (uint32_t *) (MC_BASE_ADDR + MC_TO_BP_REQ_ENTRIES_ADDR); + if ((*entries = *mc_to_bp_req_fifo_entries_addr) < 0) { + bsg_pr_err("Entries occupied cannot be negative. Entries = %d", *entries); + return HB_MC_FAIL; + } + } + break; + case HB_MC_FIFO_RX_RSP: + { + uint32_t *mc_to_bp_resp_fifo_entries_addr = (uint32_t *) (MC_BASE_ADDR + MC_TO_BP_RESP_ENTRIES_ADDR); + if ((*entries = *mc_to_bp_resp_fifo_entries_addr) < 0) { + bsg_pr_err("Entries occupied cannot be negative. Entries = %d", *entries); + return HB_MC_FAIL; + } + } + break; + default: + { + bsg_pr_err("%s: Unknown packet type\n", __func__); + return HB_MC_FAIL; + } + break; + } + return HB_MC_SUCCESS; +} + +/* + * Reads the manycore bridge FIFOs in 32-bit chunks to form the 128-bit packet + * @param[in] pkt --> Pointer to the manycore packet + * @param[in] type --> Type of FIFO to read from + * @returns HB_MC_SUCCESS on success, HB_MC_FAIL if FIFO type is unknown + */ +int bp_hb_read_from_mc_bridge(hb_mc_packet_t *pkt, hb_mc_fifo_rx_t type) { + switch(type) { + case HB_MC_FIFO_RX_REQ: + { + uint32_t *mc_to_bp_req_fifo_addr = (uint32_t *) (MC_BASE_ADDR + MC_TO_BP_REQ_FIFO_ADDR); + uint32_t fifo_read_status = DROMAJO_RW_FAIL_CODE; + do { + for (int i = 0; i < 4; i++) { + pkt->words[i] = *mc_to_bp_req_fifo_addr; + fifo_read_status &= pkt->words[i]; + mc_to_bp_req_fifo_addr++; + } + } while (fifo_read_status == DROMAJO_RW_FAIL_CODE); + + // There is something wrong if the read status is equal to the FAIL code + if (fifo_read_status == DROMAJO_RW_FAIL_CODE) + return HB_MC_FAIL; + } + break; + case HB_MC_FIFO_RX_RSP: + { + uint32_t *mc_to_bp_resp_fifo_addr = (uint32_t *) (MC_BASE_ADDR + MC_TO_BP_RESP_FIFO_ADDR); + uint32_t fifo_read_status = DROMAJO_RW_FAIL_CODE; + do { + for (int i = 0; i < 4; i++) { + pkt->words[i] = *mc_to_bp_resp_fifo_addr; + fifo_read_status &= pkt->words[i]; + mc_to_bp_resp_fifo_addr++; + } + } while(fifo_read_status == DROMAJO_RW_FAIL_CODE); + + // There is something wrong if the read status is equal to the FAIL code + if (fifo_read_status == DROMAJO_RW_FAIL_CODE) + return HB_MC_FAIL; + } + break; + default: + { + bsg_pr_err("%s: Unknown packet type\n", __func__); + return HB_MC_FAIL; + } + break; + } + return HB_MC_SUCCESS; +} + +/* + * Get hardware thread ID + * @returns result of reading the mhartid register + */ uint64_t bp_get_hart() { uint64_t core_id; __asm__ volatile("csrr %0, mhartid": "=r"(core_id): :); return core_id; } +/* + * Checks to see if a barrier is finished + * @param[in] barrier_address --> An address in memory that all cores to write to after hitting the barrier + * @param[in] total_num_cores --> Number of cores + */ void bp_barrier_end(volatile uint64_t * barrier_address, uint64_t total_num_cores) { uint64_t core_id; uint64_t atomic_inc = 1; @@ -43,110 +168,73 @@ void bp_barrier_end(volatile uint64_t * barrier_address, uint64_t total_num_core } } -void bp_finish(uint8_t code) { +/* + * Sends a finish packet to the host + * @param[in] code --> Finish code + */ +void bp_finish(int16_t code) { uint64_t core_id; + // Fixme: Core IDs for all BP cores might be zero. How do we handle this? __asm__ volatile("csrr %0, mhartid": "=r"(core_id): :); - *(FINISH_BASE_ADDR+core_id*8) = code; -} - -void bp_hprint(uint8_t hex) { - - *(PUTCHAR_BASE_ADDR) = ('0' + hex); -} - -void bp_cprint(uint8_t ch) { - - *(PUTCHAR_BASE_ADDR) = ch; + // Finish packet contains core id at the top 16 bits and + // finish code at the bottom 16 bits + // zero --> success code + // nonzero --> fail code + hb_mc_packet_t finish_pkt; + finish_pkt.request.x_dst = (0 << 4) | 0; + finish_pkt.request.y_dst = (1 << 3) | 0; + finish_pkt.request.x_src = (0 << 4) | 0; + finish_pkt.request.y_src = (1 << 3) | 1; + finish_pkt.request.op_v2 = HB_MC_PACKET_OP_REMOTE_SW; + finish_pkt.request.payload = (core_id << 16) | (0x0000FFFF & code); + finish_pkt.request.reg_id = 0; + if (code >= 0) + finish_pkt.request.addr = MC_FINISH_EPA_ADDR; + else + finish_pkt.request.addr = MC_FAIL_EPA_ADDR; + + int err; + do { + err = bp_hb_write_to_mc_bridge(&finish_pkt); + } while (err != HB_MC_SUCCESS); } /* - * Reads the manycore bridge for number of credits remaining in the endpoint - * @returns number of credits in the manycore bridge enddpoint + * Sends a hex digit to the host to print + * @param[in] hex --> Hex digit to print */ -int bp_hb_get_credits() { - uint32_t *bp_to_mc_req_credits_addr = (uint32_t *) (MC_BASE_ADDR + BP_TO_MC_REQ_CREDITS_ADDR); - int credits = (int) *bp_to_mc_req_credits_addr; - return credits; -} - -/* - * Writes a 128-bit manycore packet in 32-bit chunks to the manycore bridge FIFO - * @param[in] pkt --> Pointer to the manycore packet - */ -void bp_hb_write_to_manycore_bridge(hb_mc_packet_t *pkt) { - int credits; - - // Wait till there is atleast 1 credit to send the write - do { - credits = bp_hb_get_credits(); - } while (credits == 0); +void bp_hprint(uint8_t hex) { - uint32_t *bp_to_mc_req_fifo_addr = (uint32_t *) (MC_BASE_ADDR + BP_TO_MC_REQ_FIFO_ADDR); - for(int i = 0; i < 4; i++) { - *bp_to_mc_req_fifo_addr = pkt->words[i]; - bp_to_mc_req_fifo_addr++; - } + hb_mc_packet_t hprint_pkt; + hprint_pkt.request.x_dst = (0 << 4) | 0; + hprint_pkt.request.y_dst = (1 << 3) | 0; + hprint_pkt.request.x_src = (0 << 4) | 0; + hprint_pkt.request.y_src = (1 << 3) | 1; + hprint_pkt.request.op_v2 = HB_MC_PACKET_OP_REMOTE_SW; + hprint_pkt.request.payload = ('0' + hex); + hprint_pkt.request.reg_id = 0; + hprint_pkt.request.addr = MC_STDOUT_EPA_ADDR; + + int err = bp_hb_write_to_mc_bridge(&hprint_pkt); } /* - * Reads the manycore bridge FIFOs in 32-bit chunks to form the 128-bit packet - * @param[in] pkt --> Pointer to the manycore packet - * @param[in] type --> Type of FIFO to read from - * @returns HB_MC_SUCCESS on success, HB_MC_FAIL if FIFO type is unknown + * Sends a character to the host to print + * @param[in] ch --> Character to print */ -int bp_hb_read_from_manycore_bridge(hb_mc_packet_t *pkt, hb_mc_fifo_rx_t type) { - switch(type) { - case HB_MC_FIFO_RX_REQ: - { - // Check if the entries are full - uint32_t *mc_to_bp_req_entries_addr = (uint32_t *) (MC_BASE_ADDR + MC_TO_BP_REQ_ENTRIES_ADDR); - while(!(*mc_to_bp_req_entries_addr)) - ; - - // Read the value - uint32_t *mc_to_bp_req_fifo_addr = (uint32_t *) (MC_BASE_ADDR + MC_TO_BP_REQ_FIFO_ADDR); - uint32_t read_status = 0xFFFFFFFF; - for (int i = 0; i < 4; i++) { - pkt->words[i] = *mc_to_bp_req_fifo_addr; - read_status &= pkt->words[i]; - mc_to_bp_req_fifo_addr++; - } - - // If all packets are 0xFFFFFFFF --> there is something wrong - if (read_status == 0xFFFFFFFF) - return HB_MC_FAIL; - } - break; - case HB_MC_FIFO_RX_RSP: - { - // Check if the entries are full - uint32_t *mc_to_bp_resp_entries_addr = (uint32_t *) (MC_BASE_ADDR + MC_TO_BP_RESP_ENTRIES_ADDR); - while(!(*mc_to_bp_resp_entries_addr)) - ; - - // Read the value - uint32_t *mc_to_bp_resp_fifo_addr = (uint32_t *) (MC_BASE_ADDR + MC_TO_BP_RESP_FIFO_ADDR); - uint32_t read_status = 0xFFFFFFFF; - for (int i = 0; i < 4; i++) { - pkt->words[i] = *mc_to_bp_resp_fifo_addr; - read_status &= pkt->words[i]; - mc_to_bp_resp_fifo_addr++; - } - - // If all packets are 0xFFFFFFFF --> there is something wrong - if (read_status == 0xFFFFFFFF) - return HB_MC_FAIL; - } - break; - default: - { - bsg_pr_err("%s: Unknown packet type\n", __func__); - return HB_MC_FAIL; - } - break; - } - return HB_MC_SUCCESS; -} +void bp_cprint(uint8_t ch) { + hb_mc_packet_t cprint_pkt; + cprint_pkt.request.x_dst = (0 << 4) | 0; + cprint_pkt.request.y_dst = (1 << 3) | 0; + cprint_pkt.request.x_src = (0 << 4) | 0; + cprint_pkt.request.y_src = (1 << 3) | 1; + cprint_pkt.request.op_v2 = HB_MC_PACKET_OP_REMOTE_SW; + cprint_pkt.request.payload = ch; + cprint_pkt.request.reg_id = 0; + cprint_pkt.request.addr = MC_STDOUT_EPA_ADDR; + + int err = bp_hb_write_to_mc_bridge(&cprint_pkt); +} \ No newline at end of file From 6669a15f36415cd6cc7dc1f26fbe684ac24f1d9a Mon Sep 17 00:00:00 2001 From: sripathi-muralitharan Date: Wed, 23 Jun 2021 14:28:39 -0700 Subject: [PATCH 34/70] Various Updates * Target for generating the disassembly of the final elf file * Updates for BlackParrot repo reorg --- .../dromajo-vcs/bsg_manycore_simulator.cpp | 2 +- .../platforms/dromajo-vcs/compilation.mk | 10 ++++++- libraries/platforms/dromajo-vcs/library.mk | 28 ++++++++++--------- libraries/platforms/dromajo-vcs/link.mk | 4 +-- .../dromajo-vcs/software/include/bp_utils.h | 2 +- .../platforms/dromajo-vcs/software/src/crt0.S | 2 +- 6 files changed, 29 insertions(+), 19 deletions(-) diff --git a/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.cpp b/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.cpp index ef1f9ac1e..7a19d7001 100644 --- a/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.cpp +++ b/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.cpp @@ -179,7 +179,7 @@ int SimulationWrapper::dromajo_init() { sprintf(dromajo_str, "dromajo"); sprintf(host_str, "--host"); sprintf(manycore_str, "--manycore"); - sprintf(prog_str, "test.elf"); + sprintf(prog_str, "main.elf"); char* argv[] = {dromajo_str, host_str, manycore_str, prog_str}; dromajo = dromajo_cosim_init(4, argv); diff --git a/libraries/platforms/dromajo-vcs/compilation.mk b/libraries/platforms/dromajo-vcs/compilation.mk index 710e432ff..f00b5ddc4 100644 --- a/libraries/platforms/dromajo-vcs/compilation.mk +++ b/libraries/platforms/dromajo-vcs/compilation.mk @@ -39,12 +39,16 @@ DEFINES += -D_DRAMFS INCLUDES += -I$(LIBRARIES_PATH) INCLUDES += -I$(BSG_PLATFORM_PATH) INCLUDES += -I$(BSG_PLATFORM_PATH)/software/include -INCLUDES += -I$(BLACKPARROT_DIR)/sdk/perch +INCLUDES += -I$(BLACKPARROT_SDK_DIR)/perch CXXFLAGS += $(DEFINES) -march=rv64imafd -mabi=lp64 -mcmodel=medany CFLAGS += $(DEFINES) -march=rv64imafd -mabi=lp64 -mcmodel=medany SFLAGS += $(DEFINES) -march=rv64imafd -mabi=lp64 -mcmodel=medany +CC ?= $(BLACKPARROT_SDK_DIR)/install/bin/riscv64-unknown-elf-dramfs-gcc +CXX ?= $(BLACKPARROT_SDK_DIR)/install/bin/riscv64-unknown-elf-dramfs-g++ +OBJDUMP ?= $(BLACKPARROT_SDK_DIR)/install/bin/riscv64-unknown-elf-dramfs-objdump + # each regression target needs to build its .o from a .c and .h of the # same name %.o: %.c @@ -57,10 +61,14 @@ SFLAGS += $(DEFINES) -march=rv64imafd -mabi=lp64 -mcmodel=medany %.o: %.S $(CC) -c -o $@ $< $(INCLUDES) $(SFLAGS) +%.dis: %.elf + $(OBJDUMP) -d $^ > $@ + .PRECIOUS: %.o .PHONY: platform.compilation.clean platform.compilation.clean: rm -rf *.o + rm -rf *.dis compilation.clean: platform.compilation.clean diff --git a/libraries/platforms/dromajo-vcs/library.mk b/libraries/platforms/dromajo-vcs/library.mk index 67a50fffc..8f42badcc 100644 --- a/libraries/platforms/dromajo-vcs/library.mk +++ b/libraries/platforms/dromajo-vcs/library.mk @@ -26,11 +26,12 @@ # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # RISC-V tools -RV_CC = $(BLACKPARROT_DIR)/sdk/install/bin/riscv64-unknown-elf-dramfs-gcc -RV_CXX = $(BLACKPARROT_DIR)/sdk/install/bin/riscv64-unknown-elf-dramfs-g++ -RV_AR = $(BLACKPARROT_DIR)/sdk/install/bin/riscv64-unknown-elf-dramfs-ar +RV_CC = $(BLACKPARROT_SDK_DIR)/install/bin/riscv64-unknown-elf-dramfs-gcc +RV_CXX = $(BLACKPARROT_SDK_DIR)/install/bin/riscv64-unknown-elf-dramfs-g++ +RV_AR = $(BLACKPARROT_SDK_DIR)/install/bin/riscv64-unknown-elf-dramfs-ar +RV_OBJDUMP = $(BLACKPARROT_SDK_DIR)/install/bin/riscv64-unknown-elf-dramfs-objdump -DROMAJO_DIR = $(BLACKPARROT_DIR)/sdk/dromajo +DROMAJO_DIR = $(BLACKPARROT_SDK_DIR)/dromajo LIB_CXXSOURCES += $(LIBRARIES_PATH)/features/tracer/noimpl/bsg_manycore_tracer.cpp LIB_CXXSOURCES += $(LIBRARIES_PATH)/features/profiler/noimpl/bsg_manycore_profiler.cpp @@ -49,12 +50,12 @@ LIB_CSOURCES += $(BSG_PLATFORM_PATH)/software/src/argp/argp-pvh.c LIB_CSOURCES += $(BSG_PLATFORM_PATH)/software/src/argp/argp-xinl.c LIB_CSOURCES += $(BSG_PLATFORM_PATH)/software/src/bp_utils.c LIB_CSOURCES += $(BSG_PLATFORM_PATH)/software/src/args.c -LIB_CSOURCES += $(BLACKPARROT_DIR)/sdk/perch/bsg_newlib_intf.c -LIB_CSOURCES += $(BLACKPARROT_DIR)/sdk/perch/emulation.c +LIB_CSOURCES += $(BLACKPARROT_SDK_DIR)/perch/bsg_newlib_intf.c +LIB_CSOURCES += $(BLACKPARROT_SDK_DIR)/perch/emulation.c -LIB_SSOURCES += $(BLACKPARROT_DIR)/sdk/perch/atomics.S -LIB_SSOURCES += $(BLACKPARROT_DIR)/sdk/perch/exception.S -LIB_SSOURCES += $(BLACKPARROT_DIR)/sdk/perch/muldiv.S +LIB_SSOURCES += $(BLACKPARROT_SDK_DIR)/perch/atomics.S +LIB_SSOURCES += $(BLACKPARROT_SDK_DIR)/perch/exception.S +LIB_SSOURCES += $(BLACKPARROT_SDK_DIR)/perch/muldiv.S LIB_SSOURCES += $(BSG_PLATFORM_PATH)/software/src/crt0.S # For now, use the noimpl version of the features @@ -66,7 +67,7 @@ $(DMA_FEATURE_OBJECTS): CXXFLAGS += -march=rv64imafd -mcmodel=medany -mabi=lp64 # Add the riscv-newlib specific includes for the library LIB_PLATFORM_INCLUDES = -I$(BSG_PLATFORM_PATH)/software/include -LIB_PLATFORM_INCLUDES += -I$(BLACKPARROT_DIR)/sdk/perch +LIB_PLATFORM_INCLUDES += -I$(BLACKPARROT_SDK_DIR)/perch $(LIB_OBJECTS) $(LIB_OBJECTS_CUDA_POD_REPL) $(LIB_OBJECTS_REGRESSION): CC = $(RV_CC) $(LIB_OBJECTS) $(LIB_OBJECTS_CUDA_POD_REPL) $(LIB_OBJECTS_REGRESSION): CXX = $(RV_CXX) @@ -76,9 +77,10 @@ $(BSG_PLATFORM_PATH)/libbsgmc_cuda_legacy_pod_repl.a: AR = $(RV_AR) $(BSG_PLATFORM_PATH)/libbsg_manycore_regression.a: AR = $(RV_AR) # Make the litteFS file system +$(BSG_PLATFORM_PATH)/lfs.o: MKLFS = $(BLACKPARROT_SDK_DIR)/install/bin/dramfs_mklfs 128 64 $(BSG_PLATFORM_PATH)/lfs.o: - $(MAKE) -C $(BLACKPARROT_DIR)/sdk/bp-tests lfs.cpp - $(CXX) $(BLACKPARROT_DIR)/sdk/bp-tests/lfs.cpp -c -o $@ $(CXXFLAGS) $(INCLUDES) + $(MKLFS) > $(BSG_PLATFORM_PATH)/lfs.cpp + $(CXX) $(BSG_PLATFORM_PATH)/lfs.cpp -c -o $@ $(CXXFLAGS) $(INCLUDES) include $(LIBRARIES_PATH)/features/dma/simulation/dramsim3.mk include $(LIBRARIES_PATH)/features/dma/simulation/libdmamem.mk @@ -123,7 +125,7 @@ $(PLATFORM_OBJECTS): INCLUDES += -I$(BSG_PLATFORM_PATH) $(PLATFORM_OBJECTS): INCLUDES += -I$(VCS_HOME)/linux64/lib/ $(PLATFORM_OBJECTS): INCLUDES += -I$(BSG_MANYCORE_DIR)/testbenches/dpi/ $(PLATFORM_OBJECTS): INCLUDES += -I$(BASEJUMP_STL_DIR)/bsg_test/ -$(PLATFORM_OBJECTS): INCLUDES += -I$(BLACKPARROT_DIR)/sdk/dromajo/include +$(PLATFORM_OBJECTS): INCLUDES += -I$(BLACKPARROT_SDK_DIR)/dromajo/include $(PLATFORM_OBJECTS): CFLAGS := -std=c11 -fPIC -DVCS -D_GNU_SOURCE -DVERILATOR -D_BSD_SOURCE -D_XOPEN_SOURCE=500 $(PLATFORM_OBJECTS): CXXFLAGS := -std=c++11 -fPIC -DVCS -D_GNU_SOURCE -DVERILATOR -D_BSD_SOURCE -D_XOPEN_SOURCE=500 $(PLATFORM_OBJECTS): LDFLAGS := -fPIC diff --git a/libraries/platforms/dromajo-vcs/link.mk b/libraries/platforms/dromajo-vcs/link.mk index 5d44f97f6..3cf2f6136 100644 --- a/libraries/platforms/dromajo-vcs/link.mk +++ b/libraries/platforms/dromajo-vcs/link.mk @@ -116,11 +116,11 @@ $(BSG_PLATFORM_PATH)/test.riscv: $(BSG_PLATFORM_PATH)/lfs.o $(BSG_PLATFORM_PATH)/test.riscv: $(BSG_PLATFORM_PATH)/libbsg_manycore_runtime.a $(BSG_PLATFORM_PATH)/test.riscv: $(BSG_PLATFORM_PATH)/libbsgmc_cuda_legacy_pod_repl.a $(BSG_PLATFORM_PATH)/test.riscv: $(BSG_PLATFORM_PATH)/libbsg_manycore_regression.a -$(BSG_PLATFORM_PATH)/test.riscv: LDFLAGS := -T$(BLACKPARROT_DIR)/sdk/linker/riscv.ld -L$(BSG_PLATFORM_PATH) -static -nostartfiles -lstdc++ -lbsg_manycore_runtime -lbsg_manycore_regression +$(BSG_PLATFORM_PATH)/test.riscv: LDFLAGS := -T$(BLACKPARROT_SDK_DIR)/linker/riscv.ld -L$(BSG_PLATFORM_PATH) -static -nostartfiles -lstdc++ -lbsg_manycore_runtime -lbsg_manycore_regression $(BSG_PLATFORM_PATH)/test.riscv: LD = $(CXX) $(BSG_PLATFORM_PATH)/test.riscv: $(LD) -D_DRAMFS -o $@ $(BSG_PLATFORM_PATH)/software/src/crt0.o $(BSG_PLATFORM_PATH)/lfs.o $< $(LDFLAGS) - cp $@ $(subst riscv,elf,$(notdir $@)) + cp $@ main.elf # VCS Generates an executable file by linking the TEST_OBJECTS with # the the VCS work libraries for the design, and the runtime shared diff --git a/libraries/platforms/dromajo-vcs/software/include/bp_utils.h b/libraries/platforms/dromajo-vcs/software/include/bp_utils.h index 509f6fa85..1e79ae0e0 100644 --- a/libraries/platforms/dromajo-vcs/software/include/bp_utils.h +++ b/libraries/platforms/dromajo-vcs/software/include/bp_utils.h @@ -11,7 +11,7 @@ extern "C" { #endif #include -#include "bsg_newlib_intf.h" +#include #include // Memory mapped addresses to interact with the host diff --git a/libraries/platforms/dromajo-vcs/software/src/crt0.S b/libraries/platforms/dromajo-vcs/software/src/crt0.S index 1273e7edb..1977bf18e 100644 --- a/libraries/platforms/dromajo-vcs/software/src/crt0.S +++ b/libraries/platforms/dromajo-vcs/software/src/crt0.S @@ -29,7 +29,7 @@ _start: sub sp, sp, t0 # Setup mtvec - la t0, bp_mtvec_handler + la t0, __mtvec_handler csrw mtvec, t0 # Enable FPU From 25f0cf3e454a888b883e4a8e164b5220b55380c2 Mon Sep 17 00:00:00 2001 From: sripathi-muralitharan Date: Wed, 23 Jun 2021 14:30:23 -0700 Subject: [PATCH 35/70] * Always inline argp_fmtstream functions (most of them atleast) * Add a .gitignore for the platform --- libraries/platforms/dromajo-vcs/.gitignore | 1 + .../software/include/argp-fmtstream.h | 66 +++---------------- 2 files changed, 10 insertions(+), 57 deletions(-) create mode 100644 libraries/platforms/dromajo-vcs/.gitignore diff --git a/libraries/platforms/dromajo-vcs/.gitignore b/libraries/platforms/dromajo-vcs/.gitignore new file mode 100644 index 000000000..46ac11709 --- /dev/null +++ b/libraries/platforms/dromajo-vcs/.gitignore @@ -0,0 +1 @@ +lfs.cpp diff --git a/libraries/platforms/dromajo-vcs/software/include/argp-fmtstream.h b/libraries/platforms/dromajo-vcs/software/include/argp-fmtstream.h index 7a291e28c..e95bd7fc6 100644 --- a/libraries/platforms/dromajo-vcs/software/include/argp-fmtstream.h +++ b/libraries/platforms/dromajo-vcs/software/include/argp-fmtstream.h @@ -130,17 +130,6 @@ extern ssize_t __argp_fmtstream_printf (argp_fmtstream_t __fs, extern ssize_t argp_fmtstream_printf (argp_fmtstream_t __fs, __const char *__fmt, ...) __attribute__ ((__format__ (printf, 2, 3))); - -extern int __argp_fmtstream_putc (argp_fmtstream_t __fs, int __ch); -extern int argp_fmtstream_putc (argp_fmtstream_t __fs, int __ch); - -extern int __argp_fmtstream_puts (argp_fmtstream_t __fs, __const char *__str); -extern int argp_fmtstream_puts (argp_fmtstream_t __fs, __const char *__str); - -extern size_t __argp_fmtstream_write (argp_fmtstream_t __fs, - __const char *__str, size_t __len); -extern size_t argp_fmtstream_write (argp_fmtstream_t __fs, - __const char *__str, size_t __len); /* Access macros for various bits of state. */ #define argp_fmtstream_lmargin(__fs) ((__fs)->lmargin) @@ -150,35 +139,12 @@ extern size_t argp_fmtstream_write (argp_fmtstream_t __fs, #define __argp_fmtstream_rmargin argp_fmtstream_rmargin #define __argp_fmtstream_wmargin argp_fmtstream_wmargin -/* Set __FS's left margin to LMARGIN and return the old value. */ -extern size_t argp_fmtstream_set_lmargin (argp_fmtstream_t __fs, - size_t __lmargin); -extern size_t __argp_fmtstream_set_lmargin (argp_fmtstream_t __fs, - size_t __lmargin); - -/* Set __FS's right margin to __RMARGIN and return the old value. */ -extern size_t argp_fmtstream_set_rmargin (argp_fmtstream_t __fs, - size_t __rmargin); -extern size_t __argp_fmtstream_set_rmargin (argp_fmtstream_t __fs, - size_t __rmargin); - -/* Set __FS's wrap margin to __WMARGIN and return the old value. */ -extern size_t argp_fmtstream_set_wmargin (argp_fmtstream_t __fs, - size_t __wmargin); -extern size_t __argp_fmtstream_set_wmargin (argp_fmtstream_t __fs, - size_t __wmargin); - -/* Return the column number of the current output point in __FS. */ -extern size_t argp_fmtstream_point (argp_fmtstream_t __fs); -extern size_t __argp_fmtstream_point (argp_fmtstream_t __fs); - /* Internal routines. */ extern void _argp_fmtstream_update (argp_fmtstream_t __fs); extern void __argp_fmtstream_update (argp_fmtstream_t __fs); extern int _argp_fmtstream_ensure (argp_fmtstream_t __fs, size_t __amount); extern int __argp_fmtstream_ensure (argp_fmtstream_t __fs, size_t __amount); -#ifdef __OPTIMIZE__ /* Inline versions of above routines. */ #if !_LIBC @@ -193,13 +159,7 @@ extern int __argp_fmtstream_ensure (argp_fmtstream_t __fs, size_t __amount); #define __argp_fmtstream_ensure _argp_fmtstream_ensure #endif -#ifndef ARGP_FS_EI -#define ARGP_FS_EI extern inline -#endif - -ARGP_FS_EI size_t -__argp_fmtstream_write (argp_fmtstream_t __fs, - __const char *__str, size_t __len) +static inline size_t __argp_fmtstream_write (argp_fmtstream_t __fs, __const char *__str, size_t __len) { if (__fs->p + __len <= __fs->end || __argp_fmtstream_ensure (__fs, __len)) { @@ -211,8 +171,7 @@ __argp_fmtstream_write (argp_fmtstream_t __fs, return 0; } -ARGP_FS_EI int -__argp_fmtstream_puts (argp_fmtstream_t __fs, __const char *__str) +static inline int __argp_fmtstream_puts (argp_fmtstream_t __fs, __const char *__str) { size_t __len = strlen (__str); if (__len) @@ -224,8 +183,7 @@ __argp_fmtstream_puts (argp_fmtstream_t __fs, __const char *__str) return 0; } -ARGP_FS_EI int -__argp_fmtstream_putc (argp_fmtstream_t __fs, int __ch) +static inline int __argp_fmtstream_putc (argp_fmtstream_t __fs, int __ch) { if (__fs->p < __fs->end || __argp_fmtstream_ensure (__fs, 1)) return *__fs->p++ = __ch; @@ -233,9 +191,8 @@ __argp_fmtstream_putc (argp_fmtstream_t __fs, int __ch) return EOF; } -/* Set __FS's left margin to __LMARGIN and return the old value. */ -ARGP_FS_EI size_t -__argp_fmtstream_set_lmargin (argp_fmtstream_t __fs, size_t __lmargin) +/* Set __FS's left margin to LMARGIN and return the old value. */ +static inline size_t __argp_fmtstream_set_lmargin (argp_fmtstream_t __fs, size_t __lmargin) { size_t __old; if ((size_t) (__fs->p - __fs->buf) > __fs->point_offs) @@ -246,8 +203,7 @@ __argp_fmtstream_set_lmargin (argp_fmtstream_t __fs, size_t __lmargin) } /* Set __FS's right margin to __RMARGIN and return the old value. */ -ARGP_FS_EI size_t -__argp_fmtstream_set_rmargin (argp_fmtstream_t __fs, size_t __rmargin) +static inline size_t __argp_fmtstream_set_rmargin (argp_fmtstream_t __fs, size_t __rmargin) { size_t __old; if ((size_t) (__fs->p - __fs->buf) > __fs->point_offs) @@ -257,9 +213,8 @@ __argp_fmtstream_set_rmargin (argp_fmtstream_t __fs, size_t __rmargin) return __old; } -/* Set FS's wrap margin to __WMARGIN and return the old value. */ -ARGP_FS_EI size_t -__argp_fmtstream_set_wmargin (argp_fmtstream_t __fs, size_t __wmargin) +/* Set __FS's wrap margin to __WMARGIN and return the old value. */ +static inline size_t __argp_fmtstream_set_wmargin (argp_fmtstream_t __fs, size_t __wmargin) { size_t __old; if ((size_t) (__fs->p - __fs->buf) > __fs->point_offs) @@ -270,8 +225,7 @@ __argp_fmtstream_set_wmargin (argp_fmtstream_t __fs, size_t __wmargin) } /* Return the column number of the current output point in __FS. */ -ARGP_FS_EI size_t -__argp_fmtstream_point (argp_fmtstream_t __fs) +static inline size_t __argp_fmtstream_point (argp_fmtstream_t __fs) { if ((size_t) (__fs->p - __fs->buf) > __fs->point_offs) __argp_fmtstream_update (__fs); @@ -290,8 +244,6 @@ __argp_fmtstream_point (argp_fmtstream_t __fs) #undef __argp_fmtstream_ensure #endif -#endif /* __OPTIMIZE__ */ - #endif /* ARGP_FMTSTREAM_USE_LINEWRAP */ #endif /* argp-fmtstream.h */ From 30078661e79047c2dda933e9bbd4e2dcb8125651 Mon Sep 17 00:00:00 2001 From: sripathi-muralitharan Date: Thu, 24 Jun 2021 01:05:57 -0700 Subject: [PATCH 36/70] Bug fixes * Fences * Use uniform credit semantics --- .../dromajo-vcs/bsg_manycore_platform.cpp | 10 +++++----- .../dromajo-vcs/bsg_manycore_simulator.cpp | 16 ++++------------ .../dromajo-vcs/software/src/bp_utils.c | 2 +- 3 files changed, 10 insertions(+), 18 deletions(-) diff --git a/libraries/platforms/dromajo-vcs/bsg_manycore_platform.cpp b/libraries/platforms/dromajo-vcs/bsg_manycore_platform.cpp index b84919277..c699eb852 100644 --- a/libraries/platforms/dromajo-vcs/bsg_manycore_platform.cpp +++ b/libraries/platforms/dromajo-vcs/bsg_manycore_platform.cpp @@ -120,7 +120,7 @@ int hb_mc_platform_transmit(hb_mc_manycore_t *mc, hb_mc_packet_t *packet, hb_mc_ hb_mc_platform_t *platform = reinterpret_cast(mc->platform); const char *typestr = hb_mc_fifo_tx_to_string(type); const hb_mc_config_t *cfg = hb_mc_manycore_get_config(mc); - uint32_t max_credits = hb_mc_config_get_io_endpoint_max_out_credits(cfg); + uint32_t max_credits = hb_mc_config_get_transmit_vacancy_max(cfg); int err; // Timeout is unsupported @@ -140,7 +140,7 @@ int hb_mc_platform_transmit(hb_mc_manycore_t *mc, hb_mc_packet_t *packet, hb_mc_ int credits_used; do { err = bp_hb_get_credits_used(&credits_used); - } while ((err != HB_MC_SUCCESS) || (max_credits - credits_used <= 0)); + } while ((err != HB_MC_SUCCESS) || ((max_credits - credits_used) <= 0)); err = bp_hb_write_to_mc_bridge(packet); if (err != HB_MC_SUCCESS) { @@ -276,11 +276,11 @@ int hb_mc_platform_fence(hb_mc_manycore_t *mc, long timeout) { do { err = bp_hb_get_fifo_entries(&num_entries, HB_MC_FIFO_RX_RSP); - } while (num_entries == 0 || err != HB_MC_SUCCESS); - err |= bp_hb_read_from_mc_bridge(&fence_resp_pkt, HB_MC_FIFO_RX_RSP); + } while ((num_entries == 0) && (err == HB_MC_SUCCESS)); + err |= bp_hb_read_from_mc_bridge(&fence_resp_pkt, HB_MC_FIFO_RX_RSP); is_vacant = fence_resp_pkt.response.data; - } while ((err != HB_MC_SUCCESS) || (credits_used != 0) || (is_vacant != 1)); + } while ((err == HB_MC_SUCCESS) && !((credits_used == 0) && is_vacant)); return err; } diff --git a/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.cpp b/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.cpp index 7a19d7001..b652e5ca6 100644 --- a/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.cpp +++ b/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.cpp @@ -380,7 +380,6 @@ int SimulationWrapper::dromajo_transmit_packet() { } // Update the credits in dromajo - bsg_pr_dbg("Checking for credits\n"); err = dromajo_set_credits(); if (err != HB_MC_SUCCESS) return err; @@ -452,7 +451,7 @@ int SimulationWrapper::dromajo_receive_packet() { * for the Dromajo->Manycore request FIFO in dromajo */ int SimulationWrapper::dromajo_set_credits() { - int credits, credits_used, max_credits; + int credits_used; int err; err = dpi->get_credits_used(credits_used); @@ -461,17 +460,10 @@ int SimulationWrapper::dromajo_set_credits() { return HB_MC_FAIL; } - err = dpi->get_credits_max(max_credits); - if (err == BSG_NONSYNTH_DPI_SUCCESS) { - credits = max_credits - credits_used; - if (credits < 0) - bsg_pr_err("Credit value is < 0. Must be non-negative\n"); - host_to_mc_req_fifo->credits = credits; - } - else { - bsg_pr_err(bsg_nonsynth_dpi_strerror(err)); - return err; + if (credits_used < 0) { + bsg_pr_err("Credit value is < 0. Must be non-negative\n"); } + host_to_mc_req_fifo->credits = credits_used; return HB_MC_SUCCESS; } diff --git a/libraries/platforms/dromajo-vcs/software/src/bp_utils.c b/libraries/platforms/dromajo-vcs/software/src/bp_utils.c index 63859794b..e3ecb1d30 100644 --- a/libraries/platforms/dromajo-vcs/software/src/bp_utils.c +++ b/libraries/platforms/dromajo-vcs/software/src/bp_utils.c @@ -14,7 +14,7 @@ int bp_hb_get_credits_used(int *credits_used) { uint32_t *bp_to_mc_req_credits_addr = (uint32_t *) (MC_BASE_ADDR + BP_TO_MC_REQ_CREDITS_ADDR); if ((*credits_used = (int) *bp_to_mc_req_credits_addr) < 0) { - bsg_pr_err("Credits used cannot be negative. Credits = %d", *credits_used); + bsg_pr_err("Credits used cannot be negative. Credits used = %d", *credits_used); return HB_MC_FAIL; } return HB_MC_SUCCESS; From fc34d6db507ad03f8b7680bb27f0547992175fd2 Mon Sep 17 00:00:00 2001 From: sripathi-muralitharan Date: Fri, 25 Jun 2021 20:11:08 -0700 Subject: [PATCH 37/70] Switching from using basename to using the string itself --- examples/library/test_manycore_packets/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/library/test_manycore_packets/main.c b/examples/library/test_manycore_packets/main.c index 8225ec827..ff8b48397 100644 --- a/examples/library/test_manycore_packets/main.c +++ b/examples/library/test_manycore_packets/main.c @@ -193,4 +193,4 @@ int test_manycore_packets(int argc, char *argv[]) { return HB_MC_SUCCESS; } -declare_program_main(basename(__FILE__), test_manycore_packets); +declare_program_main("test_manycore_packets", test_manycore_packets); From 44d5db7b4dac0cfa13e4cf53a8237b67036b2f67 Mon Sep 17 00:00:00 2001 From: sripathi-muralitharan Date: Fri, 25 Jun 2021 20:16:09 -0700 Subject: [PATCH 38/70] Making functions visible and static inline --- libraries/platforms/dromajo-vcs/link.mk | 2 +- .../dromajo-vcs/software/include/argp.h | 33 +++++++------------ .../dromajo-vcs/software/src/argp/argp-help.c | 4 +-- .../software/src/argp/argp-parse.c | 2 +- 4 files changed, 15 insertions(+), 26 deletions(-) diff --git a/libraries/platforms/dromajo-vcs/link.mk b/libraries/platforms/dromajo-vcs/link.mk index 3cf2f6136..47b3ae6c6 100644 --- a/libraries/platforms/dromajo-vcs/link.mk +++ b/libraries/platforms/dromajo-vcs/link.mk @@ -116,7 +116,7 @@ $(BSG_PLATFORM_PATH)/test.riscv: $(BSG_PLATFORM_PATH)/lfs.o $(BSG_PLATFORM_PATH)/test.riscv: $(BSG_PLATFORM_PATH)/libbsg_manycore_runtime.a $(BSG_PLATFORM_PATH)/test.riscv: $(BSG_PLATFORM_PATH)/libbsgmc_cuda_legacy_pod_repl.a $(BSG_PLATFORM_PATH)/test.riscv: $(BSG_PLATFORM_PATH)/libbsg_manycore_regression.a -$(BSG_PLATFORM_PATH)/test.riscv: LDFLAGS := -T$(BLACKPARROT_SDK_DIR)/linker/riscv.ld -L$(BSG_PLATFORM_PATH) -static -nostartfiles -lstdc++ -lbsg_manycore_runtime -lbsg_manycore_regression +$(BSG_PLATFORM_PATH)/test.riscv: LDFLAGS := -T$(BLACKPARROT_SDK_DIR)/linker/riscv.ld -L$(BSG_PLATFORM_PATH) -static -nostartfiles -lstdc++ -lbsg_manycore_regression -lbsg_manycore_runtime $(BSG_PLATFORM_PATH)/test.riscv: LD = $(CXX) $(BSG_PLATFORM_PATH)/test.riscv: $(LD) -D_DRAMFS -o $@ $(BSG_PLATFORM_PATH)/software/src/crt0.o $(BSG_PLATFORM_PATH)/lfs.o $< $(LDFLAGS) diff --git a/libraries/platforms/dromajo-vcs/software/include/argp.h b/libraries/platforms/dromajo-vcs/software/include/argp.h index e63196cb1..49f9173ef 100644 --- a/libraries/platforms/dromajo-vcs/software/include/argp.h +++ b/libraries/platforms/dromajo-vcs/software/include/argp.h @@ -477,10 +477,6 @@ extern void __argp_state_help (__const struct argp_state *__restrict __state, FILE *__restrict __stream, unsigned int __flags) __THROW; -/* Possibly output the standard usage message for ARGP to stderr and exit. */ -extern void argp_usage (__const struct argp_state *__state) __THROW; -extern void __argp_usage (__const struct argp_state *__state) __THROW; - /* If appropriate, print the printf string FMT and following args, preceded by the program name and `:', to stderr, and followed by a `Try ... --help' message, then exit (1). */ @@ -508,15 +504,6 @@ extern void __argp_failure (__const struct argp_state *__restrict __state, __const char *__restrict __fmt, ...) __THROW __attribute__ ((__format__ (__printf__, 4, 5))); -/* Returns true if the option OPT is a valid short option. */ -extern int _option_is_short (__const struct argp_option *__opt) __THROW; -extern int __option_is_short (__const struct argp_option *__opt) __THROW; - -/* Returns true if the option OPT is in fact the last (unused) entry in an - options array. */ -extern int _option_is_end (__const struct argp_option *__opt) __THROW; -extern int __option_is_end (__const struct argp_option *__opt) __THROW; - /* Return the input field for ARGP in the parser corresponding to STATE; used by the help routines. */ extern void *_argp_input (__const struct argp *__restrict __argp, @@ -526,7 +513,10 @@ extern void *__argp_input (__const struct argp *__restrict __argp, __const struct argp_state *__restrict __state) __THROW; -#ifdef __USE_EXTERN_INLINES +// Always define functions in a header file with the static modifier. +// Defining functions with "extern inline" in a header file is just wrong. +// Switch to using "static inline" to make the function visible wherever +// this header file is included # if !_LIBC # define __argp_usage argp_usage @@ -535,17 +525,15 @@ extern void *__argp_input (__const struct argp *__restrict __argp, # define __option_is_end _option_is_end # endif -# ifndef ARGP_EI -# define ARGP_EI extern __inline__ -# endif - -ARGP_EI void +/* Possibly output the standard usage message for ARGP to stderr and exit. */ +static inline void __argp_usage (__const struct argp_state *__state) __THROW { __argp_state_help (__state, stderr, ARGP_HELP_STD_USAGE); } -ARGP_EI int +/* Returns true if the option OPT is a valid short option. */ +static inline int __option_is_short (__const struct argp_option *__opt) __THROW { if (__opt->flags & OPTION_DOC) @@ -557,7 +545,9 @@ __option_is_short (__const struct argp_option *__opt) __THROW } } -ARGP_EI int +/* Returns true if the option OPT is in fact the last (unused) entry in an + options array. */ +static inline int __option_is_end (__const struct argp_option *__opt) __THROW { return !__opt->key && !__opt->name && !__opt->doc && !__opt->group; @@ -569,7 +559,6 @@ __option_is_end (__const struct argp_option *__opt) __THROW # undef __option_is_short # undef __option_is_end # endif -#endif /* Use extern inlines. */ #ifdef __cplusplus } diff --git a/libraries/platforms/dromajo-vcs/software/src/argp/argp-help.c b/libraries/platforms/dromajo-vcs/software/src/argp/argp-help.c index 6b278065c..69325fecd 100644 --- a/libraries/platforms/dromajo-vcs/software/src/argp/argp-help.c +++ b/libraries/platforms/dromajo-vcs/software/src/argp/argp-help.c @@ -70,8 +70,8 @@ char *alloca (); #endif #include -#include "argp-fmtstream.h" -#include "argp-namefrob.h" +#include +#include /* User-selectable (using an environment variable) formatting parameters. diff --git a/libraries/platforms/dromajo-vcs/software/src/argp/argp-parse.c b/libraries/platforms/dromajo-vcs/software/src/argp/argp-parse.c index 7d29edd98..3ed553a5d 100644 --- a/libraries/platforms/dromajo-vcs/software/src/argp/argp-parse.c +++ b/libraries/platforms/dromajo-vcs/software/src/argp/argp-parse.c @@ -55,7 +55,7 @@ #endif /* _LIBC */ #include -#include "argp-namefrob.h" +#include /* Getopt return values. */ #define KEY_END (-1) /* The end of the options. */ From e24ccecde5dbaddfeee7edcba7148f28c72dc19c Mon Sep 17 00:00:00 2001 From: sripathi-muralitharan Date: Mon, 28 Jun 2021 11:41:49 -0700 Subject: [PATCH 39/70] Various updates * Flush stdout after every print * Initialize variables to prevent hangups --- .../dromajo-vcs/bsg_manycore_platform.cpp | 18 +++++++++--------- .../dromajo-vcs/bsg_manycore_simulator.cpp | 3 +++ 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/libraries/platforms/dromajo-vcs/bsg_manycore_platform.cpp b/libraries/platforms/dromajo-vcs/bsg_manycore_platform.cpp index c699eb852..05081505a 100644 --- a/libraries/platforms/dromajo-vcs/bsg_manycore_platform.cpp +++ b/libraries/platforms/dromajo-vcs/bsg_manycore_platform.cpp @@ -137,11 +137,13 @@ int hb_mc_platform_transmit(hb_mc_manycore_t *mc, hb_mc_packet_t *packet, hb_mc_ return HB_MC_NOIMPL; } - int credits_used; + int credits_used = 0; do { err = bp_hb_get_credits_used(&credits_used); } while ((err != HB_MC_SUCCESS) || ((max_credits - credits_used) <= 0)); + // Don't need to check for error code since this operation should always be a success since it is not going + // over the network err = bp_hb_write_to_mc_bridge(packet); if (err != HB_MC_SUCCESS) { bsg_pr_err("Write to the host request FIFO failed!"); @@ -170,14 +172,11 @@ int hb_mc_platform_receive(hb_mc_manycore_t *mc, hb_mc_packet_t *packet, hb_mc_f } int err; - int num_entries; + int num_entries = 0; do { err = bp_hb_get_fifo_entries(&num_entries, type); } while (num_entries == 0 || err != HB_MC_SUCCESS); - if (err != HB_MC_SUCCESS) - return err; - err = bp_hb_read_from_mc_bridge(packet, type); if (err != HB_MC_SUCCESS) { bsg_pr_err("Read from the %s FIFO did not succeed", typestr); @@ -197,7 +196,8 @@ int hb_mc_platform_receive(hb_mc_manycore_t *mc, hb_mc_packet_t *packet, hb_mc_f int hb_mc_platform_get_config_at(hb_mc_manycore_t *mc, unsigned int idx, hb_mc_config_raw_t *config) { hb_mc_platform_t *platform = reinterpret_cast(mc->platform); hb_mc_packet_t config_req_pkt, config_resp_pkt; - int num_entries, err; + int num_entries = 0; + int err; if (idx < HB_MC_CONFIG_MAX) { @@ -246,8 +246,8 @@ int hb_mc_platform_get_config_at(hb_mc_manycore_t *mc, unsigned int idx, hb_mc_c */ int hb_mc_platform_fence(hb_mc_manycore_t *mc, long timeout) { int credits_used, is_vacant, num_entries, err; - uint32_t max_credits; hb_mc_packet_t fence_req_pkt, fence_resp_pkt; + num_entries = 0; hb_mc_platform_t *platform = reinterpret_cast(mc->platform); @@ -276,7 +276,7 @@ int hb_mc_platform_fence(hb_mc_manycore_t *mc, long timeout) { do { err = bp_hb_get_fifo_entries(&num_entries, HB_MC_FIFO_RX_RSP); - } while ((num_entries == 0) && (err == HB_MC_SUCCESS)); + } while ((num_entries == 0) || (err != HB_MC_SUCCESS)); err |= bp_hb_read_from_mc_bridge(&fence_resp_pkt, HB_MC_FIFO_RX_RSP); is_vacant = fence_resp_pkt.response.data; @@ -367,7 +367,7 @@ int hb_mc_platform_log_disable(hb_mc_manycore_t *mc) { */ int hb_mc_platform_wait_reset_done(hb_mc_manycore_t *mc) { hb_mc_packet_t reset_req_pkt, reset_resp_pkt; - int err, credits_used; + int err; uint32_t data; reset_req_pkt.request.x_dst = (0 << 4) | 0; diff --git a/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.cpp b/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.cpp index b652e5ca6..a7774dac5 100644 --- a/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.cpp +++ b/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.cpp @@ -299,7 +299,10 @@ int SimulationWrapper::dromajo_transmit_packet() { switch (dromajo_to_mc_packet.request.addr) { case MC_STDOUT_EPA_ADDR: case MC_STDERR_EPA_ADDR: + { printf("%c", (uint8_t) dromajo_to_mc_packet.request.payload); + fflush(stdout); + } break; case MC_FINISH_EPA_ADDR: { From 6338c072c6f8a5df2f7575399ff26886c14ac5b6 Mon Sep 17 00:00:00 2001 From: sripathi-muralitharan Date: Thu, 8 Jul 2021 13:49:05 -0700 Subject: [PATCH 40/70] Separating assigments and conditionals --- .../platforms/dromajo-vcs/bsg_manycore_platform.cpp | 7 ++++--- libraries/platforms/dromajo-vcs/software/src/bp_utils.c | 9 ++++++--- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/libraries/platforms/dromajo-vcs/bsg_manycore_platform.cpp b/libraries/platforms/dromajo-vcs/bsg_manycore_platform.cpp index 05081505a..515dc7c5e 100644 --- a/libraries/platforms/dromajo-vcs/bsg_manycore_platform.cpp +++ b/libraries/platforms/dromajo-vcs/bsg_manycore_platform.cpp @@ -175,7 +175,7 @@ int hb_mc_platform_receive(hb_mc_manycore_t *mc, hb_mc_packet_t *packet, hb_mc_f int num_entries = 0; do { err = bp_hb_get_fifo_entries(&num_entries, type); - } while (num_entries == 0 || err != HB_MC_SUCCESS); + } while ((num_entries == 0) || (err != HB_MC_SUCCESS)); err = bp_hb_read_from_mc_bridge(packet, type); if (err != HB_MC_SUCCESS) { @@ -221,7 +221,7 @@ int hb_mc_platform_get_config_at(hb_mc_manycore_t *mc, unsigned int idx, hb_mc_c do { err = bp_hb_get_fifo_entries(&num_entries, HB_MC_FIFO_RX_RSP); - } while (num_entries == 0 || err != HB_MC_SUCCESS); + } while ((num_entries == 0) || (err != HB_MC_SUCCESS)); err = bp_hb_read_from_mc_bridge(&config_resp_pkt, HB_MC_FIFO_RX_RSP); if (err != HB_MC_SUCCESS) { @@ -248,6 +248,7 @@ int hb_mc_platform_fence(hb_mc_manycore_t *mc, long timeout) { int credits_used, is_vacant, num_entries, err; hb_mc_packet_t fence_req_pkt, fence_resp_pkt; num_entries = 0; + credits_used = 0; hb_mc_platform_t *platform = reinterpret_cast(mc->platform); @@ -368,7 +369,7 @@ int hb_mc_platform_log_disable(hb_mc_manycore_t *mc) { int hb_mc_platform_wait_reset_done(hb_mc_manycore_t *mc) { hb_mc_packet_t reset_req_pkt, reset_resp_pkt; int err; - uint32_t data; + uint32_t data = 0; reset_req_pkt.request.x_dst = (0 << 4) | 0; reset_req_pkt.request.y_dst = (1 << 3) | 0; diff --git a/libraries/platforms/dromajo-vcs/software/src/bp_utils.c b/libraries/platforms/dromajo-vcs/software/src/bp_utils.c index e3ecb1d30..4b50beb3d 100644 --- a/libraries/platforms/dromajo-vcs/software/src/bp_utils.c +++ b/libraries/platforms/dromajo-vcs/software/src/bp_utils.c @@ -13,7 +13,8 @@ */ int bp_hb_get_credits_used(int *credits_used) { uint32_t *bp_to_mc_req_credits_addr = (uint32_t *) (MC_BASE_ADDR + BP_TO_MC_REQ_CREDITS_ADDR); - if ((*credits_used = (int) *bp_to_mc_req_credits_addr) < 0) { + *credits_used = (int) *bp_to_mc_req_credits_addr; + if (*credits_used < 0) { bsg_pr_err("Credits used cannot be negative. Credits used = %d", *credits_used); return HB_MC_FAIL; } @@ -46,7 +47,8 @@ int bp_hb_get_fifo_entries(int *entries, hb_mc_fifo_rx_t type) { case HB_MC_FIFO_RX_REQ: { uint32_t *mc_to_bp_req_fifo_entries_addr = (uint32_t *) (MC_BASE_ADDR + MC_TO_BP_REQ_ENTRIES_ADDR); - if ((*entries = *mc_to_bp_req_fifo_entries_addr) < 0) { + *entries = *mc_to_bp_req_fifo_entries_addr; + if (*entries < 0) { bsg_pr_err("Entries occupied cannot be negative. Entries = %d", *entries); return HB_MC_FAIL; } @@ -55,7 +57,8 @@ int bp_hb_get_fifo_entries(int *entries, hb_mc_fifo_rx_t type) { case HB_MC_FIFO_RX_RSP: { uint32_t *mc_to_bp_resp_fifo_entries_addr = (uint32_t *) (MC_BASE_ADDR + MC_TO_BP_RESP_ENTRIES_ADDR); - if ((*entries = *mc_to_bp_resp_fifo_entries_addr) < 0) { + *entries = *mc_to_bp_resp_fifo_entries_addr; + if (*entries < 0) { bsg_pr_err("Entries occupied cannot be negative. Entries = %d", *entries); return HB_MC_FAIL; } From 8ff6a526c6c16c208b86f169e4096fde0b7def58 Mon Sep 17 00:00:00 2001 From: sripathi-muralitharan Date: Thu, 8 Jul 2021 14:33:15 -0700 Subject: [PATCH 41/70] Removing newlines and whitespaces --- .../dromajo-vcs/bsg_manycore_simulator.hpp | 2 +- libraries/platforms/dromajo-vcs/link.mk | 1 - .../software/include/dromajo/config.h | 2 +- .../dromajo-vcs/software/src/bp_utils.c | 18 +++++++++--------- .../dromajo-vcs/software/src/flockfile.c | 2 +- .../dromajo-vcs/software/src/funlockfile.c | 2 +- 6 files changed, 13 insertions(+), 14 deletions(-) diff --git a/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.hpp b/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.hpp index 3194f8d61..9908b8924 100644 --- a/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.hpp +++ b/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.hpp @@ -121,4 +121,4 @@ class SimulationWrapper{ // and forwards packets between Dromajo and the manycore int eval(); }; -#endif // __BSG_MANYCORE_SIMULATOR_HPP \ No newline at end of file +#endif // __BSG_MANYCORE_SIMULATOR_HPP diff --git a/libraries/platforms/dromajo-vcs/link.mk b/libraries/platforms/dromajo-vcs/link.mk index 47b3ae6c6..941885292 100644 --- a/libraries/platforms/dromajo-vcs/link.mk +++ b/libraries/platforms/dromajo-vcs/link.mk @@ -171,4 +171,3 @@ platform.link.clean: rm -rf $(BSG_PLATFORM_PATH)/*.riscv link.clean: platform.link.clean ; - diff --git a/libraries/platforms/dromajo-vcs/software/include/dromajo/config.h b/libraries/platforms/dromajo-vcs/software/include/dromajo/config.h index b6a6a72fa..55b63151b 100644 --- a/libraries/platforms/dromajo-vcs/software/include/dromajo/config.h +++ b/libraries/platforms/dromajo-vcs/software/include/dromajo/config.h @@ -1 +1 @@ -#define CONFIG_VERSION "Dromajo-0.1" \ No newline at end of file +#define CONFIG_VERSION "Dromajo-0.1" diff --git a/libraries/platforms/dromajo-vcs/software/src/bp_utils.c b/libraries/platforms/dromajo-vcs/software/src/bp_utils.c index 4b50beb3d..731b2e9d9 100644 --- a/libraries/platforms/dromajo-vcs/software/src/bp_utils.c +++ b/libraries/platforms/dromajo-vcs/software/src/bp_utils.c @@ -191,8 +191,8 @@ void bp_finish(int16_t code) { finish_pkt.request.x_src = (0 << 4) | 0; finish_pkt.request.y_src = (1 << 3) | 1; finish_pkt.request.op_v2 = HB_MC_PACKET_OP_REMOTE_SW; - finish_pkt.request.payload = (core_id << 16) | (0x0000FFFF & code); - finish_pkt.request.reg_id = 0; + finish_pkt.request.payload = (core_id << 16) | (0x0000FFFF & code); + finish_pkt.request.reg_id = 0; if (code >= 0) finish_pkt.request.addr = MC_FINISH_EPA_ADDR; else @@ -210,14 +210,14 @@ void bp_finish(int16_t code) { */ void bp_hprint(uint8_t hex) { - hb_mc_packet_t hprint_pkt; + hb_mc_packet_t hprint_pkt; hprint_pkt.request.x_dst = (0 << 4) | 0; hprint_pkt.request.y_dst = (1 << 3) | 0; hprint_pkt.request.x_src = (0 << 4) | 0; hprint_pkt.request.y_src = (1 << 3) | 1; hprint_pkt.request.op_v2 = HB_MC_PACKET_OP_REMOTE_SW; - hprint_pkt.request.payload = ('0' + hex); - hprint_pkt.request.reg_id = 0; + hprint_pkt.request.payload = ('0' + hex); + hprint_pkt.request.reg_id = 0; hprint_pkt.request.addr = MC_STDOUT_EPA_ADDR; int err = bp_hb_write_to_mc_bridge(&hprint_pkt); @@ -229,15 +229,15 @@ void bp_hprint(uint8_t hex) { */ void bp_cprint(uint8_t ch) { - hb_mc_packet_t cprint_pkt; + hb_mc_packet_t cprint_pkt; cprint_pkt.request.x_dst = (0 << 4) | 0; cprint_pkt.request.y_dst = (1 << 3) | 0; cprint_pkt.request.x_src = (0 << 4) | 0; cprint_pkt.request.y_src = (1 << 3) | 1; cprint_pkt.request.op_v2 = HB_MC_PACKET_OP_REMOTE_SW; - cprint_pkt.request.payload = ch; - cprint_pkt.request.reg_id = 0; + cprint_pkt.request.payload = ch; + cprint_pkt.request.reg_id = 0; cprint_pkt.request.addr = MC_STDOUT_EPA_ADDR; int err = bp_hb_write_to_mc_bridge(&cprint_pkt); -} \ No newline at end of file +} diff --git a/libraries/platforms/dromajo-vcs/software/src/flockfile.c b/libraries/platforms/dromajo-vcs/software/src/flockfile.c index 315c8e33a..57110f6a4 100644 --- a/libraries/platforms/dromajo-vcs/software/src/flockfile.c +++ b/libraries/platforms/dromajo-vcs/software/src/flockfile.c @@ -38,4 +38,4 @@ void flockfile(FILE *fp) { // Do nothing -} \ No newline at end of file +} diff --git a/libraries/platforms/dromajo-vcs/software/src/funlockfile.c b/libraries/platforms/dromajo-vcs/software/src/funlockfile.c index dee9ef05a..24d495e96 100644 --- a/libraries/platforms/dromajo-vcs/software/src/funlockfile.c +++ b/libraries/platforms/dromajo-vcs/software/src/funlockfile.c @@ -38,4 +38,4 @@ void funlockfile(FILE *fp) { // Do nothing -} \ No newline at end of file +} From 91bad5e491e9dd0f6943c49bce403220383ffbba Mon Sep 17 00:00:00 2001 From: sripathi-muralitharan Date: Thu, 8 Jul 2021 14:33:47 -0700 Subject: [PATCH 42/70] Clean platform shared object files --- libraries/platforms/dromajo-vcs/library.mk | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libraries/platforms/dromajo-vcs/library.mk b/libraries/platforms/dromajo-vcs/library.mk index 8f42badcc..d55597afe 100644 --- a/libraries/platforms/dromajo-vcs/library.mk +++ b/libraries/platforms/dromajo-vcs/library.mk @@ -155,5 +155,8 @@ platform.clean: rm -f $(BSG_PLATFORM_PATH)/libbsg_manycore_runtime.a rm -f $(BSG_PLATFORM_PATH)/libbsgmc_cuda_legacy_pod_repl.a rm -f $(BSG_PLATFORM_PATH)/libbsg_manycore_regression.a + rm -f $(BSG_PLATFORM_PATH)/libbsg_manycore_platform.so.1.0 + rm -f $(BSG_PLATFORM_PATH)/libbsg_manycore_platform.so.1 + rm -f $(BSG_PLATFORM_PATH)/libbsg_manycore_platform.so libraries.clean: platform.clean From 6b6b0dfcb89fb54352a55ce02124cf2ef3b2d45c Mon Sep 17 00:00:00 2001 From: sripathi-muralitharan Date: Thu, 8 Jul 2021 14:34:06 -0700 Subject: [PATCH 43/70] Add deprecation note to start code --- libraries/platforms/dromajo-vcs/software/src/crt0.S | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libraries/platforms/dromajo-vcs/software/src/crt0.S b/libraries/platforms/dromajo-vcs/software/src/crt0.S index 1977bf18e..e9794c4d6 100644 --- a/libraries/platforms/dromajo-vcs/software/src/crt0.S +++ b/libraries/platforms/dromajo-vcs/software/src/crt0.S @@ -1,7 +1,11 @@ # Start code + +# This file should be deprecated when the BlackParrot firmware is capable of +# parsing arguments. + # This assembly file mimics the BlackParrot perch library start.S # with minor modifications to allow arguments to be loaded into the -# corresponding registers for main +# argument registers for main .section ".text.init" .globl _start From 7afde5538ebe16b6b00746d39579428ea2b16019 Mon Sep 17 00:00:00 2001 From: sripathi-muralitharan Date: Thu, 8 Jul 2021 14:34:32 -0700 Subject: [PATCH 44/70] Clarify the use of these headers --- .../platforms/dromajo-vcs/software/include/endian.h | 8 +++++++- .../platforms/dromajo-vcs/software/include/features.h | 10 ++++++++-- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/libraries/platforms/dromajo-vcs/software/include/endian.h b/libraries/platforms/dromajo-vcs/software/include/endian.h index c788d2fee..db84ae0a0 100644 --- a/libraries/platforms/dromajo-vcs/software/include/endian.h +++ b/libraries/platforms/dromajo-vcs/software/include/endian.h @@ -25,7 +25,13 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// A dummy header to interface with the endian.h header from the newlib toolchain +// Note: Users should only use this file for compiling with NEWLIB + +// In GLIBC, this header file is present in the default include path however +// in NEWLIB, the same header file is present in /machine/ +// therefore, this dummy file is used to actually call the correct header file in +// NEWLIB whilst still maintaining the same interface as GLIBC. This is done to prevent +// changes to the CUDA-lite library code. #ifndef _ENDIAN_H #define _ENDIAN_H diff --git a/libraries/platforms/dromajo-vcs/software/include/features.h b/libraries/platforms/dromajo-vcs/software/include/features.h index 352797c3d..acada50ca 100644 --- a/libraries/platforms/dromajo-vcs/software/include/features.h +++ b/libraries/platforms/dromajo-vcs/software/include/features.h @@ -25,11 +25,17 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// A dummy header to interface with the features.h header from the newlib toolchain +// Note: Users should only use this file for compiling with NEWLIB + +// In GLIBC, this header file is present in the default include path however +// in NEWLIB, the same header file is present in /sys/ +// therefore, this dummy file is used to actually call the correct header file in +// NEWLIB whilst still maintaining the same interface as GLIBC. This is done to prevent +// changes to the CUDA-lite library code. #ifndef _FEATURES_H #define _FEATURES_H #include -#endif /* _FEATURES_H */ \ No newline at end of file +#endif /* _FEATURES_H */ From 2fb75a1a1733bbacd427cbb01b4b9f0eacdd310d Mon Sep 17 00:00:00 2001 From: sripathi-muralitharan Date: Thu, 8 Jul 2021 15:05:52 -0700 Subject: [PATCH 45/70] Add separate rules to generate lfs.cpp and compile it --- libraries/platforms/dromajo-vcs/library.mk | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/libraries/platforms/dromajo-vcs/library.mk b/libraries/platforms/dromajo-vcs/library.mk index d55597afe..59bc64b3b 100644 --- a/libraries/platforms/dromajo-vcs/library.mk +++ b/libraries/platforms/dromajo-vcs/library.mk @@ -77,10 +77,12 @@ $(BSG_PLATFORM_PATH)/libbsgmc_cuda_legacy_pod_repl.a: AR = $(RV_AR) $(BSG_PLATFORM_PATH)/libbsg_manycore_regression.a: AR = $(RV_AR) # Make the litteFS file system -$(BSG_PLATFORM_PATH)/lfs.o: MKLFS = $(BLACKPARROT_SDK_DIR)/install/bin/dramfs_mklfs 128 64 -$(BSG_PLATFORM_PATH)/lfs.o: - $(MKLFS) > $(BSG_PLATFORM_PATH)/lfs.cpp - $(CXX) $(BSG_PLATFORM_PATH)/lfs.cpp -c -o $@ $(CXXFLAGS) $(INCLUDES) +$(BSG_PLATFORM_PATH)/lfs.cpp: MKLFS = $(BLACKPARROT_SDK_DIR)/install/bin/dramfs_mklfs 128 64 +$(BSG_PLATFORM_PATH)/lfs.cpp: + $(MKLFS) > $@ + +$(BSG_PLATFORM_PATH)/lfs.o: $(BSG_PLATFORM_PATH)/lfs.cpp + $(CXX) $^ -c -o $@ $(CXXFLAGS) $(INCLUDES) include $(LIBRARIES_PATH)/features/dma/simulation/dramsim3.mk include $(LIBRARIES_PATH)/features/dma/simulation/libdmamem.mk @@ -151,6 +153,7 @@ $(BSG_PLATFORM_PATH)/libbsg_manycore_platform.so: %: %.1 platform.clean: rm -f $(PLATFORM_OBJECTS) rm -f $(DROMAJO_OBJECTS) + rm -f $(BSG_PLATFORM_PATH)/lfs.cpp rm -f $(BSG_PLATFORM_PATH)/lfs.o rm -f $(BSG_PLATFORM_PATH)/libbsg_manycore_runtime.a rm -f $(BSG_PLATFORM_PATH)/libbsgmc_cuda_legacy_pod_repl.a From e9b0123d24336b4f39b3293bc42cc3f8112223a8 Mon Sep 17 00:00:00 2001 From: sripathi_muralitharan Date: Thu, 8 Jul 2021 21:53:19 -0700 Subject: [PATCH 46/70] Create README.md --- libraries/platforms/dromajo-vcs/README.md | 76 +++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 libraries/platforms/dromajo-vcs/README.md diff --git a/libraries/platforms/dromajo-vcs/README.md b/libraries/platforms/dromajo-vcs/README.md new file mode 100644 index 000000000..270c847bb --- /dev/null +++ b/libraries/platforms/dromajo-vcs/README.md @@ -0,0 +1,76 @@ +# Dromajo HammerBlade Platform on VCS + +## Introduction + +The Dromajo-HammerBlade platform is a precursor to the BlackParrot-HammerBlade platform a.k.a HammerParrot. It builds on the traditional x86 setup and replaces x86 with Dromajo as the main host (except for a few operations) that executes the CUDA-lite program. Broadly speaking there are three main components to the entire system + +- x86: It is the base platform on which the entire simulation infrastructure is built. In a traditional setup, the x86 core runs the CUDA-lite binary while simulating the manycore hardware. In this case, the x86 core instead runs the Dromajo emulator in addition to simulating the manycore hardware whilst performing some host-like operations and interacting with the hardware through DPI. +- Dromajo: A C++ based 64-bit RISC-V processor emulator developed by Esperanto Technologies with modifications to communicate with the HammerBlade manycore. All CUDA-lite host code is executed by a RISC-V processor emulated by Dromajo. Since, HammerParrot is the eventual goal, Dromajo has been modified to work like BlackParrot. +- HammerBlade hardware: Like all other platforms, the manycore hardware consists of the manycore with a specific machine configuration and is equipped with DPI FIFOs on the west side forming the manycore bridge. + +## Dependencies + +### BlackParrot SDK + +The BlackParrot SDK contains multiple submodules +- Dromajo +- Perch, the BlackParrot firmware +- RV64 compilation toolchain + +This directory must be placed at the same level as the replicant repository. It is recommended that users clone the Bladerunner meta repository which includes (or will include) the BlackParrot SDK as a submodule [(PR #66)](https://github.com/bespoke-silicon-group/bsg_bladerunner/pull/66) since this will set all the required environment variables correctly. Otherwise users must define the BLACKPARROT_SDK_DIR variable for the given execution environment. + +## Detailed Technical Manual + +Coming soon! + +## Using the Simulation Infrastructure + +The simulation infrastructure can be used just like any other platform. An example is given below. + +``` +cd examples/library/test_coordinate +make main.exec.log +``` + +This will build the libraries and the platform binaries, compile and elaborate the hardware and run the test program. The example output for the above program should look as given below + +``` +BSG INFO: Regression Test: test_coordinate +INFO: Starting test foreach_coordinate +INFO: iteration 0: (0,0) +INFO: Starting test foreach_x_y +INFO: iteration 0: (0,0) +INFO: Starting test foreach_coordinate +INFO: iteration 0: (0,0) +INFO: iteration 1: (1,0) +INFO: Starting test foreach_x_y +INFO: iteration 0: (0,0) +INFO: iteration 1: (1,0) +INFO: Starting test foreach_coordinate +INFO: iteration 0: (0,0) +INFO: iteration 1: (0,1) +INFO: Starting test foreach_x_y +INFO: iteration 0: (0,0) +INFO: iteration 1: (0,1) +INFO: Starting test foreach_coordinate +INFO: iteration 0: (0,2) +INFO: iteration 1: (0,3) +INFO: iteration 2: (1,2) +INFO: iteration 3: (1,3) +INFO: Starting test foreach_x_y +INFO: iteration 0: (0,2) +INFO: iteration 1: (0,3) +INFO: iteration 2: (1,2) +INFO: iteration 3: (1,3) +BSG REGRESSION TEST PASSED +INFO: Core 0 successfully terminated +BSG REGRESSION TEST PASSED +BSG COSIM PASS: Test passed! +``` + +### Notes + +- This infrastructure has only been tested with tests in `examples/library`. SPMD and CUDA-lite testing is still remaining. +- All testing has been carried out for a single pod configuration. +- Only the `exec` make target has been tested. The `saif` and `debug` targets still remain to be tested. However, since this pertains to gathering metrics with respect to the hardware being simulated, there is a fair amount of confidence that it will work right out of the box. +- The simulation takes a very long time even for some of the library tests. This can be attributed to the fact that Dromajo is used in co-simulation mode (one instruction per time step) with code executing on the x86 core controlling the notion of time for the whole system. Dromajo also has a standalone mode in which case it must become the driver of time for the whole system. While the reason mentioned here should be verified after an in-depth performance analysis of the system, it is still worthwhile to explore Dromajo in the standalone mode. This is one of major barriers to running CUDA-lite test programs and completing its execution in a reasonable time frame. From 24796f318c6e468a916e1956b7f2c1d3e55a4deb Mon Sep 17 00:00:00 2001 From: sripathi_muralitharan Date: Thu, 8 Jul 2021 22:10:50 -0700 Subject: [PATCH 47/70] Add links to dependencies --- libraries/platforms/dromajo-vcs/README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libraries/platforms/dromajo-vcs/README.md b/libraries/platforms/dromajo-vcs/README.md index 270c847bb..0a5103f0f 100644 --- a/libraries/platforms/dromajo-vcs/README.md +++ b/libraries/platforms/dromajo-vcs/README.md @@ -12,10 +12,10 @@ The Dromajo-HammerBlade platform is a precursor to the BlackParrot-HammerBlade p ### BlackParrot SDK -The BlackParrot SDK contains multiple submodules -- Dromajo -- Perch, the BlackParrot firmware -- RV64 compilation toolchain +The [BlackParrot SDK](https://github.com/black-parrot-sdk/black-parrot-sdk) contains multiple submodules +- [Dromajo](https://github.com/bsg-external/dromajo/tree/4cbf5d91b880e172f15e0658cc72d4d6426ddcaa), the 64-bit RISC-V emulator +- [Perch](https://github.com/black-parrot-sdk/perch/tree/f3a302b3a902e80952aa8b3b8649713398d1b749), the BlackParrot firmware +- [PanicRoom](https://github.com/bespoke-silicon-group/bsg_newlib_dramfs/tree/28b5ac5a75847f346b54a91d4b9b9f58a62b590e), a RISC-V Newlib compiler with support for some system calls and a minimal filesystem. This directory must be placed at the same level as the replicant repository. It is recommended that users clone the Bladerunner meta repository which includes (or will include) the BlackParrot SDK as a submodule [(PR #66)](https://github.com/bespoke-silicon-group/bsg_bladerunner/pull/66) since this will set all the required environment variables correctly. Otherwise users must define the BLACKPARROT_SDK_DIR variable for the given execution environment. From a407e350190830a12bd29e104dfdceafad536a1a Mon Sep 17 00:00:00 2001 From: sripathi_muralitharan Date: Fri, 9 Jul 2021 19:26:25 -0700 Subject: [PATCH 48/70] Add link to TRM --- libraries/platforms/dromajo-vcs/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/platforms/dromajo-vcs/README.md b/libraries/platforms/dromajo-vcs/README.md index 0a5103f0f..1c1f15f6d 100644 --- a/libraries/platforms/dromajo-vcs/README.md +++ b/libraries/platforms/dromajo-vcs/README.md @@ -19,9 +19,9 @@ The [BlackParrot SDK](https://github.com/black-parrot-sdk/black-parrot-sdk) cont This directory must be placed at the same level as the replicant repository. It is recommended that users clone the Bladerunner meta repository which includes (or will include) the BlackParrot SDK as a submodule [(PR #66)](https://github.com/bespoke-silicon-group/bsg_bladerunner/pull/66) since this will set all the required environment variables correctly. Otherwise users must define the BLACKPARROT_SDK_DIR variable for the given execution environment. -## Detailed Technical Manual +## Technical Reference Manual -Coming soon! +Click [here](https://docs.google.com/document/d/1kUtyD3SiXP2qvbUDhtpx_eFufegscQs2cWla3pcxA-Q/edit?usp=sharing) to access the technical reference manual. ## Using the Simulation Infrastructure From 51ed941e93bf1cca72ef2ae40a10e17f6f24b595 Mon Sep 17 00:00:00 2001 From: sripathi-muralitharan Date: Tue, 13 Jul 2021 10:47:28 -0700 Subject: [PATCH 49/70] Qualifying author comments from original comments in this copied library source --- libraries/platforms/dromajo-vcs/software/include/argp.h | 1 + .../platforms/dromajo-vcs/software/src/argp/argp-parse.c | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/libraries/platforms/dromajo-vcs/software/include/argp.h b/libraries/platforms/dromajo-vcs/software/include/argp.h index 49f9173ef..07d864962 100644 --- a/libraries/platforms/dromajo-vcs/software/include/argp.h +++ b/libraries/platforms/dromajo-vcs/software/include/argp.h @@ -513,6 +513,7 @@ extern void *__argp_input (__const struct argp *__restrict __argp, __const struct argp_state *__restrict __state) __THROW; +// Sripathi: // Always define functions in a header file with the static modifier. // Defining functions with "extern inline" in a header file is just wrong. // Switch to using "static inline" to make the function visible wherever diff --git a/libraries/platforms/dromajo-vcs/software/src/argp/argp-parse.c b/libraries/platforms/dromajo-vcs/software/src/argp/argp-parse.c index 3ed553a5d..cd177e556 100644 --- a/libraries/platforms/dromajo-vcs/software/src/argp/argp-parse.c +++ b/libraries/platforms/dromajo-vcs/software/src/argp/argp-parse.c @@ -136,6 +136,7 @@ argp_default_parser (int key, char *arg, struct argp_state *state) case OPT_HANG: _argp_hang = atoi (arg ? arg : "3600"); while (_argp_hang-- > 0) + // Sripathi: // Use a for loop to hang the execution rather than sleep // since it is not implemented // This will consume power but we don't really care since we will @@ -914,12 +915,14 @@ __argp_parse (const struct argp *argp, int argc, char **argv, unsigned flags, to be parsed (which in some cases isn't actually an error). */ int arg_ebadkey = 0; + // Sripathi: // Forward declare the struct pointers since malloc is being used instead of alloca struct argp_child *child; struct argp *top_argp; if (! (flags & ARGP_NO_HELP)) /* Add our own options. */ { + // Sripathi: // Originally alloca was used but since newlib does not implement that // we are switching over to malloc which is a lot slower child = (struct argp_child *) malloc (4 * sizeof (struct argp_child)); @@ -953,6 +956,7 @@ __argp_parse (const struct argp *argp, int argc, char **argv, unsigned flags, err = parser_finalize (&parser, err, arg_ebadkey, end_index); } + // Sripathi: // malloc was used to allocate space for the argp_child and argp structs // alloca automatically freed the memory when the function returned // but since we are using malloc, we need to explicitly free it to From d010cce0abb0b24dc24fb23ce7c4d6eee1aa1405 Mon Sep 17 00:00:00 2001 From: sripathi-muralitharan Date: Tue, 13 Jul 2021 10:51:01 -0700 Subject: [PATCH 50/70] Refactor * New BP-HB platform header * Defining some manycore only EPAs in bsg_manycore_epa.h * Moving platform-specific functions from firmware to platform API file * Adding new HOST coordinate macro and defining them through the simulation flow --- libraries/bsg_manycore_epa.h | 5 + .../platforms/dromajo-vcs/bp_hb_platform.h | 80 ++++++++++ .../dromajo-vcs/bsg_manycore_platform.cpp | 147 ++++++++++++++++-- .../dromajo-vcs/bsg_manycore_simulator.cpp | 28 ++-- .../dromajo-vcs/bsg_manycore_simulator.hpp | 17 +- .../platforms/dromajo-vcs/compilation.mk | 2 +- libraries/platforms/dromajo-vcs/library.mk | 7 +- .../dromajo-vcs/software/include/bp_utils.h | 66 +------- .../platforms/dromajo-vcs/software/src/args.c | 14 +- .../dromajo-vcs/software/src/bp_utils.c | 145 ++--------------- 10 files changed, 263 insertions(+), 248 deletions(-) create mode 100644 libraries/platforms/dromajo-vcs/bp_hb_platform.h diff --git a/libraries/bsg_manycore_epa.h b/libraries/bsg_manycore_epa.h index 8abf94a85..00bdd386a 100644 --- a/libraries/bsg_manycore_epa.h +++ b/libraries/bsg_manycore_epa.h @@ -62,7 +62,12 @@ extern "C" { #define HB_MC_GLOBAL_EPA_LOGSZ 16 #define HB_MC_HOST_EPA_FINISH 0xEAD0 +#define HB_MC_HOST_EPA_TIME 0xEAD4 #define HB_MC_HOST_EPA_FAIL 0xEAD8 +#define HB_MC_HOST_EPA_STDOUT 0xEADC +#define HB_MC_HOST_EPA_STDERR 0xEAE0 +#define HB_MC_HOST_EPA_BRANCH_TRACE 0xEAE4 +#define HB_MC_HOST_EPA_PRINT_STAT 0xEA0C #define EPA_FROM_BASE_AND_OFFSET(base, offset) \ (((base)+(offset))) diff --git a/libraries/platforms/dromajo-vcs/bp_hb_platform.h b/libraries/platforms/dromajo-vcs/bp_hb_platform.h new file mode 100644 index 000000000..9cb865e3c --- /dev/null +++ b/libraries/platforms/dromajo-vcs/bp_hb_platform.h @@ -0,0 +1,80 @@ +// BlackParrot platform-specific header file +// This file contains manycore-specific platform functions and constants + +#ifndef BP_HB_PLATFORM_H +#define BP_HB_PLATFORM_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +// Host X and Y coordinates +#ifndef HOST_X_COORD +#define HOST_X_COORD 15 +#endif + +#ifndef HOST_Y_COORD +#define HOST_Y_COORD 8 +#endif + +// Memory mapped addresses to interact with the BlackParrot host (aka simulator) +#define HB_MC_HOST_EPA_ARGS_START 0x0000 +#define HB_MC_HOST_EPA_ARGS_FINISH 0x00FF +#define HB_MC_HOST_EPA_CONFIG_START 0x0100 +#define HB_MC_HOST_EPA_CONFIG_FINISH 0x01FF +#define HB_MC_HOST_EPA_RESET_DONE 0x0200 +#define HB_MC_HOST_EPA_TX_VACANT 0x0300 + +#define HB_MC_HOST_OP_FINISH_CODE 0xFFFFFFFF +#define DROMAJO_RW_FAIL_CODE 0xFFFFFFFF + +// Memory mapped addresses to interact with the manycore bridge +// BlackParrot currently sets the MSB of its address to 1 to commnicate with the manycore +// Dromajo however is setup to identify the manycore as a device +#define MC_BASE_ADDR 0x500000 +#define BP_TO_MC_REQ_FIFO_ADDR 0x1000 +#define BP_TO_MC_REQ_CREDITS_ADDR 0x2000 +#define MC_TO_BP_RESP_FIFO_ADDR 0x3000 +#define MC_TO_BP_RESP_ENTRIES_ADDR 0x4000 +#define MC_TO_BP_REQ_FIFO_ADDR 0x5000 +#define MC_TO_BP_REQ_ENTRIES_ADDR 0x6000 + +/**************************** Manycore Bridge helper functions ****************************/ +// Use these functions to enable Dromajo/BlackParrot to write to the bridge. These functions +// are undefined and carry no meaning when used by the BlackParrot host (aka simulator) + +/* + * Reads the manycore bridge for number of credits used in the endpoint + * @returns number of credits in the manycore bridge enddpoint + */ +int bp_hb_get_credits_used(int *credits_used); + +/* + * Writes a 128-bit manycore packet in 32-bit chunks to the manycore bridge FIFO + * @param[in] pkt --> Pointer to the manycore packet + */ +int bp_hb_write_to_mc_bridge(hb_mc_packet_t *pkt); + +/* + * Checks if the MC to BP FIFO contains any entries + * @param[in] type --> Type of FIFO to read from + * @returns number of entries in the MC to BP FIFO + */ +int bp_hb_get_fifo_entries(int *entries, hb_mc_fifo_rx_t type); + +/* + * Reads the manycore bridge FIFOs in 32-bit chunks to form the 128-bit packet + * @param[in] pkt --> Pointer to the manycore packet + * @param[in] type --> Type of FIFO to read from + * @returns HB_MC_SUCCESS on success, HB_MC_FAIL if FIFO type is unknown + */ +int bp_hb_read_from_mc_bridge(hb_mc_packet_t *pkt, hb_mc_fifo_rx_t type); + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/libraries/platforms/dromajo-vcs/bsg_manycore_platform.cpp b/libraries/platforms/dromajo-vcs/bsg_manycore_platform.cpp index 515dc7c5e..efc04b0b7 100644 --- a/libraries/platforms/dromajo-vcs/bsg_manycore_platform.cpp +++ b/libraries/platforms/dromajo-vcs/bsg_manycore_platform.cpp @@ -30,8 +30,9 @@ #include #include +#include + #include -#include /* these are convenience macros that are only good for one line prints */ #define manycore_pr_dbg(mc, fmt, ...) \ @@ -46,6 +47,130 @@ #define manycore_pr_info(mc, fmt, ...) \ bsg_pr_info("%s: " fmt, mc->name, ##__VA_ARGS__) +/********************************** BlackParrot platform API **********************************/ + +/* + * Reads the manycore bridge for number of credits used in the endpoint + * @param[in] credits_used --> Pointer to a location in memory that will hold the number of credits used + * @returns HB_MC_SUCCESS + */ +int bp_hb_get_credits_used(int *credits_used) { + uint32_t *bp_to_mc_req_credits_addr = (uint32_t *) (MC_BASE_ADDR + BP_TO_MC_REQ_CREDITS_ADDR); + *credits_used = (int) *bp_to_mc_req_credits_addr; + if (*credits_used < 0) { + bsg_pr_err("Credits used cannot be negative. Credits used = %d", *credits_used); + return HB_MC_FAIL; + } + return HB_MC_SUCCESS; +} + +/* + * Writes a 128-bit manycore packet in 32-bit chunks to the manycore bridge FIFO + * @param[in] pkt --> Pointer to the manycore packet + * @returns HB_MC_SUCCESS + * TODO: Implement error checking (Requires some modifications in Dromajo) + */ +int bp_hb_write_to_mc_bridge(hb_mc_packet_t *pkt) { + uint32_t *bp_to_mc_req_fifo_addr = (uint32_t *) (MC_BASE_ADDR + BP_TO_MC_REQ_FIFO_ADDR); + for(int i = 0; i < 4; i++) { + *bp_to_mc_req_fifo_addr = pkt->words[i]; + bp_to_mc_req_fifo_addr++; + } + return HB_MC_SUCCESS; +} + +/* + * Checks if the MC to BP FIFO contains any valid elements to be read + * @param[in] entries --> Pointer to a location in memory that will hold the number of entries + * @param[in] type --> Type of FIFO to read from + * @returns HB_MC_SUCCESS on success or HB_MC_FAIL on fail + */ +int bp_hb_get_fifo_entries(int *entries, hb_mc_fifo_rx_t type) { + switch (type) { + case HB_MC_FIFO_RX_REQ: + { + uint32_t *mc_to_bp_req_fifo_entries_addr = (uint32_t *) (MC_BASE_ADDR + MC_TO_BP_REQ_ENTRIES_ADDR); + *entries = *mc_to_bp_req_fifo_entries_addr; + if (*entries < 0) { + bsg_pr_err("Entries occupied cannot be negative. Entries = %d", *entries); + return HB_MC_FAIL; + } + } + break; + case HB_MC_FIFO_RX_RSP: + { + uint32_t *mc_to_bp_resp_fifo_entries_addr = (uint32_t *) (MC_BASE_ADDR + MC_TO_BP_RESP_ENTRIES_ADDR); + *entries = *mc_to_bp_resp_fifo_entries_addr; + if (*entries < 0) { + bsg_pr_err("Entries occupied cannot be negative. Entries = %d", *entries); + return HB_MC_FAIL; + } + } + break; + default: + { + bsg_pr_err("%s: Unknown packet type\n", __func__); + return HB_MC_FAIL; + } + break; + } + return HB_MC_SUCCESS; +} + +/* + * Reads the manycore bridge FIFOs in 32-bit chunks to form the 128-bit packet + * @param[in] pkt --> Pointer to the manycore packet + * @param[in] type --> Type of FIFO to read from + * @returns HB_MC_SUCCESS on success, HB_MC_FAIL if FIFO type is unknown + */ +int bp_hb_read_from_mc_bridge(hb_mc_packet_t *pkt, hb_mc_fifo_rx_t type) { + switch(type) { + case HB_MC_FIFO_RX_REQ: + { + uint32_t *mc_to_bp_req_fifo_addr = (uint32_t *) (MC_BASE_ADDR + MC_TO_BP_REQ_FIFO_ADDR); + uint32_t fifo_read_status = DROMAJO_RW_FAIL_CODE; + do { + for (int i = 0; i < 4; i++) { + pkt->words[i] = *mc_to_bp_req_fifo_addr; + fifo_read_status &= pkt->words[i]; + mc_to_bp_req_fifo_addr++; + } + } while (fifo_read_status == DROMAJO_RW_FAIL_CODE); + + // There is something wrong if the read status is equal to the FAIL code + if (fifo_read_status == DROMAJO_RW_FAIL_CODE) + return HB_MC_FAIL; + } + break; + case HB_MC_FIFO_RX_RSP: + { + uint32_t *mc_to_bp_resp_fifo_addr = (uint32_t *) (MC_BASE_ADDR + MC_TO_BP_RESP_FIFO_ADDR); + uint32_t fifo_read_status = DROMAJO_RW_FAIL_CODE; + do { + for (int i = 0; i < 4; i++) { + pkt->words[i] = *mc_to_bp_resp_fifo_addr; + fifo_read_status &= pkt->words[i]; + mc_to_bp_resp_fifo_addr++; + } + } while(fifo_read_status == DROMAJO_RW_FAIL_CODE); + + // There is something wrong if the read status is equal to the FAIL code + if (fifo_read_status == DROMAJO_RW_FAIL_CODE) + return HB_MC_FAIL; + } + break; + default: + { + bsg_pr_err("%s: Unknown packet type\n", __func__); + return HB_MC_FAIL; + } + break; + } + return HB_MC_SUCCESS; +} + +/********************************** Manycore platform API **********************************/ + typedef struct hb_mc_platform_t { hb_mc_manycore_id_t id; @@ -201,14 +326,14 @@ int hb_mc_platform_get_config_at(hb_mc_manycore_t *mc, unsigned int idx, hb_mc_c if (idx < HB_MC_CONFIG_MAX) { - config_req_pkt.request.x_dst = (0 << 4) | 0; - config_req_pkt.request.y_dst = (1 << 3) | 0; + config_req_pkt.request.x_dst = HOST_X_COORD; + config_req_pkt.request.y_dst = HOST_Y_COORD; config_req_pkt.request.x_src = (0 << 4) | 0; config_req_pkt.request.y_src = (1 << 3) | 1; config_req_pkt.request.op_v2 = HB_MC_PACKET_OP_REMOTE_LOAD; config_req_pkt.request.payload = 0; config_req_pkt.request.reg_id = 0; - config_req_pkt.request.addr = MC_CONFIG_START_EPA_ADDR + idx; + config_req_pkt.request.addr = HB_MC_HOST_EPA_CONFIG_START + idx; // Note: Potentially dangerous to write to the FIFO without checking for credits // We get back credits used and not credits remaining and without the configuration @@ -230,7 +355,7 @@ int hb_mc_platform_get_config_at(hb_mc_manycore_t *mc, unsigned int idx, hb_mc_c } uint32_t data = config_resp_pkt.response.data; - *config = (data != MC_HOST_OP_FINISH_CODE) ? data : 0; + *config = (data != HB_MC_HOST_OP_FINISH_CODE) ? data : 0; return HB_MC_SUCCESS; } @@ -258,14 +383,14 @@ int hb_mc_platform_fence(hb_mc_manycore_t *mc, long timeout) { } // Prepare host packet to query TX vacancy - fence_req_pkt.request.x_dst = (0 << 4) | 0; - fence_req_pkt.request.y_dst = (1 << 3) | 0; + fence_req_pkt.request.x_dst = HOST_X_COORD; + fence_req_pkt.request.y_dst = HOST_Y_COORD; fence_req_pkt.request.x_src = (0 << 4) | 0; fence_req_pkt.request.y_src = (1 << 3) | 1; fence_req_pkt.request.op_v2 = HB_MC_PACKET_OP_REMOTE_LOAD; fence_req_pkt.request.payload = 0; fence_req_pkt.request.reg_id = 0; - fence_req_pkt.request.addr = MC_TX_VACANT_EPA_ADDR; // x86 Host address to poll tx vacancy + fence_req_pkt.request.addr = HB_MC_HOST_EPA_TX_VACANT; // x86 Host address to poll tx vacancy do { @@ -371,14 +496,14 @@ int hb_mc_platform_wait_reset_done(hb_mc_manycore_t *mc) { int err; uint32_t data = 0; - reset_req_pkt.request.x_dst = (0 << 4) | 0; - reset_req_pkt.request.y_dst = (1 << 3) | 0; + reset_req_pkt.request.x_dst = HOST_X_COORD; + reset_req_pkt.request.y_dst = HOST_Y_COORD; reset_req_pkt.request.x_src = (0 << 4) | 0; reset_req_pkt.request.y_src = (1 << 3) | 1; reset_req_pkt.request.op_v2 = HB_MC_PACKET_OP_REMOTE_LOAD; reset_req_pkt.request.payload = 0; reset_req_pkt.request.reg_id = 0; - reset_req_pkt.request.addr = MC_RESET_DONE_EPA_ADDR; + reset_req_pkt.request.addr = HB_MC_HOST_EPA_RESET_DONE; do { // The platform setup ensures that this packet will not go over the network so diff --git a/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.cpp b/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.cpp index a7774dac5..5cc8e5254 100644 --- a/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.cpp +++ b/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.cpp @@ -196,7 +196,6 @@ int SimulationWrapper::dromajo_init() { * @returns true if execution is incomplete and/or without errors */ bool SimulationWrapper::dromajo_step() { - // Execute dromajo with verbose mode on int err = dromajo_cosim_step(dromajo, 0, 0, 0, 0, 0, false, false); return (err != 0) ? false : true; } @@ -224,7 +223,8 @@ int SimulationWrapper::dromajo_transmit_packet() { dromajo_to_mc_packet.words[3] = host_to_mc_req_fifo->fifo[3].front(); // Intercept packets that are for the host and generate appropriate responses - if ((dromajo_to_mc_packet.request.x_dst == ((0 << 4) | 0)) && (dromajo_to_mc_packet.request.y_dst == ((1 << 3) | 0))) { + // TODO: Currently, these packets don't go over the network. They should + if ((dromajo_to_mc_packet.request.x_dst == HOST_X_COORD) && (dromajo_to_mc_packet.request.y_dst == HOST_Y_COORD)) { host_to_dromajo_packet.response.x_dst = dromajo_to_mc_packet.request.x_src; host_to_dromajo_packet.response.y_dst = dromajo_to_mc_packet.request.y_src; host_to_dromajo_packet.response.load_id = 0; @@ -236,9 +236,9 @@ int SimulationWrapper::dromajo_transmit_packet() { // Fixme: Is there no struct for response opcode like in the manycore hardware host_to_dromajo_packet.response.op = dromajo_to_mc_packet.request.op_v2; switch (dromajo_to_mc_packet.request.addr) { - case MC_ARGS_START_EPA_ADDR ... MC_ARGS_FINISH_EPA_ADDR: + case HB_MC_HOST_EPA_ARGS_START ... HB_MC_HOST_EPA_ARGS_FINISH: { - uint32_t idx = dromajo_to_mc_packet.request.addr - MC_ARGS_START_EPA_ADDR; + uint32_t idx = dromajo_to_mc_packet.request.addr - HB_MC_HOST_EPA_ARGS_START; int num_characters = 0; // If all arguments have been read or there are no arguments to read // send a finish code @@ -257,23 +257,23 @@ int SimulationWrapper::dromajo_transmit_packet() { } } else - data = MC_HOST_OP_FINISH_CODE; + data = HB_MC_HOST_OP_FINISH_CODE; } break; - case MC_CONFIG_START_EPA_ADDR ... MC_CONFIG_FINISH_EPA_ADDR: + case HB_MC_HOST_EPA_CONFIG_START ... HB_MC_HOST_EPA_CONFIG_FINISH: { - uint32_t idx = dromajo_to_mc_packet.request.addr - MC_CONFIG_START_EPA_ADDR; - data = (idx <= HB_MC_CONFIG_MAX) ? dpi->config[idx] : MC_HOST_OP_FINISH_CODE; + uint32_t idx = dromajo_to_mc_packet.request.addr - HB_MC_HOST_EPA_CONFIG_START; + data = (idx <= HB_MC_CONFIG_MAX) ? dpi->config[idx] : HB_MC_HOST_OP_FINISH_CODE; } break; - case MC_RESET_DONE_EPA_ADDR: + case HB_MC_HOST_EPA_RESET_DONE: { bool done; dpi->reset_is_done(done); data = done ? 1 : 0; } break; - case MC_TX_VACANT_EPA_ADDR: + case HB_MC_HOST_EPA_TX_VACANT: { bool is_vacant; dpi->tx_is_vacant(is_vacant); @@ -297,14 +297,14 @@ int SimulationWrapper::dromajo_transmit_packet() { case HB_MC_PACKET_OP_REMOTE_SW: { switch (dromajo_to_mc_packet.request.addr) { - case MC_STDOUT_EPA_ADDR: - case MC_STDERR_EPA_ADDR: + case HB_MC_HOST_EPA_STDOUT: + case HB_MC_HOST_EPA_STDERR: { printf("%c", (uint8_t) dromajo_to_mc_packet.request.payload); fflush(stdout); } break; - case MC_FINISH_EPA_ADDR: + case HB_MC_HOST_EPA_FINISH: { int16_t core_id = dromajo_to_mc_packet.request.payload >> 16; // Success error codes in BP is 0, but 0 is already used by the manycore. Any positive number indicates @@ -317,7 +317,7 @@ int SimulationWrapper::dromajo_transmit_packet() { return err; } break; - case MC_FAIL_EPA_ADDR: + case HB_MC_HOST_EPA_FAIL: { int16_t core_id = dromajo_to_mc_packet.request.payload >> 16; int16_t err = 0x0000FFFF & dromajo_to_mc_packet.request.payload; diff --git a/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.hpp b/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.hpp index 9908b8924..09529db1d 100644 --- a/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.hpp +++ b/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.hpp @@ -53,27 +53,14 @@ #include +#include + // Define invisible library functions declare_hb_mc_get_bits declare_bsg_printing #define NUM_DROMAJO_INSTR_PER_TICK 1000 -#define MC_ARGS_START_EPA_ADDR 0x0000 -#define MC_ARGS_FINISH_EPA_ADDR 0x00FF -#define MC_CONFIG_START_EPA_ADDR 0x0100 -#define MC_CONFIG_FINISH_EPA_ADDR 0x01FF -#define MC_RESET_DONE_EPA_ADDR 0x0200 -#define MC_TX_VACANT_EPA_ADDR 0x0300 -#define MC_FINISH_EPA_ADDR 0xEAD0 -#define MC_TIME_EPA_ADDR 0xEAD4 -#define MC_FAIL_EPA_ADDR 0xEAD8 -#define MC_STDOUT_EPA_ADDR 0xEADC -#define MC_STDERR_EPA_ADDR 0xEAE0 -#define MC_BRANCH_TRACE_EPA_ADDR 0xEAE4 -#define MC_PRINT_STAT_EPA_ADDR 0xEA0C -#define MC_HOST_OP_FINISH_CODE 0xFFFFFFFF - class SimulationWrapper{ // This is the generic pointer for implementation-specific // simulator details. In Verilator, this is diff --git a/libraries/platforms/dromajo-vcs/compilation.mk b/libraries/platforms/dromajo-vcs/compilation.mk index f00b5ddc4..d7b6bb245 100644 --- a/libraries/platforms/dromajo-vcs/compilation.mk +++ b/libraries/platforms/dromajo-vcs/compilation.mk @@ -35,7 +35,7 @@ NC=\033[0m # This file REQUIRES several variables to be set. They are typically # set by the Makefile that includes this makefile.. # -DEFINES += -D_DRAMFS +DEFINES += -D_DRAMFS -DHOST_X_COORD=$(BSG_MACHINE_HOST_COORD_X) -DHOST_Y_COORD=$(BSG_MACHINE_HOST_COORD_Y) INCLUDES += -I$(LIBRARIES_PATH) INCLUDES += -I$(BSG_PLATFORM_PATH) INCLUDES += -I$(BSG_PLATFORM_PATH)/software/include diff --git a/libraries/platforms/dromajo-vcs/library.mk b/libraries/platforms/dromajo-vcs/library.mk index 59bc64b3b..fb582cb51 100644 --- a/libraries/platforms/dromajo-vcs/library.mk +++ b/libraries/platforms/dromajo-vcs/library.mk @@ -66,7 +66,8 @@ $(DMA_FEATURE_OBJECTS): CFLAGS += -march=rv64imafd -mcmodel=medany -mabi=lp64 -D $(DMA_FEATURE_OBJECTS): CXXFLAGS += -march=rv64imafd -mcmodel=medany -mabi=lp64 -D_BSD_SOURCE -D_XOPEN_SOURCE=500 # Add the riscv-newlib specific includes for the library -LIB_PLATFORM_INCLUDES = -I$(BSG_PLATFORM_PATH)/software/include +LIB_PLATFORM_INCLUDES = -I$(BSG_PLATFORM_PATH) +LIB_PLATFORM_INCLUDES += -I$(BSG_PLATFORM_PATH)/software/include LIB_PLATFORM_INCLUDES += -I$(BLACKPARROT_SDK_DIR)/perch $(LIB_OBJECTS) $(LIB_OBJECTS_CUDA_POD_REPL) $(LIB_OBJECTS_REGRESSION): CC = $(RV_CC) @@ -128,8 +129,8 @@ $(PLATFORM_OBJECTS): INCLUDES += -I$(VCS_HOME)/linux64/lib/ $(PLATFORM_OBJECTS): INCLUDES += -I$(BSG_MANYCORE_DIR)/testbenches/dpi/ $(PLATFORM_OBJECTS): INCLUDES += -I$(BASEJUMP_STL_DIR)/bsg_test/ $(PLATFORM_OBJECTS): INCLUDES += -I$(BLACKPARROT_SDK_DIR)/dromajo/include -$(PLATFORM_OBJECTS): CFLAGS := -std=c11 -fPIC -DVCS -D_GNU_SOURCE -DVERILATOR -D_BSD_SOURCE -D_XOPEN_SOURCE=500 -$(PLATFORM_OBJECTS): CXXFLAGS := -std=c++11 -fPIC -DVCS -D_GNU_SOURCE -DVERILATOR -D_BSD_SOURCE -D_XOPEN_SOURCE=500 +$(PLATFORM_OBJECTS): CFLAGS := -std=c11 -fPIC -DVCS -D_GNU_SOURCE -DVERILATOR -D_BSD_SOURCE -D_XOPEN_SOURCE=500 -DHOST_X_COORD=$(BSG_MACHINE_HOST_COORD_X) -DHOST_Y_COORD=$(BSG_MACHINE_HOST_COORD_Y) +$(PLATFORM_OBJECTS): CXXFLAGS := -std=c++11 -fPIC -DVCS -D_GNU_SOURCE -DVERILATOR -D_BSD_SOURCE -D_XOPEN_SOURCE=500 -DHOST_X_COORD=$(BSG_MACHINE_HOST_COORD_X) -DHOST_Y_COORD=$(BSG_MACHINE_HOST_COORD_Y) $(PLATFORM_OBJECTS): LDFLAGS := -fPIC $(PLATFORM_OBJECTS): CXX = g++ diff --git a/libraries/platforms/dromajo-vcs/software/include/bp_utils.h b/libraries/platforms/dromajo-vcs/software/include/bp_utils.h index 1e79ae0e0..e6890506c 100644 --- a/libraries/platforms/dromajo-vcs/software/include/bp_utils.h +++ b/libraries/platforms/dromajo-vcs/software/include/bp_utils.h @@ -1,7 +1,6 @@ // BlackParrot utilities header file -// Note: This file is included here instead of the existing code -// in the perch library in order to allow for easy changes to the finish code -// in the future +// Commonly used BlackParrot functions with modifications for +// the manycore platform #ifndef BP_UTILS_H #define BP_UTILS_H @@ -12,75 +11,18 @@ extern "C" { #include #include -#include - -// Memory mapped addresses to interact with the host -#define MC_ARGS_START_EPA_ADDR 0x0000 -#define MC_ARGS_FINISH_EPA_ADDR 0x00FF -#define MC_CONFIG_START_EPA_ADDR 0x0100 -#define MC_CONFIG_FINISH_EPA_ADDR 0x01FF -#define MC_RESET_DONE_EPA_ADDR 0x0200 -#define MC_TX_VACANT_EPA_ADDR 0x0300 -#define MC_FINISH_EPA_ADDR 0xEAD0 -#define MC_TIME_EPA_ADDR 0xEAD4 -#define MC_FAIL_EPA_ADDR 0xEAD8 -#define MC_STDOUT_EPA_ADDR 0xEADC -#define MC_STDERR_EPA_ADDR 0xEAE0 -#define MC_BRANCH_TRACE_EPA_ADDR 0xEAE4 -#define MC_PRINT_STAT_EPA_ADDR 0xEA0C - -#define MC_HOST_OP_FINISH_CODE 0xFFFFFFFF -#define DROMAJO_RW_FAIL_CODE 0xFFFFFFFF - -// Memory mapped addresses to interact with the manycore bridge -// BlackParrot actually sets the MSB of its address to 1 to commnicate with the manycore -// Dromajo however is setup to identify the manycore as a device -#define MC_BASE_ADDR 0x500000 -#define BP_TO_MC_REQ_FIFO_ADDR 0x1000 -#define BP_TO_MC_REQ_CREDITS_ADDR 0x2000 -#define MC_TO_BP_RESP_FIFO_ADDR 0x3000 -#define MC_TO_BP_RESP_ENTRIES_ADDR 0x4000 -#define MC_TO_BP_REQ_FIFO_ADDR 0x5000 -#define MC_TO_BP_REQ_ENTRIES_ADDR 0x6000 +#include #define BP_CFG_BASE_ADDR 0x00200000 -// Manycore Bridge helper functions -/* - * Reads the manycore bridge for number of credits used in the endpoint - * @returns number of credits in the manycore bridge enddpoint - */ -int bp_hb_get_credits_used(int *credits_used); - -/* - * Writes a 128-bit manycore packet in 32-bit chunks to the manycore bridge FIFO - * @param[in] pkt --> Pointer to the manycore packet - */ -int bp_hb_write_to_mc_bridge(hb_mc_packet_t *pkt); +/**************************** BlackParrot helper functions ****************************/ -/* - * Checks if the MC to BP FIFO contains any entries - * @param[in] type --> Type of FIFO to read from - * @returns number of entries in the MC to BP FIFO - */ -int bp_hb_get_fifo_entries(int *entries, hb_mc_fifo_rx_t type); - -/* - * Reads the manycore bridge FIFOs in 32-bit chunks to form the 128-bit packet - * @param[in] pkt --> Pointer to the manycore packet - * @param[in] type --> Type of FIFO to read from - * @returns HB_MC_SUCCESS on success, HB_MC_FAIL if FIFO type is unknown - */ -int bp_hb_read_from_mc_bridge(hb_mc_packet_t *pkt, hb_mc_fifo_rx_t type); - -// BlackParrot helper functions /* * Get hardware thread ID * @returns result of reading the mhartid register */ uint64_t bp_get_hart(); - /* * Checks to see if a barrier is finished * @param[in] barrier_address --> An address in memory that all cores to write to after hitting the barrier diff --git a/libraries/platforms/dromajo-vcs/software/src/args.c b/libraries/platforms/dromajo-vcs/software/src/args.c index f1821bfc6..a3c52a95a 100644 --- a/libraries/platforms/dromajo-vcs/software/src/args.c +++ b/libraries/platforms/dromajo-vcs/software/src/args.c @@ -4,15 +4,14 @@ * loads them into corresponding registers so that BlackParrot can access them */ -#include +#include #include #include -#include #include // Number of arguments that can be retrieved is currently based on the size of the buffer. // Other ideas (TODO): -// 1. Create pointers to locations of arguments on the stack (traditional, preferred method) +// 1. Create pointers to locations of arguments on the stack (traditional method) // 2. Flush the argument buffer periodically int _argc; char **_argv; @@ -31,10 +30,9 @@ void __init_args(void) { char *bufptr = buffer; // Create a packet for the x86 host - // Host is at POD (X, Y) = (0, 1), SUBCOORD (X, Y) = (0, 0) // BlackParrot FIFO interface is at POD (X, Y) = (0, 1), SUBCOORD (X, Y) = (0, 1) - args_req_pkt.request.x_dst = (0 << 4) | 0; - args_req_pkt.request.y_dst = (1 << 3) | 0; + args_req_pkt.request.x_dst = HOST_X_COORD; + args_req_pkt.request.y_dst = HOST_Y_COORD; args_req_pkt.request.x_src = (0 << 4) | 0; args_req_pkt.request.y_src = (1 << 3) | 1; args_req_pkt.request.op_v2 = HB_MC_PACKET_OP_REMOTE_LOAD; @@ -45,14 +43,14 @@ void __init_args(void) { // The platform setup in simulation ensures that this packet will not go over the network so // we don't need to check for credits. Also, this code is executed before the CUDA-lite // program starts. - args_req_pkt.request.addr = MC_ARGS_START_EPA_ADDR + arg_index; + args_req_pkt.request.addr = HB_MC_HOST_EPA_ARGS_START + arg_index; err = bp_hb_write_to_mc_bridge(&args_req_pkt); err = bp_hb_read_from_mc_bridge(&args_resp_pkt, HB_MC_FIFO_RX_RSP); if (err != HB_MC_SUCCESS) bp_finish(err); uint32_t data = args_resp_pkt.response.data; - if (data != MC_HOST_OP_FINISH_CODE) { + if (data != HB_MC_HOST_OP_FINISH_CODE) { uint32_t mask = 0xFF000000; uint8_t byte; for(int i = 0; i < 4; i++) { diff --git a/libraries/platforms/dromajo-vcs/software/src/bp_utils.c b/libraries/platforms/dromajo-vcs/software/src/bp_utils.c index 731b2e9d9..a3a6cac03 100644 --- a/libraries/platforms/dromajo-vcs/software/src/bp_utils.c +++ b/libraries/platforms/dromajo-vcs/software/src/bp_utils.c @@ -1,130 +1,7 @@ -// BlackParrot utilities -// Compile this file instead of the existing one in the BlackParrot firmware +// BlackParrot utilities' definitions #include #include -#include -#include - -/* - * Reads the manycore bridge for number of credits used in the endpoint - * @param[in] credits_used --> Pointer to a location in memory that will hold the number of credits used - * @returns HB_MC_SUCCESS - */ -int bp_hb_get_credits_used(int *credits_used) { - uint32_t *bp_to_mc_req_credits_addr = (uint32_t *) (MC_BASE_ADDR + BP_TO_MC_REQ_CREDITS_ADDR); - *credits_used = (int) *bp_to_mc_req_credits_addr; - if (*credits_used < 0) { - bsg_pr_err("Credits used cannot be negative. Credits used = %d", *credits_used); - return HB_MC_FAIL; - } - return HB_MC_SUCCESS; -} - -/* - * Writes a 128-bit manycore packet in 32-bit chunks to the manycore bridge FIFO - * @param[in] pkt --> Pointer to the manycore packet - * @returns HB_MC_SUCCESS - * TODO: Implement error checking (Requires some modifications in Dromajo) - */ -int bp_hb_write_to_mc_bridge(hb_mc_packet_t *pkt) { - uint32_t *bp_to_mc_req_fifo_addr = (uint32_t *) (MC_BASE_ADDR + BP_TO_MC_REQ_FIFO_ADDR); - for(int i = 0; i < 4; i++) { - *bp_to_mc_req_fifo_addr = pkt->words[i]; - bp_to_mc_req_fifo_addr++; - } - return HB_MC_SUCCESS; -} - -/* - * Checks if the MC to BP FIFO contains any valid elements to be read - * @param[in] entries --> Pointer to a location in memory that will hold the number of entries - * @param[in] type --> Type of FIFO to read from - * @returns HB_MC_SUCCESS on success or HB_MC_FAIL on fail - */ -int bp_hb_get_fifo_entries(int *entries, hb_mc_fifo_rx_t type) { - switch (type) { - case HB_MC_FIFO_RX_REQ: - { - uint32_t *mc_to_bp_req_fifo_entries_addr = (uint32_t *) (MC_BASE_ADDR + MC_TO_BP_REQ_ENTRIES_ADDR); - *entries = *mc_to_bp_req_fifo_entries_addr; - if (*entries < 0) { - bsg_pr_err("Entries occupied cannot be negative. Entries = %d", *entries); - return HB_MC_FAIL; - } - } - break; - case HB_MC_FIFO_RX_RSP: - { - uint32_t *mc_to_bp_resp_fifo_entries_addr = (uint32_t *) (MC_BASE_ADDR + MC_TO_BP_RESP_ENTRIES_ADDR); - *entries = *mc_to_bp_resp_fifo_entries_addr; - if (*entries < 0) { - bsg_pr_err("Entries occupied cannot be negative. Entries = %d", *entries); - return HB_MC_FAIL; - } - } - break; - default: - { - bsg_pr_err("%s: Unknown packet type\n", __func__); - return HB_MC_FAIL; - } - break; - } - return HB_MC_SUCCESS; -} - -/* - * Reads the manycore bridge FIFOs in 32-bit chunks to form the 128-bit packet - * @param[in] pkt --> Pointer to the manycore packet - * @param[in] type --> Type of FIFO to read from - * @returns HB_MC_SUCCESS on success, HB_MC_FAIL if FIFO type is unknown - */ -int bp_hb_read_from_mc_bridge(hb_mc_packet_t *pkt, hb_mc_fifo_rx_t type) { - switch(type) { - case HB_MC_FIFO_RX_REQ: - { - uint32_t *mc_to_bp_req_fifo_addr = (uint32_t *) (MC_BASE_ADDR + MC_TO_BP_REQ_FIFO_ADDR); - uint32_t fifo_read_status = DROMAJO_RW_FAIL_CODE; - do { - for (int i = 0; i < 4; i++) { - pkt->words[i] = *mc_to_bp_req_fifo_addr; - fifo_read_status &= pkt->words[i]; - mc_to_bp_req_fifo_addr++; - } - } while (fifo_read_status == DROMAJO_RW_FAIL_CODE); - - // There is something wrong if the read status is equal to the FAIL code - if (fifo_read_status == DROMAJO_RW_FAIL_CODE) - return HB_MC_FAIL; - } - break; - case HB_MC_FIFO_RX_RSP: - { - uint32_t *mc_to_bp_resp_fifo_addr = (uint32_t *) (MC_BASE_ADDR + MC_TO_BP_RESP_FIFO_ADDR); - uint32_t fifo_read_status = DROMAJO_RW_FAIL_CODE; - do { - for (int i = 0; i < 4; i++) { - pkt->words[i] = *mc_to_bp_resp_fifo_addr; - fifo_read_status &= pkt->words[i]; - mc_to_bp_resp_fifo_addr++; - } - } while(fifo_read_status == DROMAJO_RW_FAIL_CODE); - - // There is something wrong if the read status is equal to the FAIL code - if (fifo_read_status == DROMAJO_RW_FAIL_CODE) - return HB_MC_FAIL; - } - break; - default: - { - bsg_pr_err("%s: Unknown packet type\n", __func__); - return HB_MC_FAIL; - } - break; - } - return HB_MC_SUCCESS; -} /* * Get hardware thread ID @@ -186,17 +63,17 @@ void bp_finish(int16_t code) { // zero --> success code // nonzero --> fail code hb_mc_packet_t finish_pkt; - finish_pkt.request.x_dst = (0 << 4) | 0; - finish_pkt.request.y_dst = (1 << 3) | 0; + finish_pkt.request.x_dst = HOST_X_COORD; + finish_pkt.request.y_dst = HOST_Y_COORD; finish_pkt.request.x_src = (0 << 4) | 0; finish_pkt.request.y_src = (1 << 3) | 1; finish_pkt.request.op_v2 = HB_MC_PACKET_OP_REMOTE_SW; finish_pkt.request.payload = (core_id << 16) | (0x0000FFFF & code); finish_pkt.request.reg_id = 0; if (code >= 0) - finish_pkt.request.addr = MC_FINISH_EPA_ADDR; + finish_pkt.request.addr = HB_MC_HOST_EPA_FINISH; else - finish_pkt.request.addr = MC_FAIL_EPA_ADDR; + finish_pkt.request.addr = HB_MC_HOST_EPA_FAIL; int err; do { @@ -211,14 +88,14 @@ void bp_finish(int16_t code) { void bp_hprint(uint8_t hex) { hb_mc_packet_t hprint_pkt; - hprint_pkt.request.x_dst = (0 << 4) | 0; - hprint_pkt.request.y_dst = (1 << 3) | 0; + hprint_pkt.request.x_dst = HOST_X_COORD; + hprint_pkt.request.y_dst = HOST_Y_COORD; hprint_pkt.request.x_src = (0 << 4) | 0; hprint_pkt.request.y_src = (1 << 3) | 1; hprint_pkt.request.op_v2 = HB_MC_PACKET_OP_REMOTE_SW; hprint_pkt.request.payload = ('0' + hex); hprint_pkt.request.reg_id = 0; - hprint_pkt.request.addr = MC_STDOUT_EPA_ADDR; + hprint_pkt.request.addr = HB_MC_HOST_EPA_STDOUT; int err = bp_hb_write_to_mc_bridge(&hprint_pkt); } @@ -230,14 +107,14 @@ void bp_hprint(uint8_t hex) { void bp_cprint(uint8_t ch) { hb_mc_packet_t cprint_pkt; - cprint_pkt.request.x_dst = (0 << 4) | 0; - cprint_pkt.request.y_dst = (1 << 3) | 0; + cprint_pkt.request.x_dst = HOST_X_COORD; + cprint_pkt.request.y_dst = HOST_Y_COORD; cprint_pkt.request.x_src = (0 << 4) | 0; cprint_pkt.request.y_src = (1 << 3) | 1; cprint_pkt.request.op_v2 = HB_MC_PACKET_OP_REMOTE_SW; cprint_pkt.request.payload = ch; cprint_pkt.request.reg_id = 0; - cprint_pkt.request.addr = MC_STDOUT_EPA_ADDR; + cprint_pkt.request.addr = HB_MC_HOST_EPA_STDOUT; int err = bp_hb_write_to_mc_bridge(&cprint_pkt); } From 157585c0b4c754d463987221e3ec503cfeeeed92 Mon Sep 17 00:00:00 2001 From: sripathi-muralitharan Date: Tue, 13 Jul 2021 11:01:59 -0700 Subject: [PATCH 51/70] Getting rid of git merge artifacts --- libraries/libraries.mk | 4 ---- 1 file changed, 4 deletions(-) diff --git a/libraries/libraries.mk b/libraries/libraries.mk index efeca9d9e..d05adc5f8 100644 --- a/libraries/libraries.mk +++ b/libraries/libraries.mk @@ -120,10 +120,6 @@ $(LIB_OBJECTS) $(LIB_OBJECTS_CUDA_POD_REPL) $(LIB_OBJECTS_REGRESSION): INCLUDES $(LIB_OBJECTS) $(LIB_OBJECTS_CUDA_POD_REPL) $(LIB_OBJECTS_REGRESSION): INCLUDES += -I$(BSG_PLATFORM_PATH) $(LIB_OBJECTS) $(LIB_OBJECTS_CUDA_POD_REPL) $(LIB_OBJECTS_REGRESSION): INCLUDES += $(LIB_PLATFORM_INCLUDES) -$(LIB_OBJECTS) $(LIB_OBJECTS_CUDA_POD_REPL) $(LIB_OBJECTS_REGRESSION): CFLAGS += -std=c11 -fPIC $(INCLUDES) -D_GNU_SOURCE -D_BSD_SOURCE -D_DEFAULT_SOURCE -$(LIB_OBJECTS) $(LIB_OBJECTS_CUDA_POD_REPL) $(LIB_OBJECTS_REGRESSION): CXXFLAGS += -std=c++11 -fPIC $(INCLUDES) -D_GNU_SOURCE -D_BSD_SOURCE -D_DEFAULT_SOURCE -# We should move this from AWS (and keep the license) -$(LIB_OBJECTS) $(LIB_OBJECTS_CUDA_POD_REPL) $(LIB_OBJECTS_REGRESSION): INCLUDES += -I$(AWS_FPGA_REPO_DIR)/SDAccel/userspace/include $(LIB_OBJECTS) $(LIB_OBJECTS_CUDA_POD_REPL) $(LIB_OBJECTS_REGRESSION): CFLAGS += -O3 -std=c11 -fPIC -D_GNU_SOURCE -D_BSD_SOURCE -D_DEFAULT_SOURCE $(LIB_OBJECTS) $(LIB_OBJECTS_CUDA_POD_REPL) $(LIB_OBJECTS_REGRESSION): CXXFLAGS += -O3 -std=c++11 -fPIC -D_GNU_SOURCE -D_BSD_SOURCE -D_DEFAULT_SOURCE # Need to move this, eventually From 5b7e038234e96c10c261b64777548d689b55a4c0 Mon Sep 17 00:00:00 2001 From: sripathi-muralitharan Date: Tue, 13 Jul 2021 13:52:13 -0700 Subject: [PATCH 52/70] Add BlackParrot coordinates --- libraries/platforms/dromajo-vcs/bp_hb_platform.h | 16 ++++++++++++++++ .../dromajo-vcs/bsg_manycore_platform.cpp | 12 ++++++------ .../platforms/dromajo-vcs/software/src/args.c | 4 ++-- .../dromajo-vcs/software/src/bp_utils.c | 12 ++++++------ 4 files changed, 30 insertions(+), 14 deletions(-) diff --git a/libraries/platforms/dromajo-vcs/bp_hb_platform.h b/libraries/platforms/dromajo-vcs/bp_hb_platform.h index 9cb865e3c..01c534d42 100644 --- a/libraries/platforms/dromajo-vcs/bp_hb_platform.h +++ b/libraries/platforms/dromajo-vcs/bp_hb_platform.h @@ -20,6 +20,22 @@ extern "C" { #define HOST_Y_COORD 8 #endif +// BlackParrot coordinates +// Note: Currently not all of these coordinates are in use +// but might be useful during BlackParrot integration +#ifndef BP_COORDS +#define BP_POD_X 0 +#define BP_POD_Y 1 +// Coordinates of BP-HB bridge used for manycore communication +#define BP_HOST_LINK_X 15 +#define BP_HOST_LINK_Y 9 +// Coordinates of BP-HB bridge used for DRAM loads and stores +#define BP_DRAM_0_LINK_X 15 +#define BP_DRAM_0_LINK_Y 10 +#define BP_DRAM_1_LINK_X 15 +#define BP_DRAM_1_LINK_Y 11 +#endif + // Memory mapped addresses to interact with the BlackParrot host (aka simulator) #define HB_MC_HOST_EPA_ARGS_START 0x0000 #define HB_MC_HOST_EPA_ARGS_FINISH 0x00FF diff --git a/libraries/platforms/dromajo-vcs/bsg_manycore_platform.cpp b/libraries/platforms/dromajo-vcs/bsg_manycore_platform.cpp index efc04b0b7..5ed143e71 100644 --- a/libraries/platforms/dromajo-vcs/bsg_manycore_platform.cpp +++ b/libraries/platforms/dromajo-vcs/bsg_manycore_platform.cpp @@ -328,8 +328,8 @@ int hb_mc_platform_get_config_at(hb_mc_manycore_t *mc, unsigned int idx, hb_mc_c { config_req_pkt.request.x_dst = HOST_X_COORD; config_req_pkt.request.y_dst = HOST_Y_COORD; - config_req_pkt.request.x_src = (0 << 4) | 0; - config_req_pkt.request.y_src = (1 << 3) | 1; + config_req_pkt.request.x_src = BP_HOST_LINK_X; + config_req_pkt.request.y_src = BP_HOST_LINK_Y; config_req_pkt.request.op_v2 = HB_MC_PACKET_OP_REMOTE_LOAD; config_req_pkt.request.payload = 0; config_req_pkt.request.reg_id = 0; @@ -385,8 +385,8 @@ int hb_mc_platform_fence(hb_mc_manycore_t *mc, long timeout) { // Prepare host packet to query TX vacancy fence_req_pkt.request.x_dst = HOST_X_COORD; fence_req_pkt.request.y_dst = HOST_Y_COORD; - fence_req_pkt.request.x_src = (0 << 4) | 0; - fence_req_pkt.request.y_src = (1 << 3) | 1; + fence_req_pkt.request.x_src = BP_HOST_LINK_X; + fence_req_pkt.request.y_src = BP_HOST_LINK_Y; fence_req_pkt.request.op_v2 = HB_MC_PACKET_OP_REMOTE_LOAD; fence_req_pkt.request.payload = 0; fence_req_pkt.request.reg_id = 0; @@ -498,8 +498,8 @@ int hb_mc_platform_wait_reset_done(hb_mc_manycore_t *mc) { reset_req_pkt.request.x_dst = HOST_X_COORD; reset_req_pkt.request.y_dst = HOST_Y_COORD; - reset_req_pkt.request.x_src = (0 << 4) | 0; - reset_req_pkt.request.y_src = (1 << 3) | 1; + reset_req_pkt.request.x_src = BP_HOST_LINK_X; + reset_req_pkt.request.y_src = BP_HOST_LINK_Y; reset_req_pkt.request.op_v2 = HB_MC_PACKET_OP_REMOTE_LOAD; reset_req_pkt.request.payload = 0; reset_req_pkt.request.reg_id = 0; diff --git a/libraries/platforms/dromajo-vcs/software/src/args.c b/libraries/platforms/dromajo-vcs/software/src/args.c index a3c52a95a..f65f1def7 100644 --- a/libraries/platforms/dromajo-vcs/software/src/args.c +++ b/libraries/platforms/dromajo-vcs/software/src/args.c @@ -33,8 +33,8 @@ void __init_args(void) { // BlackParrot FIFO interface is at POD (X, Y) = (0, 1), SUBCOORD (X, Y) = (0, 1) args_req_pkt.request.x_dst = HOST_X_COORD; args_req_pkt.request.y_dst = HOST_Y_COORD; - args_req_pkt.request.x_src = (0 << 4) | 0; - args_req_pkt.request.y_src = (1 << 3) | 1; + args_req_pkt.request.x_src = BP_HOST_LINK_X; + args_req_pkt.request.y_src = BP_HOST_LINK_Y; args_req_pkt.request.op_v2 = HB_MC_PACKET_OP_REMOTE_LOAD; args_req_pkt.request.payload = 0; args_req_pkt.request.reg_id = 0; diff --git a/libraries/platforms/dromajo-vcs/software/src/bp_utils.c b/libraries/platforms/dromajo-vcs/software/src/bp_utils.c index a3a6cac03..4291cdb48 100644 --- a/libraries/platforms/dromajo-vcs/software/src/bp_utils.c +++ b/libraries/platforms/dromajo-vcs/software/src/bp_utils.c @@ -65,8 +65,8 @@ void bp_finish(int16_t code) { hb_mc_packet_t finish_pkt; finish_pkt.request.x_dst = HOST_X_COORD; finish_pkt.request.y_dst = HOST_Y_COORD; - finish_pkt.request.x_src = (0 << 4) | 0; - finish_pkt.request.y_src = (1 << 3) | 1; + finish_pkt.request.x_src = BP_HOST_LINK_X; + finish_pkt.request.y_src = BP_HOST_LINK_Y; finish_pkt.request.op_v2 = HB_MC_PACKET_OP_REMOTE_SW; finish_pkt.request.payload = (core_id << 16) | (0x0000FFFF & code); finish_pkt.request.reg_id = 0; @@ -90,8 +90,8 @@ void bp_hprint(uint8_t hex) { hb_mc_packet_t hprint_pkt; hprint_pkt.request.x_dst = HOST_X_COORD; hprint_pkt.request.y_dst = HOST_Y_COORD; - hprint_pkt.request.x_src = (0 << 4) | 0; - hprint_pkt.request.y_src = (1 << 3) | 1; + hprint_pkt.request.x_src = BP_HOST_LINK_X; + hprint_pkt.request.y_src = BP_HOST_LINK_Y; hprint_pkt.request.op_v2 = HB_MC_PACKET_OP_REMOTE_SW; hprint_pkt.request.payload = ('0' + hex); hprint_pkt.request.reg_id = 0; @@ -109,8 +109,8 @@ void bp_cprint(uint8_t ch) { hb_mc_packet_t cprint_pkt; cprint_pkt.request.x_dst = HOST_X_COORD; cprint_pkt.request.y_dst = HOST_Y_COORD; - cprint_pkt.request.x_src = (0 << 4) | 0; - cprint_pkt.request.y_src = (1 << 3) | 1; + cprint_pkt.request.x_src = BP_HOST_LINK_X; + cprint_pkt.request.y_src = BP_HOST_LINK_Y; cprint_pkt.request.op_v2 = HB_MC_PACKET_OP_REMOTE_SW; cprint_pkt.request.payload = ch; cprint_pkt.request.reg_id = 0; From cbacfdae88f800103368c012aff034979f593b0b Mon Sep 17 00:00:00 2001 From: sripathi-muralitharan Date: Wed, 14 Jul 2021 10:40:10 -0700 Subject: [PATCH 53/70] Addressing review comments --- .../platforms/dromajo-vcs/bp_hb_platform.h | 6 +- .../dromajo-vcs/bsg_manycore_platform.cpp | 143 ++++++++---------- .../dromajo-vcs/bsg_manycore_simulator.cpp | 13 +- .../platforms/dromajo-vcs/compilation.mk | 7 +- libraries/platforms/dromajo-vcs/library.mk | 3 + platform.mk | 7 + 6 files changed, 87 insertions(+), 92 deletions(-) diff --git a/libraries/platforms/dromajo-vcs/bp_hb_platform.h b/libraries/platforms/dromajo-vcs/bp_hb_platform.h index 01c534d42..d5eac7f59 100644 --- a/libraries/platforms/dromajo-vcs/bp_hb_platform.h +++ b/libraries/platforms/dromajo-vcs/bp_hb_platform.h @@ -13,11 +13,11 @@ extern "C" { // Host X and Y coordinates #ifndef HOST_X_COORD -#define HOST_X_COORD 15 +#error HOST_X_COORD is undefined #endif #ifndef HOST_Y_COORD -#define HOST_Y_COORD 8 +#error HOST_Y_COORD is undefined #endif // BlackParrot coordinates @@ -93,4 +93,4 @@ int bp_hb_read_from_mc_bridge(hb_mc_packet_t *pkt, hb_mc_fifo_rx_t type); } #endif -#endif \ No newline at end of file +#endif diff --git a/libraries/platforms/dromajo-vcs/bsg_manycore_platform.cpp b/libraries/platforms/dromajo-vcs/bsg_manycore_platform.cpp index 5ed143e71..54c18cc7d 100644 --- a/libraries/platforms/dromajo-vcs/bsg_manycore_platform.cpp +++ b/libraries/platforms/dromajo-vcs/bsg_manycore_platform.cpp @@ -55,13 +55,13 @@ * @returns HB_MC_SUCCESS */ int bp_hb_get_credits_used(int *credits_used) { - uint32_t *bp_to_mc_req_credits_addr = (uint32_t *) (MC_BASE_ADDR + BP_TO_MC_REQ_CREDITS_ADDR); - *credits_used = (int) *bp_to_mc_req_credits_addr; - if (*credits_used < 0) { - bsg_pr_err("Credits used cannot be negative. Credits used = %d", *credits_used); - return HB_MC_FAIL; - } - return HB_MC_SUCCESS; + uint32_t *bp_to_mc_req_credits_addr = reinterpret_cast(MC_BASE_ADDR + BP_TO_MC_REQ_CREDITS_ADDR); + *credits_used = (int) (*bp_to_mc_req_credits_addr); + if (*credits_used < 0) { + bsg_pr_err("Credits used cannot be negative. Credits used = %d", *credits_used); + return HB_MC_FAIL; + } + return HB_MC_SUCCESS; } /* @@ -71,12 +71,12 @@ int bp_hb_get_credits_used(int *credits_used) { * TODO: Implement error checking (Requires some modifications in Dromajo) */ int bp_hb_write_to_mc_bridge(hb_mc_packet_t *pkt) { - uint32_t *bp_to_mc_req_fifo_addr = (uint32_t *) (MC_BASE_ADDR + BP_TO_MC_REQ_FIFO_ADDR); - for(int i = 0; i < 4; i++) { - *bp_to_mc_req_fifo_addr = pkt->words[i]; - bp_to_mc_req_fifo_addr++; - } - return HB_MC_SUCCESS; + uint32_t *bp_to_mc_req_fifo_addr = reinterpret_cast(MC_BASE_ADDR + BP_TO_MC_REQ_FIFO_ADDR); + for(int i = 0; i < 4; i++) { + *bp_to_mc_req_fifo_addr = pkt->words[i]; + bp_to_mc_req_fifo_addr++; + } + return HB_MC_SUCCESS; } /* @@ -86,35 +86,27 @@ int bp_hb_write_to_mc_bridge(hb_mc_packet_t *pkt) { * @returns HB_MC_SUCCESS on success or HB_MC_FAIL on fail */ int bp_hb_get_fifo_entries(int *entries, hb_mc_fifo_rx_t type) { - switch (type) { - case HB_MC_FIFO_RX_REQ: - { - uint32_t *mc_to_bp_req_fifo_entries_addr = (uint32_t *) (MC_BASE_ADDR + MC_TO_BP_REQ_ENTRIES_ADDR); - *entries = *mc_to_bp_req_fifo_entries_addr; - if (*entries < 0) { - bsg_pr_err("Entries occupied cannot be negative. Entries = %d", *entries); - return HB_MC_FAIL; - } - } - break; - case HB_MC_FIFO_RX_RSP: - { - uint32_t *mc_to_bp_resp_fifo_entries_addr = (uint32_t *) (MC_BASE_ADDR + MC_TO_BP_RESP_ENTRIES_ADDR); - *entries = *mc_to_bp_resp_fifo_entries_addr; - if (*entries < 0) { - bsg_pr_err("Entries occupied cannot be negative. Entries = %d", *entries); - return HB_MC_FAIL; - } - } - break; - default: - { - bsg_pr_err("%s: Unknown packet type\n", __func__); + uint32_t *addr; + switch (type) { + case HB_MC_FIFO_RX_REQ: addr = reinterpret_cast(MC_BASE_ADDR + MC_TO_BP_REQ_ENTRIES_ADDR); + break; + case HB_MC_FIFO_RX_RSP: addr = reinterpret_cast(MC_BASE_ADDR + MC_TO_BP_RESP_ENTRIES_ADDR); + break; + default: + { + bsg_pr_err("%s: Unknown packet type\n", __func__); return HB_MC_FAIL; - } - break; - } - return HB_MC_SUCCESS; + } + break; + } + + *entries = *addr; + if (*entries < 0) { + bsg_pr_err("Entries occupied cannot be negative. Entries = %d", *entries); + return HB_MC_FAIL; + } + + return HB_MC_SUCCESS; } /* @@ -124,49 +116,34 @@ int bp_hb_get_fifo_entries(int *entries, hb_mc_fifo_rx_t type) { * @returns HB_MC_SUCCESS on success, HB_MC_FAIL if FIFO type is unknown */ int bp_hb_read_from_mc_bridge(hb_mc_packet_t *pkt, hb_mc_fifo_rx_t type) { - switch(type) { - case HB_MC_FIFO_RX_REQ: - { - uint32_t *mc_to_bp_req_fifo_addr = (uint32_t *) (MC_BASE_ADDR + MC_TO_BP_REQ_FIFO_ADDR); - uint32_t fifo_read_status = DROMAJO_RW_FAIL_CODE; - do { - for (int i = 0; i < 4; i++) { - pkt->words[i] = *mc_to_bp_req_fifo_addr; - fifo_read_status &= pkt->words[i]; - mc_to_bp_req_fifo_addr++; - } - } while (fifo_read_status == DROMAJO_RW_FAIL_CODE); - - // There is something wrong if the read status is equal to the FAIL code - if (fifo_read_status == DROMAJO_RW_FAIL_CODE) - return HB_MC_FAIL; - } - break; - case HB_MC_FIFO_RX_RSP: - { - uint32_t *mc_to_bp_resp_fifo_addr = (uint32_t *) (MC_BASE_ADDR + MC_TO_BP_RESP_FIFO_ADDR); - uint32_t fifo_read_status = DROMAJO_RW_FAIL_CODE; - do { - for (int i = 0; i < 4; i++) { - pkt->words[i] = *mc_to_bp_resp_fifo_addr; - fifo_read_status &= pkt->words[i]; - mc_to_bp_resp_fifo_addr++; - } - } while(fifo_read_status == DROMAJO_RW_FAIL_CODE); - - // There is something wrong if the read status is equal to the FAIL code - if (fifo_read_status == DROMAJO_RW_FAIL_CODE) - return HB_MC_FAIL; - } - break; - default: - { - bsg_pr_err("%s: Unknown packet type\n", __func__); + uint32_t *addr; + switch(type) { + case HB_MC_FIFO_RX_REQ: addr = reinterpret_cast(MC_BASE_ADDR + MC_TO_BP_REQ_FIFO_ADDR); + break; + case HB_MC_FIFO_RX_RSP: addr = reinterpret_cast(MC_BASE_ADDR + MC_TO_BP_RESP_FIFO_ADDR); + break; + default: + { + bsg_pr_err("%s: Unknown packet type\n", __func__); return HB_MC_FAIL; - } - break; - } - return HB_MC_SUCCESS; + } + break; + } + + uint32_t fifo_read_status = DROMAJO_RW_FAIL_CODE; + do { + for (int i = 0; i < 4; i++) { + pkt->words[i] = *addr; + fifo_read_status &= pkt->words[i]; + addr++; + } + } while (fifo_read_status == DROMAJO_RW_FAIL_CODE); + + // There is something wrong if the read status is equal to the FAIL code + if (fifo_read_status == DROMAJO_RW_FAIL_CODE) + return HB_MC_FAIL; + + return HB_MC_SUCCESS; } /********************************** Manycore platform API **********************************/ diff --git a/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.cpp b/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.cpp index 5cc8e5254..5d9373750 100644 --- a/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.cpp +++ b/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.cpp @@ -57,8 +57,12 @@ SimulationWrapper::SimulationWrapper(){ dromajo_init(); dpi_init(); - if ((!dromajo) || (!dpi)) { - bsg_pr_err("Failed to initialize DPI or Dromajo pointer\n"); + if (!dromajo) { + bsg_pr_err("Failed to initialize Dromajo pointer\n"); + } + + if (!dpi) { + bsg_pr_err("Failed to initialize DPI pointer\n"); } } @@ -69,7 +73,7 @@ SimulationWrapper::~SimulationWrapper(){ this->top = nullptr; } -// Causes time to proceed by 1 unit +// Advances time to the next clock edge void SimulationWrapper::advance_time() { svScope prev; prev = svSetScope(top); @@ -223,7 +227,8 @@ int SimulationWrapper::dromajo_transmit_packet() { dromajo_to_mc_packet.words[3] = host_to_mc_req_fifo->fifo[3].front(); // Intercept packets that are for the host and generate appropriate responses - // TODO: Currently, these packets don't go over the network. They should + // TODO: Currently, these packets don't go over the network. In the real system, they will and the simulation infrastructure + // must emulate that as best as possible. if ((dromajo_to_mc_packet.request.x_dst == HOST_X_COORD) && (dromajo_to_mc_packet.request.y_dst == HOST_Y_COORD)) { host_to_dromajo_packet.response.x_dst = dromajo_to_mc_packet.request.x_src; host_to_dromajo_packet.response.y_dst = dromajo_to_mc_packet.request.y_src; diff --git a/libraries/platforms/dromajo-vcs/compilation.mk b/libraries/platforms/dromajo-vcs/compilation.mk index d7b6bb245..149597778 100644 --- a/libraries/platforms/dromajo-vcs/compilation.mk +++ b/libraries/platforms/dromajo-vcs/compilation.mk @@ -32,6 +32,9 @@ ORANGE=\033[0;33m RED=\033[0;31m NC=\033[0m +# Include the machine configuration to make things clear(er) +include $(BSG_MACHINE_PATH)/Makefile.machine.include + # This file REQUIRES several variables to be set. They are typically # set by the Makefile that includes this makefile.. # @@ -43,7 +46,7 @@ INCLUDES += -I$(BLACKPARROT_SDK_DIR)/perch CXXFLAGS += $(DEFINES) -march=rv64imafd -mabi=lp64 -mcmodel=medany CFLAGS += $(DEFINES) -march=rv64imafd -mabi=lp64 -mcmodel=medany -SFLAGS += $(DEFINES) -march=rv64imafd -mabi=lp64 -mcmodel=medany +ASFLAGS += $(DEFINES) -march=rv64imafd -mabi=lp64 -mcmodel=medany CC ?= $(BLACKPARROT_SDK_DIR)/install/bin/riscv64-unknown-elf-dramfs-gcc CXX ?= $(BLACKPARROT_SDK_DIR)/install/bin/riscv64-unknown-elf-dramfs-g++ @@ -59,7 +62,7 @@ OBJDUMP ?= $(BLACKPARROT_SDK_DIR)/install/bin/riscv64-unknown-elf-dramfs-objdump $(CXX) -c -o $@ $< $(INCLUDES) $(CXXFLAGS) $(CXXDEFINES) %.o: %.S - $(CC) -c -o $@ $< $(INCLUDES) $(SFLAGS) + $(CC) -c -o $@ $< $(INCLUDES) $(ASFLAGS) %.dis: %.elf $(OBJDUMP) -d $^ > $@ diff --git a/libraries/platforms/dromajo-vcs/library.mk b/libraries/platforms/dromajo-vcs/library.mk index fb582cb51..859f6f1c9 100644 --- a/libraries/platforms/dromajo-vcs/library.mk +++ b/libraries/platforms/dromajo-vcs/library.mk @@ -25,6 +25,9 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# Include the machine configuration to make things clear(er) +include $(BSG_MACHINE_PATH)/Makefile.machine.include + # RISC-V tools RV_CC = $(BLACKPARROT_SDK_DIR)/install/bin/riscv64-unknown-elf-dramfs-gcc RV_CXX = $(BLACKPARROT_SDK_DIR)/install/bin/riscv64-unknown-elf-dramfs-g++ diff --git a/platform.mk b/platform.mk index 73d1e8d4e..222f5c9c3 100644 --- a/platform.mk +++ b/platform.mk @@ -80,6 +80,13 @@ $(error $(shell echo -e "$(RED)BSG MAKE ERROR: VERILATOR not defined$(NC)")) endif endif +# If using Dromajo, check if BLACKPARROT_SDK_DIR is defined +ifeq ($(BSG_PLATFORM),dromajo-vcs) +ifndef BLACKPARROT_SDK_DIR +$(error $(shell echo -e "$(RED)BSG MAKE ERROR: BLACKPARROT_SDK_DIR not defined$(NC)")) +endif +endif + # BSG Platform Path is the path to the target platform, i.e. the # substrate that actually runs the machine. From bab87858af4b41c5b24a0bf0856abb8e0b0ae9fe Mon Sep 17 00:00:00 2001 From: sripathi-muralitharan Date: Thu, 15 Jul 2021 18:37:56 -0700 Subject: [PATCH 54/70] Addressing more review comments * Adding comments * bp_hb -> hb_bp * (Much) faster simulation * tabs -> spaces --- libraries/libraries.mk | 2 + .../dromajo-vcs/bsg_manycore_platform.cpp | 99 +- .../dromajo-vcs/bsg_manycore_simulator.cpp | 136 +- .../dromajo-vcs/bsg_manycore_simulator.hpp | 14 +- .../platforms/dromajo-vcs/compilation.mk | 5 +- .../{bp_hb_platform.h => hb_bp_platform.h} | 28 +- libraries/platforms/dromajo-vcs/library.mk | 4 +- .../dromajo-vcs/software/include/argp.h | 54 +- .../dromajo-vcs/software/include/bp_utils.h | 2 +- .../software/src/argp/argp-fmtstream.c | 490 +++--- .../dromajo-vcs/software/src/argp/argp-help.c | 1396 ++++++++--------- .../software/src/argp/argp-parse.c | 650 ++++---- .../platforms/dromajo-vcs/software/src/args.c | 11 +- .../dromajo-vcs/software/src/bp_utils.c | 80 +- 14 files changed, 1497 insertions(+), 1474 deletions(-) rename libraries/platforms/dromajo-vcs/{bp_hb_platform.h => hb_bp_platform.h} (81%) diff --git a/libraries/libraries.mk b/libraries/libraries.mk index d05adc5f8..23604a7e8 100644 --- a/libraries/libraries.mk +++ b/libraries/libraries.mk @@ -118,6 +118,8 @@ $(LIB_OBJECTS) $(LIB_OBJECTS_CUDA_POD_REPL) $(LIB_OBJECTS_REGRESSION): INCLUDES $(LIB_OBJECTS) $(LIB_OBJECTS_CUDA_POD_REPL) $(LIB_OBJECTS_REGRESSION): INCLUDES += -I$(LIBRARIES_PATH)/features/profiler $(LIB_OBJECTS) $(LIB_OBJECTS_CUDA_POD_REPL) $(LIB_OBJECTS_REGRESSION): INCLUDES += -I$(LIBRARIES_PATH)/features/tracer $(LIB_OBJECTS) $(LIB_OBJECTS_CUDA_POD_REPL) $(LIB_OBJECTS_REGRESSION): INCLUDES += -I$(BSG_PLATFORM_PATH) +# A way to add include paths for the platform; This can't be a part of the platform's library.mk because of the overriding +# definition of the variables in this flow. $(LIB_OBJECTS) $(LIB_OBJECTS_CUDA_POD_REPL) $(LIB_OBJECTS_REGRESSION): INCLUDES += $(LIB_PLATFORM_INCLUDES) $(LIB_OBJECTS) $(LIB_OBJECTS_CUDA_POD_REPL) $(LIB_OBJECTS_REGRESSION): CFLAGS += -O3 -std=c11 -fPIC -D_GNU_SOURCE -D_BSD_SOURCE -D_DEFAULT_SOURCE diff --git a/libraries/platforms/dromajo-vcs/bsg_manycore_platform.cpp b/libraries/platforms/dromajo-vcs/bsg_manycore_platform.cpp index 54c18cc7d..c50756104 100644 --- a/libraries/platforms/dromajo-vcs/bsg_manycore_platform.cpp +++ b/libraries/platforms/dromajo-vcs/bsg_manycore_platform.cpp @@ -30,7 +30,7 @@ #include #include -#include +#include #include @@ -54,7 +54,7 @@ * @param[in] credits_used --> Pointer to a location in memory that will hold the number of credits used * @returns HB_MC_SUCCESS */ -int bp_hb_get_credits_used(int *credits_used) { +int hb_bp_get_credits_used(int *credits_used) { uint32_t *bp_to_mc_req_credits_addr = reinterpret_cast(MC_BASE_ADDR + BP_TO_MC_REQ_CREDITS_ADDR); *credits_used = (int) (*bp_to_mc_req_credits_addr); if (*credits_used < 0) { @@ -70,7 +70,7 @@ int bp_hb_get_credits_used(int *credits_used) { * @returns HB_MC_SUCCESS * TODO: Implement error checking (Requires some modifications in Dromajo) */ -int bp_hb_write_to_mc_bridge(hb_mc_packet_t *pkt) { +int hb_bp_write_to_mc_bridge(hb_mc_packet_t *pkt) { uint32_t *bp_to_mc_req_fifo_addr = reinterpret_cast(MC_BASE_ADDR + BP_TO_MC_REQ_FIFO_ADDR); for(int i = 0; i < 4; i++) { *bp_to_mc_req_fifo_addr = pkt->words[i]; @@ -85,7 +85,7 @@ int bp_hb_write_to_mc_bridge(hb_mc_packet_t *pkt) { * @param[in] type --> Type of FIFO to read from * @returns HB_MC_SUCCESS on success or HB_MC_FAIL on fail */ -int bp_hb_get_fifo_entries(int *entries, hb_mc_fifo_rx_t type) { +int hb_bp_get_fifo_entries(int *entries, hb_mc_fifo_rx_t type) { uint32_t *addr; switch (type) { case HB_MC_FIFO_RX_REQ: addr = reinterpret_cast(MC_BASE_ADDR + MC_TO_BP_REQ_ENTRIES_ADDR); @@ -115,7 +115,7 @@ int bp_hb_get_fifo_entries(int *entries, hb_mc_fifo_rx_t type) { * @param[in] type --> Type of FIFO to read from * @returns HB_MC_SUCCESS on success, HB_MC_FAIL if FIFO type is unknown */ -int bp_hb_read_from_mc_bridge(hb_mc_packet_t *pkt, hb_mc_fifo_rx_t type) { +int hb_bp_read_from_mc_bridge(hb_mc_packet_t *pkt, hb_mc_fifo_rx_t type) { uint32_t *addr; switch(type) { case HB_MC_FIFO_RX_REQ: addr = reinterpret_cast(MC_BASE_ADDR + MC_TO_BP_REQ_FIFO_ADDR); @@ -241,12 +241,12 @@ int hb_mc_platform_transmit(hb_mc_manycore_t *mc, hb_mc_packet_t *packet, hb_mc_ int credits_used = 0; do { - err = bp_hb_get_credits_used(&credits_used); + err = hb_bp_get_credits_used(&credits_used); } while ((err != HB_MC_SUCCESS) || ((max_credits - credits_used) <= 0)); // Don't need to check for error code since this operation should always be a success since it is not going // over the network - err = bp_hb_write_to_mc_bridge(packet); + err = hb_bp_write_to_mc_bridge(packet); if (err != HB_MC_SUCCESS) { bsg_pr_err("Write to the host request FIFO failed!"); return err; @@ -276,10 +276,10 @@ int hb_mc_platform_receive(hb_mc_manycore_t *mc, hb_mc_packet_t *packet, hb_mc_f int err; int num_entries = 0; do { - err = bp_hb_get_fifo_entries(&num_entries, type); + err = hb_bp_get_fifo_entries(&num_entries, type); } while ((num_entries == 0) || (err != HB_MC_SUCCESS)); - err = bp_hb_read_from_mc_bridge(packet, type); + err = hb_bp_read_from_mc_bridge(packet, type); if (err != HB_MC_SUCCESS) { bsg_pr_err("Read from the %s FIFO did not succeed", typestr); return HB_MC_INVALID; @@ -301,43 +301,42 @@ int hb_mc_platform_get_config_at(hb_mc_manycore_t *mc, unsigned int idx, hb_mc_c int num_entries = 0; int err; - if (idx < HB_MC_CONFIG_MAX) - { - config_req_pkt.request.x_dst = HOST_X_COORD; - config_req_pkt.request.y_dst = HOST_Y_COORD; - config_req_pkt.request.x_src = BP_HOST_LINK_X; - config_req_pkt.request.y_src = BP_HOST_LINK_Y; - config_req_pkt.request.op_v2 = HB_MC_PACKET_OP_REMOTE_LOAD; - config_req_pkt.request.payload = 0; - config_req_pkt.request.reg_id = 0; - config_req_pkt.request.addr = HB_MC_HOST_EPA_CONFIG_START + idx; - - // Note: Potentially dangerous to write to the FIFO without checking for credits - // We get back credits used and not credits remaining and without the configuration - // there is no way to know the credits remaining. - err = bp_hb_write_to_mc_bridge(&config_req_pkt); - if (err != HB_MC_SUCCESS) { - bsg_pr_err("Write to the host request FIFO failed!"); - return err; - } - - do { - err = bp_hb_get_fifo_entries(&num_entries, HB_MC_FIFO_RX_RSP); - } while ((num_entries == 0) || (err != HB_MC_SUCCESS)); - - err = bp_hb_read_from_mc_bridge(&config_resp_pkt, HB_MC_FIFO_RX_RSP); - if (err != HB_MC_SUCCESS) { - bsg_pr_err("Config read failed\n"); - return HB_MC_FAIL; - } + config_req_pkt.request.x_dst = HOST_X_COORD; + config_req_pkt.request.y_dst = HOST_Y_COORD; + config_req_pkt.request.x_src = BP_HOST_LINK_X; + config_req_pkt.request.y_src = BP_HOST_LINK_Y; + config_req_pkt.request.op_v2 = HB_MC_PACKET_OP_REMOTE_LOAD; + config_req_pkt.request.payload = 0; + config_req_pkt.request.reg_id = 0; + // Note 1: This will not translate to hardware correctly because + // addr is word addressable. Works in C/C++ because the C code considers + // the address as a byte addressable field. + // Note 2: The onus is on the simulator (i.e. x86 code) to check if the config + // index is within bounds before accessing the DPI ROM. + config_req_pkt.request.addr = HB_BP_HOST_EPA_CONFIG_START + idx; + + // Note: Potentially dangerous to write to the FIFO without checking for credits + // We get back credits used and not credits remaining and without the configuration + // there is no way to know the credits remaining. + err = hb_bp_write_to_mc_bridge(&config_req_pkt); + if (err != HB_MC_SUCCESS) { + bsg_pr_err("Write to the host request FIFO failed!"); + return err; + } - uint32_t data = config_resp_pkt.response.data; - *config = (data != HB_MC_HOST_OP_FINISH_CODE) ? data : 0; + do { + err = hb_bp_get_fifo_entries(&num_entries, HB_MC_FIFO_RX_RSP); + } while ((num_entries == 0) || (err != HB_MC_SUCCESS)); - return HB_MC_SUCCESS; + err = hb_bp_read_from_mc_bridge(&config_resp_pkt, HB_MC_FIFO_RX_RSP); + if (err != HB_MC_SUCCESS) { + bsg_pr_err("Config read failed\n"); + return HB_MC_FAIL; } - return HB_MC_INVALID; + *config = config_resp_pkt.response.data; + + return HB_MC_SUCCESS; } /** @@ -367,21 +366,21 @@ int hb_mc_platform_fence(hb_mc_manycore_t *mc, long timeout) { fence_req_pkt.request.op_v2 = HB_MC_PACKET_OP_REMOTE_LOAD; fence_req_pkt.request.payload = 0; fence_req_pkt.request.reg_id = 0; - fence_req_pkt.request.addr = HB_MC_HOST_EPA_TX_VACANT; // x86 Host address to poll tx vacancy + fence_req_pkt.request.addr = HB_BP_HOST_EPA_TX_VACANT; // x86 Host address to poll tx vacancy do { - err = bp_hb_get_credits_used(&credits_used); + err = hb_bp_get_credits_used(&credits_used); // In a real system, this function call makes no sense since we will be sending packets to the // host on the network and are trying to check for credits to be zero and complete the fence. // It is fine here because of the system setup. - err |= bp_hb_write_to_mc_bridge(&fence_req_pkt); + err |= hb_bp_write_to_mc_bridge(&fence_req_pkt); do { - err = bp_hb_get_fifo_entries(&num_entries, HB_MC_FIFO_RX_RSP); + err = hb_bp_get_fifo_entries(&num_entries, HB_MC_FIFO_RX_RSP); } while ((num_entries == 0) || (err != HB_MC_SUCCESS)); - err |= bp_hb_read_from_mc_bridge(&fence_resp_pkt, HB_MC_FIFO_RX_RSP); + err |= hb_bp_read_from_mc_bridge(&fence_resp_pkt, HB_MC_FIFO_RX_RSP); is_vacant = fence_resp_pkt.response.data; } while ((err == HB_MC_SUCCESS) && !((credits_used == 0) && is_vacant)); @@ -480,13 +479,13 @@ int hb_mc_platform_wait_reset_done(hb_mc_manycore_t *mc) { reset_req_pkt.request.op_v2 = HB_MC_PACKET_OP_REMOTE_LOAD; reset_req_pkt.request.payload = 0; reset_req_pkt.request.reg_id = 0; - reset_req_pkt.request.addr = HB_MC_HOST_EPA_RESET_DONE; + reset_req_pkt.request.addr = HB_BP_HOST_EPA_RESET_DONE; do { // The platform setup ensures that this packet will not go over the network so // we don't need to check for credits. - err = bp_hb_write_to_mc_bridge(&reset_req_pkt); - err |= bp_hb_read_from_mc_bridge(&reset_resp_pkt, HB_MC_FIFO_RX_RSP); + err = hb_bp_write_to_mc_bridge(&reset_req_pkt); + err |= hb_bp_read_from_mc_bridge(&reset_resp_pkt, HB_MC_FIFO_RX_RSP); data = reset_resp_pkt.response.data; } while((err != HB_MC_SUCCESS) || (data == 0)); diff --git a/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.cpp b/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.cpp index 5d9373750..acbd4568c 100644 --- a/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.cpp +++ b/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.cpp @@ -215,11 +215,9 @@ int SimulationWrapper::dromajo_transmit_packet() { int err; __m128i *pkt; - // Check if FIFO has an element and hence ready to transmit mc_fifo_type_t type = FIFO_HOST_TO_MC_REQ; - bool is_empty = mc_is_fifo_empty(type); - if (!is_empty) { + do { // Read the FIFO head pointer for all 32-bit FIFOs dromajo_to_mc_packet.words[0] = host_to_mc_req_fifo->fifo[0].front(); dromajo_to_mc_packet.words[1] = host_to_mc_req_fifo->fifo[1].front(); @@ -241,9 +239,9 @@ int SimulationWrapper::dromajo_transmit_packet() { // Fixme: Is there no struct for response opcode like in the manycore hardware host_to_dromajo_packet.response.op = dromajo_to_mc_packet.request.op_v2; switch (dromajo_to_mc_packet.request.addr) { - case HB_MC_HOST_EPA_ARGS_START ... HB_MC_HOST_EPA_ARGS_FINISH: + case HB_BP_HOST_EPA_ARGS_START ... HB_BP_HOST_EPA_ARGS_FINISH: { - uint32_t idx = dromajo_to_mc_packet.request.addr - HB_MC_HOST_EPA_ARGS_START; + uint32_t idx = dromajo_to_mc_packet.request.addr - HB_BP_HOST_EPA_ARGS_START; int num_characters = 0; // If all arguments have been read or there are no arguments to read // send a finish code @@ -262,23 +260,28 @@ int SimulationWrapper::dromajo_transmit_packet() { } } else - data = HB_MC_HOST_OP_FINISH_CODE; + data = HB_BP_HOST_OP_FINISH_CODE; } break; - case HB_MC_HOST_EPA_CONFIG_START ... HB_MC_HOST_EPA_CONFIG_FINISH: + case HB_BP_HOST_EPA_CONFIG_START ... HB_BP_HOST_EPA_CONFIG_FINISH: { - uint32_t idx = dromajo_to_mc_packet.request.addr - HB_MC_HOST_EPA_CONFIG_START; - data = (idx <= HB_MC_CONFIG_MAX) ? dpi->config[idx] : HB_MC_HOST_OP_FINISH_CODE; + uint32_t idx = dromajo_to_mc_packet.request.addr - HB_BP_HOST_EPA_CONFIG_START; + if (idx <= HB_MC_CONFIG_MAX) + data = dpi->config[idx]; + else { + bsg_pr_err("Configuration ROM index out of bounds\n"); + return HB_MC_NOTFOUND; + } } break; - case HB_MC_HOST_EPA_RESET_DONE: + case HB_BP_HOST_EPA_RESET_DONE: { bool done; dpi->reset_is_done(done); data = done ? 1 : 0; } break; - case HB_MC_HOST_EPA_TX_VACANT: + case HB_BP_HOST_EPA_TX_VACANT: { bool is_vacant; dpi->tx_is_vacant(is_vacant); @@ -373,10 +376,10 @@ int SimulationWrapper::dromajo_transmit_packet() { err = dpi->tx_req(*pkt, expect_response); } while (err != BSG_NONSYNTH_DPI_SUCCESS && (err == BSG_NONSYNTH_DPI_NO_CREDITS || - err == BSG_NONSYNTH_DPI_NO_CAPACITY || - err == BSG_NONSYNTH_DPI_NOT_WINDOW || - err == BSG_NONSYNTH_DPI_BUSY || - err == BSG_NONSYNTH_DPI_NOT_READY)); + err == BSG_NONSYNTH_DPI_NO_CAPACITY || + err == BSG_NONSYNTH_DPI_NOT_WINDOW || + err == BSG_NONSYNTH_DPI_BUSY || + err == BSG_NONSYNTH_DPI_NOT_READY)); if (err == BSG_NONSYNTH_DPI_SUCCESS) { for (int i = 0;i < 4; i++) @@ -392,7 +395,7 @@ int SimulationWrapper::dromajo_transmit_packet() { if (err != HB_MC_SUCCESS) return err; } - } + } while (!mc_is_fifo_empty(type)); return HB_MC_SUCCESS; } @@ -408,47 +411,43 @@ int SimulationWrapper::dromajo_receive_packet() { __m128i pkt; // Read from the manycore request FIFO - // At every time step we are polling the request FIFO to see if there + // At every clock edge we are polling the request FIFO to see if there // is a packet. If there is no packet (i.e err == BSG_NONSYNTH_NOT_VALID) // we must move on do { - advance_time(); - err = dpi->rx_req(pkt); - } while (err != BSG_NONSYNTH_DPI_SUCCESS && - (err == BSG_NONSYNTH_DPI_NOT_WINDOW || - err == BSG_NONSYNTH_DPI_BUSY || - err == BSG_NONSYNTH_DPI_INVALID)); - - if (err == BSG_NONSYNTH_DPI_SUCCESS) { - mc_to_dromajo_req_packet = reinterpret_cast(&pkt); - for (int i = 0; i < 4; i++) { - mc_to_host_req_fifo->fifo[i].push(mc_to_dromajo_req_packet->words[i]); + do { + advance_time(); + err = dpi->rx_req(pkt); + } while (err != BSG_NONSYNTH_DPI_SUCCESS && + (err == BSG_NONSYNTH_DPI_NOT_WINDOW || + err == BSG_NONSYNTH_DPI_BUSY || + err == BSG_NONSYNTH_DPI_INVALID)); + + if (err == BSG_NONSYNTH_DPI_SUCCESS) { + mc_to_dromajo_req_packet = reinterpret_cast(&pkt); + for (int i = 0; i < 4; i++) { + mc_to_host_req_fifo->fifo[i].push(mc_to_dromajo_req_packet->words[i]); + } } - } - else if (err != BSG_NONSYNTH_DPI_NOT_VALID){ - bsg_pr_err("Failed to receive manycore request packet"); - return HB_MC_FAIL; - } + } while (err != BSG_NONSYNTH_DPI_NOT_VALID); // Read from the manycore response FIFO do { - advance_time(); - err = dpi->rx_rsp(pkt); - } while (err != BSG_NONSYNTH_DPI_SUCCESS && - (err == BSG_NONSYNTH_DPI_NOT_WINDOW || - err == BSG_NONSYNTH_DPI_BUSY || - err == BSG_NONSYNTH_DPI_INVALID)); - - if (err == BSG_NONSYNTH_DPI_SUCCESS) { - mc_to_dromajo_resp_packet = reinterpret_cast(&pkt); - for (int i = 0; i < 4; i++) { - mc_to_host_resp_fifo->fifo[i].push(mc_to_dromajo_resp_packet->words[i]); + do { + advance_time(); + err = dpi->rx_rsp(pkt); + } while (err != BSG_NONSYNTH_DPI_SUCCESS && + (err == BSG_NONSYNTH_DPI_NOT_WINDOW || + err == BSG_NONSYNTH_DPI_BUSY || + err == BSG_NONSYNTH_DPI_INVALID)); + + if (err == BSG_NONSYNTH_DPI_SUCCESS) { + mc_to_dromajo_resp_packet = reinterpret_cast(&pkt); + for (int i = 0; i < 4; i++) { + mc_to_host_resp_fifo->fifo[i].push(mc_to_dromajo_resp_packet->words[i]); + } } - } - else if (err != BSG_NONSYNTH_DPI_NOT_VALID) { - bsg_pr_err("Failed to receive manycore response packet"); - return HB_MC_FAIL; - } + } while (err != BSG_NONSYNTH_DPI_NOT_VALID); return HB_MC_SUCCESS; } @@ -477,7 +476,10 @@ int SimulationWrapper::dromajo_set_credits() { } int SimulationWrapper::eval(){ - // Execute 100 instructions on Dromajo + bool transmit = false; + int err; + + // Execute NUM_DROMAJO_INSTR_PER_TICK instructions on Dromajo for(int i = 0; i < NUM_DROMAJO_INSTR_PER_TICK; i++) { if (!dromajo_step()) { // Fixme: Dromajo could also terminate due to premature errors. @@ -487,22 +489,36 @@ int SimulationWrapper::eval(){ return HB_MC_SUCCESS; } - int err; - // Poll for packets to be transmitted + // Check if transmit FIFO has an element and hence ready to transmit + // This operation is relatively low overhead since only a single FIFO's + // empty status is being checked. Hence, we can afford to do it every 100 + // iterations. + if (i % NUM_TX_FIFO_CHK_PER_TICK) { + mc_fifo_type_t type = FIFO_HOST_TO_MC_REQ; + bool is_empty = mc_is_fifo_empty(type); + if (!is_empty) { + transmit = true; + break; + } + } + } + + if (transmit) { + // Poll for packets to be transmitted and transmit them bsg_pr_dbg("Checking for packets to transmit\n"); err = dromajo_transmit_packet(); if (err != HB_MC_SUCCESS) return err; - - // Poll for packets to be received - bsg_pr_dbg("Checking for packets to receive\n"); - err = dromajo_receive_packet(); - if (err != HB_MC_SUCCESS) - return err; } - // Advance time 1 unit - advance_time(); + // Poll for packets to be received and push them to Dromajo + // This involves a DPI call and might incur a large overhead, therefore + // check for packets to receive only once per tick + bsg_pr_dbg("Checking for packets to receive\n"); + err = dromajo_receive_packet(); + if (err != HB_MC_SUCCESS) + return err; + return HB_MC_SUCCESS; } diff --git a/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.hpp b/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.hpp index 09529db1d..b0eee21b0 100644 --- a/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.hpp +++ b/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.hpp @@ -53,13 +53,19 @@ #include -#include +#include // Define invisible library functions declare_hb_mc_get_bits declare_bsg_printing +#ifndef NUM_DROMAJO_INSTR_PER_TICK #define NUM_DROMAJO_INSTR_PER_TICK 1000 +#endif + +#ifndef NUM_TX_FIFO_CHK_PER_TICK +#define NUM_TX_FIFO_CHK_PER_TICK 100 +#endif class SimulationWrapper{ // This is the generic pointer for implementation-specific @@ -89,7 +95,7 @@ class SimulationWrapper{ std::string getRoot(); - // Causes time to proceed by 1 unit + // Advances to the next clock edge void advance_time(); // DPI functions @@ -104,8 +110,8 @@ class SimulationWrapper{ int dromajo_receive_packet(); int dromajo_set_credits(); - // Evaluates one instruction in RISC-V - // and forwards packets between Dromajo and the manycore + // Evaluates a maximum of NUM_DROMAJO_INSTR_PER_TICK instructions + // in RISC-V and forwards packets between Dromajo and the manycore int eval(); }; #endif // __BSG_MANYCORE_SIMULATOR_HPP diff --git a/libraries/platforms/dromajo-vcs/compilation.mk b/libraries/platforms/dromajo-vcs/compilation.mk index 149597778..9c4a8c03f 100644 --- a/libraries/platforms/dromajo-vcs/compilation.mk +++ b/libraries/platforms/dromajo-vcs/compilation.mk @@ -46,8 +46,9 @@ INCLUDES += -I$(BLACKPARROT_SDK_DIR)/perch CXXFLAGS += $(DEFINES) -march=rv64imafd -mabi=lp64 -mcmodel=medany CFLAGS += $(DEFINES) -march=rv64imafd -mabi=lp64 -mcmodel=medany -ASFLAGS += $(DEFINES) -march=rv64imafd -mabi=lp64 -mcmodel=medany +ASFLAGS += $(DEFINES) -march=rv64imafd -mabi=lp64 -mcmodel=medany +# Default to RISC-V but overridden by the flow to other compilers as needed CC ?= $(BLACKPARROT_SDK_DIR)/install/bin/riscv64-unknown-elf-dramfs-gcc CXX ?= $(BLACKPARROT_SDK_DIR)/install/bin/riscv64-unknown-elf-dramfs-g++ OBJDUMP ?= $(BLACKPARROT_SDK_DIR)/install/bin/riscv64-unknown-elf-dramfs-objdump @@ -65,7 +66,7 @@ OBJDUMP ?= $(BLACKPARROT_SDK_DIR)/install/bin/riscv64-unknown-elf-dramfs-objdump $(CC) -c -o $@ $< $(INCLUDES) $(ASFLAGS) %.dis: %.elf - $(OBJDUMP) -d $^ > $@ + $(OBJDUMP) -d -t $^ > $@ .PRECIOUS: %.o diff --git a/libraries/platforms/dromajo-vcs/bp_hb_platform.h b/libraries/platforms/dromajo-vcs/hb_bp_platform.h similarity index 81% rename from libraries/platforms/dromajo-vcs/bp_hb_platform.h rename to libraries/platforms/dromajo-vcs/hb_bp_platform.h index d5eac7f59..063e95665 100644 --- a/libraries/platforms/dromajo-vcs/bp_hb_platform.h +++ b/libraries/platforms/dromajo-vcs/hb_bp_platform.h @@ -1,8 +1,8 @@ // BlackParrot platform-specific header file // This file contains manycore-specific platform functions and constants -#ifndef BP_HB_PLATFORM_H -#define BP_HB_PLATFORM_H +#ifndef HB_BP_PLATFORM_H +#define HB_BP_PLATFORM_H #ifdef __cplusplus extern "C" { @@ -37,14 +37,14 @@ extern "C" { #endif // Memory mapped addresses to interact with the BlackParrot host (aka simulator) -#define HB_MC_HOST_EPA_ARGS_START 0x0000 -#define HB_MC_HOST_EPA_ARGS_FINISH 0x00FF -#define HB_MC_HOST_EPA_CONFIG_START 0x0100 -#define HB_MC_HOST_EPA_CONFIG_FINISH 0x01FF -#define HB_MC_HOST_EPA_RESET_DONE 0x0200 -#define HB_MC_HOST_EPA_TX_VACANT 0x0300 - -#define HB_MC_HOST_OP_FINISH_CODE 0xFFFFFFFF +#define HB_BP_HOST_EPA_ARGS_START 0x0000 +#define HB_BP_HOST_EPA_ARGS_FINISH 0x00FF +#define HB_BP_HOST_EPA_CONFIG_START 0x0100 +#define HB_BP_HOST_EPA_CONFIG_FINISH 0x01FF +#define HB_BP_HOST_EPA_RESET_DONE 0x0200 +#define HB_BP_HOST_EPA_TX_VACANT 0x0300 + +#define HB_BP_HOST_OP_FINISH_CODE 0xFFFFFFFF #define DROMAJO_RW_FAIL_CODE 0xFFFFFFFF // Memory mapped addresses to interact with the manycore bridge @@ -66,20 +66,20 @@ extern "C" { * Reads the manycore bridge for number of credits used in the endpoint * @returns number of credits in the manycore bridge enddpoint */ -int bp_hb_get_credits_used(int *credits_used); +int hb_bp_get_credits_used(int *credits_used); /* * Writes a 128-bit manycore packet in 32-bit chunks to the manycore bridge FIFO * @param[in] pkt --> Pointer to the manycore packet */ -int bp_hb_write_to_mc_bridge(hb_mc_packet_t *pkt); +int hb_bp_write_to_mc_bridge(hb_mc_packet_t *pkt); /* * Checks if the MC to BP FIFO contains any entries * @param[in] type --> Type of FIFO to read from * @returns number of entries in the MC to BP FIFO */ -int bp_hb_get_fifo_entries(int *entries, hb_mc_fifo_rx_t type); +int hb_bp_get_fifo_entries(int *entries, hb_mc_fifo_rx_t type); /* * Reads the manycore bridge FIFOs in 32-bit chunks to form the 128-bit packet @@ -87,7 +87,7 @@ int bp_hb_get_fifo_entries(int *entries, hb_mc_fifo_rx_t type); * @param[in] type --> Type of FIFO to read from * @returns HB_MC_SUCCESS on success, HB_MC_FAIL if FIFO type is unknown */ -int bp_hb_read_from_mc_bridge(hb_mc_packet_t *pkt, hb_mc_fifo_rx_t type); +int hb_bp_read_from_mc_bridge(hb_mc_packet_t *pkt, hb_mc_fifo_rx_t type); #ifdef __cplusplus } diff --git a/libraries/platforms/dromajo-vcs/library.mk b/libraries/platforms/dromajo-vcs/library.mk index 859f6f1c9..bc9b3e827 100644 --- a/libraries/platforms/dromajo-vcs/library.mk +++ b/libraries/platforms/dromajo-vcs/library.mk @@ -132,8 +132,8 @@ $(PLATFORM_OBJECTS): INCLUDES += -I$(VCS_HOME)/linux64/lib/ $(PLATFORM_OBJECTS): INCLUDES += -I$(BSG_MANYCORE_DIR)/testbenches/dpi/ $(PLATFORM_OBJECTS): INCLUDES += -I$(BASEJUMP_STL_DIR)/bsg_test/ $(PLATFORM_OBJECTS): INCLUDES += -I$(BLACKPARROT_SDK_DIR)/dromajo/include -$(PLATFORM_OBJECTS): CFLAGS := -std=c11 -fPIC -DVCS -D_GNU_SOURCE -DVERILATOR -D_BSD_SOURCE -D_XOPEN_SOURCE=500 -DHOST_X_COORD=$(BSG_MACHINE_HOST_COORD_X) -DHOST_Y_COORD=$(BSG_MACHINE_HOST_COORD_Y) -$(PLATFORM_OBJECTS): CXXFLAGS := -std=c++11 -fPIC -DVCS -D_GNU_SOURCE -DVERILATOR -D_BSD_SOURCE -D_XOPEN_SOURCE=500 -DHOST_X_COORD=$(BSG_MACHINE_HOST_COORD_X) -DHOST_Y_COORD=$(BSG_MACHINE_HOST_COORD_Y) +$(PLATFORM_OBJECTS): CFLAGS := -std=c11 -fPIC -DVCS -D_GNU_SOURCE -DVERILATOR -D_BSD_SOURCE -D_XOPEN_SOURCE=500 -DHOST_X_COORD=$(BSG_MACHINE_HOST_COORD_X) -DHOST_Y_COORD=$(BSG_MACHINE_HOST_COORD_Y) -DNUM_DROMAJO_INSTR_PER_TICK=1000 -DNUM_TX_FIFO_CHK_PER_TICK=100 +$(PLATFORM_OBJECTS): CXXFLAGS := -std=c++11 -fPIC -DVCS -D_GNU_SOURCE -DVERILATOR -D_BSD_SOURCE -D_XOPEN_SOURCE=500 -DHOST_X_COORD=$(BSG_MACHINE_HOST_COORD_X) -DHOST_Y_COORD=$(BSG_MACHINE_HOST_COORD_Y) -DNUM_DROMAJO_INSTR_PER_TICK=1000 -DNUM_TX_FIFO_CHK_PER_TICK=100 $(PLATFORM_OBJECTS): LDFLAGS := -fPIC $(PLATFORM_OBJECTS): CXX = g++ diff --git a/libraries/platforms/dromajo-vcs/software/include/argp.h b/libraries/platforms/dromajo-vcs/software/include/argp.h index 07d864962..1e694a7f3 100644 --- a/libraries/platforms/dromajo-vcs/software/include/argp.h +++ b/libraries/platforms/dromajo-vcs/software/include/argp.h @@ -128,7 +128,7 @@ struct argp_child; /* " */ /* The type of a pointer to an argp parsing function. */ typedef error_t (*argp_parser_t) (int key, char *arg, - struct argp_state *state); + struct argp_state *state); /* What to return for unrecognized keys. For special ARGP_KEY_ keys, such returns will simply be ignored. For user keys, this error will be turned @@ -254,7 +254,7 @@ struct argp #define ARGP_KEY_HELP_POST_DOC 0x2000002 /* Help text following options. */ #define ARGP_KEY_HELP_HEADER 0x2000003 /* Option header string. */ #define ARGP_KEY_HELP_EXTRA 0x2000004 /* After all other documentation; - TEXT is NULL for this key. */ + TEXT is NULL for this key. */ /* Explanatory note emitted when duplicate option arguments have been suppressed. */ #define ARGP_KEY_HELP_DUP_ARGS_NOTE 0x2000005 @@ -385,13 +385,13 @@ struct argp_state returned. This function may also call exit unless the ARGP_NO_HELP flag is set. INPUT is a pointer to a value to be passed in to the parser. */ extern error_t argp_parse (__const struct argp *__restrict __argp, - int __argc, char **__restrict __argv, - unsigned __flags, int *__restrict __arg_index, - void *__restrict __input) __THROW; + int __argc, char **__restrict __argv, + unsigned __flags, int *__restrict __arg_index, + void *__restrict __input) __THROW; extern error_t __argp_parse (__const struct argp *__restrict __argp, - int __argc, char **__restrict __argv, - unsigned __flags, int *__restrict __arg_index, - void *__restrict __input) __THROW; + int __argc, char **__restrict __argv, + unsigned __flags, int *__restrict __arg_index, + void *__restrict __input) __THROW; /* Global variables. */ @@ -407,8 +407,8 @@ extern __const char *argp_program_version; the current parsing state, and then exits (unless the ARGP_NO_EXIT flag is used). This variable takes precedent over ARGP_PROGRAM_VERSION. */ extern void (*argp_program_version_hook) (FILE *__restrict __stream, - struct argp_state *__restrict - __state); + struct argp_state *__restrict + __state); /* If defined or set by the user program, it should point to string that is the bug-reporting address for the program. It will be printed by @@ -432,7 +432,7 @@ extern error_t argp_err_exit_status; #define ARGP_HELP_DOC (ARGP_HELP_PRE_DOC | ARGP_HELP_POST_DOC) #define ARGP_HELP_BUG_ADDR 0x40 /* bug report address */ #define ARGP_HELP_LONG_ONLY 0x80 /* modify output appropriately to - reflect ARGP_LONG_ONLY mode. */ + reflect ARGP_LONG_ONLY mode. */ /* These ARGP_HELP flags are only understood by argp_state_help. */ #define ARGP_HELP_EXIT_ERR 0x100 /* Call exit(1) instead of returning. */ @@ -454,11 +454,11 @@ extern error_t argp_err_exit_status; /* Output a usage message for ARGP to STREAM. FLAGS are from the set ARGP_HELP_*. */ extern void argp_help (__const struct argp *__restrict __argp, - FILE *__restrict __stream, - unsigned __flags, char *__restrict __name) __THROW; + FILE *__restrict __stream, + unsigned __flags, char *__restrict __name) __THROW; extern void __argp_help (__const struct argp *__restrict __argp, - FILE *__restrict __stream, unsigned __flags, - char *__name) __THROW; + FILE *__restrict __stream, unsigned __flags, + char *__name) __THROW; /* The following routines are intended to be called from within an argp parsing routine (thus taking an argp_state structure as the first @@ -471,20 +471,20 @@ extern void __argp_help (__const struct argp *__restrict __argp, /* Output, if appropriate, a usage message for STATE to STREAM. FLAGS are from the set ARGP_HELP_*. */ extern void argp_state_help (__const struct argp_state *__restrict __state, - FILE *__restrict __stream, - unsigned int __flags) __THROW; + FILE *__restrict __stream, + unsigned int __flags) __THROW; extern void __argp_state_help (__const struct argp_state *__restrict __state, - FILE *__restrict __stream, - unsigned int __flags) __THROW; + FILE *__restrict __stream, + unsigned int __flags) __THROW; /* If appropriate, print the printf string FMT and following args, preceded by the program name and `:', to stderr, and followed by a `Try ... --help' message, then exit (1). */ extern void argp_error (__const struct argp_state *__restrict __state, - __const char *__restrict __fmt, ...) __THROW + __const char *__restrict __fmt, ...) __THROW __attribute__ ((__format__ (__printf__, 2, 3))); extern void __argp_error (__const struct argp_state *__restrict __state, - __const char *__restrict __fmt, ...) __THROW + __const char *__restrict __fmt, ...) __THROW __attribute__ ((__format__ (__printf__, 2, 3))); /* Similar to the standard gnu error-reporting function error(), but will @@ -496,21 +496,21 @@ extern void __argp_error (__const struct argp_state *__restrict __state, *parsing errors*, and the former is for other problems that occur during parsing but don't reflect a (syntactic) problem with the input. */ extern void argp_failure (__const struct argp_state *__restrict __state, - int __status, int __errnum, - __const char *__restrict __fmt, ...) __THROW + int __status, int __errnum, + __const char *__restrict __fmt, ...) __THROW __attribute__ ((__format__ (__printf__, 4, 5))); extern void __argp_failure (__const struct argp_state *__restrict __state, - int __status, int __errnum, - __const char *__restrict __fmt, ...) __THROW + int __status, int __errnum, + __const char *__restrict __fmt, ...) __THROW __attribute__ ((__format__ (__printf__, 4, 5))); /* Return the input field for ARGP in the parser corresponding to STATE; used by the help routines. */ extern void *_argp_input (__const struct argp *__restrict __argp, - __const struct argp_state *__restrict __state) + __const struct argp_state *__restrict __state) __THROW; extern void *__argp_input (__const struct argp *__restrict __argp, - __const struct argp_state *__restrict __state) + __const struct argp_state *__restrict __state) __THROW; // Sripathi: diff --git a/libraries/platforms/dromajo-vcs/software/include/bp_utils.h b/libraries/platforms/dromajo-vcs/software/include/bp_utils.h index e6890506c..bcb2a4eeb 100644 --- a/libraries/platforms/dromajo-vcs/software/include/bp_utils.h +++ b/libraries/platforms/dromajo-vcs/software/include/bp_utils.h @@ -11,7 +11,7 @@ extern "C" { #include #include -#include +#include #define BP_CFG_BASE_ADDR 0x00200000 diff --git a/libraries/platforms/dromajo-vcs/software/src/argp/argp-fmtstream.c b/libraries/platforms/dromajo-vcs/software/src/argp/argp-fmtstream.c index 647ed985d..69f51cd4d 100644 --- a/libraries/platforms/dromajo-vcs/software/src/argp/argp-fmtstream.c +++ b/libraries/platforms/dromajo-vcs/software/src/argp/argp-fmtstream.c @@ -62,26 +62,26 @@ __argp_make_fmtstream (FILE *stream, size_t lmargin, size_t rmargin, ssize_t wma fs = (struct argp_fmtstream *) malloc (sizeof (struct argp_fmtstream)); if (fs != NULL) - { - fs->stream = stream; - - fs->lmargin = lmargin; - fs->rmargin = rmargin; - fs->wmargin = wmargin; - fs->point_col = 0; - fs->point_offs = 0; - - fs->buf = (char *) malloc (INIT_BUF_SIZE); - if (! fs->buf) - { - free (fs); - fs = 0; - } + { + fs->stream = stream; + + fs->lmargin = lmargin; + fs->rmargin = rmargin; + fs->wmargin = wmargin; + fs->point_col = 0; + fs->point_offs = 0; + + fs->buf = (char *) malloc (INIT_BUF_SIZE); + if (! fs->buf) + { + free (fs); + fs = 0; + } else - { - fs->p = fs->buf; - fs->end = fs->buf + INIT_BUF_SIZE; - } + { + fs->p = fs->buf; + fs->end = fs->buf + INIT_BUF_SIZE; + } } return fs; @@ -99,10 +99,10 @@ __argp_fmtstream_free (argp_fmtstream_t fs) { #ifdef USE_IN_LIBIO if (_IO_fwide (fs->stream, 0) > 0) - __fwprintf (fs->stream, L"%.*s", (int) (fs->p - fs->buf), fs->buf); + __fwprintf (fs->stream, L"%.*s", (int) (fs->p - fs->buf), fs->buf); else #endif - fwrite (fs->buf, 1, fs->p - fs->buf, fs->stream); + fwrite (fs->buf, 1, fs->p - fs->buf, fs->stream); } free (fs->buf); free (fs); @@ -126,214 +126,214 @@ __argp_fmtstream_update (argp_fmtstream_t fs) size_t r; if (fs->point_col == 0 && fs->lmargin != 0) - { - /* We are starting a new line. Print spaces to the left margin. */ - const size_t pad = fs->lmargin; - if (fs->p + pad < fs->end) - { - /* We can fit in them in the buffer by moving the - buffer text up and filling in the beginning. */ - memmove (buf + pad, buf, fs->p - buf); - fs->p += pad; /* Compensate for bigger buffer. */ - memset (buf, ' ', pad); /* Fill in the spaces. */ - buf += pad; /* Don't bother searching them. */ - } - else - { - /* No buffer space for spaces. Must flush. */ - size_t i; - for (i = 0; i < pad; i++) - { + { + /* We are starting a new line. Print spaces to the left margin. */ + const size_t pad = fs->lmargin; + if (fs->p + pad < fs->end) + { + /* We can fit in them in the buffer by moving the + buffer text up and filling in the beginning. */ + memmove (buf + pad, buf, fs->p - buf); + fs->p += pad; /* Compensate for bigger buffer. */ + memset (buf, ' ', pad); /* Fill in the spaces. */ + buf += pad; /* Don't bother searching them. */ + } + else + { + /* No buffer space for spaces. Must flush. */ + size_t i; + for (i = 0; i < pad; i++) + { #ifdef USE_IN_LIBIO - if (_IO_fwide (fs->stream, 0) > 0) - putwc_unlocked (L' ', fs->stream); - else + if (_IO_fwide (fs->stream, 0) > 0) + putwc_unlocked (L' ', fs->stream); + else #endif - putc_unlocked (' ', fs->stream); - } - } - fs->point_col = pad; - } + putc_unlocked (' ', fs->stream); + } + } + fs->point_col = pad; + } len = fs->p - buf; nl = memchr (buf, '\n', len); - if (fs->point_col < 0) - fs->point_col = 0; + if (fs->point_col < 0) + fs->point_col = 0; if (!nl) - { - /* The buffer ends in a partial line. */ - - if (fs->point_col + len < fs->rmargin) - { - /* The remaining buffer text is a partial line and fits - within the maximum line width. Advance point for the - characters to be written and stop scanning. */ - fs->point_col += len; - break; - } - else - /* Set the end-of-line pointer for the code below to - the end of the buffer. */ - nl = fs->p; - } + { + /* The buffer ends in a partial line. */ + + if (fs->point_col + len < fs->rmargin) + { + /* The remaining buffer text is a partial line and fits + within the maximum line width. Advance point for the + characters to be written and stop scanning. */ + fs->point_col += len; + break; + } + else + /* Set the end-of-line pointer for the code below to + the end of the buffer. */ + nl = fs->p; + } else if (fs->point_col + (nl - buf) < (ssize_t) fs->rmargin) - { - /* The buffer contains a full line that fits within the maximum - line width. Reset point and scan the next line. */ - fs->point_col = 0; - buf = nl + 1; - continue; - } + { + /* The buffer contains a full line that fits within the maximum + line width. Reset point and scan the next line. */ + fs->point_col = 0; + buf = nl + 1; + continue; + } /* This line is too long. */ r = fs->rmargin - 1; if (fs->wmargin < 0) - { - /* Truncate the line by overwriting the excess with the - newline and anything after it in the buffer. */ - if (nl < fs->p) - { - memmove (buf + (r - fs->point_col), nl, fs->p - nl); - fs->p -= buf + (r - fs->point_col) - nl; - /* Reset point for the next line and start scanning it. */ - fs->point_col = 0; - buf += r + 1; /* Skip full line plus \n. */ - } - else - { - /* The buffer ends with a partial line that is beyond the - maximum line width. Advance point for the characters - written, and discard those past the max from the buffer. */ - fs->point_col += len; - fs->p -= fs->point_col - r; - break; - } - } + { + /* Truncate the line by overwriting the excess with the + newline and anything after it in the buffer. */ + if (nl < fs->p) + { + memmove (buf + (r - fs->point_col), nl, fs->p - nl); + fs->p -= buf + (r - fs->point_col) - nl; + /* Reset point for the next line and start scanning it. */ + fs->point_col = 0; + buf += r + 1; /* Skip full line plus \n. */ + } + else + { + /* The buffer ends with a partial line that is beyond the + maximum line width. Advance point for the characters + written, and discard those past the max from the buffer. */ + fs->point_col += len; + fs->p -= fs->point_col - r; + break; + } + } else - { - /* Do word wrap. Go to the column just past the maximum line - width and scan back for the beginning of the word there. - Then insert a line break. */ - - char *p, *nextline; - int i; - - p = buf + (r + 1 - fs->point_col); - while (p >= buf && !isblank (*p)) - --p; - nextline = p + 1; /* This will begin the next line. */ - - if (nextline > buf) - { - /* Swallow separating blanks. */ - if (p >= buf) - do - --p; - while (p >= buf && isblank (*p)); - nl = p + 1; /* The newline will replace the first blank. */ - } - else - { - /* A single word that is greater than the maximum line width. - Oh well. Put it on an overlong line by itself. */ - p = buf + (r + 1 - fs->point_col); - /* Find the end of the long word. */ - do - ++p; - while (p < nl && !isblank (*p)); - if (p == nl) - { - /* It already ends a line. No fussing required. */ - fs->point_col = 0; - buf = nl + 1; - continue; - } - /* We will move the newline to replace the first blank. */ - nl = p; - /* Swallow separating blanks. */ - do - ++p; - while (isblank (*p)); - /* The next line will start here. */ - nextline = p; - } - - /* Note: There are a bunch of tests below for - NEXTLINE == BUF + LEN + 1; this case is where NL happens to fall - at the end of the buffer, and NEXTLINE is in fact empty (and so - we need not be careful to maintain its contents). */ - - if (nextline == buf + len + 1 - ? fs->end - nl < fs->wmargin + 1 - : nextline - (nl + 1) < fs->wmargin) - { - /* The margin needs more blanks than we removed. */ - if (fs->end - fs->p > fs->wmargin + 1) - /* Make some space for them. */ - { - size_t mv = fs->p - nextline; - memmove (nl + 1 + fs->wmargin, nextline, mv); - nextline = nl + 1 + fs->wmargin; - len = nextline + mv - buf; - *nl++ = '\n'; - } - else - /* Output the first line so we can use the space. */ - { + { + /* Do word wrap. Go to the column just past the maximum line + width and scan back for the beginning of the word there. + Then insert a line break. */ + + char *p, *nextline; + int i; + + p = buf + (r + 1 - fs->point_col); + while (p >= buf && !isblank (*p)) + --p; + nextline = p + 1; /* This will begin the next line. */ + + if (nextline > buf) + { + /* Swallow separating blanks. */ + if (p >= buf) + do + --p; + while (p >= buf && isblank (*p)); + nl = p + 1; /* The newline will replace the first blank. */ + } + else + { + /* A single word that is greater than the maximum line width. + Oh well. Put it on an overlong line by itself. */ + p = buf + (r + 1 - fs->point_col); + /* Find the end of the long word. */ + do + ++p; + while (p < nl && !isblank (*p)); + if (p == nl) + { + /* It already ends a line. No fussing required. */ + fs->point_col = 0; + buf = nl + 1; + continue; + } + /* We will move the newline to replace the first blank. */ + nl = p; + /* Swallow separating blanks. */ + do + ++p; + while (isblank (*p)); + /* The next line will start here. */ + nextline = p; + } + + /* Note: There are a bunch of tests below for + NEXTLINE == BUF + LEN + 1; this case is where NL happens to fall + at the end of the buffer, and NEXTLINE is in fact empty (and so + we need not be careful to maintain its contents). */ + + if (nextline == buf + len + 1 + ? fs->end - nl < fs->wmargin + 1 + : nextline - (nl + 1) < fs->wmargin) + { + /* The margin needs more blanks than we removed. */ + if (fs->end - fs->p > fs->wmargin + 1) + /* Make some space for them. */ + { + size_t mv = fs->p - nextline; + memmove (nl + 1 + fs->wmargin, nextline, mv); + nextline = nl + 1 + fs->wmargin; + len = nextline + mv - buf; + *nl++ = '\n'; + } + else + /* Output the first line so we can use the space. */ + { #ifdef USE_IN_LIBIO - if (_IO_fwide (fs->stream, 0) > 0) - __fwprintf (fs->stream, L"%.*s\n", - (int) (nl - fs->buf), fs->buf); - else + if (_IO_fwide (fs->stream, 0) > 0) + __fwprintf (fs->stream, L"%.*s\n", + (int) (nl - fs->buf), fs->buf); + else #endif - { - if (nl > fs->buf) - fwrite (fs->buf, 1, nl - fs->buf, fs->stream); - putc_unlocked ('\n', fs->stream); - } - len += buf - fs->buf; - nl = buf = fs->buf; - } - } - else - /* We can fit the newline and blanks in before - the next word. */ - *nl++ = '\n'; - - if (nextline - nl >= fs->wmargin - || (nextline == buf + len + 1 && fs->end - nextline >= fs->wmargin)) - /* Add blanks up to the wrap margin column. */ - for (i = 0; i < fs->wmargin; ++i) - *nl++ = ' '; - else - for (i = 0; i < fs->wmargin; ++i) + { + if (nl > fs->buf) + fwrite (fs->buf, 1, nl - fs->buf, fs->stream); + putc_unlocked ('\n', fs->stream); + } + len += buf - fs->buf; + nl = buf = fs->buf; + } + } + else + /* We can fit the newline and blanks in before + the next word. */ + *nl++ = '\n'; + + if (nextline - nl >= fs->wmargin + || (nextline == buf + len + 1 && fs->end - nextline >= fs->wmargin)) + /* Add blanks up to the wrap margin column. */ + for (i = 0; i < fs->wmargin; ++i) + *nl++ = ' '; + else + for (i = 0; i < fs->wmargin; ++i) #ifdef USE_IN_LIBIO - if (_IO_fwide (fs->stream, 0) > 0) - putwc_unlocked (L' ', fs->stream); - else + if (_IO_fwide (fs->stream, 0) > 0) + putwc_unlocked (L' ', fs->stream); + else #endif - putc_unlocked (' ', fs->stream); + putc_unlocked (' ', fs->stream); - /* Copy the tail of the original buffer into the current buffer - position. */ - if (nl < nextline) - memmove (nl, nextline, buf + len - nextline); - len -= nextline - buf; + /* Copy the tail of the original buffer into the current buffer + position. */ + if (nl < nextline) + memmove (nl, nextline, buf + len - nextline); + len -= nextline - buf; - /* Continue the scan on the remaining lines in the buffer. */ - buf = nl; + /* Continue the scan on the remaining lines in the buffer. */ + buf = nl; - /* Restore bufp to include all the remaining text. */ - fs->p = nl + len; + /* Restore bufp to include all the remaining text. */ + fs->p = nl + len; - /* Reset the counter of what has been output this line. If wmargin - is 0, we want to avoid the lmargin getting added, so we set - point_col to a magic value of -1 in that case. */ - fs->point_col = fs->wmargin ? fs->wmargin : -1; - } + /* Reset the counter of what has been output this line. If wmargin + is 0, we want to avoid the lmargin getting added, so we set + point_col to a magic value of -1 in that case. */ + fs->point_col = fs->wmargin ? fs->wmargin : -1; + } } /* Remember that we've scanned as far as the end of the buffer. */ @@ -354,42 +354,42 @@ __argp_fmtstream_ensure (struct argp_fmtstream *fs, size_t amount) #ifdef USE_IN_LIBIO if (_IO_fwide (fs->stream, 0) > 0) - { - __fwprintf (fs->stream, L"%.*s", (int) (fs->p - fs->buf), fs->buf); - wrote = fs->p - fs->buf; - } - else + { + __fwprintf (fs->stream, L"%.*s", (int) (fs->p - fs->buf), fs->buf); + wrote = fs->p - fs->buf; + } + else #endif - wrote = fwrite (fs->buf, 1, fs->p - fs->buf, fs->stream); + wrote = fwrite (fs->buf, 1, fs->p - fs->buf, fs->stream); if (wrote == fs->p - fs->buf) - { - fs->p = fs->buf; - fs->point_offs = 0; - } + { + fs->p = fs->buf; + fs->point_offs = 0; + } else - { - fs->p -= wrote; - fs->point_offs -= wrote; - memmove (fs->buf, fs->buf + wrote, fs->p - fs->buf); - return 0; - } + { + fs->p -= wrote; + fs->point_offs -= wrote; + memmove (fs->buf, fs->buf + wrote, fs->p - fs->buf); + return 0; + } if ((size_t) (fs->end - fs->buf) < amount) - /* Gotta grow the buffer. */ - { - size_t new_size = fs->end - fs->buf + amount; - char *new_buf = realloc (fs->buf, new_size); - - if (! new_buf) - { - __set_errno (ENOMEM); - return 0; - } - - fs->buf = new_buf; - fs->end = new_buf + new_size; - fs->p = fs->buf; - } + /* Gotta grow the buffer. */ + { + size_t new_size = fs->end - fs->buf + amount; + char *new_buf = realloc (fs->buf, new_size); + + if (! new_buf) + { + __set_errno (ENOMEM); + return 0; + } + + fs->buf = new_buf; + fs->end = new_buf + new_size; + fs->p = fs->buf; + } } return 1; @@ -407,14 +407,14 @@ __argp_fmtstream_printf (struct argp_fmtstream *fs, const char *fmt, ...) va_list args; if (! __argp_fmtstream_ensure (fs, size_guess)) - return -1; - - va_start (args, fmt); - avail = fs->end - fs->p; - out = __vsnprintf (fs->p, avail, fmt, args); - va_end (args); - if (out >= avail) - size_guess = out + 1; + return -1; + + va_start (args, fmt); + avail = fs->end - fs->p; + out = __vsnprintf (fs->p, avail, fmt, args); + va_end (args); + if (out >= avail) + size_guess = out + 1; } while (out >= avail); diff --git a/libraries/platforms/dromajo-vcs/software/src/argp/argp-help.c b/libraries/platforms/dromajo-vcs/software/src/argp/argp-help.c index 69325fecd..0b13e2502 100644 --- a/libraries/platforms/dromajo-vcs/software/src/argp/argp-help.c +++ b/libraries/platforms/dromajo-vcs/software/src/argp/argp-help.c @@ -161,78 +161,78 @@ fill_in_uparams (const struct argp_state *state) /* Parse var. */ while (*var) { - SKIPWS (var); - - if (isalpha (*var)) - { - size_t var_len; - const struct uparam_name *un; - int unspec = 0, val = 0; - const char *arg = var; - - while (isalnum (*arg) || *arg == '-' || *arg == '_') - arg++; - var_len = arg - var; - - SKIPWS (arg); - - if (*arg == '\0' || *arg == ',') - unspec = 1; - else if (*arg == '=') - { - arg++; - SKIPWS (arg); - } - - if (unspec) - { - if (var[0] == 'n' && var[1] == 'o' && var[2] == '-') - { - val = 0; - var += 3; - var_len -= 3; - } - else - val = 1; - } - else if (isdigit (*arg)) - { - val = atoi (arg); - while (isdigit (*arg)) - arg++; - SKIPWS (arg); - } - - for (un = uparam_names; un->name; un++) - if (strlen (un->name) == var_len - && strncmp (var, un->name, var_len) == 0) - { - if (unspec && !un->is_bool) - __argp_failure (state, 0, 0, - dgettext (state->root_argp->argp_domain, "\ - %.*s: ARGP_HELP_FMT parameter requires a value"), - (int) var_len, var); - else - *(int *)((char *)&uparams + un->uparams_offs) = val; - break; - } - if (! un->name) - __argp_failure (state, 0, 0, - dgettext (state->root_argp->argp_domain, "\ - %.*s: Unknown ARGP_HELP_FMT parameter"), - (int) var_len, var); - - var = arg; - if (*var == ',') - var++; - } - else if (*var) - { - __argp_failure (state, 0, 0, - dgettext (state->root_argp->argp_domain, - "Garbage in ARGP_HELP_FMT: %s"), var); - break; - } + SKIPWS (var); + + if (isalpha (*var)) + { + size_t var_len; + const struct uparam_name *un; + int unspec = 0, val = 0; + const char *arg = var; + + while (isalnum (*arg) || *arg == '-' || *arg == '_') + arg++; + var_len = arg - var; + + SKIPWS (arg); + + if (*arg == '\0' || *arg == ',') + unspec = 1; + else if (*arg == '=') + { + arg++; + SKIPWS (arg); + } + + if (unspec) + { + if (var[0] == 'n' && var[1] == 'o' && var[2] == '-') + { + val = 0; + var += 3; + var_len -= 3; + } + else + val = 1; + } + else if (isdigit (*arg)) + { + val = atoi (arg); + while (isdigit (*arg)) + arg++; + SKIPWS (arg); + } + + for (un = uparam_names; un->name; un++) + if (strlen (un->name) == var_len + && strncmp (var, un->name, var_len) == 0) + { + if (unspec && !un->is_bool) + __argp_failure (state, 0, 0, + dgettext (state->root_argp->argp_domain, "\ + %.*s: ARGP_HELP_FMT parameter requires a value"), + (int) var_len, var); + else + *(int *)((char *)&uparams + un->uparams_offs) = val; + break; + } + if (! un->name) + __argp_failure (state, 0, 0, + dgettext (state->root_argp->argp_domain, "\ + %.*s: Unknown ARGP_HELP_FMT parameter"), + (int) var_len, var); + + var = arg; + if (*var == ',') + var++; + } + else if (*var) + { + __argp_failure (state, 0, 0, + dgettext (state->root_argp->argp_domain, + "Garbage in ARGP_HELP_FMT: %s"), var); + break; + } } } @@ -268,22 +268,22 @@ fill_in_uparams (const struct argp_state *state) For example, the following output (from ps): -p PID, --pid=PID List the process PID - --pgrp=PGRP List processes in the process group PGRP + --pgrp=PGRP List processes in the process group PGRP -P, -x, --no-parent Include processes without parents -Q, --all-fields Don't elide unusable fields (normally if there's - some reason ps can't print a field for any - process, it's removed from the output entirely) + some reason ps can't print a field for any + process, it's removed from the output entirely) -r, --reverse, --gratuitously-long-reverse-option - Reverse the order of any sort - --session[=SID] Add the processes from the session SID (which - defaults to the sid of the current process) + Reverse the order of any sort + --session[=SID] Add the processes from the session SID (which + defaults to the sid of the current process) Here are some more options: -f ZOT, --foonly=ZOT Glork a foonly -z, --zaza Snit a zar -?, --help Give this help list - --usage Give a short usage message + --usage Give a short usage message -V, --version Print program version The struct argp_option array for the above could look like: @@ -295,14 +295,14 @@ fill_in_uparams (const struct argp_state *state) {0, 'x', 0, OPTION_ALIAS}, {"all-fields",'Q', 0, 0, "Don't elide unusable fields (normally" " if there's some reason ps can't" - " print a field for any process, it's" + " print a field for any process, it's" " removed from the output entirely)" }, {"reverse", 'r', 0, 0, "Reverse the order of any sort"}, {"gratuitously-long-reverse-option", 0, 0, OPTION_ALIAS}, {"session", OPT_SESS, "SID", OPTION_ARG_OPTIONAL, "Add the processes from the session" - " SID (which defaults to the sid of" - " the current process)" }, + " SID (which defaults to the sid of" + " the current process)" }, {0,0,0,0, "Here are some more options:"}, {"foonly", 'f', "ZOT", 0, "Glork a foonly"}, @@ -422,52 +422,52 @@ make_hol (const struct argp *argp, struct hol_cluster *cluster) hol->clusters = 0; if (opts) - { - int cur_group = 0; - - /* The first option must not be an alias. */ - assert (! oalias (opts)); - - /* Calculate the space needed. */ - for (o = opts; ! oend (o); o++) - { - if (! oalias (o)) - hol->num_entries++; - if (oshort (o)) - num_short_options++; /* This is an upper bound. */ - } - - hol->entries = malloc (sizeof (struct hol_entry) * hol->num_entries); - hol->short_options = malloc (num_short_options + 1); - - assert (hol->entries && hol->short_options); - - /* Fill in the entries. */ - so = hol->short_options; - for (o = opts, entry = hol->entries; ! oend (o); entry++) - { - entry->opt = o; - entry->num = 0; - entry->short_options = so; - entry->group = cur_group = - o->group - ? o->group - : ((!o->name && !o->key) - ? cur_group + 1 - : cur_group); - entry->cluster = cluster; - entry->argp = argp; - - do - { - entry->num++; - if (oshort (o) && ! find_char (o->key, hol->short_options, so)) - /* O has a valid short option which hasn't already been used.*/ - *so++ = o->key; - o++; - } - while (! oend (o) && oalias (o)); - } + { + int cur_group = 0; + + /* The first option must not be an alias. */ + assert (! oalias (opts)); + + /* Calculate the space needed. */ + for (o = opts; ! oend (o); o++) + { + if (! oalias (o)) + hol->num_entries++; + if (oshort (o)) + num_short_options++; /* This is an upper bound. */ + } + + hol->entries = malloc (sizeof (struct hol_entry) * hol->num_entries); + hol->short_options = malloc (num_short_options + 1); + + assert (hol->entries && hol->short_options); + + /* Fill in the entries. */ + so = hol->short_options; + for (o = opts, entry = hol->entries; ! oend (o); entry++) + { + entry->opt = o; + entry->num = 0; + entry->short_options = so; + entry->group = cur_group = + o->group + ? o->group + : ((!o->name && !o->key) + ? cur_group + 1 + : cur_group); + entry->cluster = cluster; + entry->argp = argp; + + do + { + entry->num++; + if (oshort (o) && ! find_char (o->key, hol->short_options, so)) + /* O has a valid short option which hasn't already been used.*/ + *so++ = o->key; + o++; + } + while (! oend (o) && oalias (o)); + } *so = '\0'; /* null terminated so we can find the length */ } @@ -479,22 +479,22 @@ make_hol (const struct argp *argp, struct hol_cluster *cluster) to it. ARGP is the argp that this cluster results from. */ static struct hol_cluster * hol_add_cluster (struct hol *hol, int group, const char *header, int index, - struct hol_cluster *parent, const struct argp *argp) + struct hol_cluster *parent, const struct argp *argp) { struct hol_cluster *cl = malloc (sizeof (struct hol_cluster)); if (cl) - { - cl->group = group; - cl->header = header; - - cl->index = index; - cl->parent = parent; - cl->argp = argp; - cl->depth = parent ? parent->depth + 1 : 0; - - cl->next = hol->clusters; - hol->clusters = cl; - } + { + cl->group = group; + cl->header = header; + + cl->index = index; + cl->parent = parent; + cl->argp = argp; + cl->depth = parent ? parent->depth + 1 : 0; + + cl->next = hol->clusters; + hol->clusters = cl; + } return cl; } @@ -505,27 +505,27 @@ hol_free (struct hol *hol) struct hol_cluster *cl = hol->clusters; while (cl) - { - struct hol_cluster *next = cl->next; - free (cl); - cl = next; - } + { + struct hol_cluster *next = cl->next; + free (cl); + cl = next; + } if (hol->num_entries > 0) - { - free (hol->entries); - free (hol->short_options); - } + { + free (hol->entries); + free (hol->short_options); + } free (hol); } static inline int hol_entry_short_iterate (const struct hol_entry *entry, - int (*func)(const struct argp_option *opt, - const struct argp_option *real, - const char *domain, void *cookie), - const char *domain, void *cookie) + int (*func)(const struct argp_option *opt, + const struct argp_option *real, + const char *domain, void *cookie), + const char *domain, void *cookie) { unsigned nopts; int val = 0; @@ -535,11 +535,11 @@ hol_entry_short_iterate (const struct hol_entry *entry, for (opt = real, nopts = entry->num; nopts > 0 && !val; opt++, nopts--) if (oshort (opt) && *so == opt->key) { - if (!oalias (opt)) - real = opt; - if (ovisible (opt)) - val = (*func)(opt, real, domain, cookie); - so++; + if (!oalias (opt)) + real = opt; + if (ovisible (opt)) + val = (*func)(opt, real, domain, cookie); + so++; } return val; @@ -547,10 +547,10 @@ hol_entry_short_iterate (const struct hol_entry *entry, static inline int hol_entry_long_iterate (const struct hol_entry *entry, - int (*func)(const struct argp_option *opt, - const struct argp_option *real, - const char *domain, void *cookie), - const char *domain, void *cookie) + int (*func)(const struct argp_option *opt, + const struct argp_option *real, + const char *domain, void *cookie), + const char *domain, void *cookie) { unsigned nopts; int val = 0; @@ -559,10 +559,10 @@ hol_entry_long_iterate (const struct hol_entry *entry, for (opt = real, nopts = entry->num; nopts > 0 && !val; opt++, nopts--) if (opt->name) { - if (!oalias (opt)) - real = opt; - if (ovisible (opt)) - val = (*func)(opt, real, domain, cookie); + if (!oalias (opt)) + real = opt; + if (ovisible (opt)) + val = (*func)(opt, real, domain, cookie); } return val; @@ -571,7 +571,7 @@ hol_entry_long_iterate (const struct hol_entry *entry, /* Iterator that returns true for the first short option. */ static inline int until_short (const struct argp_option *opt, const struct argp_option *real, - const char *domain, void *cookie) + const char *domain, void *cookie) { return oshort (opt) ? opt->key : 0; } @@ -581,7 +581,7 @@ static char hol_entry_first_short (const struct hol_entry *entry) { return hol_entry_short_iterate (entry, until_short, - entry->argp->argp_domain, 0); + entry->argp->argp_domain, 0); } /* Returns the first valid long option in ENTRY, or 0 if there is none. */ @@ -605,15 +605,15 @@ hol_find_entry (struct hol *hol, const char *name) unsigned num_entries = hol->num_entries; while (num_entries-- > 0) - { - const struct argp_option *opt = entry->opt; - unsigned num_opts = entry->num; + { + const struct argp_option *opt = entry->opt; + unsigned num_opts = entry->num; - while (num_opts-- > 0) - if (opt->name && ovisible (opt) && strcmp (opt->name, name) == 0) - return entry; - else - opt++; + while (num_opts-- > 0) + if (opt->name && ovisible (opt) && strcmp (opt->name, name) == 0) + return entry; + else + opt++; entry++; } @@ -677,7 +677,7 @@ hol_cluster_base (struct hol_cluster *cl) /* Return true if CL1 is a child of CL2. */ static int hol_cluster_is_child (const struct hol_cluster *cl1, - const struct hol_cluster *cl2) + const struct hol_cluster *cl2) { while (cl1 && cl1 != cl2) cl1 = cl1->parent; @@ -706,70 +706,70 @@ canon_doc_option (const char **name) listing. */ static int hol_entry_cmp (const struct hol_entry *entry1, - const struct hol_entry *entry2) + const struct hol_entry *entry2) { /* The group numbers by which the entries should be ordered; if either is in a cluster, then this is just the group within the cluster. */ int group1 = entry1->group, group2 = entry2->group; if (entry1->cluster != entry2->cluster) - { - /* The entries are not within the same cluster, so we can't compare them - directly, we have to use the appropiate clustering level too. */ - if (! entry1->cluster) - /* ENTRY1 is at the `base level', not in a cluster, so we have to - compare it's group number with that of the base cluster in which - ENTRY2 resides. Note that if they're in the same group, the - clustered option always comes laster. */ - return group_cmp (group1, hol_cluster_base (entry2->cluster)->group, -1); - else if (! entry2->cluster) - /* Likewise, but ENTRY2's not in a cluster. */ - return group_cmp (hol_cluster_base (entry1->cluster)->group, group2, 1); + { + /* The entries are not within the same cluster, so we can't compare them + directly, we have to use the appropiate clustering level too. */ + if (! entry1->cluster) + /* ENTRY1 is at the `base level', not in a cluster, so we have to + compare it's group number with that of the base cluster in which + ENTRY2 resides. Note that if they're in the same group, the + clustered option always comes laster. */ + return group_cmp (group1, hol_cluster_base (entry2->cluster)->group, -1); + else if (! entry2->cluster) + /* Likewise, but ENTRY2's not in a cluster. */ + return group_cmp (hol_cluster_base (entry1->cluster)->group, group2, 1); else - /* Both entries are in clusters, we can just compare the clusters. */ - return hol_cluster_cmp (entry1->cluster, entry2->cluster); + /* Both entries are in clusters, we can just compare the clusters. */ + return hol_cluster_cmp (entry1->cluster, entry2->cluster); } else if (group1 == group2) /* The entries are both in the same cluster and group, so compare them alphabetically. */ - { - int short1 = hol_entry_first_short (entry1); - int short2 = hol_entry_first_short (entry2); - int doc1 = odoc (entry1->opt); - int doc2 = odoc (entry2->opt); - const char *long1 = hol_entry_first_long (entry1); - const char *long2 = hol_entry_first_long (entry2); + { + int short1 = hol_entry_first_short (entry1); + int short2 = hol_entry_first_short (entry2); + int doc1 = odoc (entry1->opt); + int doc2 = odoc (entry2->opt); + const char *long1 = hol_entry_first_long (entry1); + const char *long2 = hol_entry_first_long (entry2); if (doc1) - doc1 = canon_doc_option (&long1); + doc1 = canon_doc_option (&long1); if (doc2) - doc2 = canon_doc_option (&long2); + doc2 = canon_doc_option (&long2); if (doc1 != doc2) - /* `documentation' options always follow normal options (or - documentation options that *look* like normal options). */ - return doc1 - doc2; + /* `documentation' options always follow normal options (or + documentation options that *look* like normal options). */ + return doc1 - doc2; else if (!short1 && !short2 && long1 && long2) - /* Only long options. */ - return __strcasecmp (long1, long2); + /* Only long options. */ + return __strcasecmp (long1, long2); else - /* Compare short/short, long/short, short/long, using the first - character of long options. Entries without *any* valid - options (such as options with OPTION_HIDDEN set) will be put - first, but as they're not displayed, it doesn't matter where - they are. */ - { - char first1 = short1 ? short1 : long1 ? *long1 : 0; - char first2 = short2 ? short2 : long2 ? *long2 : 0; + /* Compare short/short, long/short, short/long, using the first + character of long options. Entries without *any* valid + options (such as options with OPTION_HIDDEN set) will be put + first, but as they're not displayed, it doesn't matter where + they are. */ + { + char first1 = short1 ? short1 : long1 ? *long1 : 0; + char first2 = short2 ? short2 : long2 ? *long2 : 0; #ifdef _tolower - int lower_cmp = _tolower (first1) - _tolower (first2); + int lower_cmp = _tolower (first1) - _tolower (first2); #else - int lower_cmp = tolower (first1) - tolower (first2); + int lower_cmp = tolower (first1) - tolower (first2); #endif - /* Compare ignoring case, except when the options are both the - same letter, in which case lower-case always comes first. */ - return lower_cmp ? lower_cmp : first2 - first1; - } + /* Compare ignoring case, except when the options are both the + same letter, in which case lower-case always comes first. */ + return lower_cmp ? lower_cmp : first2 - first1; + } } else /* Within the same cluster, but not the same group, so just compare @@ -792,7 +792,7 @@ hol_sort (struct hol *hol) { if (hol->num_entries > 0) qsort (hol->entries, hol->num_entries, sizeof (struct hol_entry), - hol_entry_qcmp); + hol_entry_qcmp); } /* Append MORE to HOL, destroying MORE in the process. Options in HOL shadow @@ -813,75 +813,75 @@ hol_append (struct hol *hol, struct hol *more) if (more->num_entries > 0) { if (hol->num_entries == 0) - { - hol->num_entries = more->num_entries; - hol->entries = more->entries; - hol->short_options = more->short_options; - more->num_entries = 0; /* Mark MORE's fields as invalid. */ - } + { + hol->num_entries = more->num_entries; + hol->entries = more->entries; + hol->short_options = more->short_options; + more->num_entries = 0; /* Mark MORE's fields as invalid. */ + } else - /* Append the entries in MORE to those in HOL, taking care to only add - non-shadowed SHORT_OPTIONS values. */ - { - unsigned left; - char *so, *more_so; - struct hol_entry *e; - unsigned num_entries = hol->num_entries + more->num_entries; - struct hol_entry *entries = - malloc (num_entries * sizeof (struct hol_entry)); - unsigned hol_so_len = strlen (hol->short_options); - char *short_options = - malloc (hol_so_len + strlen (more->short_options) + 1); + /* Append the entries in MORE to those in HOL, taking care to only add + non-shadowed SHORT_OPTIONS values. */ + { + unsigned left; + char *so, *more_so; + struct hol_entry *e; + unsigned num_entries = hol->num_entries + more->num_entries; + struct hol_entry *entries = + malloc (num_entries * sizeof (struct hol_entry)); + unsigned hol_so_len = strlen (hol->short_options); + char *short_options = + malloc (hol_so_len + strlen (more->short_options) + 1); tmp = memcpy (entries, hol->entries, hol->num_entries * sizeof (struct hol_entry)); tmp += hol->num_entries * sizeof (struct hol_entry); - memcpy (tmp, - more->entries, + memcpy (tmp, + more->entries, more->num_entries * sizeof (struct hol_entry)); - memcpy (short_options, hol->short_options, hol_so_len); - - /* Fix up the short options pointers from HOL. */ - for (e = entries, left = hol->num_entries; left > 0; e++, left--) - e->short_options += (short_options - hol->short_options); - - /* Now add the short options from MORE, fixing up its entries - too. */ - so = short_options + hol_so_len; - more_so = more->short_options; - for (left = more->num_entries; left > 0; e++, left--) - { - int opts_left; - const struct argp_option *opt; - - e->short_options = so; - - for (opts_left = e->num, opt = e->opt; opts_left; opt++, opts_left--) - { - int ch = *more_so; - if (oshort (opt) && ch == opt->key) - /* The next short option in MORE_SO, CH, is from OPT. */ - { - if (! find_char (ch, short_options, - short_options + hol_so_len)) - /* The short option CH isn't shadowed by HOL's options, - so add it to the sum. */ - *so++ = ch; - more_so++; - } - } - } - - *so = '\0'; - - free (hol->entries); - free (hol->short_options); - - hol->entries = entries; - hol->num_entries = num_entries; - hol->short_options = short_options; - } + memcpy (short_options, hol->short_options, hol_so_len); + + /* Fix up the short options pointers from HOL. */ + for (e = entries, left = hol->num_entries; left > 0; e++, left--) + e->short_options += (short_options - hol->short_options); + + /* Now add the short options from MORE, fixing up its entries + too. */ + so = short_options + hol_so_len; + more_so = more->short_options; + for (left = more->num_entries; left > 0; e++, left--) + { + int opts_left; + const struct argp_option *opt; + + e->short_options = so; + + for (opts_left = e->num, opt = e->opt; opts_left; opt++, opts_left--) + { + int ch = *more_so; + if (oshort (opt) && ch == opt->key) + /* The next short option in MORE_SO, CH, is from OPT. */ + { + if (! find_char (ch, short_options, + short_options + hol_so_len)) + /* The short option CH isn't shadowed by HOL's options, + so add it to the sum. */ + *so++ = ch; + more_so++; + } + } + } + + *so = '\0'; + + free (hol->entries); + free (hol->short_options); + + hol->entries = entries; + hol->num_entries = num_entries; + hol->short_options = short_options; + } } hol_free (more); @@ -918,11 +918,11 @@ arg (const struct argp_option *real, const char *req_fmt, const char *opt_fmt, if (real->arg) { if (real->flags & OPTION_ARG_OPTIONAL) - __argp_fmtstream_printf (stream, opt_fmt, - dgettext (domain, real->arg)); + __argp_fmtstream_printf (stream, opt_fmt, + dgettext (domain, real->arg)); else - __argp_fmtstream_printf (stream, req_fmt, - dgettext (domain, real->arg)); + __argp_fmtstream_printf (stream, req_fmt, + dgettext (domain, real->arg)); } } @@ -962,14 +962,14 @@ struct pentry_state /* If a user doc filter should be applied to DOC, do so. */ static const char * filter_doc (const char *doc, int key, const struct argp *argp, - const struct argp_state *state) + const struct argp_state *state) { if (argp->help_filter) /* We must apply a user filter to this output. */ { - void *input = __argp_input (argp, state); - return (*argp->help_filter) (key, doc, input); - } + void *input = __argp_input (argp, state); + return (*argp->help_filter) (key, doc, input); + } else /* No filter. */ return doc; @@ -982,7 +982,7 @@ filter_doc (const char *doc, int key, const struct argp *argp, to 0. */ static void print_header (const char *str, const struct argp *argp, - struct pentry_state *pest) + struct pentry_state *pest) { const char *tstr = dgettext (argp->argp_domain, str); const char *fstr = filter_doc (tstr, ARGP_KEY_HELP_HEADER, argp, pest->state); @@ -990,17 +990,17 @@ print_header (const char *str, const struct argp *argp, if (fstr) { if (*fstr) - { - if (pest->hhstate->prev_entry) - /* Precede with a blank line. */ - __argp_fmtstream_putc (pest->stream, '\n'); - indent_to (pest->stream, uparams.header_col); - __argp_fmtstream_set_lmargin (pest->stream, uparams.header_col); - __argp_fmtstream_set_wmargin (pest->stream, uparams.header_col); - __argp_fmtstream_puts (pest->stream, fstr); - __argp_fmtstream_set_lmargin (pest->stream, 0); - __argp_fmtstream_putc (pest->stream, '\n'); - } + { + if (pest->hhstate->prev_entry) + /* Precede with a blank line. */ + __argp_fmtstream_putc (pest->stream, '\n'); + indent_to (pest->stream, uparams.header_col); + __argp_fmtstream_set_lmargin (pest->stream, uparams.header_col); + __argp_fmtstream_set_wmargin (pest->stream, uparams.header_col); + __argp_fmtstream_puts (pest->stream, fstr); + __argp_fmtstream_set_lmargin (pest->stream, 0); + __argp_fmtstream_putc (pest->stream, '\n'); + } pest->hhstate->sep_groups = 1; /* Separate subsequent groups. */ } @@ -1022,21 +1022,21 @@ comma (unsigned col, struct pentry_state *pest) const struct hol_cluster *cl = pest->entry->cluster; if (pest->hhstate->sep_groups && pe && pest->entry->group != pe->group) - __argp_fmtstream_putc (pest->stream, '\n'); + __argp_fmtstream_putc (pest->stream, '\n'); if (cl && cl->header && *cl->header - && (!pe - || (pe->cluster != cl - && !hol_cluster_is_child (pe->cluster, cl)))) - /* If we're changing clusters, then this must be the start of the - ENTRY's cluster unless that is an ancestor of the previous one - (in which case we had just popped into a sub-cluster for a bit). - If so, then print the cluster's header line. */ - { - int old_wm = __argp_fmtstream_wmargin (pest->stream); - print_header (cl->header, cl->argp, pest); - __argp_fmtstream_set_wmargin (pest->stream, old_wm); - } + && (!pe + || (pe->cluster != cl + && !hol_cluster_is_child (pe->cluster, cl)))) + /* If we're changing clusters, then this must be the start of the + ENTRY's cluster unless that is an ancestor of the previous one + (in which case we had just popped into a sub-cluster for a bit). + If so, then print the cluster's header line. */ + { + int old_wm = __argp_fmtstream_wmargin (pest->stream); + print_header (cl->header, cl->argp, pest); + __argp_fmtstream_set_wmargin (pest->stream, old_wm); + } pest->first = 0; } @@ -1049,7 +1049,7 @@ comma (unsigned col, struct pentry_state *pest) /* Print help for ENTRY to STREAM. */ static void hol_entry_help (struct hol_entry *entry, const struct argp_state *state, - argp_fmtstream_t stream, struct hol_help_state *hhstate) + argp_fmtstream_t stream, struct hol_help_state *hhstate) { unsigned num; const struct argp_option *real = entry->opt, *opt; @@ -1065,10 +1065,10 @@ hol_entry_help (struct hol_entry *entry, const struct argp_state *state, if (! odoc (real)) for (opt = real, num = entry->num; num > 0; opt++, num--) if (opt->name && ovisible (opt)) - { - have_long_opt = 1; - break; - } + { + have_long_opt = 1; + break; + } /* First emit short options. */ __argp_fmtstream_set_wmargin (stream, uparams.short_opt_col); /* For truly bizarre cases. */ @@ -1076,17 +1076,17 @@ hol_entry_help (struct hol_entry *entry, const struct argp_state *state, if (oshort (opt) && opt->key == *so) /* OPT has a valid (non shadowed) short option. */ { - if (ovisible (opt)) - { - comma (uparams.short_opt_col, &pest); - __argp_fmtstream_putc (stream, '-'); - __argp_fmtstream_putc (stream, *so); - if (!have_long_opt || uparams.dup_args) - arg (real, " %s", "[%s]", state->root_argp->argp_domain, stream); - else if (real->arg) - hhstate->suppressed_dup_arg = 1; - } - so++; + if (ovisible (opt)) + { + comma (uparams.short_opt_col, &pest); + __argp_fmtstream_putc (stream, '-'); + __argp_fmtstream_putc (stream, *so); + if (!have_long_opt || uparams.dup_args) + arg (real, " %s", "[%s]", state->root_argp->argp_domain, stream); + else if (real->arg) + hhstate->suppressed_dup_arg = 1; + } + so++; } /* Now, long options. */ @@ -1095,78 +1095,78 @@ hol_entry_help (struct hol_entry *entry, const struct argp_state *state, { __argp_fmtstream_set_wmargin (stream, uparams.doc_opt_col); for (opt = real, num = entry->num; num > 0; opt++, num--) - if (opt->name && ovisible (opt)) - { - comma (uparams.doc_opt_col, &pest); - /* Calling gettext here isn't quite right, since sorting will - have been done on the original; but documentation options - should be pretty rare anyway... */ - __argp_fmtstream_puts (stream, - dgettext (state->root_argp->argp_domain, - opt->name)); - } + if (opt->name && ovisible (opt)) + { + comma (uparams.doc_opt_col, &pest); + /* Calling gettext here isn't quite right, since sorting will + have been done on the original; but documentation options + should be pretty rare anyway... */ + __argp_fmtstream_puts (stream, + dgettext (state->root_argp->argp_domain, + opt->name)); + } } - else + else /* A real long option. */ { int first_long_opt = 1; __argp_fmtstream_set_wmargin (stream, uparams.long_opt_col); for (opt = real, num = entry->num; num > 0; opt++, num--) - if (opt->name && ovisible (opt)) - { - comma (uparams.long_opt_col, &pest); - __argp_fmtstream_printf (stream, "--%s", opt->name); - if (first_long_opt || uparams.dup_args) - arg (real, "=%s", "[=%s]", state->root_argp->argp_domain, stream); - else if (real->arg) - hhstate->suppressed_dup_arg = 1; - } + if (opt->name && ovisible (opt)) + { + comma (uparams.long_opt_col, &pest); + __argp_fmtstream_printf (stream, "--%s", opt->name); + if (first_long_opt || uparams.dup_args) + arg (real, "=%s", "[=%s]", state->root_argp->argp_domain, stream); + else if (real->arg) + hhstate->suppressed_dup_arg = 1; + } } - /* Next, documentation strings. */ - __argp_fmtstream_set_lmargin (stream, 0); + /* Next, documentation strings. */ + __argp_fmtstream_set_lmargin (stream, 0); - if (pest.first) + if (pest.first) { /* Didn't print any switches, what's up? */ if (!oshort (real) && !real->name) - /* This is a group header, print it nicely. */ - print_header (real->doc, entry->argp, &pest); + /* This is a group header, print it nicely. */ + print_header (real->doc, entry->argp, &pest); else - /* Just a totally shadowed option or null header; print nothing. */ - goto cleanup; /* Just return, after cleaning up. */ + /* Just a totally shadowed option or null header; print nothing. */ + goto cleanup; /* Just return, after cleaning up. */ } - else + else { const char *tstr = real->doc ? dgettext (state->root_argp->argp_domain, - real->doc) : 0; + real->doc) : 0; const char *fstr = filter_doc (tstr, real->key, entry->argp, state); if (fstr && *fstr) - { - unsigned int col = __argp_fmtstream_point (stream); + { + unsigned int col = __argp_fmtstream_point (stream); - __argp_fmtstream_set_lmargin (stream, uparams.opt_doc_col); - __argp_fmtstream_set_wmargin (stream, uparams.opt_doc_col); + __argp_fmtstream_set_lmargin (stream, uparams.opt_doc_col); + __argp_fmtstream_set_wmargin (stream, uparams.opt_doc_col); - if (col > (unsigned int) (uparams.opt_doc_col + 3)) - __argp_fmtstream_putc (stream, '\n'); - else if (col >= (unsigned int) uparams.opt_doc_col) - __argp_fmtstream_puts (stream, " "); - else - indent_to (stream, uparams.opt_doc_col); + if (col > (unsigned int) (uparams.opt_doc_col + 3)) + __argp_fmtstream_putc (stream, '\n'); + else if (col >= (unsigned int) uparams.opt_doc_col) + __argp_fmtstream_puts (stream, " "); + else + indent_to (stream, uparams.opt_doc_col); - __argp_fmtstream_puts (stream, fstr); - } + __argp_fmtstream_puts (stream, fstr); + } if (fstr && fstr != tstr) - free ((char *) fstr); + free ((char *) fstr); /* Reset the left margin. */ __argp_fmtstream_set_lmargin (stream, 0); __argp_fmtstream_putc (stream, '\n'); } - hhstate->prev_entry = entry; + hhstate->prev_entry = entry; cleanup: __argp_fmtstream_set_lmargin (stream, old_lm); @@ -1176,7 +1176,7 @@ hol_entry_help (struct hol_entry *entry, const struct argp_state *state, /* Output a long help message about the options in HOL to STREAM. */ static void hol_help (struct hol *hol, const struct argp_state *state, - argp_fmtstream_t stream) + argp_fmtstream_t stream) { unsigned num; struct hol_entry *entry; @@ -1187,19 +1187,19 @@ hol_help (struct hol *hol, const struct argp_state *state, if (hhstate.suppressed_dup_arg && uparams.dup_args_note) { - const char *tstr = dgettext (state->root_argp->argp_domain, "\ - Mandatory or optional arguments to long options are also mandatory or \ - optional for any corresponding short options."); + const char *tstr = dgettext (state->root_argp->argp_domain, "\ + Mandatory or optional arguments to long options are also mandatory or \ + optional for any corresponding short options."); const char *fstr = filter_doc (tstr, ARGP_KEY_HELP_DUP_ARGS_NOTE, - state ? state->root_argp : 0, state); + state ? state->root_argp : 0, state); if (fstr && *fstr) - { - __argp_fmtstream_putc (stream, '\n'); - __argp_fmtstream_puts (stream, fstr); - __argp_fmtstream_putc (stream, '\n'); - } + { + __argp_fmtstream_putc (stream, '\n'); + __argp_fmtstream_puts (stream, fstr); + __argp_fmtstream_putc (stream, '\n'); + } if (fstr && fstr != tstr) - free ((char *) fstr); + free ((char *) fstr); } } @@ -1209,8 +1209,8 @@ hol_help (struct hol *hol, const struct argp_state *state, pointer pointer to by COOKIE, and advance the pointer. */ static int add_argless_short_opt (const struct argp_option *opt, - const struct argp_option *real, - const char *domain, void *cookie) + const struct argp_option *real, + const char *domain, void *cookie) { char **snao_end = cookie; if (!(opt->arg || real->arg) @@ -1223,8 +1223,8 @@ add_argless_short_opt (const struct argp_option *opt, stream pointed at by COOKIE. */ static int usage_argful_short_opt (const struct argp_option *opt, - const struct argp_option *real, - const char *domain, void *cookie) + const struct argp_option *real, + const char *domain, void *cookie) { argp_fmtstream_t stream = cookie; const char *arg = opt->arg; @@ -1234,18 +1234,18 @@ usage_argful_short_opt (const struct argp_option *opt, arg = real->arg; if (arg && !(flags & OPTION_NO_USAGE)) - { - arg = dgettext (domain, arg); + { + arg = dgettext (domain, arg); - if (flags & OPTION_ARG_OPTIONAL) - __argp_fmtstream_printf (stream, " [-%c[%s]]", opt->key, arg); + if (flags & OPTION_ARG_OPTIONAL) + __argp_fmtstream_printf (stream, " [-%c[%s]]", opt->key, arg); else - { - /* Manually do line wrapping so that it (probably) won't - get wrapped at the embedded space. */ - space (stream, 6 + strlen (arg)); - __argp_fmtstream_printf (stream, "[-%c %s]", opt->key, arg); - } + { + /* Manually do line wrapping so that it (probably) won't + get wrapped at the embedded space. */ + space (stream, 6 + strlen (arg)); + __argp_fmtstream_printf (stream, "[-%c %s]", opt->key, arg); + } } return 0; @@ -1255,8 +1255,8 @@ usage_argful_short_opt (const struct argp_option *opt, COOKIE. */ static int usage_long_opt (const struct argp_option *opt, - const struct argp_option *real, - const char *domain, void *cookie) + const struct argp_option *real, + const char *domain, void *cookie) { argp_fmtstream_t stream = cookie; const char *arg = opt->arg; @@ -1268,15 +1268,15 @@ usage_long_opt (const struct argp_option *opt, if (! (flags & OPTION_NO_USAGE)) { if (arg) - { - arg = dgettext (domain, arg); - if (flags & OPTION_ARG_OPTIONAL) - __argp_fmtstream_printf (stream, " [--%s[=%s]]", opt->name, arg); - else - __argp_fmtstream_printf (stream, " [--%s=%s]", opt->name, arg); - } + { + arg = dgettext (domain, arg); + if (flags & OPTION_ARG_OPTIONAL) + __argp_fmtstream_printf (stream, " [--%s[=%s]]", opt->name, arg); + else + __argp_fmtstream_printf (stream, " [--%s=%s]", opt->name, arg); + } else - __argp_fmtstream_printf (stream, " [--%s]", opt->name); + __argp_fmtstream_printf (stream, " [--%s]", opt->name); } return 0; @@ -1287,38 +1287,38 @@ static void hol_usage (struct hol *hol, argp_fmtstream_t stream) { if (hol->num_entries > 0) - { - unsigned nentries; - struct hol_entry *entry; - char *short_no_arg_opts = alloca (strlen (hol->short_options) + 1); - char *snao_end = short_no_arg_opts; - - /* First we put a list of short options without arguments. */ - for (entry = hol->entries, nentries = hol->num_entries - ; nentries > 0 - ; entry++, nentries--) - hol_entry_short_iterate (entry, add_argless_short_opt, - entry->argp->argp_domain, &snao_end); - if (snao_end > short_no_arg_opts) - { - *snao_end++ = 0; - __argp_fmtstream_printf (stream, " [-%s]", short_no_arg_opts); - } - - /* Now a list of short options *with* arguments. */ - for (entry = hol->entries, nentries = hol->num_entries - ; nentries > 0 - ; entry++, nentries--) - hol_entry_short_iterate (entry, usage_argful_short_opt, - entry->argp->argp_domain, stream); - - /* Finally, a list of long options (whew!). */ - for (entry = hol->entries, nentries = hol->num_entries - ; nentries > 0 - ; entry++, nentries--) - hol_entry_long_iterate (entry, usage_long_opt, - entry->argp->argp_domain, stream); - } + { + unsigned nentries; + struct hol_entry *entry; + char *short_no_arg_opts = alloca (strlen (hol->short_options) + 1); + char *snao_end = short_no_arg_opts; + + /* First we put a list of short options without arguments. */ + for (entry = hol->entries, nentries = hol->num_entries + ; nentries > 0 + ; entry++, nentries--) + hol_entry_short_iterate (entry, add_argless_short_opt, + entry->argp->argp_domain, &snao_end); + if (snao_end > short_no_arg_opts) + { + *snao_end++ = 0; + __argp_fmtstream_printf (stream, " [-%s]", short_no_arg_opts); + } + + /* Now a list of short options *with* arguments. */ + for (entry = hol->entries, nentries = hol->num_entries + ; nentries > 0 + ; entry++, nentries--) + hol_entry_short_iterate (entry, usage_argful_short_opt, + entry->argp->argp_domain, stream); + + /* Finally, a list of long options (whew!). */ + for (entry = hol->entries, nentries = hol->num_entries + ; nentries > 0 + ; entry++, nentries--) + hol_entry_long_iterate (entry, usage_long_opt, + entry->argp->argp_domain, stream); + } } /* Make a HOL containing all levels of options in ARGP. CLUSTER is the @@ -1331,15 +1331,15 @@ argp_hol (const struct argp *argp, struct hol_cluster *cluster) if (child) while (child->argp) { - struct hol_cluster *child_cluster = - ((child->group || child->header) - /* Put CHILD->argp within its own cluster. */ - ? hol_add_cluster (hol, child->group, child->header, - child - argp->children, cluster, argp) - /* Just merge it into the parent's cluster. */ - : cluster); - hol_append (hol, argp_hol (child->argp, child_cluster)) ; - child++; + struct hol_cluster *child_cluster = + ((child->group || child->header) + /* Put CHILD->argp within its own cluster. */ + ? hol_add_cluster (hol, child->group, child->header, + child - argp->children, cluster, argp) + /* Just merge it into the parent's cluster. */ + : cluster); + hol_append (hol, argp_hol (child->argp, child_cluster)) ; + child++; } return hol; } @@ -1369,7 +1369,7 @@ argp_args_levels (const struct argp *argp) returned as long as there are more patterns to output. */ static int argp_args_usage (const struct argp *argp, const struct argp_state *state, - char **levels, int advance, argp_fmtstream_t stream) + char **levels, int advance, argp_fmtstream_t stream) { char *our_level = *levels; int multiple = 0; @@ -1378,39 +1378,39 @@ argp_args_usage (const struct argp *argp, const struct argp_state *state, const char *fdoc = filter_doc (tdoc, ARGP_KEY_HELP_ARGS_DOC, argp, state); if (fdoc) - { - const char *cp = fdoc; - nl = strchr (cp, '\n'); - if (!nl) - { - nl = cp; - while (*nl != '\0') nl++; - } + { + const char *cp = fdoc; + nl = strchr (cp, '\n'); + if (!nl) + { + nl = cp; + while (*nl != '\0') nl++; + } if (*nl != '\0') - /* This is a `multi-level' args doc; advance to the correct position - as determined by our state in LEVELS, and update LEVELS. */ - { - int i; - multiple = 1; - for (i = 0; i < *our_level; i++) + /* This is a `multi-level' args doc; advance to the correct position + as determined by our state in LEVELS, and update LEVELS. */ + { + int i; + multiple = 1; + for (i = 0; i < *our_level; i++) { - cp = nl + 1; - nl = strchr (cp, '\n'); - if (!nl) - { - nl = cp; - while (*nl != '\0') nl++; - } - } - (*levels)++; - } - - /* Manually do line wrapping so that it (probably) won't get wrapped at - any embedded spaces. */ - space (stream, 1 + nl - cp); - - __argp_fmtstream_write (stream, cp, nl - cp); + cp = nl + 1; + nl = strchr (cp, '\n'); + if (!nl) + { + nl = cp; + while (*nl != '\0') nl++; + } + } + (*levels)++; + } + + /* Manually do line wrapping so that it (probably) won't get wrapped at + any embedded spaces. */ + space (stream, 1 + nl - cp); + + __argp_fmtstream_write (stream, cp, nl - cp); } if (fdoc && fdoc != tdoc) free ((char *)fdoc); /* Free user's modified doc string. */ @@ -1421,16 +1421,16 @@ argp_args_usage (const struct argp *argp, const struct argp_state *state, if (advance && multiple) { - /* Need to increment our level. */ - if (*nl) - /* There's more we can do here. */ - { - (*our_level)++; - advance = 0; /* Our parent shouldn't advance also. */ - } + /* Need to increment our level. */ + if (*nl) + /* There's more we can do here. */ + { + (*our_level)++; + advance = 0; /* Our parent shouldn't advance also. */ + } else if (*our_level > 0) - /* We had multiple levels, but used them up; reset to zero. */ - *our_level = 0; + /* We had multiple levels, but used them up; reset to zero. */ + *our_level = 0; } return !advance; @@ -1445,8 +1445,8 @@ argp_args_usage (const struct argp *argp, const struct argp_state *state, occurrence is output. Returns true if anything was output. */ static int argp_doc (const struct argp *argp, const struct argp_state *state, - int post, int pre_blank, int first_only, - argp_fmtstream_t stream) + int post, int pre_blank, int first_only, + argp_fmtstream_t stream) { const char *text; const char *inp_text; @@ -1458,31 +1458,31 @@ argp_doc (const struct argp *argp, const struct argp_state *state, const struct argp_child *child = argp->children; if (doc) - { - char *vt = strchr (doc, '\v'); - inp_text = post ? (vt ? vt + 1 : 0) : doc; - inp_text_limit = (!post && vt) ? (vt - doc) : 0; - } + { + char *vt = strchr (doc, '\v'); + inp_text = post ? (vt ? vt + 1 : 0) : doc; + inp_text_limit = (!post && vt) ? (vt - doc) : 0; + } else inp_text = 0; if (argp->help_filter) - /* We have to filter the doc strings. */ - { - if (inp_text_limit) - { - /* Copy INP_TEXT so that it's nul-terminated. */ - tmp_text = _malloc_r (_REENT, inp_text_limit); - strncpy (tmp_text, inp_text, inp_text_limit); - _free_r (_REENT, inp_text); - inp_text = tmp_text; - } + /* We have to filter the doc strings. */ + { + if (inp_text_limit) + { + /* Copy INP_TEXT so that it's nul-terminated. */ + tmp_text = _malloc_r (_REENT, inp_text_limit); + strncpy (tmp_text, inp_text, inp_text_limit); + _free_r (_REENT, inp_text); + inp_text = tmp_text; + } input = __argp_input (argp, state); text = - (*argp->help_filter) (post - ? ARGP_KEY_HELP_POST_DOC - : ARGP_KEY_HELP_PRE_DOC, - inp_text, input); + (*argp->help_filter) (post + ? ARGP_KEY_HELP_POST_DOC + : ARGP_KEY_HELP_PRE_DOC, + inp_text, input); } else text = (const char *) inp_text; @@ -1490,15 +1490,15 @@ argp_doc (const struct argp *argp, const struct argp_state *state, if (text) { if (pre_blank) - __argp_fmtstream_putc (stream, '\n'); + __argp_fmtstream_putc (stream, '\n'); if (text == inp_text && inp_text_limit) - __argp_fmtstream_write (stream, inp_text, inp_text_limit); + __argp_fmtstream_write (stream, inp_text, inp_text_limit); else - __argp_fmtstream_puts (stream, text); + __argp_fmtstream_puts (stream, text); if (__argp_fmtstream_point (stream) > __argp_fmtstream_lmargin (stream)) - __argp_fmtstream_putc (stream, '\n'); + __argp_fmtstream_putc (stream, '\n'); anything = 1; } @@ -1509,28 +1509,28 @@ argp_doc (const struct argp *argp, const struct argp_state *state, free ((char *) inp_text); /* We copied INP_TEXT, so free it now. */ if (post && argp->help_filter) - /* Now see if we have to output a ARGP_KEY_HELP_EXTRA text. */ - { + /* Now see if we have to output a ARGP_KEY_HELP_EXTRA text. */ + { text = (*argp->help_filter) (ARGP_KEY_HELP_EXTRA, 0, input); if (text) - { - if (anything || pre_blank) - __argp_fmtstream_putc (stream, '\n'); - __argp_fmtstream_puts (stream, text); - free ((char *) text); - if (__argp_fmtstream_point (stream) - > __argp_fmtstream_lmargin (stream)) - __argp_fmtstream_putc (stream, '\n'); - anything = 1; - } + { + if (anything || pre_blank) + __argp_fmtstream_putc (stream, '\n'); + __argp_fmtstream_puts (stream, text); + free ((char *) text); + if (__argp_fmtstream_point (stream) + > __argp_fmtstream_lmargin (stream)) + __argp_fmtstream_putc (stream, '\n'); + anything = 1; + } } if (child) while (child->argp && !(first_only && anything)) anything |= - argp_doc ((child++)->argp, state, - post, anything || pre_blank, first_only, - stream); + argp_doc ((child++)->argp, state, + post, anything || pre_blank, first_only, + stream); return anything; } @@ -1557,74 +1557,74 @@ _help (const struct argp *argp, const struct argp_state *state, FILE *stream, fs = __argp_make_fmtstream (stream, 0, uparams.rmargin, 0); if (! fs) - { - _funlockfile (stream); - return; - } + { + _funlockfile (stream); + return; + } if (flags & (ARGP_HELP_USAGE | ARGP_HELP_SHORT_USAGE | ARGP_HELP_LONG)) - { - hol = argp_hol (argp, 0); + { + hol = argp_hol (argp, 0); - /* If present, these options always come last. */ - hol_set_group (hol, "help", -1); - hol_set_group (hol, "version", -1); + /* If present, these options always come last. */ + hol_set_group (hol, "help", -1); + hol_set_group (hol, "version", -1); - hol_sort (hol); - } + hol_sort (hol); + } if (flags & (ARGP_HELP_USAGE | ARGP_HELP_SHORT_USAGE)) - /* Print a short `Usage:' message. */ - { - int first_pattern = 1, more_patterns; - size_t num_pattern_levels = argp_args_levels (argp); - char *pattern_levels = alloca (num_pattern_levels); - - memset (pattern_levels, 0, num_pattern_levels); - - do - { - int old_lm; - int old_wm = __argp_fmtstream_set_wmargin (fs, uparams.usage_indent); - char *levels = pattern_levels; - - if (first_pattern) - __argp_fmtstream_printf (fs, "%s %s", - dgettext (argp->argp_domain, "Usage:"), - name); - else - __argp_fmtstream_printf (fs, "%s %s", - dgettext (argp->argp_domain, " or: "), - name); - - /* We set the lmargin as well as the wmargin, because hol_usage - manually wraps options with newline to avoid annoying breaks. */ - old_lm = __argp_fmtstream_set_lmargin (fs, uparams.usage_indent); - - if (flags & ARGP_HELP_SHORT_USAGE) - /* Just show where the options go. */ - { - if (hol->num_entries > 0) - __argp_fmtstream_puts (fs, dgettext (argp->argp_domain, - " [OPTION...]")); - } - else - /* Actually print the options. */ - { - hol_usage (hol, fs); - flags |= ARGP_HELP_SHORT_USAGE; /* But only do so once. */ - } - - more_patterns = argp_args_usage (argp, state, &levels, 1, fs); - - __argp_fmtstream_set_wmargin (fs, old_wm); - __argp_fmtstream_set_lmargin (fs, old_lm); - - __argp_fmtstream_putc (fs, '\n'); - anything = 1; - - first_pattern = 0; - } + /* Print a short `Usage:' message. */ + { + int first_pattern = 1, more_patterns; + size_t num_pattern_levels = argp_args_levels (argp); + char *pattern_levels = alloca (num_pattern_levels); + + memset (pattern_levels, 0, num_pattern_levels); + + do + { + int old_lm; + int old_wm = __argp_fmtstream_set_wmargin (fs, uparams.usage_indent); + char *levels = pattern_levels; + + if (first_pattern) + __argp_fmtstream_printf (fs, "%s %s", + dgettext (argp->argp_domain, "Usage:"), + name); + else + __argp_fmtstream_printf (fs, "%s %s", + dgettext (argp->argp_domain, " or: "), + name); + + /* We set the lmargin as well as the wmargin, because hol_usage + manually wraps options with newline to avoid annoying breaks. */ + old_lm = __argp_fmtstream_set_lmargin (fs, uparams.usage_indent); + + if (flags & ARGP_HELP_SHORT_USAGE) + /* Just show where the options go. */ + { + if (hol->num_entries > 0) + __argp_fmtstream_puts (fs, dgettext (argp->argp_domain, + " [OPTION...]")); + } + else + /* Actually print the options. */ + { + hol_usage (hol, fs); + flags |= ARGP_HELP_SHORT_USAGE; /* But only do so once. */ + } + + more_patterns = argp_args_usage (argp, state, &levels, 1, fs); + + __argp_fmtstream_set_wmargin (fs, old_wm); + __argp_fmtstream_set_lmargin (fs, old_lm); + + __argp_fmtstream_putc (fs, '\n'); + anything = 1; + + first_pattern = 0; + } while (more_patterns); } @@ -1634,22 +1634,22 @@ _help (const struct argp *argp, const struct argp_state *state, FILE *stream, if (flags & ARGP_HELP_SEE) { __argp_fmtstream_printf (fs, dgettext (argp->argp_domain, "\ - Try `%s --help' or `%s --usage' for more information.\n"), - name, name); + Try `%s --help' or `%s --usage' for more information.\n"), + name, name); anything = 1; } if (flags & ARGP_HELP_LONG) /* Print a long, detailed help message. */ { - /* Print info about all the options. */ - if (hol->num_entries > 0) - { - if (anything) - __argp_fmtstream_putc (fs, '\n'); - hol_help (hol, state, fs); - anything = 1; - } + /* Print info about all the options. */ + if (hol->num_entries > 0) + { + if (anything) + __argp_fmtstream_putc (fs, '\n'); + hol_help (hol, state, fs); + anything = 1; + } } if (flags & ARGP_HELP_POST_DOC) @@ -1657,14 +1657,14 @@ _help (const struct argp *argp, const struct argp_state *state, FILE *stream, anything |= argp_doc (argp, state, 1, anything, 0, fs); if ((flags & ARGP_HELP_BUG_ADDR) && argp_program_bug_address) - { - if (anything) - __argp_fmtstream_putc (fs, '\n'); - __argp_fmtstream_printf (fs, dgettext (argp->argp_domain, - "Report bugs to %s.\n"), - argp_program_bug_address); - anything = 1; - } + { + if (anything) + __argp_fmtstream_putc (fs, '\n'); + __argp_fmtstream_printf (fs, dgettext (argp->argp_domain, + "Report bugs to %s.\n"), + argp_program_bug_address); + anything = 1; + } _funlockfile (stream); @@ -1677,7 +1677,7 @@ _help (const struct argp *argp, const struct argp_state *state, FILE *stream, /* Output a usage message for ARGP to STREAM. FLAGS are from the set ARGP_HELP_*. NAME is what to use wherever a `program name' is needed. */ void __argp_help (const struct argp *argp, FILE *stream, - unsigned flags, char *name) + unsigned flags, char *name) { _help (argp, 0, stream, flags, name); } @@ -1693,18 +1693,18 @@ __argp_state_help (const struct argp_state *state, FILE *stream, unsigned flags) if ((!state || ! (state->flags & ARGP_NO_ERRS)) && stream) { if (state && (state->flags & ARGP_LONG_ONLY)) - flags |= ARGP_HELP_LONG_ONLY; + flags |= ARGP_HELP_LONG_ONLY; _help (state ? state->root_argp : 0, state, stream, flags, - state ? state->name : program_invocation_short_name); + state ? state->name : program_invocation_short_name); if (!state || ! (state->flags & ARGP_NO_EXIT)) - { - if (flags & ARGP_HELP_EXIT_ERR) - exit (argp_err_exit_status); - if (flags & ARGP_HELP_EXIT_OK) - exit (0); - } + { + if (flags & ARGP_HELP_EXIT_ERR) + exit (argp_err_exit_status); + if (flags & ARGP_HELP_EXIT_OK) + exit (0); + } } } #ifdef weak_alias @@ -1722,46 +1722,46 @@ __argp_error (const struct argp_state *state, const char *fmt, ...) FILE *stream = state ? state->err_stream : stderr; if (stream) - { - va_list ap; + { + va_list ap; - _flockfile (stream); + _flockfile (stream); - va_start (ap, fmt); + va_start (ap, fmt); #ifdef USE_IN_LIBIO - if (_IO_fwide (stream, 0) > 0) - { - char *buf; + if (_IO_fwide (stream, 0) > 0) + { + char *buf; - __asprintf (&buf, fmt, ap); + __asprintf (&buf, fmt, ap); - __fwprintf (stream, L"%s: %s\n", - state ? state->name : program_invocation_short_name, - buf); + __fwprintf (stream, L"%s: %s\n", + state ? state->name : program_invocation_short_name, + buf); - free (buf); - } - else + free (buf); + } + else #endif - { - fputs (state - ? state->name : program_invocation_short_name, - stream); - putc_unlocked (':', stream); - putc_unlocked (' ', stream); + { + fputs (state + ? state->name : program_invocation_short_name, + stream); + putc_unlocked (':', stream); + putc_unlocked (' ', stream); - vfprintf (stream, fmt, ap); + vfprintf (stream, fmt, ap); - putc_unlocked ('\n', stream); - } + putc_unlocked ('\n', stream); + } - __argp_state_help (state, stream, ARGP_HELP_STD_ERR); + __argp_state_help (state, stream, ARGP_HELP_STD_ERR); - va_end (ap); + va_end (ap); - _funlockfile (stream); - } + _funlockfile (stream); + } } } #ifdef weak_alias @@ -1778,83 +1778,83 @@ weak_alias (__argp_error, argp_error) parsing but don't reflect a (syntactic) problem with the input. */ void __argp_failure (const struct argp_state *state, int status, int errnum, - const char *fmt, ...) + const char *fmt, ...) { if (!state || !(state->flags & ARGP_NO_ERRS)) { FILE *stream = state ? state->err_stream : stderr; if (stream) - { - _flockfile (stream); + { + _flockfile (stream); #ifdef USE_IN_LIBIO - if (_IO_fwide (stream, 0) > 0) - __fwprintf (stream, L"%s", - state ? state->name : program_invocation_short_name); - else + if (_IO_fwide (stream, 0) > 0) + __fwprintf (stream, L"%s", + state ? state->name : program_invocation_short_name); + else #endif - fputs (state - ? state->name : program_invocation_short_name, - stream); + fputs (state + ? state->name : program_invocation_short_name, + stream); - if (fmt) - { - va_list ap; + if (fmt) + { + va_list ap; - va_start (ap, fmt); + va_start (ap, fmt); #ifdef USE_IN_LIBIO - if (_IO_fwide (stream, 0) > 0) - { - char *buf; + if (_IO_fwide (stream, 0) > 0) + { + char *buf; - __asprintf (&buf, fmt, ap); + __asprintf (&buf, fmt, ap); - __fwprintf (stream, L": %s", buf); + __fwprintf (stream, L": %s", buf); - free (buf); - } - else + free (buf); + } + else #endif - { - putc_unlocked (':', stream); - putc_unlocked (' ', stream); + { + putc_unlocked (':', stream); + putc_unlocked (' ', stream); - vfprintf (stream, fmt, ap); - } + vfprintf (stream, fmt, ap); + } - va_end (ap); - } + va_end (ap); + } - if (errnum) - { - char buf[200]; + if (errnum) + { + char buf[200]; #ifdef USE_IN_LIBIO - if (_IO_fwide (stream, 0) > 0) - __fwprintf (stream, L": %s", - strerror_r (errnum, buf, sizeof (buf))); - else + if (_IO_fwide (stream, 0) > 0) + __fwprintf (stream, L": %s", + strerror_r (errnum, buf, sizeof (buf))); + else #endif - { - putc_unlocked (':', stream); - putc_unlocked (' ', stream); - fputs (strerror_r (errnum, buf, sizeof (buf)), stream); - } - } + { + putc_unlocked (':', stream); + putc_unlocked (' ', stream); + fputs (strerror_r (errnum, buf, sizeof (buf)), stream); + } + } #ifdef USE_IN_LIBIO - if (_IO_fwide (stream, 0) > 0) - putwc_unlocked (L'\n', stream); - else + if (_IO_fwide (stream, 0) > 0) + putwc_unlocked (L'\n', stream); + else #endif - putc_unlocked ('\n', stream); + putc_unlocked ('\n', stream); - _funlockfile (stream); + _funlockfile (stream); - if (status && (!state || !(state->flags & ARGP_NO_EXIT))) - exit (status); - } + if (status && (!state || !(state->flags & ARGP_NO_EXIT))) + exit (status); + } } } #ifdef weak_alias diff --git a/libraries/platforms/dromajo-vcs/software/src/argp/argp-parse.c b/libraries/platforms/dromajo-vcs/software/src/argp/argp-parse.c index cd177e556..77d87d154 100644 --- a/libraries/platforms/dromajo-vcs/software/src/argp/argp-parse.c +++ b/libraries/platforms/dromajo-vcs/software/src/argp/argp-parse.c @@ -103,55 +103,55 @@ argp_default_parser (int key, char *arg, struct argp_state *state) { switch (key) { - case '?': - __argp_state_help (state, state->out_stream, ARGP_HELP_STD_HELP); - break; - case OPT_USAGE: - __argp_state_help (state, state->out_stream, - ARGP_HELP_USAGE | ARGP_HELP_EXIT_OK); - break; - - case OPT_PROGNAME: /* Set the program name. */ - program_invocation_name = arg; - - /* [Note that some systems only have PROGRAM_INVOCATION_SHORT_NAME (aka - __PROGNAME), in which case, PROGRAM_INVOCATION_NAME is just defined - to be that, so we have to be a bit careful here.] */ - arg = strrchr (arg, '/'); - if (arg) - program_invocation_short_name = arg + 1; - else - program_invocation_short_name = program_invocation_name; - - /* Update what we use for messages. */ - state->name = program_invocation_short_name; - - if ((state->flags & (ARGP_PARSE_ARGV0 | ARGP_NO_ERRS)) - == ARGP_PARSE_ARGV0) - /* Update what getopt uses too. */ - state->argv[0] = program_invocation_name; - - break; - - case OPT_HANG: - _argp_hang = atoi (arg ? arg : "3600"); - while (_argp_hang-- > 0) + case '?': + __argp_state_help (state, state->out_stream, ARGP_HELP_STD_HELP); + break; + case OPT_USAGE: + __argp_state_help (state, state->out_stream, + ARGP_HELP_USAGE | ARGP_HELP_EXIT_OK); + break; + + case OPT_PROGNAME: /* Set the program name. */ + program_invocation_name = arg; + + /* [Note that some systems only have PROGRAM_INVOCATION_SHORT_NAME (aka + __PROGNAME), in which case, PROGRAM_INVOCATION_NAME is just defined + to be that, so we have to be a bit careful here.] */ + arg = strrchr (arg, '/'); + if (arg) + program_invocation_short_name = arg + 1; + else + program_invocation_short_name = program_invocation_name; + + /* Update what we use for messages. */ + state->name = program_invocation_short_name; + + if ((state->flags & (ARGP_PARSE_ARGV0 | ARGP_NO_ERRS)) + == ARGP_PARSE_ARGV0) + /* Update what getopt uses too. */ + state->argv[0] = program_invocation_name; + + break; + + case OPT_HANG: + _argp_hang = atoi (arg ? arg : "3600"); + while (_argp_hang-- > 0) // Sripathi: - // Use a for loop to hang the execution rather than sleep - // since it is not implemented - // This will consume power but we don't really care since we will - // run a full-featured linux in real use cases and this will not be a problem - // Also, this a single-thread execution and there is nothing to context switch to - // while sleeping, so it shouldn't matter anyways. - // Choosing an arbitrary number to sleep. This necessarily may not map to 1 second - for (int i = 0; i < 1000; i++) - for (int j = 0; j <= (1 << 31); j++) - // Use this to prevent the compiler from optimizing this piece of code out. - __asm__ __volatile__("" : "+g" (i), "+g" (j) : :); - break; - - default: - return EBADKEY; + // Use a for loop to hang the execution rather than sleep + // since it is not implemented + // This will consume power but we don't really care since we will + // run a full-featured linux in real use cases and this will not be a problem + // Also, this a single-thread execution and there is nothing to context switch to + // while sleeping, so it shouldn't matter anyways. + // Choosing an arbitrary number to sleep. This necessarily may not map to 1 second + for (int i = 0; i < 1000; i++) + for (int j = 0; j <= (1 << 31); j++) + // Use this to prevent the compiler from optimizing this piece of code out. + __asm__ __volatile__("" : "+g" (i), "+g" (j) : :); + break; + + default: + return EBADKEY; } return 0; } @@ -173,14 +173,14 @@ argp_version_parser (int key, char *arg, struct argp_state *state) { case 'V': if (argp_program_version_hook) - (*argp_program_version_hook) (state->out_stream, state); + (*argp_program_version_hook) (state->out_stream, state); else if (argp_program_version) - fprintf (state->out_stream, "%s\n", argp_program_version); + fprintf (state->out_stream, "%s\n", argp_program_version); else - __argp_error (state, dgettext (state->root_argp->argp_domain, - "(PROGRAM ERROR) No version known!?")); + __argp_error (state, dgettext (state->root_argp->argp_domain, + "(PROGRAM ERROR) No version known!?")); if (! (state->flags & ARGP_NO_EXIT)) - exit (0); + exit (0); break; default: return EBADKEY; @@ -281,16 +281,16 @@ static error_t group_parse (struct group *group, struct argp_state *state, int key, char *arg) { if (group->parser) - { - error_t err; - state->hook = group->hook; - state->input = group->input; - state->child_inputs = group->child_inputs; - state->arg_num = group->args_processed; - err = (*group->parser)(key, arg, state); - group->hook = state->hook; - return err; - } + { + error_t err; + state->hook = group->hook; + state->input = group->input; + state->child_inputs = group->child_inputs; + state->arg_num = group->args_processed; + err = (*group->parser)(key, arg, state); + group->hook = state->hook; + return err; + } else return EBADKEY; } @@ -342,8 +342,8 @@ struct parser_convert_state next unused group entry. CVT holds state used during the conversion. */ static struct group * convert_options (const struct argp *argp, - struct group *parent, unsigned parent_index, - struct group *group, struct parser_convert_state *cvt) + struct group *parent, unsigned parent_index, + struct group *group, struct parser_convert_state *cvt) { /* REAL is the most recent non-alias value of OPT. */ const struct argp_option *real = argp->options; @@ -354,76 +354,76 @@ convert_options (const struct argp *argp, const struct argp_option *opt; if (real) - for (opt = real; !__option_is_end (opt); opt++) - { - if (! (opt->flags & OPTION_ALIAS)) - /* OPT isn't an alias, so we can use values from it. */ - real = opt; - - if (! (real->flags & OPTION_DOC)) - /* A real option (not just documentation). */ - { - if (__option_is_short (opt)) - /* OPT can be used as a short option. */ - { - *cvt->short_end++ = opt->key; - if (real->arg) - { - *cvt->short_end++ = ':'; - if (real->flags & OPTION_ARG_OPTIONAL) - *cvt->short_end++ = ':'; - } - *cvt->short_end = '\0'; /* keep 0 terminated */ - } - - if (opt->name - && find_long_option (cvt->parser->long_opts, opt->name) < 0) - /* OPT can be used as a long option. */ - { - cvt->long_end->name = opt->name; - cvt->long_end->has_arg = - (real->arg - ? (real->flags & OPTION_ARG_OPTIONAL - ? optional_argument - : required_argument) - : no_argument); - cvt->long_end->flag = 0; - /* we add a disambiguating code to all the user's - values (which is removed before we actually call - the function to parse the value); this means that - the user loses use of the high 8 bits in all his - values (the sign of the lower bits is preserved - however)... */ - cvt->long_end->val = - ((opt->key | real->key) & USER_MASK) - + (((group - cvt->parser->groups) + 1) << USER_BITS); - - /* Keep the LONG_OPTS list terminated. */ - (++cvt->long_end)->name = NULL; - } - } - } - - group->parser = argp->parser; - group->argp = argp; - group->short_end = cvt->short_end; - group->args_processed = 0; - group->parent = parent; - group->parent_index = parent_index; - group->input = 0; - group->hook = 0; - group->child_inputs = 0; + for (opt = real; !__option_is_end (opt); opt++) + { + if (! (opt->flags & OPTION_ALIAS)) + /* OPT isn't an alias, so we can use values from it. */ + real = opt; + + if (! (real->flags & OPTION_DOC)) + /* A real option (not just documentation). */ + { + if (__option_is_short (opt)) + /* OPT can be used as a short option. */ + { + *cvt->short_end++ = opt->key; + if (real->arg) + { + *cvt->short_end++ = ':'; + if (real->flags & OPTION_ARG_OPTIONAL) + *cvt->short_end++ = ':'; + } + *cvt->short_end = '\0'; /* keep 0 terminated */ + } + + if (opt->name + && find_long_option (cvt->parser->long_opts, opt->name) < 0) + /* OPT can be used as a long option. */ + { + cvt->long_end->name = opt->name; + cvt->long_end->has_arg = + (real->arg + ? (real->flags & OPTION_ARG_OPTIONAL + ? optional_argument + : required_argument) + : no_argument); + cvt->long_end->flag = 0; + /* we add a disambiguating code to all the user's + values (which is removed before we actually call + the function to parse the value); this means that + the user loses use of the high 8 bits in all his + values (the sign of the lower bits is preserved + however)... */ + cvt->long_end->val = + ((opt->key | real->key) & USER_MASK) + + (((group - cvt->parser->groups) + 1) << USER_BITS); + + /* Keep the LONG_OPTS list terminated. */ + (++cvt->long_end)->name = NULL; + } + } + } + + group->parser = argp->parser; + group->argp = argp; + group->short_end = cvt->short_end; + group->args_processed = 0; + group->parent = parent; + group->parent_index = parent_index; + group->input = 0; + group->hook = 0; + group->child_inputs = 0; if (children) - /* Assign GROUP's CHILD_INPUTS field some space from + /* Assign GROUP's CHILD_INPUTS field some space from CVT->child_inputs_end.*/ - { - unsigned num_children = 0; - while (children[num_children].argp) - num_children++; - group->child_inputs = cvt->child_inputs_end; - cvt->child_inputs_end += num_children; - } + { + unsigned num_children = 0; + while (children[num_children].argp) + num_children++; + group->child_inputs = cvt->child_inputs_end; + cvt->child_inputs_end += num_children; + } parent = group++; } @@ -434,8 +434,8 @@ convert_options (const struct argp *argp, { unsigned index = 0; while (children->argp) - group = - convert_options (children++->argp, parent, index++, group, cvt); + group = + convert_options (children++->argp, parent, index++, group, cvt); } return group; @@ -491,27 +491,27 @@ calc_sizes (const struct argp *argp, struct parser_sizes *szs) { szs->num_groups++; if (opt) - { - int num_opts = 0; - while (!__option_is_end (opt++)) - num_opts++; - szs->short_len += num_opts * 3; /* opt + up to 2 `:'s */ - szs->long_len += num_opts; - } + { + int num_opts = 0; + while (!__option_is_end (opt++)) + num_opts++; + szs->short_len += num_opts * 3; /* opt + up to 2 `:'s */ + szs->long_len += num_opts; + } } if (child) while (child->argp) { - calc_sizes ((child++)->argp, szs); - szs->num_child_inputs++; + calc_sizes ((child++)->argp, szs); + szs->num_child_inputs++; } } /* Initializes PARSER to parse ARGP in a manner described by FLAGS. */ static error_t parser_init (struct parser *parser, const struct argp *argp, - int argc, char **argv, int flags, void *input) + int argc, char **argv, int flags, void *input) { error_t err = 0; struct group *group; @@ -564,15 +564,15 @@ parser_init (struct parser *parser, const struct argp *argp, group++) { if (group->parent) - /* If a child parser, get the initial input value from the parent. */ - group->input = group->parent->child_inputs[group->parent_index]; + /* If a child parser, get the initial input value from the parent. */ + group->input = group->parent->child_inputs[group->parent_index]; if (!group->parser - && group->argp->children && group->argp->children->argp) - /* For the special case where no parsing function is supplied for an - argp, propagate its input to its first child, if any (this just - makes very simple wrapper argps more convenient). */ - group->child_inputs[0] = group->input; + && group->argp->children && group->argp->children->argp) + /* For the special case where no parsing function is supplied for an + argp, propagate its input to its first child, if any (this just + makes very simple wrapper argps more convenient). */ + group->child_inputs[0] = group->input; err = group_parse (group, &parser->state, ARGP_KEY_INIT, 0); } @@ -589,9 +589,9 @@ parser_init (struct parser *parser, const struct argp *argp, { opterr = 0; if (parser->state.flags & ARGP_PARSE_ARGV0) - /* getopt always skips ARGV[0], so we have to fake it out. As long - as OPTERR is 0, then it shouldn't actually try to access it. */ - parser->state.argv--, parser->state.argc++; + /* getopt always skips ARGV[0], so we have to fake it out. As long + as OPTERR is 0, then it shouldn't actually try to access it. */ + parser->state.argv--, parser->state.argc++; } else opterr = 1; /* Print error messages. */ @@ -600,7 +600,7 @@ parser_init (struct parser *parser, const struct argp *argp, /* There's an argv[0]; use it for messages. */ { char *short_name = strrchr (argv[0], '/'); - parser->state.name = short_name ? short_name + 1 : argv[0]; + parser->state.name = short_name ? short_name + 1 : argv[0]; } else parser->state.name = program_invocation_short_name; @@ -611,7 +611,7 @@ parser_init (struct parser *parser, const struct argp *argp, /* Free any storage consumed by PARSER (but not PARSER itself). */ static error_t parser_finalize (struct parser *parser, - error_t err, int arg_ebadkey, int *end_index) + error_t err, int arg_ebadkey, int *end_index) { struct group *group; @@ -624,40 +624,40 @@ parser_finalize (struct parser *parser, if (! err) { if (parser->state.next == parser->state.argc) - /* We successfully parsed all arguments! Call all the parsers again, - just a few more times... */ - { - for (group = parser->groups; - group < parser->egroup && (!err || err==EBADKEY); - group++) - if (group->args_processed == 0) - err = group_parse (group, &parser->state, ARGP_KEY_NO_ARGS, 0); - for (group = parser->egroup - 1; - group >= parser->groups && (!err || err==EBADKEY); - group--) - err = group_parse (group, &parser->state, ARGP_KEY_END, 0); - - if (err == EBADKEY) - err = 0; /* Some parser didn't understand. */ - - /* Tell the user that all arguments are parsed. */ - if (end_index) - *end_index = parser->state.next; - } + /* We successfully parsed all arguments! Call all the parsers again, + just a few more times... */ + { + for (group = parser->groups; + group < parser->egroup && (!err || err==EBADKEY); + group++) + if (group->args_processed == 0) + err = group_parse (group, &parser->state, ARGP_KEY_NO_ARGS, 0); + for (group = parser->egroup - 1; + group >= parser->groups && (!err || err==EBADKEY); + group--) + err = group_parse (group, &parser->state, ARGP_KEY_END, 0); + + if (err == EBADKEY) + err = 0; /* Some parser didn't understand. */ + + /* Tell the user that all arguments are parsed. */ + if (end_index) + *end_index = parser->state.next; + } else if (end_index) - /* Return any remaining arguments to the user. */ - *end_index = parser->state.next; + /* Return any remaining arguments to the user. */ + *end_index = parser->state.next; else - /* No way to return the remaining arguments, they must be bogus. */ - { - if (!(parser->state.flags & ARGP_NO_ERRS) - && parser->state.err_stream) - fprintf (parser->state.err_stream, - dgettext (parser->argp->argp_domain, - "%s: Too many arguments\n"), - parser->state.name); - err = EBADKEY; - } + /* No way to return the remaining arguments, they must be bogus. */ + { + if (!(parser->state.flags & ARGP_NO_ERRS) + && parser->state.err_stream) + fprintf (parser->state.err_stream, + dgettext (parser->argp->argp_domain, + "%s: Too many arguments\n"), + parser->state.name); + err = EBADKEY; + } } /* Okay, we're all done, with either an error or success; call the parsers @@ -667,27 +667,27 @@ parser_finalize (struct parser *parser, { /* Maybe print an error message. */ if (err == EBADKEY) - /* An appropriate message describing what the error was should have - been printed earlier. */ - __argp_state_help (&parser->state, parser->state.err_stream, - ARGP_HELP_STD_ERR); + /* An appropriate message describing what the error was should have + been printed earlier. */ + __argp_state_help (&parser->state, parser->state.err_stream, + ARGP_HELP_STD_ERR); /* Since we didn't exit, give each parser an error indication. */ for (group = parser->groups; group < parser->egroup; group++) - group_parse (group, &parser->state, ARGP_KEY_ERROR, 0); + group_parse (group, &parser->state, ARGP_KEY_ERROR, 0); } else /* Notify parsers of success, and propagate back values from parsers. */ { /* We pass over the groups in reverse order so that child groups are - given a chance to do there processing before passing back a value to - the parent. */ + given a chance to do there processing before passing back a value to + the parent. */ for (group = parser->egroup - 1 - ; group >= parser->groups && (!err || err == EBADKEY) - ; group--) - err = group_parse (group, &parser->state, ARGP_KEY_SUCCESS, 0); + ; group >= parser->groups && (!err || err == EBADKEY) + ; group--) + err = group_parse (group, &parser->state, ARGP_KEY_SUCCESS, 0); if (err == EBADKEY) - err = 0; /* Some parser didn't understand. */ + err = 0; /* Some parser didn't understand. */ } /* Call parsers once more, to do any final cleanup. Errors are ignored. */ @@ -722,35 +722,35 @@ parser_parse_arg (struct parser *parser, char *val) ; group < parser->egroup && err == EBADKEY ; group++) { - parser->state.next++; /* For ARGP_KEY_ARG, consume the arg. */ - key = ARGP_KEY_ARG; - err = group_parse (group, &parser->state, key, val); - - if (err == EBADKEY) - /* This parser doesn't like ARGP_KEY_ARG; try ARGP_KEY_ARGS instead. */ - { - parser->state.next--; /* For ARGP_KEY_ARGS, put back the arg. */ - key = ARGP_KEY_ARGS; - err = group_parse (group, &parser->state, key, 0); - } + parser->state.next++; /* For ARGP_KEY_ARG, consume the arg. */ + key = ARGP_KEY_ARG; + err = group_parse (group, &parser->state, key, val); + + if (err == EBADKEY) + /* This parser doesn't like ARGP_KEY_ARG; try ARGP_KEY_ARGS instead. */ + { + parser->state.next--; /* For ARGP_KEY_ARGS, put back the arg. */ + key = ARGP_KEY_ARGS; + err = group_parse (group, &parser->state, key, 0); + } } if (! err) - { - if (key == ARGP_KEY_ARGS) - /* The default for ARGP_KEY_ARGS is to assume that if NEXT isn't - changed by the user, *all* arguments should be considered - consumed. */ - parser->state.next = parser->state.argc; + { + if (key == ARGP_KEY_ARGS) + /* The default for ARGP_KEY_ARGS is to assume that if NEXT isn't + changed by the user, *all* arguments should be considered + consumed. */ + parser->state.next = parser->state.argc; if (parser->state.next > index) - /* Remember that we successfully processed a non-option - argument -- but only if the user hasn't gotten tricky and set - the clock back. */ - (--group)->args_processed += (parser->state.next - index); + /* Remember that we successfully processed a non-option + argument -- but only if the user hasn't gotten tricky and set + the clock back. */ + (--group)->args_processed += (parser->state.next - index); else - /* The user wants to reparse some args, give getopt another try. */ - parser->try_getopt = 1; + /* The user wants to reparse some args, give getopt another try. */ + parser->try_getopt = 1; } return err; @@ -767,47 +767,47 @@ parser_parse_opt (struct parser *parser, int opt, char *val) error_t err = EBADKEY; if (group_key == 0) - /* A short option. By comparing OPT's position in SHORT_OPTS to the - various starting positions in each group's SHORT_END field, we can - determine which group OPT came from. */ - { - struct group *group; - char *short_index = strchr (parser->short_opts, opt); - - if (short_index) - for (group = parser->groups; group < parser->egroup; group++) - if (group->short_end > short_index) - { - err = group_parse (group, &parser->state, opt, optarg); - break; - } + /* A short option. By comparing OPT's position in SHORT_OPTS to the + various starting positions in each group's SHORT_END field, we can + determine which group OPT came from. */ + { + struct group *group; + char *short_index = strchr (parser->short_opts, opt); + + if (short_index) + for (group = parser->groups; group < parser->egroup; group++) + if (group->short_end > short_index) + { + err = group_parse (group, &parser->state, opt, optarg); + break; + } } else - /* A long option. We use shifts instead of masking for extracting - the user value in order to preserve the sign. */ + /* A long option. We use shifts instead of masking for extracting + the user value in order to preserve the sign. */ err = group_parse (&parser->groups[group_key - 1], &parser->state, - (opt << GROUP_BITS) >> GROUP_BITS, optarg); + (opt << GROUP_BITS) >> GROUP_BITS, optarg); if (err == EBADKEY) - /* At least currently, an option not recognized is an error in the - parser, because we pre-compute which parser is supposed to deal - with each option. */ - { + /* At least currently, an option not recognized is an error in the + parser, because we pre-compute which parser is supposed to deal + with each option. */ + { static const char bad_key_err[] = - N_("(PROGRAM ERROR) Option should have been recognized!?"); + N_("(PROGRAM ERROR) Option should have been recognized!?"); if (group_key == 0) - __argp_error (&parser->state, "-%c: %s", opt, - dgettext (parser->argp->argp_domain, bad_key_err)); + __argp_error (&parser->state, "-%c: %s", opt, + dgettext (parser->argp->argp_domain, bad_key_err)); else - { - struct option *long_opt = parser->long_opts; - while (long_opt->val != opt && long_opt->name) - long_opt++; - __argp_error (&parser->state, "--%s: %s", - long_opt->name ? long_opt->name : "???", - dgettext (parser->argp->argp_domain, bad_key_err)); - } + { + struct option *long_opt = parser->long_opts; + while (long_opt->val != opt && long_opt->name) + long_opt++; + __argp_error (&parser->state, "--%s: %s", + long_opt->name ? long_opt->name : "???", + dgettext (parser->argp->argp_domain, bad_key_err)); + } } return err; @@ -831,40 +831,40 @@ parser_parse_next (struct parser *parser, int *arg_ebadkey) parser->state.quoted = 0; if (parser->try_getopt && !parser->state.quoted) - /* Give getopt a chance to parse this. */ - { - optind = parser->state.next; /* Put it back in OPTIND for getopt. */ - optopt = KEY_END; /* Distinguish KEY_ERR from a real option. */ - if (parser->state.flags & ARGP_LONG_ONLY) - opt = getopt_long_only (parser->state.argc, parser->state.argv, - parser->short_opts, parser->long_opts, 0); + /* Give getopt a chance to parse this. */ + { + optind = parser->state.next; /* Put it back in OPTIND for getopt. */ + optopt = KEY_END; /* Distinguish KEY_ERR from a real option. */ + if (parser->state.flags & ARGP_LONG_ONLY) + opt = getopt_long_only (parser->state.argc, parser->state.argv, + parser->short_opts, parser->long_opts, 0); else - opt = getopt_long (parser->state.argc, parser->state.argv, - parser->short_opts, parser->long_opts, 0); + opt = getopt_long (parser->state.argc, parser->state.argv, + parser->short_opts, parser->long_opts, 0); parser->state.next = optind; /* And see what getopt did. */ if (opt == KEY_END) - /* Getopt says there are no more options, so stop using - getopt; we'll continue if necessary on our own. */ - { - parser->try_getopt = 0; - if (parser->state.next > 1 - && strcmp (parser->state.argv[parser->state.next - 1], QUOTE) - == 0) - /* Not only is this the end of the options, but it's a - `quoted' region, which may have args that *look* like - options, so we definitely shouldn't try to use getopt past - here, whatever happens. */ - parser->state.quoted = parser->state.next; - } + /* Getopt says there are no more options, so stop using + getopt; we'll continue if necessary on our own. */ + { + parser->try_getopt = 0; + if (parser->state.next > 1 + && strcmp (parser->state.argv[parser->state.next - 1], QUOTE) + == 0) + /* Not only is this the end of the options, but it's a + `quoted' region, which may have args that *look* like + options, so we definitely shouldn't try to use getopt past + here, whatever happens. */ + parser->state.quoted = parser->state.next; + } else if (opt == KEY_ERR && optopt != KEY_END) - /* KEY_ERR can have the same value as a valid user short - option, but in the case of a real error, getopt sets OPTOPT - to the offending character, which can never be KEY_END. */ - { - *arg_ebadkey = 0; - return EBADKEY; - } + /* KEY_ERR can have the same value as a valid user short + option, but in the case of a real error, getopt sets OPTOPT + to the offending character, which can never be KEY_END. */ + { + *arg_ebadkey = 0; + return EBADKEY; + } } else opt = KEY_END; @@ -873,18 +873,18 @@ parser_parse_next (struct parser *parser, int *arg_ebadkey) { /* We're past what getopt considers the options. */ if (parser->state.next >= parser->state.argc - || (parser->state.flags & ARGP_NO_ARGS)) - /* Indicate that we're done. */ - { - *arg_ebadkey = 1; - return EBADKEY; - } + || (parser->state.flags & ARGP_NO_ARGS)) + /* Indicate that we're done. */ + { + *arg_ebadkey = 1; + return EBADKEY; + } else - /* A non-option arg; simulate what getopt might have done. */ - { - opt = KEY_ARG; - optarg = parser->state.argv[parser->state.next++]; - } + /* A non-option arg; simulate what getopt might have done. */ + { + opt = KEY_ARG; + optarg = parser->state.argv[parser->state.next++]; + } } if (opt == KEY_ARG) @@ -906,7 +906,7 @@ parser_parse_next (struct parser *parser, int *arg_ebadkey) returned a non-zero value, it is returned; otherwise 0 is returned. */ error_t __argp_parse (const struct argp *argp, int argc, char **argv, unsigned flags, - int *end_index, void *input) + int *end_index, void *input) { error_t err; struct parser parser; @@ -916,30 +916,30 @@ __argp_parse (const struct argp *argp, int argc, char **argv, unsigned flags, int arg_ebadkey = 0; // Sripathi: - // Forward declare the struct pointers since malloc is being used instead of alloca - struct argp_child *child; - struct argp *top_argp; + // Forward declare the struct pointers since malloc is being used instead of alloca + struct argp_child *child; + struct argp *top_argp; if (! (flags & ARGP_NO_HELP)) - /* Add our own options. */ - { + /* Add our own options. */ + { // Sripathi: - // Originally alloca was used but since newlib does not implement that - // we are switching over to malloc which is a lot slower - child = (struct argp_child *) malloc (4 * sizeof (struct argp_child)); - top_argp = (struct argp *) malloc (sizeof (struct argp)); + // Originally alloca was used but since newlib does not implement that + // we are switching over to malloc which is a lot slower + child = (struct argp_child *) malloc (4 * sizeof (struct argp_child)); + top_argp = (struct argp *) malloc (sizeof (struct argp)); - /* TOP_ARGP has no options, it just serves to group the user & default - argps. */ - memset (top_argp, 0, sizeof (*top_argp)); - top_argp->children = child; + /* TOP_ARGP has no options, it just serves to group the user & default + argps. */ + memset (top_argp, 0, sizeof (*top_argp)); + top_argp->children = child; - memset (child, 0, 4 * sizeof (struct argp_child)); + memset (child, 0, 4 * sizeof (struct argp_child)); - if (argp) - (child++)->argp = argp; + if (argp) + (child++)->argp = argp; (child++)->argp = &argp_default_argp; if (argp_program_version || argp_program_version_hook) - (child++)->argp = &argp_version_argp; + (child++)->argp = &argp_version_argp; child->argp = 0; argp = top_argp; @@ -952,17 +952,17 @@ __argp_parse (const struct argp *argp, int argc, char **argv, unsigned flags, /* Parse! */ { while (! err) - err = parser_parse_next (&parser, &arg_ebadkey); + err = parser_parse_next (&parser, &arg_ebadkey); err = parser_finalize (&parser, err, arg_ebadkey, end_index); } // Sripathi: - // malloc was used to allocate space for the argp_child and argp structs - // alloca automatically freed the memory when the function returned - // but since we are using malloc, we need to explicitly free it to - // avoid memory leaks - free(child); - free(top_argp); + // malloc was used to allocate space for the argp_child and argp structs + // alloca automatically freed the memory when the function returned + // but since we are using malloc, we need to explicitly free it to + // avoid memory leaks + free(child); + free(top_argp); return err; } @@ -976,13 +976,13 @@ void * __argp_input (const struct argp *argp, const struct argp_state *state) { if (state) - { - struct group *group; - struct parser *parser = state->pstate; + { + struct group *group; + struct parser *parser = state->pstate; - for (group = parser->groups; group < parser->egroup; group++) - if (group->argp == argp) - return group->input; + for (group = parser->groups; group < parser->egroup; group++) + if (group->argp == argp) + return group->input; } return 0; diff --git a/libraries/platforms/dromajo-vcs/software/src/args.c b/libraries/platforms/dromajo-vcs/software/src/args.c index f65f1def7..f7b1ca53a 100644 --- a/libraries/platforms/dromajo-vcs/software/src/args.c +++ b/libraries/platforms/dromajo-vcs/software/src/args.c @@ -4,7 +4,7 @@ * loads them into corresponding registers so that BlackParrot can access them */ -#include +#include #include #include #include @@ -30,7 +30,6 @@ void __init_args(void) { char *bufptr = buffer; // Create a packet for the x86 host - // BlackParrot FIFO interface is at POD (X, Y) = (0, 1), SUBCOORD (X, Y) = (0, 1) args_req_pkt.request.x_dst = HOST_X_COORD; args_req_pkt.request.y_dst = HOST_Y_COORD; args_req_pkt.request.x_src = BP_HOST_LINK_X; @@ -43,14 +42,14 @@ void __init_args(void) { // The platform setup in simulation ensures that this packet will not go over the network so // we don't need to check for credits. Also, this code is executed before the CUDA-lite // program starts. - args_req_pkt.request.addr = HB_MC_HOST_EPA_ARGS_START + arg_index; - err = bp_hb_write_to_mc_bridge(&args_req_pkt); - err = bp_hb_read_from_mc_bridge(&args_resp_pkt, HB_MC_FIFO_RX_RSP); + args_req_pkt.request.addr = HB_BP_HOST_EPA_ARGS_START + arg_index; + err = hb_bp_write_to_mc_bridge(&args_req_pkt); + err = hb_bp_read_from_mc_bridge(&args_resp_pkt, HB_MC_FIFO_RX_RSP); if (err != HB_MC_SUCCESS) bp_finish(err); uint32_t data = args_resp_pkt.response.data; - if (data != HB_MC_HOST_OP_FINISH_CODE) { + if (data != HB_BP_HOST_OP_FINISH_CODE) { uint32_t mask = 0xFF000000; uint8_t byte; for(int i = 0; i < 4; i++) { diff --git a/libraries/platforms/dromajo-vcs/software/src/bp_utils.c b/libraries/platforms/dromajo-vcs/software/src/bp_utils.c index 4291cdb48..6c69de572 100644 --- a/libraries/platforms/dromajo-vcs/software/src/bp_utils.c +++ b/libraries/platforms/dromajo-vcs/software/src/bp_utils.c @@ -55,30 +55,30 @@ void bp_barrier_end(volatile uint64_t * barrier_address, uint64_t total_num_core void bp_finish(int16_t code) { uint64_t core_id; - // Fixme: Core IDs for all BP cores might be zero. How do we handle this? + // Fixme: Core IDs for all BP cores might be zero. How do we handle this? __asm__ volatile("csrr %0, mhartid": "=r"(core_id): :); // Finish packet contains core id at the top 16 bits and - // finish code at the bottom 16 bits - // zero --> success code - // nonzero --> fail code - hb_mc_packet_t finish_pkt; - finish_pkt.request.x_dst = HOST_X_COORD; - finish_pkt.request.y_dst = HOST_Y_COORD; - finish_pkt.request.x_src = BP_HOST_LINK_X; - finish_pkt.request.y_src = BP_HOST_LINK_Y; - finish_pkt.request.op_v2 = HB_MC_PACKET_OP_REMOTE_SW; - finish_pkt.request.payload = (core_id << 16) | (0x0000FFFF & code); - finish_pkt.request.reg_id = 0; - if (code >= 0) - finish_pkt.request.addr = HB_MC_HOST_EPA_FINISH; - else - finish_pkt.request.addr = HB_MC_HOST_EPA_FAIL; + // finish code at the bottom 16 bits + // zero --> success code + // nonzero --> fail code + hb_mc_packet_t finish_pkt; + finish_pkt.request.x_dst = HOST_X_COORD; + finish_pkt.request.y_dst = HOST_Y_COORD; + finish_pkt.request.x_src = BP_HOST_LINK_X; + finish_pkt.request.y_src = BP_HOST_LINK_Y; + finish_pkt.request.op_v2 = HB_MC_PACKET_OP_REMOTE_SW; + finish_pkt.request.payload = (core_id << 16) | (0x0000FFFF & code); + finish_pkt.request.reg_id = 0; + if (code >= 0) + finish_pkt.request.addr = HB_MC_HOST_EPA_FINISH; + else + finish_pkt.request.addr = HB_MC_HOST_EPA_FAIL; - int err; - do { - err = bp_hb_write_to_mc_bridge(&finish_pkt); - } while (err != HB_MC_SUCCESS); + int err; + do { + err = hb_bp_write_to_mc_bridge(&finish_pkt); + } while (err != HB_MC_SUCCESS); } /* @@ -87,17 +87,17 @@ void bp_finish(int16_t code) { */ void bp_hprint(uint8_t hex) { - hb_mc_packet_t hprint_pkt; - hprint_pkt.request.x_dst = HOST_X_COORD; - hprint_pkt.request.y_dst = HOST_Y_COORD; - hprint_pkt.request.x_src = BP_HOST_LINK_X; - hprint_pkt.request.y_src = BP_HOST_LINK_Y; - hprint_pkt.request.op_v2 = HB_MC_PACKET_OP_REMOTE_SW; - hprint_pkt.request.payload = ('0' + hex); - hprint_pkt.request.reg_id = 0; - hprint_pkt.request.addr = HB_MC_HOST_EPA_STDOUT; + hb_mc_packet_t hprint_pkt; + hprint_pkt.request.x_dst = HOST_X_COORD; + hprint_pkt.request.y_dst = HOST_Y_COORD; + hprint_pkt.request.x_src = BP_HOST_LINK_X; + hprint_pkt.request.y_src = BP_HOST_LINK_Y; + hprint_pkt.request.op_v2 = HB_MC_PACKET_OP_REMOTE_SW; + hprint_pkt.request.payload = ('0' + hex); + hprint_pkt.request.reg_id = 0; + hprint_pkt.request.addr = HB_MC_HOST_EPA_STDOUT; - int err = bp_hb_write_to_mc_bridge(&hprint_pkt); + int err = hb_bp_write_to_mc_bridge(&hprint_pkt); } /* @@ -106,15 +106,15 @@ void bp_hprint(uint8_t hex) { */ void bp_cprint(uint8_t ch) { - hb_mc_packet_t cprint_pkt; - cprint_pkt.request.x_dst = HOST_X_COORD; - cprint_pkt.request.y_dst = HOST_Y_COORD; - cprint_pkt.request.x_src = BP_HOST_LINK_X; - cprint_pkt.request.y_src = BP_HOST_LINK_Y; - cprint_pkt.request.op_v2 = HB_MC_PACKET_OP_REMOTE_SW; - cprint_pkt.request.payload = ch; - cprint_pkt.request.reg_id = 0; - cprint_pkt.request.addr = HB_MC_HOST_EPA_STDOUT; + hb_mc_packet_t cprint_pkt; + cprint_pkt.request.x_dst = HOST_X_COORD; + cprint_pkt.request.y_dst = HOST_Y_COORD; + cprint_pkt.request.x_src = BP_HOST_LINK_X; + cprint_pkt.request.y_src = BP_HOST_LINK_Y; + cprint_pkt.request.op_v2 = HB_MC_PACKET_OP_REMOTE_SW; + cprint_pkt.request.payload = ch; + cprint_pkt.request.reg_id = 0; + cprint_pkt.request.addr = HB_MC_HOST_EPA_STDOUT; - int err = bp_hb_write_to_mc_bridge(&cprint_pkt); + int err = hb_bp_write_to_mc_bridge(&cprint_pkt); } From 54ffd57664f762f7dfb683644e7f1c7c6435f469 Mon Sep 17 00:00:00 2001 From: sripathi-muralitharan Date: Sat, 17 Jul 2021 14:27:39 -0700 Subject: [PATCH 55/70] Fixing alloca to malloc inversion in argp library --- .../platforms/dromajo-vcs/software/src/argp/argp-parse.c | 9 +++++++-- libraries/platforms/dromajo-vcs/software/src/args.c | 2 +- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/libraries/platforms/dromajo-vcs/software/src/argp/argp-parse.c b/libraries/platforms/dromajo-vcs/software/src/argp/argp-parse.c index 77d87d154..7eb5cc6dd 100644 --- a/libraries/platforms/dromajo-vcs/software/src/argp/argp-parse.c +++ b/libraries/platforms/dromajo-vcs/software/src/argp/argp-parse.c @@ -919,6 +919,11 @@ __argp_parse (const struct argp *argp, int argc, char **argv, unsigned flags, // Forward declare the struct pointers since malloc is being used instead of alloca struct argp_child *child; struct argp *top_argp; + + // Set these to NULL when not used + child = NULL; + top_argp = NULL; + if (! (flags & ARGP_NO_HELP)) /* Add our own options. */ { @@ -930,7 +935,7 @@ __argp_parse (const struct argp *argp, int argc, char **argv, unsigned flags, /* TOP_ARGP has no options, it just serves to group the user & default argps. */ - memset (top_argp, 0, sizeof (*top_argp)); + memset (top_argp, 0, sizeof (struct argp)); top_argp->children = child; memset (child, 0, 4 * sizeof (struct argp_child)); @@ -961,7 +966,7 @@ __argp_parse (const struct argp *argp, int argc, char **argv, unsigned flags, // alloca automatically freed the memory when the function returned // but since we are using malloc, we need to explicitly free it to // avoid memory leaks - free(child); + free(top_argp->children); free(top_argp); return err; diff --git a/libraries/platforms/dromajo-vcs/software/src/args.c b/libraries/platforms/dromajo-vcs/software/src/args.c index f7b1ca53a..a9661a3b4 100644 --- a/libraries/platforms/dromajo-vcs/software/src/args.c +++ b/libraries/platforms/dromajo-vcs/software/src/args.c @@ -42,7 +42,7 @@ void __init_args(void) { // The platform setup in simulation ensures that this packet will not go over the network so // we don't need to check for credits. Also, this code is executed before the CUDA-lite // program starts. - args_req_pkt.request.addr = HB_BP_HOST_EPA_ARGS_START + arg_index; + args_req_pkt.request.addr = HB_BP_HOST_EPA_ARGS_START + (arg_index << 2); err = hb_bp_write_to_mc_bridge(&args_req_pkt); err = hb_bp_read_from_mc_bridge(&args_resp_pkt, HB_MC_FIFO_RX_RSP); if (err != HB_MC_SUCCESS) From 3961bfd2ff40cc384f886ff6bda81a9cbaba886b Mon Sep 17 00:00:00 2001 From: sripathi-muralitharan Date: Sat, 17 Jul 2021 14:28:29 -0700 Subject: [PATCH 56/70] Addressing review comments --- .../dromajo-vcs/bsg_manycore_platform.cpp | 11 ++---- .../dromajo-vcs/bsg_manycore_simulator.cpp | 39 +++++++++++-------- .../dromajo-vcs/bsg_manycore_simulator.hpp | 7 ++++ .../platforms/dromajo-vcs/compilation.mk | 2 +- .../platforms/dromajo-vcs/hb_bp_platform.h | 14 ++++--- libraries/platforms/dromajo-vcs/library.mk | 4 +- 6 files changed, 45 insertions(+), 32 deletions(-) diff --git a/libraries/platforms/dromajo-vcs/bsg_manycore_platform.cpp b/libraries/platforms/dromajo-vcs/bsg_manycore_platform.cpp index c50756104..6a6fabe75 100644 --- a/libraries/platforms/dromajo-vcs/bsg_manycore_platform.cpp +++ b/libraries/platforms/dromajo-vcs/bsg_manycore_platform.cpp @@ -239,13 +239,13 @@ int hb_mc_platform_transmit(hb_mc_manycore_t *mc, hb_mc_packet_t *packet, hb_mc_ return HB_MC_NOIMPL; } + // Don't need to check for error code since this operation should always be a success since it is not going + // over the network int credits_used = 0; do { err = hb_bp_get_credits_used(&credits_used); } while ((err != HB_MC_SUCCESS) || ((max_credits - credits_used) <= 0)); - // Don't need to check for error code since this operation should always be a success since it is not going - // over the network err = hb_bp_write_to_mc_bridge(packet); if (err != HB_MC_SUCCESS) { bsg_pr_err("Write to the host request FIFO failed!"); @@ -308,12 +308,9 @@ int hb_mc_platform_get_config_at(hb_mc_manycore_t *mc, unsigned int idx, hb_mc_c config_req_pkt.request.op_v2 = HB_MC_PACKET_OP_REMOTE_LOAD; config_req_pkt.request.payload = 0; config_req_pkt.request.reg_id = 0; - // Note 1: This will not translate to hardware correctly because - // addr is word addressable. Works in C/C++ because the C code considers - // the address as a byte addressable field. - // Note 2: The onus is on the simulator (i.e. x86 code) to check if the config + // Note: The onus is on the simulator (i.e. x86 code) to check if the config // index is within bounds before accessing the DPI ROM. - config_req_pkt.request.addr = HB_BP_HOST_EPA_CONFIG_START + idx; + config_req_pkt.request.addr = HB_BP_HOST_EPA_CONFIG_START + (idx << 2); // Note: Potentially dangerous to write to the FIFO without checking for credits // We get back credits used and not credits remaining and without the configuration diff --git a/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.cpp b/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.cpp index acbd4568c..d2caee0c9 100644 --- a/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.cpp +++ b/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.cpp @@ -39,15 +39,10 @@ extern "C" { void bsg_dpi_next(); } -// Global variables to store arguments -int _argc; -char **_argv; -static int char_index = 0; - ////////////////////////////// SimulationWrapper functions ////////////////////////////// // Constructor -SimulationWrapper::SimulationWrapper(){ +SimulationWrapper::SimulationWrapper() { root = new std::string("replicant_tb_top"); std::string mc_dpi = *root + ".mc_dpi"; top = svGetScopeFromName(mc_dpi.c_str()); @@ -64,15 +59,24 @@ SimulationWrapper::SimulationWrapper(){ if (!dpi) { bsg_pr_err("Failed to initialize DPI pointer\n"); } + + // Initialize the argument character counter + char_index = 0; } // Destructor -SimulationWrapper::~SimulationWrapper(){ +SimulationWrapper::~SimulationWrapper() { dpi_cleanup(); dromajo_cosim_fini(dromajo); this->top = nullptr; } +// Sets the arguments +void SimulationWrapper::set_args(int argc, char **argv) { + this->argc = argc; + this->argv = argv; +} + // Advances time to the next clock edge void SimulationWrapper::advance_time() { svScope prev; @@ -241,15 +245,16 @@ int SimulationWrapper::dromajo_transmit_packet() { switch (dromajo_to_mc_packet.request.addr) { case HB_BP_HOST_EPA_ARGS_START ... HB_BP_HOST_EPA_ARGS_FINISH: { - uint32_t idx = dromajo_to_mc_packet.request.addr - HB_BP_HOST_EPA_ARGS_START; + // Argument indexes for x86 should be byte addressable but the hardware uses word addresses + uint32_t arg_index = ((dromajo_to_mc_packet.request.addr - HB_BP_HOST_EPA_ARGS_START) >> 2); int num_characters = 0; // If all arguments have been read or there are no arguments to read // send a finish code - if ((idx != _argc) && (_argc != 0)) { + if ((arg_index != argc) && (argc != 0)) { // Copy 4 bytes of the arguments for(int i = 0; i < 4; i++) { - if (_argv[idx][char_index] != '\0') { - data = (data << 8) | _argv[idx][char_index]; + if (argv[arg_index][char_index] != '\0') { + data = (data << 8) | argv[arg_index][char_index]; num_characters++; char_index++; } @@ -265,7 +270,7 @@ int SimulationWrapper::dromajo_transmit_packet() { break; case HB_BP_HOST_EPA_CONFIG_START ... HB_BP_HOST_EPA_CONFIG_FINISH: { - uint32_t idx = dromajo_to_mc_packet.request.addr - HB_BP_HOST_EPA_CONFIG_START; + uint32_t idx = ((dromajo_to_mc_packet.request.addr - HB_BP_HOST_EPA_CONFIG_START) >> 2); if (idx <= HB_MC_CONFIG_MAX) data = dpi->config[idx]; else { @@ -594,10 +599,6 @@ static void get_argv(char * args, int argc, char **argv){ * @returns */ int vcs_main(int argc, char **argv) { - // Push command-line arguments into global variables - _argc = argc; - _argv = argv; - // Initialize Host SimulationWrapper *host = new SimulationWrapper(); if (!host) { @@ -605,7 +606,13 @@ int vcs_main(int argc, char **argv) { return HB_MC_FAIL; } + // Assign arguments + host->set_args(argc, argv); + int err; + // TODO: Currently the simulation terminates by encoding the error code and the core + // ID in the 32-bit data field of a finish packet sent to the host. Need to come up + // with a more elegant solution for this. do { err = host->eval(); // Codes greater than 0 can be used to terminate a program diff --git a/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.hpp b/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.hpp index b0eee21b0..eebb2dc19 100644 --- a/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.hpp +++ b/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.hpp @@ -78,11 +78,18 @@ class SimulationWrapper{ dromajo_cosim_state_t *dromajo; // Pointer to the manycore DPI controller bsg_nonsynth_dpi::dpi_manycore *dpi; + // Fields to keep track of arguments + int argc; + char **argv; + int char_index; public: SimulationWrapper(); ~SimulationWrapper(); + // Set the argument fields to pass them into Dromajo + void set_args(int argc, char **argv); + // Change the assertion state. // When Verilator simulation starts, we want to disable diff --git a/libraries/platforms/dromajo-vcs/compilation.mk b/libraries/platforms/dromajo-vcs/compilation.mk index 9c4a8c03f..e85f4295c 100644 --- a/libraries/platforms/dromajo-vcs/compilation.mk +++ b/libraries/platforms/dromajo-vcs/compilation.mk @@ -38,7 +38,7 @@ include $(BSG_MACHINE_PATH)/Makefile.machine.include # This file REQUIRES several variables to be set. They are typically # set by the Makefile that includes this makefile.. # -DEFINES += -D_DRAMFS -DHOST_X_COORD=$(BSG_MACHINE_HOST_COORD_X) -DHOST_Y_COORD=$(BSG_MACHINE_HOST_COORD_Y) +DEFINES += -D_DRAMFS -DHOST_X_COORD=$(BSG_MACHINE_HOST_COORD_X) -DHOST_Y_COORD=$(BSG_MACHINE_HOST_COORD_Y) -DBP_POD_X=0 -DBP_POD_Y=1 INCLUDES += -I$(LIBRARIES_PATH) INCLUDES += -I$(BSG_PLATFORM_PATH) INCLUDES += -I$(BSG_PLATFORM_PATH)/software/include diff --git a/libraries/platforms/dromajo-vcs/hb_bp_platform.h b/libraries/platforms/dromajo-vcs/hb_bp_platform.h index 063e95665..1ffd1ee38 100644 --- a/libraries/platforms/dromajo-vcs/hb_bp_platform.h +++ b/libraries/platforms/dromajo-vcs/hb_bp_platform.h @@ -20,12 +20,6 @@ extern "C" { #error HOST_Y_COORD is undefined #endif -// BlackParrot coordinates -// Note: Currently not all of these coordinates are in use -// but might be useful during BlackParrot integration -#ifndef BP_COORDS -#define BP_POD_X 0 -#define BP_POD_Y 1 // Coordinates of BP-HB bridge used for manycore communication #define BP_HOST_LINK_X 15 #define BP_HOST_LINK_Y 9 @@ -34,6 +28,14 @@ extern "C" { #define BP_DRAM_0_LINK_Y 10 #define BP_DRAM_1_LINK_X 15 #define BP_DRAM_1_LINK_Y 11 + +// BlackParrot pod coordinates +#ifndef BP_POD_X +#error BP_POD_X is not defined +#endif + +#ifndef BP_POD_Y +#error BP_POD_Y is not defined #endif // Memory mapped addresses to interact with the BlackParrot host (aka simulator) diff --git a/libraries/platforms/dromajo-vcs/library.mk b/libraries/platforms/dromajo-vcs/library.mk index bc9b3e827..dabebdb8d 100644 --- a/libraries/platforms/dromajo-vcs/library.mk +++ b/libraries/platforms/dromajo-vcs/library.mk @@ -132,8 +132,8 @@ $(PLATFORM_OBJECTS): INCLUDES += -I$(VCS_HOME)/linux64/lib/ $(PLATFORM_OBJECTS): INCLUDES += -I$(BSG_MANYCORE_DIR)/testbenches/dpi/ $(PLATFORM_OBJECTS): INCLUDES += -I$(BASEJUMP_STL_DIR)/bsg_test/ $(PLATFORM_OBJECTS): INCLUDES += -I$(BLACKPARROT_SDK_DIR)/dromajo/include -$(PLATFORM_OBJECTS): CFLAGS := -std=c11 -fPIC -DVCS -D_GNU_SOURCE -DVERILATOR -D_BSD_SOURCE -D_XOPEN_SOURCE=500 -DHOST_X_COORD=$(BSG_MACHINE_HOST_COORD_X) -DHOST_Y_COORD=$(BSG_MACHINE_HOST_COORD_Y) -DNUM_DROMAJO_INSTR_PER_TICK=1000 -DNUM_TX_FIFO_CHK_PER_TICK=100 -$(PLATFORM_OBJECTS): CXXFLAGS := -std=c++11 -fPIC -DVCS -D_GNU_SOURCE -DVERILATOR -D_BSD_SOURCE -D_XOPEN_SOURCE=500 -DHOST_X_COORD=$(BSG_MACHINE_HOST_COORD_X) -DHOST_Y_COORD=$(BSG_MACHINE_HOST_COORD_Y) -DNUM_DROMAJO_INSTR_PER_TICK=1000 -DNUM_TX_FIFO_CHK_PER_TICK=100 +$(PLATFORM_OBJECTS): CFLAGS := -std=c11 -fPIC -DVCS -D_GNU_SOURCE -DVERILATOR -D_BSD_SOURCE -D_XOPEN_SOURCE=500 -DHOST_X_COORD=$(BSG_MACHINE_HOST_COORD_X) -DHOST_Y_COORD=$(BSG_MACHINE_HOST_COORD_Y) -DNUM_DROMAJO_INSTR_PER_TICK=1000 -DNUM_TX_FIFO_CHK_PER_TICK=100 -DBP_POD_X=0 -DBP_POD_Y=1 +$(PLATFORM_OBJECTS): CXXFLAGS := -std=c++11 -fPIC -DVCS -D_GNU_SOURCE -DVERILATOR -D_BSD_SOURCE -D_XOPEN_SOURCE=500 -DHOST_X_COORD=$(BSG_MACHINE_HOST_COORD_X) -DHOST_Y_COORD=$(BSG_MACHINE_HOST_COORD_Y) -DNUM_DROMAJO_INSTR_PER_TICK=1000 -DNUM_TX_FIFO_CHK_PER_TICK=100 -DBP_POD_X=0 -DBP_POD_Y=1 $(PLATFORM_OBJECTS): LDFLAGS := -fPIC $(PLATFORM_OBJECTS): CXX = g++ From 3c0ac03e9b9f768eaae98676c791ad0fba98c4de Mon Sep 17 00:00:00 2001 From: sripathi-muralitharan Date: Tue, 20 Jul 2021 00:35:13 -0700 Subject: [PATCH 57/70] Some Aesthetics and Simulation updates --- .../dromajo-vcs/bsg_manycore_simulator.cpp | 33 ++++++++++++++----- .../dromajo-vcs/bsg_manycore_simulator.hpp | 2 ++ libraries/platforms/dromajo-vcs/library.mk | 13 ++++++-- 3 files changed, 37 insertions(+), 11 deletions(-) diff --git a/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.cpp b/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.cpp index d2caee0c9..76d88d748 100644 --- a/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.cpp +++ b/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.cpp @@ -85,6 +85,15 @@ void SimulationWrapper::advance_time() { svSetScope(prev); } +// Advances time by N clock edges +void SimulationWrapper::advance_time_cycles(int N) { + svScope prev; + prev = svSetScope(top); + for (int i = 0; i < N; i++) + bsg_dpi_next(); + svSetScope(prev); +} + // Does nothing. Turning on/off assertions is only supported in // Verilator. void SimulationWrapper::assertOn(bool val){ @@ -220,6 +229,7 @@ int SimulationWrapper::dromajo_transmit_packet() { __m128i *pkt; mc_fifo_type_t type = FIFO_HOST_TO_MC_REQ; + bool is_empty; do { // Read the FIFO head pointer for all 32-bit FIFOs @@ -379,11 +389,11 @@ int SimulationWrapper::dromajo_transmit_packet() { do { advance_time(); err = dpi->tx_req(*pkt, expect_response); - } while (err != BSG_NONSYNTH_DPI_SUCCESS && - (err == BSG_NONSYNTH_DPI_NO_CREDITS || + } while (err != BSG_NONSYNTH_DPI_SUCCESS && + (err == BSG_NONSYNTH_DPI_NO_CREDITS || err == BSG_NONSYNTH_DPI_NO_CAPACITY || - err == BSG_NONSYNTH_DPI_NOT_WINDOW || - err == BSG_NONSYNTH_DPI_BUSY || + err == BSG_NONSYNTH_DPI_NOT_WINDOW || + err == BSG_NONSYNTH_DPI_BUSY || err == BSG_NONSYNTH_DPI_NOT_READY)); if (err == BSG_NONSYNTH_DPI_SUCCESS) { @@ -400,7 +410,8 @@ int SimulationWrapper::dromajo_transmit_packet() { if (err != HB_MC_SUCCESS) return err; } - } while (!mc_is_fifo_empty(type)); + is_empty = mc_is_fifo_empty(type); + } while (!is_empty); return HB_MC_SUCCESS; } @@ -425,8 +436,7 @@ int SimulationWrapper::dromajo_receive_packet() { err = dpi->rx_req(pkt); } while (err != BSG_NONSYNTH_DPI_SUCCESS && (err == BSG_NONSYNTH_DPI_NOT_WINDOW || - err == BSG_NONSYNTH_DPI_BUSY || - err == BSG_NONSYNTH_DPI_INVALID)); + err == BSG_NONSYNTH_DPI_BUSY)); if (err == BSG_NONSYNTH_DPI_SUCCESS) { mc_to_dromajo_req_packet = reinterpret_cast(&pkt); @@ -443,8 +453,7 @@ int SimulationWrapper::dromajo_receive_packet() { err = dpi->rx_rsp(pkt); } while (err != BSG_NONSYNTH_DPI_SUCCESS && (err == BSG_NONSYNTH_DPI_NOT_WINDOW || - err == BSG_NONSYNTH_DPI_BUSY || - err == BSG_NONSYNTH_DPI_INVALID)); + err == BSG_NONSYNTH_DPI_BUSY)); if (err == BSG_NONSYNTH_DPI_SUCCESS) { mc_to_dromajo_resp_packet = reinterpret_cast(&pkt); @@ -494,6 +503,12 @@ int SimulationWrapper::eval(){ return HB_MC_SUCCESS; } + // Advancing time is required for things to move around in hardware, however + // it adds a large overhead to the simulation time. Balance these values to + // hit that sweet spot. + if ((i % 10) == 0) + advance_time_cycles(10); + // Check if transmit FIFO has an element and hence ready to transmit // This operation is relatively low overhead since only a single FIFO's // empty status is being checked. Hence, we can afford to do it every 100 diff --git a/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.hpp b/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.hpp index eebb2dc19..c82e159f7 100644 --- a/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.hpp +++ b/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.hpp @@ -104,6 +104,8 @@ class SimulationWrapper{ // Advances to the next clock edge void advance_time(); + // Advances time by N clock edges + void advance_time_cycles(int N); // DPI functions int dpi_fifo_drain(hb_mc_fifo_rx_t); diff --git a/libraries/platforms/dromajo-vcs/library.mk b/libraries/platforms/dromajo-vcs/library.mk index dabebdb8d..bede19a3f 100644 --- a/libraries/platforms/dromajo-vcs/library.mk +++ b/libraries/platforms/dromajo-vcs/library.mk @@ -113,6 +113,7 @@ DROMAJO_CXXSOURCES += $(DROMAJO_DIR)/src/virtio.cpp DROMAJO_OBJECTS += $(patsubst %cpp,%o,$(DROMAJO_CXXSOURCES)) +$(DROMAJO_OBJECTS): $(BSG_MACHINE_PATH)/Makefile.machine.include $(DROMAJO_OBJECTS): INCLUDES := -I$(DROMAJO_DIR)/include $(DROMAJO_OBJECTS): INCLUDES += -I$(BSG_PLATFORM_PATH)/software/include/dromajo $(DROMAJO_OBJECTS): CXXFLAGS := -std=c++11 -fPIC -Wall -Wno-parentheses -MMD -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_GNU_SOURCE -D__STDC_FORMAT_MACROS -DFIFO_MAX_ELEMENTS=$(BSG_MACHINE_IO_EP_CREDITS) -std=gnu++11 @@ -121,9 +122,17 @@ $(DROMAJO_OBJECTS): CXX = g++ PLATFORM_CXXSOURCES += $(BSG_PLATFORM_PATH)/bsg_manycore_simulator.cpp +PLATFORM_DEFINES = -DHOST_X_COORD=$(BSG_MACHINE_HOST_COORD_X) +PLATFORM_DEFINES += -DHOST_Y_COORD=$(BSG_MACHINE_HOST_COORD_Y) +PLATFORM_DEFINES += -DBP_POD_X=0 -DBP_POD_Y=1 +PLATFORM_DEFINES += -DNUM_DROMAJO_INSTR_PER_TICK=1000 +PLATFORM_DEFINES += -DNUM_TX_FIFO_CHK_PER_TICK=100 +PLATFORM_DEFINES += -DFIFO_MAX_ELEMENTS=$(BSG_MACHINE_IO_EP_CREDITS) + PLATFORM_OBJECTS += $(patsubst %cpp,%o,$(PLATFORM_CXXSOURCES)) PLATFORM_OBJECTS += $(patsubst %c,%o,$(PLATFORM_CSOURCES)) +$(PLATFORM_OBJECTS): $(BSG_MACHINE_PATH)/Makefile.machine.include $(PLATFORM_OBJECTS): INCLUDES := -I$(LIBRARIES_PATH) $(PLATFORM_OBJECTS): INCLUDES += -I$(EXAMPLES_PATH) $(PLATFORM_OBJECTS): INCLUDES += -I$(BSG_MACHINE_PATH)/notrace/ @@ -132,8 +141,8 @@ $(PLATFORM_OBJECTS): INCLUDES += -I$(VCS_HOME)/linux64/lib/ $(PLATFORM_OBJECTS): INCLUDES += -I$(BSG_MANYCORE_DIR)/testbenches/dpi/ $(PLATFORM_OBJECTS): INCLUDES += -I$(BASEJUMP_STL_DIR)/bsg_test/ $(PLATFORM_OBJECTS): INCLUDES += -I$(BLACKPARROT_SDK_DIR)/dromajo/include -$(PLATFORM_OBJECTS): CFLAGS := -std=c11 -fPIC -DVCS -D_GNU_SOURCE -DVERILATOR -D_BSD_SOURCE -D_XOPEN_SOURCE=500 -DHOST_X_COORD=$(BSG_MACHINE_HOST_COORD_X) -DHOST_Y_COORD=$(BSG_MACHINE_HOST_COORD_Y) -DNUM_DROMAJO_INSTR_PER_TICK=1000 -DNUM_TX_FIFO_CHK_PER_TICK=100 -DBP_POD_X=0 -DBP_POD_Y=1 -$(PLATFORM_OBJECTS): CXXFLAGS := -std=c++11 -fPIC -DVCS -D_GNU_SOURCE -DVERILATOR -D_BSD_SOURCE -D_XOPEN_SOURCE=500 -DHOST_X_COORD=$(BSG_MACHINE_HOST_COORD_X) -DHOST_Y_COORD=$(BSG_MACHINE_HOST_COORD_Y) -DNUM_DROMAJO_INSTR_PER_TICK=1000 -DNUM_TX_FIFO_CHK_PER_TICK=100 -DBP_POD_X=0 -DBP_POD_Y=1 +$(PLATFORM_OBJECTS): CFLAGS := -std=c11 -fPIC -DVCS -D_GNU_SOURCE -DVERILATOR -D_BSD_SOURCE -D_XOPEN_SOURCE=500 $(PLATFORM_DEFINES) +$(PLATFORM_OBJECTS): CXXFLAGS := -std=c++11 -fPIC -DVCS -D_GNU_SOURCE -DVERILATOR -D_BSD_SOURCE -D_XOPEN_SOURCE=500 $(PLATFORM_DEFINES) $(PLATFORM_OBJECTS): LDFLAGS := -fPIC $(PLATFORM_OBJECTS): CXX = g++ From a00d4567dfd09992286049fc2755dcedc65d30cc Mon Sep 17 00:00:00 2001 From: sripathi-muralitharan Date: Sat, 31 Jul 2021 20:29:12 -0700 Subject: [PATCH 58/70] Addressing review comments; Better error messages and reporting --- .../dromajo-vcs/bsg_manycore_platform.cpp | 60 +++- .../dromajo-vcs/bsg_manycore_simulator.cpp | 324 ++++++++++-------- .../dromajo-vcs/bsg_manycore_simulator.hpp | 5 +- 3 files changed, 221 insertions(+), 168 deletions(-) diff --git a/libraries/platforms/dromajo-vcs/bsg_manycore_platform.cpp b/libraries/platforms/dromajo-vcs/bsg_manycore_platform.cpp index 6a6fabe75..77e0c7cd5 100644 --- a/libraries/platforms/dromajo-vcs/bsg_manycore_platform.cpp +++ b/libraries/platforms/dromajo-vcs/bsg_manycore_platform.cpp @@ -68,10 +68,13 @@ int hb_bp_get_credits_used(int *credits_used) { * Writes a 128-bit manycore packet in 32-bit chunks to the manycore bridge FIFO * @param[in] pkt --> Pointer to the manycore packet * @returns HB_MC_SUCCESS - * TODO: Implement error checking (Requires some modifications in Dromajo) */ int hb_bp_write_to_mc_bridge(hb_mc_packet_t *pkt) { uint32_t *bp_to_mc_req_fifo_addr = reinterpret_cast(MC_BASE_ADDR + BP_TO_MC_REQ_FIFO_ADDR); + // TODO: Currently this function maps to an operation in Dromajo that has to wait until the write succeeds. + // The Dromajo function must do some error checking and return appropriate error codes to the software. + // However, currently (and understandbly) Dromajo does not allow anything to be returned on writes to + // the software. for(int i = 0; i < 4; i++) { *bp_to_mc_req_fifo_addr = pkt->words[i]; bp_to_mc_req_fifo_addr++; @@ -248,7 +251,7 @@ int hb_mc_platform_transmit(hb_mc_manycore_t *mc, hb_mc_packet_t *packet, hb_mc_ err = hb_bp_write_to_mc_bridge(packet); if (err != HB_MC_SUCCESS) { - bsg_pr_err("Write to the host request FIFO failed!"); + manycore_pr_err(mc, "%s: Write to the host request FIFO failed\n", __func__); return err; } @@ -281,8 +284,8 @@ int hb_mc_platform_receive(hb_mc_manycore_t *mc, hb_mc_packet_t *packet, hb_mc_f err = hb_bp_read_from_mc_bridge(packet, type); if (err != HB_MC_SUCCESS) { - bsg_pr_err("Read from the %s FIFO did not succeed", typestr); - return HB_MC_INVALID; + manycore_pr_err(mc, "%s: Read from the %s FIFO did not succeed", __func__, typestr); + return err; } return HB_MC_SUCCESS; @@ -317,7 +320,7 @@ int hb_mc_platform_get_config_at(hb_mc_manycore_t *mc, unsigned int idx, hb_mc_c // there is no way to know the credits remaining. err = hb_bp_write_to_mc_bridge(&config_req_pkt); if (err != HB_MC_SUCCESS) { - bsg_pr_err("Write to the host request FIFO failed!"); + manycore_pr_err(mc, "%s: Write to the host request FIFO failed\n", __func__); return err; } @@ -327,8 +330,8 @@ int hb_mc_platform_get_config_at(hb_mc_manycore_t *mc, unsigned int idx, hb_mc_c err = hb_bp_read_from_mc_bridge(&config_resp_pkt, HB_MC_FIFO_RX_RSP); if (err != HB_MC_SUCCESS) { - bsg_pr_err("Config read failed\n"); - return HB_MC_FAIL; + manycore_pr_err(mc, "%s: Read from the manycore response FIFO failed\n", __func__); + return err; } *config = config_resp_pkt.response.data; @@ -368,20 +371,35 @@ int hb_mc_platform_fence(hb_mc_manycore_t *mc, long timeout) { do { err = hb_bp_get_credits_used(&credits_used); - // In a real system, this function call makes no sense since we will be sending packets to the - // host on the network and are trying to check for credits to be zero and complete the fence. - // It is fine here because of the system setup. - err |= hb_bp_write_to_mc_bridge(&fence_req_pkt); + if (err != HB_MC_SUCCESS) { + manycore_pr_err(mc, "%s: Credit update failed\n", __func__); + return err; + } + + // In the real system (with BP), we will be performing memory-mapped reads to the bridge to grab the current + // status of the number of endpoint credits for the host. With Dromajo, it still makes sense to do this since + // host packets are not transmitted over the network. If host packets have to go over the network then it does + // not make sense since we are sending packets on the TX FIFO and are expecting the TX FIFO to be vacant. + err = hb_bp_write_to_mc_bridge(&fence_req_pkt); + if (err != HB_MC_SUCCESS) { + manycore_pr_err(mc, "%s: Write to the host request FIFO failed\n", __func__); + return err; + } do { err = hb_bp_get_fifo_entries(&num_entries, HB_MC_FIFO_RX_RSP); } while ((num_entries == 0) || (err != HB_MC_SUCCESS)); - err |= hb_bp_read_from_mc_bridge(&fence_resp_pkt, HB_MC_FIFO_RX_RSP); + err = hb_bp_read_from_mc_bridge(&fence_resp_pkt, HB_MC_FIFO_RX_RSP); + if (err != HB_MC_SUCCESS) { + manycore_pr_err(mc, "%s: Read from the manycore response FIFO failed\n", __func__); + return err; + } + is_vacant = fence_resp_pkt.response.data; - } while ((err == HB_MC_SUCCESS) && !((credits_used == 0) && is_vacant)); + } while ((credits_used != 0) || !is_vacant); - return err; + return HB_MC_SUCCESS; } /** @@ -482,10 +500,20 @@ int hb_mc_platform_wait_reset_done(hb_mc_manycore_t *mc) { // The platform setup ensures that this packet will not go over the network so // we don't need to check for credits. err = hb_bp_write_to_mc_bridge(&reset_req_pkt); - err |= hb_bp_read_from_mc_bridge(&reset_resp_pkt, HB_MC_FIFO_RX_RSP); + if (err != HB_MC_SUCCESS) { + manycore_pr_err(mc, "%s: Write to host request FIFO failed\n", __func__); + return err; + } + + err = hb_bp_read_from_mc_bridge(&reset_resp_pkt, HB_MC_FIFO_RX_RSP); + if (err != HB_MC_SUCCESS) { + manycore_pr_err(mc, "%s: Read from the host response FIFO failed\n", __func__); + return err; + } data = reset_resp_pkt.response.data; - } while((err != HB_MC_SUCCESS) || (data == 0)); + } while(data == 0); return HB_MC_SUCCESS; } + diff --git a/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.cpp b/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.cpp index 76d88d748..b44930a55 100644 --- a/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.cpp +++ b/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.cpp @@ -53,11 +53,11 @@ SimulationWrapper::SimulationWrapper() { dpi_init(); if (!dromajo) { - bsg_pr_err("Failed to initialize Dromajo pointer\n"); + bsg_pr_err("%s: Failed to initialize Dromajo pointer\n", __func__); } if (!dpi) { - bsg_pr_err("Failed to initialize DPI pointer\n"); + bsg_pr_err("%s: Failed to initialize DPI pointer\n", __func__); } // Initialize the argument character counter @@ -138,7 +138,7 @@ int SimulationWrapper::dpi_fifo_drain(hb_mc_fifo_rx_t type) { err = dpi->rx_rsp(*pkt); break; default: - bsg_pr_err("Unknown FIFO type\n"); + bsg_pr_err("%s: Unknown FIFO type\n", __func__); return HB_MC_FAIL; } @@ -148,7 +148,7 @@ int SimulationWrapper::dpi_fifo_drain(hb_mc_fifo_rx_t type) { && drains <= cap); if (drains == cap) { - bsg_pr_err("Failed to drain FIFO\n"); + bsg_pr_err("%s: Failed to drain FIFO\n", __func__); return HB_MC_FAIL; } @@ -201,7 +201,7 @@ int SimulationWrapper::dromajo_init() { char* argv[] = {dromajo_str, host_str, manycore_str, prog_str}; dromajo = dromajo_cosim_init(4, argv); if (!dromajo) { - bsg_pr_err("Failed to initialize Dromajo!\n"); + bsg_pr_err("%s: Failed to initialize Dromajo instance!\n", __func__); return HB_MC_FAIL; } return HB_MC_SUCCESS; @@ -219,158 +219,180 @@ bool SimulationWrapper::dromajo_step() { /* * dromajo_transmit_packet - * Fetches data from the Dromajo->Manycore FIFO and pushes it into the DPI FIFO - * to send packets to the manycore + * Fetches data from the Dromajo->Manycore FIFO and if its a host packet, performs + * the required host operations and pushes responses back on the response FIFO * @returns success on succesful transmission */ -int SimulationWrapper::dromajo_transmit_packet() { - hb_mc_packet_t dromajo_to_mc_packet, host_to_dromajo_packet; +int SimulationWrapper::dromajo_transmit_host_packet(hb_mc_packet_t *dromajo_to_host_packet) { + hb_mc_packet_t host_to_dromajo_packet; int err; - __m128i *pkt; - - mc_fifo_type_t type = FIFO_HOST_TO_MC_REQ; - bool is_empty; - - do { - // Read the FIFO head pointer for all 32-bit FIFOs - dromajo_to_mc_packet.words[0] = host_to_mc_req_fifo->fifo[0].front(); - dromajo_to_mc_packet.words[1] = host_to_mc_req_fifo->fifo[1].front(); - dromajo_to_mc_packet.words[2] = host_to_mc_req_fifo->fifo[2].front(); - dromajo_to_mc_packet.words[3] = host_to_mc_req_fifo->fifo[3].front(); - - // Intercept packets that are for the host and generate appropriate responses - // TODO: Currently, these packets don't go over the network. In the real system, they will and the simulation infrastructure - // must emulate that as best as possible. - if ((dromajo_to_mc_packet.request.x_dst == HOST_X_COORD) && (dromajo_to_mc_packet.request.y_dst == HOST_Y_COORD)) { - host_to_dromajo_packet.response.x_dst = dromajo_to_mc_packet.request.x_src; - host_to_dromajo_packet.response.y_dst = dromajo_to_mc_packet.request.y_src; - host_to_dromajo_packet.response.load_id = 0; - uint32_t data = 0; - switch (dromajo_to_mc_packet.request.op_v2) { - case HB_MC_PACKET_OP_REMOTE_LOAD: + host_to_dromajo_packet.response.x_dst = dromajo_to_host_packet->request.x_src; + host_to_dromajo_packet.response.y_dst = dromajo_to_host_packet->request.y_src; + host_to_dromajo_packet.response.load_id = 0; + + uint32_t data = 0; + switch (dromajo_to_host_packet->request.op_v2) { + case HB_MC_PACKET_OP_REMOTE_LOAD: + { + // All responses from the host are considered to be of type e_return_int_wb. But a struct similar to + // bsg_manycore_return_packet_type_e is not defined, so return the source packet's op type. Currently, + // the response op type is not used for any operation in the platform, therefore this should be OK. + host_to_dromajo_packet.response.op = dromajo_to_host_packet->request.op_v2; + switch (dromajo_to_host_packet->request.addr) { + case HB_BP_HOST_EPA_ARGS_START ... HB_BP_HOST_EPA_ARGS_FINISH: { - // Fixme: Is there no struct for response opcode like in the manycore hardware - host_to_dromajo_packet.response.op = dromajo_to_mc_packet.request.op_v2; - switch (dromajo_to_mc_packet.request.addr) { - case HB_BP_HOST_EPA_ARGS_START ... HB_BP_HOST_EPA_ARGS_FINISH: - { - // Argument indexes for x86 should be byte addressable but the hardware uses word addresses - uint32_t arg_index = ((dromajo_to_mc_packet.request.addr - HB_BP_HOST_EPA_ARGS_START) >> 2); - int num_characters = 0; - // If all arguments have been read or there are no arguments to read - // send a finish code - if ((arg_index != argc) && (argc != 0)) { - // Copy 4 bytes of the arguments - for(int i = 0; i < 4; i++) { - if (argv[arg_index][char_index] != '\0') { - data = (data << 8) | argv[arg_index][char_index]; - num_characters++; - char_index++; - } - else { - data = (data << (4 - num_characters) * 8); - char_index = 0; - } - } + // Argument indexes for x86 should be byte addressable but the hardware uses word addresses + uint32_t arg_index = ((dromajo_to_host_packet->request.addr - HB_BP_HOST_EPA_ARGS_START) >> 2); + int num_characters = 0; + // If all arguments have been read or there are no arguments to read + // send a finish code + if ((arg_index != argc) && (argc != 0)) { + // Copy 4 bytes of the arguments + for(int i = 0; i < 4; i++) { + if (argv[arg_index][char_index] != '\0') { + data = (data << 8) | argv[arg_index][char_index]; + num_characters++; + char_index++; } - else - data = HB_BP_HOST_OP_FINISH_CODE; - } - break; - case HB_BP_HOST_EPA_CONFIG_START ... HB_BP_HOST_EPA_CONFIG_FINISH: - { - uint32_t idx = ((dromajo_to_mc_packet.request.addr - HB_BP_HOST_EPA_CONFIG_START) >> 2); - if (idx <= HB_MC_CONFIG_MAX) - data = dpi->config[idx]; else { - bsg_pr_err("Configuration ROM index out of bounds\n"); - return HB_MC_NOTFOUND; + data = (data << (4 - num_characters) * 8); + char_index = 0; } } - break; - case HB_BP_HOST_EPA_RESET_DONE: - { - bool done; - dpi->reset_is_done(done); - data = done ? 1 : 0; - } - break; - case HB_BP_HOST_EPA_TX_VACANT: - { - bool is_vacant; - dpi->tx_is_vacant(is_vacant); - data = is_vacant ? 1 : 0; - } - break; - default: - { - bsg_pr_err("Invalid address for host load operation\n"); - return HB_MC_FAIL; - } - - } - host_to_dromajo_packet.response.data = data; - for(int j = 0; j < 4; j++) { - mc_to_host_resp_fifo->fifo[j].push(host_to_dromajo_packet.words[j]); - host_to_mc_req_fifo->fifo[j].pop(); } + else + data = HB_BP_HOST_OP_FINISH_CODE; } break; - case HB_MC_PACKET_OP_REMOTE_SW: + case HB_BP_HOST_EPA_CONFIG_START ... HB_BP_HOST_EPA_CONFIG_FINISH: { - switch (dromajo_to_mc_packet.request.addr) { - case HB_MC_HOST_EPA_STDOUT: - case HB_MC_HOST_EPA_STDERR: - { - printf("%c", (uint8_t) dromajo_to_mc_packet.request.payload); - fflush(stdout); - } - break; - case HB_MC_HOST_EPA_FINISH: - { - int16_t core_id = dromajo_to_mc_packet.request.payload >> 16; - // Success error codes in BP is 0, but 0 is already used by the manycore. Any positive number indicates - // success, therefore, add 1. - int err = (0x0000FFFF & dromajo_to_mc_packet.request.payload) + 1; - bsg_pr_info("Core %d successfully terminated\n", core_id); - // De-allocate all pointers prior to termination - dpi_cleanup(); - dromajo_cosim_fini(dromajo); - return err; - } - break; - case HB_MC_HOST_EPA_FAIL: - { - int16_t core_id = dromajo_to_mc_packet.request.payload >> 16; - int16_t err = 0x0000FFFF & dromajo_to_mc_packet.request.payload; - bsg_pr_err("Core %d terminated with code %d\n", core_id, err); - // De-allocate all pointers prior to termination - dpi_cleanup(); - dromajo_cosim_fini(dromajo); - return err; - } - break; - default: - { - bsg_pr_err("Invalid address for host store operation\n"); - return HB_MC_FAIL; - } - } - // Store requests don't have responses so only pop the host to MC fifo - for(int j = 0; j < 4; j++) { - host_to_mc_req_fifo->fifo[j].pop(); + uint32_t idx = ((dromajo_to_host_packet->request.addr - HB_BP_HOST_EPA_CONFIG_START) >> 2); + if (idx <= HB_MC_CONFIG_MAX) + data = dpi->config[idx]; + else { + bsg_pr_err("%s: Configuration ROM index out of bounds\n", __func__); + return HB_MC_NOTFOUND; } } break; + case HB_BP_HOST_EPA_RESET_DONE: + { + bool done; + dpi->reset_is_done(done); + data = done ? 1 : 0; + } + break; + case HB_BP_HOST_EPA_TX_VACANT: + { + bool is_vacant; + dpi->tx_is_vacant(is_vacant); + data = is_vacant ? 1 : 0; + } + break; default: { - bsg_pr_err("Operations other than loads and store words are not implemented for the host\n"); + bsg_pr_err("%s: Invalid address for host load operation\n", __func__); return HB_MC_FAIL; } + + } + host_to_dromajo_packet.response.data = data; + for(int j = 0; j < 4; j++) { + mc_to_host_resp_fifo->fifo[j].push(host_to_dromajo_packet.words[j]); + host_to_mc_req_fifo->fifo[j].pop(); + } + } + break; + case HB_MC_PACKET_OP_REMOTE_SW: + { + switch (dromajo_to_host_packet->request.addr) { + case HB_MC_HOST_EPA_STDOUT: + case HB_MC_HOST_EPA_STDERR: + { + printf("%c", (uint8_t) dromajo_to_host_packet->request.payload); + fflush(stdout); + } + break; + case HB_MC_HOST_EPA_FINISH: + { + int16_t core_id = dromajo_to_host_packet->request.payload >> 16; + // Success error codes in BP is 0, but 0 is already used by the manycore. Any positive number indicates + // success, therefore, add 1. + int err = (0x0000FFFF & dromajo_to_host_packet->request.payload) + 1; + bsg_pr_info("Core %d successfully terminated\n", core_id); + // De-allocate all pointers prior to termination + dpi_cleanup(); + dromajo_cosim_fini(dromajo); + return err; + } break; + case HB_MC_HOST_EPA_FAIL: + { + int16_t core_id = dromajo_to_host_packet->request.payload >> 16; + int16_t err = 0x0000FFFF & dromajo_to_host_packet->request.payload; + bsg_pr_err("Core %d terminated with code %d\n", core_id, err); + // De-allocate all pointers prior to termination + dpi_cleanup(); + dromajo_cosim_fini(dromajo); + return err; + } + break; + default: + { + bsg_pr_err("%s: Invalid address for host store operation\n", __func__); + return HB_MC_FAIL; + } + } + // Store requests don't have responses so only pop the host to MC fifo + for(int j = 0; j < 4; j++) { + host_to_mc_req_fifo->fifo[j].pop(); } } + break; + default: + { + bsg_pr_err("%s: Operations other than loads and store words are not implemented for the host\n", __func__); + return HB_MC_FAIL; + } + break; + } + + return HB_MC_SUCCESS; +} + +/* + * dromajo_transmit_packet + * Fetches data from the Dromajo->Manycore FIFO and pushes it into the DPI FIFO + * to send packets to the manycore or the host + * @returns success on succesful transmission + */ +int SimulationWrapper::dromajo_transmit_packet() { + hb_mc_packet_t dromajo_to_mc_packet, host_to_dromajo_packet; + int err; + __m128i *pkt; + + mc_fifo_type_t type = FIFO_HOST_TO_MC_REQ; + bool is_empty; + + do { + // Read the FIFO head pointer for all 32-bit FIFOs + dromajo_to_mc_packet.words[0] = host_to_mc_req_fifo->fifo[0].front(); + dromajo_to_mc_packet.words[1] = host_to_mc_req_fifo->fifo[1].front(); + dromajo_to_mc_packet.words[2] = host_to_mc_req_fifo->fifo[2].front(); + dromajo_to_mc_packet.words[3] = host_to_mc_req_fifo->fifo[3].front(); + + // Intercept packets that are for the host and generate appropriate responses + // TODO: Currently, these packets don't go over the network. In the real system (with BP), some or all of these may be required to go + // over the network. The platform implementation assumes the host packets do not go over the network. In some cases (like fences) this + // might not be desirable. Make sure to keep the platform and the system host in sync on what is actually being simulated. + if ((dromajo_to_mc_packet.request.x_dst == HOST_X_COORD) && (dromajo_to_mc_packet.request.y_dst == HOST_Y_COORD)) { + err = dromajo_transmit_host_packet(&dromajo_to_mc_packet); + // This serves to return the error from the host function + // It is also used to communicate the success code for successful program termination but this code is + // not HB_MC_SUCCESS (maps to 0) but a positive number + return err; + } else { pkt = reinterpret_cast<__m128i *>(&dromajo_to_mc_packet); @@ -381,11 +403,12 @@ int SimulationWrapper::dromajo_transmit_packet() { (dromajo_to_mc_packet.request.op_v2 != HB_MC_PACKET_OP_CACHE_OP); // Attempt packet transmission - // Since we trigger a call to the transmit FIFOs only when the Dromajo - // FIFOs are full, we need to wait until the DPI FIFOs are ready to receive - // before advancing to the next operation. This can prevent filling up of the - // FIFOs. However, not doing this can help in identifying situations that might - // create backpressure in actual hardware and provision for it. + // Since we trigger a call to the transmit FIFOs only when all the 32-bit Dromajo + // FIFOs are full (i.e. a single 128-bit packet is ready), we need to wait until + // the DPI FIFOs are ready to receive before advancing to the next operation. + // This can prevent filling up of the FIFOs. However, not doing this can help in + // identifying situations that might create backpressure in actual hardware and + // provision for it. do { advance_time(); err = dpi->tx_req(*pkt, expect_response); @@ -401,18 +424,18 @@ int SimulationWrapper::dromajo_transmit_packet() { host_to_mc_req_fifo->fifo[i].pop(); } else { - bsg_pr_err("Packet transmission failed\n"); + bsg_pr_err("%s: Packet transmission failed\n", __func__); return HB_MC_FAIL; } - - // Update the credits in dromajo - err = dromajo_set_credits(); - if (err != HB_MC_SUCCESS) - return err; } is_empty = mc_is_fifo_empty(type); } while (!is_empty); + // Update the credits in dromajo + err = dromajo_update_credits(); + if (err != HB_MC_SUCCESS) + return err; + return HB_MC_SUCCESS; } @@ -467,11 +490,11 @@ int SimulationWrapper::dromajo_receive_packet() { } /* - * dromajo_set_credits - * Polls the hardware for credit information and sets the credits info + * dromajo_update_credits + * Polls the hardware for credit information and updates the credits info * for the Dromajo->Manycore request FIFO in dromajo */ -int SimulationWrapper::dromajo_set_credits() { +int SimulationWrapper::dromajo_update_credits() { int credits_used; int err; @@ -482,7 +505,8 @@ int SimulationWrapper::dromajo_set_credits() { } if (credits_used < 0) { - bsg_pr_err("Credit value is < 0. Must be non-negative\n"); + bsg_pr_err("%s: Credit value is < 0. Must be non-negative\n", __func__); + return err; } host_to_mc_req_fifo->credits = credits_used; @@ -617,7 +641,7 @@ int vcs_main(int argc, char **argv) { // Initialize Host SimulationWrapper *host = new SimulationWrapper(); if (!host) { - bsg_pr_err("Could not initialize host!\n"); + bsg_pr_err("%s: Could not initialize host!\n", __func__); return HB_MC_FAIL; } diff --git a/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.hpp b/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.hpp index c82e159f7..69e5d6724 100644 --- a/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.hpp +++ b/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.hpp @@ -108,7 +108,7 @@ class SimulationWrapper{ void advance_time_cycles(int N); // DPI functions - int dpi_fifo_drain(hb_mc_fifo_rx_t); + int dpi_fifo_drain(hb_mc_fifo_rx_t type); void dpi_cleanup(); int dpi_init(); @@ -116,8 +116,9 @@ class SimulationWrapper{ int dromajo_init(); bool dromajo_step(); int dromajo_transmit_packet(); + int dromajo_transmit_host_packet(hb_mc_packet_t *dromajo_to_host_packet); int dromajo_receive_packet(); - int dromajo_set_credits(); + int dromajo_update_credits(); // Evaluates a maximum of NUM_DROMAJO_INSTR_PER_TICK instructions // in RISC-V and forwards packets between Dromajo and the manycore From 6aa884b251a4b53bf9c91afaa05c73d85870eded Mon Sep 17 00:00:00 2001 From: sripathi-muralitharan Date: Mon, 2 Aug 2021 09:06:31 -0700 Subject: [PATCH 59/70] Incomplete: Fixing argument retrieval --- .../dromajo-vcs/bsg_manycore_simulator.cpp | 124 ++++++++++-------- .../platforms/dromajo-vcs/software/src/args.c | 46 ++++--- 2 files changed, 98 insertions(+), 72 deletions(-) diff --git a/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.cpp b/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.cpp index b44930a55..78545d8d8 100644 --- a/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.cpp +++ b/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.cpp @@ -75,6 +75,15 @@ SimulationWrapper::~SimulationWrapper() { void SimulationWrapper::set_args(int argc, char **argv) { this->argc = argc; this->argv = argv; + + // Debugging code: + bsg_pr_info("Received arguments\n"); + bsg_pr_info("Number of arguments = %d\n", this->argc); + int debug_count = 0; + while (debug_count < this->argc) { + bsg_pr_info("Argument %d is %s\n", debug_count, this->argv[debug_count]); + debug_count++; + } } // Advances time to the next clock edge @@ -247,17 +256,18 @@ int SimulationWrapper::dromajo_transmit_host_packet(hb_mc_packet_t *dromajo_to_h int num_characters = 0; // If all arguments have been read or there are no arguments to read // send a finish code - if ((arg_index != argc) && (argc != 0)) { + if ((arg_index != this->argc) && (this->argc != 0)) { // Copy 4 bytes of the arguments for(int i = 0; i < 4; i++) { - if (argv[arg_index][char_index] != '\0') { - data = (data << 8) | argv[arg_index][char_index]; + if (this->argv[arg_index][char_index] != '\0') { + data = (data << 8) | ((uint8_t) this->argv[arg_index][char_index]); num_characters++; - char_index++; + this->char_index++; } else { data = (data << (4 - num_characters) * 8); - char_index = 0; + bsg_pr_info("Data packet at the ends %x\n", data); + this->char_index = 0; } } } @@ -575,16 +585,16 @@ int SimulationWrapper::eval(){ * @returns the number of arguments */ static int get_argc(char * args){ - char *cur = args, prev=' '; - int count = 1; - while(*cur != '\0'){ - if((prev == ' ') && (prev != *cur)){ - count ++; - } - prev = *cur; - ++cur; - } - return count; + char *cur = args, prev=' '; + int count = 1; + while(*cur != '\0'){ + if((prev == ' ') && (prev != *cur)){ + count ++; + } + prev = *cur; + ++cur; + } + return count; } /* @@ -596,36 +606,36 @@ static int get_argc(char * args){ * arguments */ static void get_argv(char * args, int argc, char **argv){ - int count = 0; - char *cur = args, prev=' '; - - // First parse the path name. This is not in the argument string because - // VCS doesn't provide it to us. Instead, we "hack" around it by reading - // the path from 'proc/self/exe'. The maximum path-name length is 1024, - // with an extra null character for safety - static char path[1025] = {'\0'}; - - readlink("/proc/self/exe", path, sizeof(path) - 1); - argv[0] = path; - count ++; - - // Then we parse the remaining arguments. Arguments are separated by N - // >= 1 spaces. We only register an argument when the previous character - // was a space, and the current character is not (so that multiple - // spaces don't count as multiple arguments). We replace spaces with - // null characters (\0) so that each argument appears to be an - // individual string and can be used later, by argparse (and other - // libraries) - while(*cur != '\0'){ - if((prev == ' ') && (prev != *cur)){ - argv[count] = cur; - count++; - } - prev = *cur; - if(*cur == ' ') - *cur = '\0'; - cur++; - } + int count = 0; + char *cur = args, prev=' '; + + // First parse the path name. This is not in the argument string because + // VCS doesn't provide it to us. Instead, we "hack" around it by reading + // the path from 'proc/self/exe'. The maximum path-name length is 1024, + // with an extra null character for safety + static char path[1025] = {'\0'}; + + readlink("/proc/self/exe", path, sizeof(path) - 1); + argv[0] = path; + count ++; + + // Then we parse the remaining arguments. Arguments are separated by N + // >= 1 spaces. We only register an argument when the previous character + // was a space, and the current character is not (so that multiple + // spaces don't count as multiple arguments). We replace spaces with + // null characters (\0) so that each argument appears to be an + // individual string and can be used later, by argparse (and other + // libraries) + while(*cur != '\0'){ + if((prev == ' ') && (prev != *cur)){ + argv[count] = cur; + count++; + } + prev = *cur; + if(*cur == ' ') + *cur = '\0'; + cur++; + } } /* @@ -670,17 +680,17 @@ int vcs_main(int argc, char **argv) { */ extern "C" { void cosim_main(uint32_t *exit_code, char *args) { - // We aren't passed command line arguments directly so we parse them - // from *args. args is a string from VCS - to pass a string of arguments - // to args, pass c_args to VCS as follows: +c_args="" - int argc = get_argc(args); - char *argv[argc]; - get_argv(args, argc, argv); - - int rc = vcs_main(argc, argv); - *exit_code = rc; - bsg_pr_test_pass_fail(rc >= HB_MC_SUCCESS); - return; + // We aren't passed command line arguments directly so we parse them + // from *args. args is a string from VCS - to pass a string of arguments + // to args, pass c_args to VCS as follows: +c_args="" + int argc = get_argc(args); + char *argv[argc]; + get_argv(args, argc, argv); + + int rc = vcs_main(argc, argv); + *exit_code = rc; + bsg_pr_test_pass_fail(rc >= HB_MC_SUCCESS); + return; } } diff --git a/libraries/platforms/dromajo-vcs/software/src/args.c b/libraries/platforms/dromajo-vcs/software/src/args.c index a9661a3b4..7a8bd9385 100644 --- a/libraries/platforms/dromajo-vcs/software/src/args.c +++ b/libraries/platforms/dromajo-vcs/software/src/args.c @@ -8,6 +8,7 @@ #include #include #include +#include // Number of arguments that can be retrieved is currently based on the size of the buffer. // Other ideas (TODO): @@ -27,7 +28,6 @@ void __init_args(void) { // Flat buffer to capture all the arguments contiguously char buffer[3000]; - char *bufptr = buffer; // Create a packet for the x86 host args_req_pkt.request.x_dst = HOST_X_COORD; @@ -49,20 +49,25 @@ void __init_args(void) { bp_finish(err); uint32_t data = args_resp_pkt.response.data; + bsg_pr_info("Returned data: %x\n", data); + uint8_t null_char = (uint8_t) '\0'; if (data != HB_BP_HOST_OP_FINISH_CODE) { uint32_t mask = 0xFF000000; uint8_t byte; for(int i = 0; i < 4; i++) { - byte = data & mask; - if (byte != (uint8_t)'\0') - buffer[char_index] = byte; + // Get the correct byte from the 4-byte data and then shift it + // to the lowest byte + byte = ((data & mask) >> (8 * (3 - i))); + bsg_pr_info("Argument %d at %x is %c\n", arg_index, char_index, (char) byte); + if (byte != null_char) { + buffer[char_index++] = (char) byte; + mask >>= 8; + } else { - buffer[char_index] = '\0'; + buffer[char_index++] = ' '; arg_index++; break; } - char_index++; - mask = mask >> 8; } } else @@ -72,18 +77,29 @@ void __init_args(void) { // Convert a flat buffer into a 2-D array of pointers as argparse // expects it to be - char *args[_argc]; - char c = '\0'; + char *curr = buffer; + char prev = ' '; int count = 0; if (_argc != 0) { - while (count != _argc) { - if ((c == '\0') && (c != *bufptr)) { - args[count] = bufptr; + while (*curr != '\0') { + if ((prev == ' ') && (prev != *curr)) { + _argv[count] = curr; count++; } - c = *bufptr; - bufptr++; + prev = *curr; + if (*curr == ' ') + *curr = '\0'; + curr++; } - _argv = args; + } + + // Debugging code: + bsg_pr_info("Received arguments\n"); + bsg_pr_info("Number of arguments = %d\n", _argc); + char **check_argv = _argv; + int debug_count = 0; + while (debug_count < _argc) { + bsg_pr_info("Argument %d is %s\n", debug_count, check_argv[debug_count]); + debug_count++; } } From faae961358085ca51cb2d7059221fa7902c6eb96 Mon Sep 17 00:00:00 2001 From: sripathi-muralitharan Date: Sat, 7 Aug 2021 20:13:35 -0700 Subject: [PATCH 60/70] Various Updates * Adding missing copyright headers * Bug fixes in passing arguments from x86 land to RISC-V land * Compiling manycore binary first in preparation to run SPMD/CUDA-lite programs on Dromajo/BP --- .../bsg_manycore_regression_platform.h | 27 +++++++ .../dromajo-vcs/bsg_manycore_simulator.hpp | 2 +- .../platforms/dromajo-vcs/compilation.mk | 2 +- libraries/platforms/dromajo-vcs/execution.mk | 9 ++- libraries/platforms/dromajo-vcs/hardware.mk | 2 +- .../platforms/dromajo-vcs/hb_bp_platform.h | 27 +++++++ libraries/platforms/dromajo-vcs/library.mk | 2 +- libraries/platforms/dromajo-vcs/link.mk | 2 +- .../software/include/argp-fmtstream.h | 29 +++++++ .../software/include/argp-namefrob.h | 29 +++++++ .../dromajo-vcs/software/include/argp.h | 29 +++++++ .../dromajo-vcs/software/include/bp_utils.h | 27 +++++++ .../software/include/dromajo/config.h | 29 +++++++ .../dromajo-vcs/software/include/sysexits.h | 29 +++++++ .../dromajo-vcs/software/src/argp/argp-ba.c | 29 +++++++ .../software/src/argp/argp-eexst.c | 29 +++++++ .../software/src/argp/argp-fmtstream.c | 29 +++++++ .../software/src/argp/argp-fs-xinl.c | 29 +++++++ .../dromajo-vcs/software/src/argp/argp-help.c | 29 +++++++ .../software/src/argp/argp-parse.c | 29 +++++++ .../dromajo-vcs/software/src/argp/argp-pv.c | 29 +++++++ .../dromajo-vcs/software/src/argp/argp-pvh.c | 29 +++++++ .../dromajo-vcs/software/src/argp/argp-xinl.c | 29 +++++++ .../platforms/dromajo-vcs/software/src/args.c | 80 +++++++++++-------- .../dromajo-vcs/software/src/bp_utils.c | 27 +++++++ .../platforms/dromajo-vcs/software/src/crt0.S | 7 +- 26 files changed, 574 insertions(+), 46 deletions(-) diff --git a/libraries/platforms/dromajo-vcs/bsg_manycore_regression_platform.h b/libraries/platforms/dromajo-vcs/bsg_manycore_regression_platform.h index 28fb35e3b..c8b53a428 100644 --- a/libraries/platforms/dromajo-vcs/bsg_manycore_regression_platform.h +++ b/libraries/platforms/dromajo-vcs/bsg_manycore_regression_platform.h @@ -1,3 +1,30 @@ +// Copyright (c) 2020, University of Washington All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// Redistributions of source code must retain the above copyright notice, this list +// of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above copyright notice, this +// list of conditions and the following disclaimer in the documentation and/or +// other materials provided with the distribution. +// +// Neither the name of the copyright holder nor the names of its contributors may +// be used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + #pragma once #ifdef __cplusplus extern "C" { diff --git a/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.hpp b/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.hpp index 69e5d6724..ee7bf6d01 100644 --- a/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.hpp +++ b/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2019, University of Washington All rights reserved. +// Copyright (c) 2020, University of Washington All rights reserved. // // Redistribution and use in source and binary forms, with or without modification, // are permitted provided that the following conditions are met: diff --git a/libraries/platforms/dromajo-vcs/compilation.mk b/libraries/platforms/dromajo-vcs/compilation.mk index e85f4295c..791d5119e 100644 --- a/libraries/platforms/dromajo-vcs/compilation.mk +++ b/libraries/platforms/dromajo-vcs/compilation.mk @@ -1,4 +1,4 @@ -# Copyright (c) 2019, University of Washington All rights reserved. +# Copyright (c) 2020, University of Washington All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: diff --git a/libraries/platforms/dromajo-vcs/execution.mk b/libraries/platforms/dromajo-vcs/execution.mk index 6699ca592..95549d9d6 100644 --- a/libraries/platforms/dromajo-vcs/execution.mk +++ b/libraries/platforms/dromajo-vcs/execution.mk @@ -1,4 +1,4 @@ -# Copyright (c) 2019, University of Washington All rights reserved. +# Copyright (c) 2020, University of Washington All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: @@ -39,8 +39,11 @@ SIM_ARGS += +ntb_random_seed_automatic # them as the VCS plusarg argument +c_args. Users can specify C-style # arguments using the C_ARGS make variable. -%.log: % $(BSG_MANYCORE_KERNELS) - ./$< $(SIM_ARGS) +c_args="$(C_ARGS)" 2>&1 | tee $@ +# Compile the manycore binary before building the rest of the library so that we can +# add the entire manycore binary somewhere for Dromajo/BlackParrot to load into the +# DRAM. This is only a patch until we can do it the right way - use a filesystem +%.log: $(BSG_MANYCORE_KERNELS) % + ./$(filter-out $<, $^) $(SIM_ARGS) +c_args="$(C_ARGS)" 2>&1 | tee $@ vanilla_stats.csv vcache_stats.csv router_stat.csv: % : %.profile.log diff --git a/libraries/platforms/dromajo-vcs/hardware.mk b/libraries/platforms/dromajo-vcs/hardware.mk index 5189f2ee1..004613fe0 100644 --- a/libraries/platforms/dromajo-vcs/hardware.mk +++ b/libraries/platforms/dromajo-vcs/hardware.mk @@ -1,4 +1,4 @@ -# Copyright (c) 2019, University of Washington All rights reserved. +# Copyright (c) 2020, University of Washington All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: diff --git a/libraries/platforms/dromajo-vcs/hb_bp_platform.h b/libraries/platforms/dromajo-vcs/hb_bp_platform.h index 1ffd1ee38..dbabba247 100644 --- a/libraries/platforms/dromajo-vcs/hb_bp_platform.h +++ b/libraries/platforms/dromajo-vcs/hb_bp_platform.h @@ -1,3 +1,30 @@ +// Copyright (c) 2020, University of Washington All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// Redistributions of source code must retain the above copyright notice, this list +// of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above copyright notice, this +// list of conditions and the following disclaimer in the documentation and/or +// other materials provided with the distribution. +// +// Neither the name of the copyright holder nor the names of its contributors may +// be used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + // BlackParrot platform-specific header file // This file contains manycore-specific platform functions and constants diff --git a/libraries/platforms/dromajo-vcs/library.mk b/libraries/platforms/dromajo-vcs/library.mk index bede19a3f..19e8d167a 100644 --- a/libraries/platforms/dromajo-vcs/library.mk +++ b/libraries/platforms/dromajo-vcs/library.mk @@ -1,4 +1,4 @@ -# Copyright (c) 2019, University of Washington All rights reserved. +# Copyright (c) 2020, University of Washington All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: diff --git a/libraries/platforms/dromajo-vcs/link.mk b/libraries/platforms/dromajo-vcs/link.mk index 941885292..f7e9201db 100644 --- a/libraries/platforms/dromajo-vcs/link.mk +++ b/libraries/platforms/dromajo-vcs/link.mk @@ -1,4 +1,4 @@ -# Copyright (c) 2019, University of Washington All rights reserved. +# Copyright (c) 2020, University of Washington All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: diff --git a/libraries/platforms/dromajo-vcs/software/include/argp-fmtstream.h b/libraries/platforms/dromajo-vcs/software/include/argp-fmtstream.h index e95bd7fc6..128558021 100644 --- a/libraries/platforms/dromajo-vcs/software/include/argp-fmtstream.h +++ b/libraries/platforms/dromajo-vcs/software/include/argp-fmtstream.h @@ -1,3 +1,32 @@ +// Copyright (c) 2020, University of Washington All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// Redistributions of source code must retain the above copyright notice, this list +// of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above copyright notice, this +// list of conditions and the following disclaimer in the documentation and/or +// other materials provided with the distribution. +// +// Neither the name of the copyright holder nor the names of its contributors may +// be used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// This is a slightly modified copy of the argp library from Newlib + /* Word-wrapping and line-truncating streams. Copyright (C) 1997 Free Software Foundation, Inc. This file is part of the GNU C Library. diff --git a/libraries/platforms/dromajo-vcs/software/include/argp-namefrob.h b/libraries/platforms/dromajo-vcs/software/include/argp-namefrob.h index 668f35d0d..cf034e6e8 100644 --- a/libraries/platforms/dromajo-vcs/software/include/argp-namefrob.h +++ b/libraries/platforms/dromajo-vcs/software/include/argp-namefrob.h @@ -1,3 +1,32 @@ +// Copyright (c) 2020, University of Washington All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// Redistributions of source code must retain the above copyright notice, this list +// of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above copyright notice, this +// list of conditions and the following disclaimer in the documentation and/or +// other materials provided with the distribution. +// +// Neither the name of the copyright holder nor the names of its contributors may +// be used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// This is a slightly modified copy of the argp library from Newlib + /* Name frobnication for compiling argp outside of glibc Copyright (C) 1997 Free Software Foundation, Inc. This file is part of the GNU C Library. diff --git a/libraries/platforms/dromajo-vcs/software/include/argp.h b/libraries/platforms/dromajo-vcs/software/include/argp.h index 1e694a7f3..43dde05fa 100644 --- a/libraries/platforms/dromajo-vcs/software/include/argp.h +++ b/libraries/platforms/dromajo-vcs/software/include/argp.h @@ -1,3 +1,32 @@ +// Copyright (c) 2020, University of Washington All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// Redistributions of source code must retain the above copyright notice, this list +// of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above copyright notice, this +// list of conditions and the following disclaimer in the documentation and/or +// other materials provided with the distribution. +// +// Neither the name of the copyright holder nor the names of its contributors may +// be used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// This is a slightly modified copy of the argp library from Newlib + /* Hierarchial argument parsing, layered over getopt. Copyright (C) 1995, 1996, 1997, 1998, 1999 Free Software Foundation, Inc. This file is part of the GNU C Library. diff --git a/libraries/platforms/dromajo-vcs/software/include/bp_utils.h b/libraries/platforms/dromajo-vcs/software/include/bp_utils.h index bcb2a4eeb..2fdc5c495 100644 --- a/libraries/platforms/dromajo-vcs/software/include/bp_utils.h +++ b/libraries/platforms/dromajo-vcs/software/include/bp_utils.h @@ -1,3 +1,30 @@ +// Copyright (c) 2020, University of Washington All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// Redistributions of source code must retain the above copyright notice, this list +// of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above copyright notice, this +// list of conditions and the following disclaimer in the documentation and/or +// other materials provided with the distribution. +// +// Neither the name of the copyright holder nor the names of its contributors may +// be used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + // BlackParrot utilities header file // Commonly used BlackParrot functions with modifications for // the manycore platform diff --git a/libraries/platforms/dromajo-vcs/software/include/dromajo/config.h b/libraries/platforms/dromajo-vcs/software/include/dromajo/config.h index 55b63151b..8ae55c8ff 100644 --- a/libraries/platforms/dromajo-vcs/software/include/dromajo/config.h +++ b/libraries/platforms/dromajo-vcs/software/include/dromajo/config.h @@ -1 +1,30 @@ +// Copyright (c) 2020, University of Washington All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// Redistributions of source code must retain the above copyright notice, this list +// of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above copyright notice, this +// list of conditions and the following disclaimer in the documentation and/or +// other materials provided with the distribution. +// +// Neither the name of the copyright holder nor the names of its contributors may +// be used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Config Header for Dromajo + #define CONFIG_VERSION "Dromajo-0.1" diff --git a/libraries/platforms/dromajo-vcs/software/include/sysexits.h b/libraries/platforms/dromajo-vcs/software/include/sysexits.h index 37246b6e7..8ac6e6ad9 100644 --- a/libraries/platforms/dromajo-vcs/software/include/sysexits.h +++ b/libraries/platforms/dromajo-vcs/software/include/sysexits.h @@ -1,3 +1,32 @@ +// Copyright (c) 2020, University of Washington All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// Redistributions of source code must retain the above copyright notice, this list +// of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above copyright notice, this +// list of conditions and the following disclaimer in the documentation and/or +// other materials provided with the distribution. +// +// Neither the name of the copyright holder nor the names of its contributors may +// be used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// A copy of the system exit error codes file from GCC + /* * Copyright (c) 1987, 1993 * The Regents of the University of California. All rights reserved. diff --git a/libraries/platforms/dromajo-vcs/software/src/argp/argp-ba.c b/libraries/platforms/dromajo-vcs/software/src/argp/argp-ba.c index f5270c88d..e083e7cee 100644 --- a/libraries/platforms/dromajo-vcs/software/src/argp/argp-ba.c +++ b/libraries/platforms/dromajo-vcs/software/src/argp/argp-ba.c @@ -1,3 +1,32 @@ +// Copyright (c) 2020, University of Washington All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// Redistributions of source code must retain the above copyright notice, this list +// of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above copyright notice, this +// list of conditions and the following disclaimer in the documentation and/or +// other materials provided with the distribution. +// +// Neither the name of the copyright holder nor the names of its contributors may +// be used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// This is a slightly modified copy of the argp library from Newlib + /* Default definition for ARGP_PROGRAM_BUG_ADDRESS. Copyright (C) 1996, 1997, 1999 Free Software Foundation, Inc. This file is part of the GNU C Library. diff --git a/libraries/platforms/dromajo-vcs/software/src/argp/argp-eexst.c b/libraries/platforms/dromajo-vcs/software/src/argp/argp-eexst.c index a94c34674..0e20f7ad7 100644 --- a/libraries/platforms/dromajo-vcs/software/src/argp/argp-eexst.c +++ b/libraries/platforms/dromajo-vcs/software/src/argp/argp-eexst.c @@ -1,3 +1,32 @@ +// Copyright (c) 2020, University of Washington All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// Redistributions of source code must retain the above copyright notice, this list +// of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above copyright notice, this +// list of conditions and the following disclaimer in the documentation and/or +// other materials provided with the distribution. +// +// Neither the name of the copyright holder nor the names of its contributors may +// be used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// This is a slightly modified copy of the argp library from Newlib + /* Default definition for ARGP_ERR_EXIT_STATUS Copyright (C) 1997 Free Software Foundation, Inc. This file is part of the GNU C Library. diff --git a/libraries/platforms/dromajo-vcs/software/src/argp/argp-fmtstream.c b/libraries/platforms/dromajo-vcs/software/src/argp/argp-fmtstream.c index 69f51cd4d..b4481f647 100644 --- a/libraries/platforms/dromajo-vcs/software/src/argp/argp-fmtstream.c +++ b/libraries/platforms/dromajo-vcs/software/src/argp/argp-fmtstream.c @@ -1,3 +1,32 @@ +// Copyright (c) 2020, University of Washington All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// Redistributions of source code must retain the above copyright notice, this list +// of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above copyright notice, this +// list of conditions and the following disclaimer in the documentation and/or +// other materials provided with the distribution. +// +// Neither the name of the copyright holder nor the names of its contributors may +// be used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// This is a slightly modified copy of the argp library from Newlib + /* Word-wrapping and line-truncating streams Copyright (C) 1997, 1998, 1999, 2001 Free Software Foundation, Inc. This file is part of the GNU C Library. diff --git a/libraries/platforms/dromajo-vcs/software/src/argp/argp-fs-xinl.c b/libraries/platforms/dromajo-vcs/software/src/argp/argp-fs-xinl.c index 9b836d138..910401859 100644 --- a/libraries/platforms/dromajo-vcs/software/src/argp/argp-fs-xinl.c +++ b/libraries/platforms/dromajo-vcs/software/src/argp/argp-fs-xinl.c @@ -1,3 +1,32 @@ +// Copyright (c) 2020, University of Washington All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// Redistributions of source code must retain the above copyright notice, this list +// of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above copyright notice, this +// list of conditions and the following disclaimer in the documentation and/or +// other materials provided with the distribution. +// +// Neither the name of the copyright holder nor the names of its contributors may +// be used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// This is a slightly modified copy of the argp library from Newlib + /* Real definitions for extern inline functions in argp-fmtstream.h Copyright (C) 1997 Free Software Foundation, Inc. This file is part of the GNU C Library. diff --git a/libraries/platforms/dromajo-vcs/software/src/argp/argp-help.c b/libraries/platforms/dromajo-vcs/software/src/argp/argp-help.c index 0b13e2502..839aa1850 100644 --- a/libraries/platforms/dromajo-vcs/software/src/argp/argp-help.c +++ b/libraries/platforms/dromajo-vcs/software/src/argp/argp-help.c @@ -1,3 +1,32 @@ +// Copyright (c) 2020, University of Washington All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// Redistributions of source code must retain the above copyright notice, this list +// of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above copyright notice, this +// list of conditions and the following disclaimer in the documentation and/or +// other materials provided with the distribution. +// +// Neither the name of the copyright holder nor the names of its contributors may +// be used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// This is a slightly modified copy of the argp library from Newlib + /* Hierarchial argument parsing help output Copyright (C) 1995-2000, 2001 Free Software Foundation, Inc. This file is part of the GNU C Library. diff --git a/libraries/platforms/dromajo-vcs/software/src/argp/argp-parse.c b/libraries/platforms/dromajo-vcs/software/src/argp/argp-parse.c index 7eb5cc6dd..afa6a3745 100644 --- a/libraries/platforms/dromajo-vcs/software/src/argp/argp-parse.c +++ b/libraries/platforms/dromajo-vcs/software/src/argp/argp-parse.c @@ -1,3 +1,32 @@ +// Copyright (c) 2020, University of Washington All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// Redistributions of source code must retain the above copyright notice, this list +// of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above copyright notice, this +// list of conditions and the following disclaimer in the documentation and/or +// other materials provided with the distribution. +// +// Neither the name of the copyright holder nor the names of its contributors may +// be used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// This is a slightly modified copy of the argp library from Newlib + /* Hierarchial argument parsing, layered over getopt Copyright (C) 1995, 96, 97, 98, 99, 2000 Free Software Foundation, Inc. This file is part of the GNU C Library. diff --git a/libraries/platforms/dromajo-vcs/software/src/argp/argp-pv.c b/libraries/platforms/dromajo-vcs/software/src/argp/argp-pv.c index 5987956a9..5902498e1 100644 --- a/libraries/platforms/dromajo-vcs/software/src/argp/argp-pv.c +++ b/libraries/platforms/dromajo-vcs/software/src/argp/argp-pv.c @@ -1,3 +1,32 @@ +// Copyright (c) 2020, University of Washington All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// Redistributions of source code must retain the above copyright notice, this list +// of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above copyright notice, this +// list of conditions and the following disclaimer in the documentation and/or +// other materials provided with the distribution. +// +// Neither the name of the copyright holder nor the names of its contributors may +// be used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// This is a slightly modified copy of the argp library from Newlib + /* Default definition for ARGP_PROGRAM_VERSION. Copyright (C) 1996, 1997, 1999 Free Software Foundation, Inc. This file is part of the GNU C Library. diff --git a/libraries/platforms/dromajo-vcs/software/src/argp/argp-pvh.c b/libraries/platforms/dromajo-vcs/software/src/argp/argp-pvh.c index 8a8fd309d..99d6522de 100644 --- a/libraries/platforms/dromajo-vcs/software/src/argp/argp-pvh.c +++ b/libraries/platforms/dromajo-vcs/software/src/argp/argp-pvh.c @@ -1,3 +1,32 @@ +// Copyright (c) 2020, University of Washington All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// Redistributions of source code must retain the above copyright notice, this list +// of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above copyright notice, this +// list of conditions and the following disclaimer in the documentation and/or +// other materials provided with the distribution. +// +// Neither the name of the copyright holder nor the names of its contributors may +// be used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// This is a slightly modified copy of the argp library from Newlib + /* Default definition for ARGP_PROGRAM_VERSION_HOOK. Copyright (C) 1996, 1997, 1999 Free Software Foundation, Inc. This file is part of the GNU C Library. diff --git a/libraries/platforms/dromajo-vcs/software/src/argp/argp-xinl.c b/libraries/platforms/dromajo-vcs/software/src/argp/argp-xinl.c index 644836d30..61c5a8801 100644 --- a/libraries/platforms/dromajo-vcs/software/src/argp/argp-xinl.c +++ b/libraries/platforms/dromajo-vcs/software/src/argp/argp-xinl.c @@ -1,3 +1,32 @@ +// Copyright (c) 2020, University of Washington All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// Redistributions of source code must retain the above copyright notice, this list +// of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above copyright notice, this +// list of conditions and the following disclaimer in the documentation and/or +// other materials provided with the distribution. +// +// Neither the name of the copyright holder nor the names of its contributors may +// be used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// This is a slightly modified copy of the argp library from Newlib + /* Real definitions for extern inline functions in argp.h Copyright (C) 1997, 1998 Free Software Foundation, Inc. This file is part of the GNU C Library. diff --git a/libraries/platforms/dromajo-vcs/software/src/args.c b/libraries/platforms/dromajo-vcs/software/src/args.c index 7a8bd9385..55789f2b5 100644 --- a/libraries/platforms/dromajo-vcs/software/src/args.c +++ b/libraries/platforms/dromajo-vcs/software/src/args.c @@ -1,31 +1,53 @@ -/* - * args.c - * This file includes routines that queries the arguments from the x86 host and - * loads them into corresponding registers so that BlackParrot can access them - */ +// Copyright (c) 2020, University of Washington All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// Redistributions of source code must retain the above copyright notice, this list +// of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above copyright notice, this +// list of conditions and the following disclaimer in the documentation and/or +// other materials provided with the distribution. +// +// Neither the name of the copyright holder nor the names of its contributors may +// be used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// This file includes routines that queries the arguments from the x86 host and +// loads them into corresponding registers so that BlackParrot can access them. +#include #include #include #include -#include #include // Number of arguments that can be retrieved is currently based on the size of the buffer. -// Other ideas (TODO): -// 1. Create pointers to locations of arguments on the stack (traditional method) -// 2. Flush the argument buffer periodically -int _argc; -char **_argv; -static int arg_index = 0; -static int char_index = 0; +int hb_bp_argc; +char **hb_bp_argv; -/** - * Retrieve arguments from the manycore host +/* + * Retrieve arguments from the host */ -void __init_args(void) { +void hb_bp_init_args(void) { int err; hb_mc_packet_t args_req_pkt, args_resp_pkt; + static int hb_bp_arg_index = 0; + static int hb_bp_char_index = 0; + // Flat buffer to capture all the arguments contiguously char buffer[3000]; @@ -42,14 +64,13 @@ void __init_args(void) { // The platform setup in simulation ensures that this packet will not go over the network so // we don't need to check for credits. Also, this code is executed before the CUDA-lite // program starts. - args_req_pkt.request.addr = HB_BP_HOST_EPA_ARGS_START + (arg_index << 2); + args_req_pkt.request.addr = HB_BP_HOST_EPA_ARGS_START + (hb_bp_arg_index << 2); err = hb_bp_write_to_mc_bridge(&args_req_pkt); err = hb_bp_read_from_mc_bridge(&args_resp_pkt, HB_MC_FIFO_RX_RSP); if (err != HB_MC_SUCCESS) bp_finish(err); uint32_t data = args_resp_pkt.response.data; - bsg_pr_info("Returned data: %x\n", data); uint8_t null_char = (uint8_t) '\0'; if (data != HB_BP_HOST_OP_FINISH_CODE) { uint32_t mask = 0xFF000000; @@ -58,14 +79,13 @@ void __init_args(void) { // Get the correct byte from the 4-byte data and then shift it // to the lowest byte byte = ((data & mask) >> (8 * (3 - i))); - bsg_pr_info("Argument %d at %x is %c\n", arg_index, char_index, (char) byte); if (byte != null_char) { - buffer[char_index++] = (char) byte; + buffer[hb_bp_char_index++] = (char) byte; mask >>= 8; } else { - buffer[char_index++] = ' '; - arg_index++; + buffer[hb_bp_char_index++] = ' '; + hb_bp_arg_index++; break; } } @@ -73,17 +93,17 @@ void __init_args(void) { else break; } - _argc = arg_index; + hb_bp_argc = hb_bp_arg_index; // Convert a flat buffer into a 2-D array of pointers as argparse // expects it to be char *curr = buffer; char prev = ' '; int count = 0; - if (_argc != 0) { + if (hb_bp_argc != 0) { while (*curr != '\0') { if ((prev == ' ') && (prev != *curr)) { - _argv[count] = curr; + hb_bp_argv[count] = curr; count++; } prev = *curr; @@ -92,14 +112,4 @@ void __init_args(void) { curr++; } } - - // Debugging code: - bsg_pr_info("Received arguments\n"); - bsg_pr_info("Number of arguments = %d\n", _argc); - char **check_argv = _argv; - int debug_count = 0; - while (debug_count < _argc) { - bsg_pr_info("Argument %d is %s\n", debug_count, check_argv[debug_count]); - debug_count++; - } } diff --git a/libraries/platforms/dromajo-vcs/software/src/bp_utils.c b/libraries/platforms/dromajo-vcs/software/src/bp_utils.c index 6c69de572..5d9fee118 100644 --- a/libraries/platforms/dromajo-vcs/software/src/bp_utils.c +++ b/libraries/platforms/dromajo-vcs/software/src/bp_utils.c @@ -1,3 +1,30 @@ +// Copyright (c) 2020, University of Washington All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// Redistributions of source code must retain the above copyright notice, this list +// of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above copyright notice, this +// list of conditions and the following disclaimer in the documentation and/or +// other materials provided with the distribution. +// +// Neither the name of the copyright holder nor the names of its contributors may +// be used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + // BlackParrot utilities' definitions #include diff --git a/libraries/platforms/dromajo-vcs/software/src/crt0.S b/libraries/platforms/dromajo-vcs/software/src/crt0.S index e9794c4d6..57ffd2419 100644 --- a/libraries/platforms/dromajo-vcs/software/src/crt0.S +++ b/libraries/platforms/dromajo-vcs/software/src/crt0.S @@ -81,10 +81,11 @@ _start: #endif # Initialize the arguments - call __init_args - la a0, _argc + call hb_bp_init_args + la a0, hb_bp_argc ld a0, 0(a0) - la a1, _argv + la a1, hb_bp_argv + ld a1, 0(a1) call main tail bp_finish From 8c49a9eae264e535b44709b430463343186851d9 Mon Sep 17 00:00:00 2001 From: sripathi-muralitharan Date: Sun, 8 Aug 2021 19:22:26 -0700 Subject: [PATCH 61/70] Some more updates * Simulator updates for argument retrieval * Simulator updated for correct updates during fence (hopefully) * Adding dromajo_transmit_device_packet() * Updating address map, adding hb_bp_get_?x_fifo_entries * Adding check for entries in Dromajo TX FIFO during fence * Putting in newlines where required --- .../dromajo-vcs/bsg_manycore_platform.cpp | 79 ++++++++--- .../dromajo-vcs/bsg_manycore_simulator.cpp | 130 ++++++++++-------- .../dromajo-vcs/bsg_manycore_simulator.hpp | 1 + libraries/platforms/dromajo-vcs/execution.mk | 2 +- .../platforms/dromajo-vcs/hb_bp_platform.h | 22 ++- 5 files changed, 147 insertions(+), 87 deletions(-) diff --git a/libraries/platforms/dromajo-vcs/bsg_manycore_platform.cpp b/libraries/platforms/dromajo-vcs/bsg_manycore_platform.cpp index 77e0c7cd5..f691a43ec 100644 --- a/libraries/platforms/dromajo-vcs/bsg_manycore_platform.cpp +++ b/libraries/platforms/dromajo-vcs/bsg_manycore_platform.cpp @@ -58,7 +58,7 @@ int hb_bp_get_credits_used(int *credits_used) { uint32_t *bp_to_mc_req_credits_addr = reinterpret_cast(MC_BASE_ADDR + BP_TO_MC_REQ_CREDITS_ADDR); *credits_used = (int) (*bp_to_mc_req_credits_addr); if (*credits_used < 0) { - bsg_pr_err("Credits used cannot be negative. Credits used = %d", *credits_used); + bsg_pr_err("Credits used cannot be negative. Credits used = %d\n", *credits_used); return HB_MC_FAIL; } return HB_MC_SUCCESS; @@ -83,12 +83,12 @@ int hb_bp_write_to_mc_bridge(hb_mc_packet_t *pkt) { } /* - * Checks if the MC to BP FIFO contains any valid elements to be read + * Checks if the MC to BP FIFO contains any entries * @param[in] entries --> Pointer to a location in memory that will hold the number of entries - * @param[in] type --> Type of FIFO to read from - * @returns HB_MC_SUCCESS on success or HB_MC_FAIL on fail + * @param[in] type --> Type of FIFO to poll for entries + * @returns number of entries in the MC to BP FIFO */ -int hb_bp_get_fifo_entries(int *entries, hb_mc_fifo_rx_t type) { +int hb_bp_get_rx_fifo_entries(int *entries, hb_mc_fifo_rx_t type) { uint32_t *addr; switch (type) { case HB_MC_FIFO_RX_REQ: addr = reinterpret_cast(MC_BASE_ADDR + MC_TO_BP_REQ_ENTRIES_ADDR); @@ -97,7 +97,35 @@ int hb_bp_get_fifo_entries(int *entries, hb_mc_fifo_rx_t type) { break; default: { - bsg_pr_err("%s: Unknown packet type\n", __func__); + bsg_pr_err("%s: Unknown FIFO type\n", __func__); + return HB_MC_FAIL; + } + break; + } + + *entries = *addr; + if (*entries < 0) { + bsg_pr_err("Entries occupied cannot be negative. Entries = %d\n", *entries); + return HB_MC_FAIL; + } + + return HB_MC_SUCCESS; +} + +/* + * Checks if the BP to MC FIFO contains any entries + * @param[in] entries --> Pointer to a location in memory that will hold the number of entries + * @param[in] type --> Type of FIFO to poll for entries + * @returns number of entries in the BP to MC FIFO + */ +int hb_bp_get_tx_fifo_entries(int *entries, hb_mc_fifo_tx_t type) { + uint32_t *addr; + switch (type) { + case HB_MC_FIFO_TX_REQ: addr = reinterpret_cast(MC_BASE_ADDR + BP_TO_MC_REQ_ENTRIES_ADDR); + break; + default: + { + bsg_pr_err("%s: Unknown FIFO type\n", __func__); return HB_MC_FAIL; } break; @@ -105,7 +133,7 @@ int hb_bp_get_fifo_entries(int *entries, hb_mc_fifo_rx_t type) { *entries = *addr; if (*entries < 0) { - bsg_pr_err("Entries occupied cannot be negative. Entries = %d", *entries); + bsg_pr_err("Entries occupied cannot be negative. Entries = %d\n", *entries); return HB_MC_FAIL; } @@ -277,14 +305,14 @@ int hb_mc_platform_receive(hb_mc_manycore_t *mc, hb_mc_packet_t *packet, hb_mc_f } int err; - int num_entries = 0; + int num_rx_entries = 0; do { - err = hb_bp_get_fifo_entries(&num_entries, type); - } while ((num_entries == 0) || (err != HB_MC_SUCCESS)); + err = hb_bp_get_rx_fifo_entries(&num_rx_entries, type); + } while ((num_rx_entries == 0) || (err != HB_MC_SUCCESS)); err = hb_bp_read_from_mc_bridge(packet, type); if (err != HB_MC_SUCCESS) { - manycore_pr_err(mc, "%s: Read from the %s FIFO did not succeed", __func__, typestr); + manycore_pr_err(mc, "%s: Read from the %s FIFO did not succeed\n", __func__, typestr); return err; } @@ -301,7 +329,7 @@ int hb_mc_platform_receive(hb_mc_manycore_t *mc, hb_mc_packet_t *packet, hb_mc_f int hb_mc_platform_get_config_at(hb_mc_manycore_t *mc, unsigned int idx, hb_mc_config_raw_t *config) { hb_mc_platform_t *platform = reinterpret_cast(mc->platform); hb_mc_packet_t config_req_pkt, config_resp_pkt; - int num_entries = 0; + int num_rx_entries = 0; int err; config_req_pkt.request.x_dst = HOST_X_COORD; @@ -325,8 +353,8 @@ int hb_mc_platform_get_config_at(hb_mc_manycore_t *mc, unsigned int idx, hb_mc_c } do { - err = hb_bp_get_fifo_entries(&num_entries, HB_MC_FIFO_RX_RSP); - } while ((num_entries == 0) || (err != HB_MC_SUCCESS)); + err = hb_bp_get_rx_fifo_entries(&num_rx_entries, HB_MC_FIFO_RX_RSP); + } while ((num_rx_entries == 0) || (err != HB_MC_SUCCESS)); err = hb_bp_read_from_mc_bridge(&config_resp_pkt, HB_MC_FIFO_RX_RSP); if (err != HB_MC_SUCCESS) { @@ -346,9 +374,9 @@ int hb_mc_platform_get_config_at(hb_mc_manycore_t *mc, unsigned int idx, hb_mc_c * @return HB_MC_SUCCESS on success. Otherwise an error code defined in bsg_manycore_errno.h. */ int hb_mc_platform_fence(hb_mc_manycore_t *mc, long timeout) { - int credits_used, is_vacant, num_entries, err; + int credits_used, is_vacant, num_rx_entries, num_tx_entries, err; hb_mc_packet_t fence_req_pkt, fence_resp_pkt; - num_entries = 0; + num_rx_entries = num_tx_entries = 0; credits_used = 0; hb_mc_platform_t *platform = reinterpret_cast(mc->platform); @@ -358,6 +386,12 @@ int hb_mc_platform_fence(hb_mc_manycore_t *mc, long timeout) { return HB_MC_NOIMPL; } + // 3 (probably 4) things need to happen during a fence - + // Used credits should be 0 + // The DPI TX FIFO should be empty + // The Dromajo TX FIFO should be empty + // The receiving FIFOs should also be empty + // Prepare host packet to query TX vacancy fence_req_pkt.request.x_dst = HOST_X_COORD; fence_req_pkt.request.y_dst = HOST_Y_COORD; @@ -379,7 +413,7 @@ int hb_mc_platform_fence(hb_mc_manycore_t *mc, long timeout) { // In the real system (with BP), we will be performing memory-mapped reads to the bridge to grab the current // status of the number of endpoint credits for the host. With Dromajo, it still makes sense to do this since // host packets are not transmitted over the network. If host packets have to go over the network then it does - // not make sense since we are sending packets on the TX FIFO and are expecting the TX FIFO to be vacant. + // not make sense since we are sending packets on the DPI TX FIFO and are expecting the TX FIFO to be vacant. err = hb_bp_write_to_mc_bridge(&fence_req_pkt); if (err != HB_MC_SUCCESS) { manycore_pr_err(mc, "%s: Write to the host request FIFO failed\n", __func__); @@ -387,8 +421,8 @@ int hb_mc_platform_fence(hb_mc_manycore_t *mc, long timeout) { } do { - err = hb_bp_get_fifo_entries(&num_entries, HB_MC_FIFO_RX_RSP); - } while ((num_entries == 0) || (err != HB_MC_SUCCESS)); + err = hb_bp_get_rx_fifo_entries(&num_rx_entries, HB_MC_FIFO_RX_RSP); + } while ((num_rx_entries == 0) || (err != HB_MC_SUCCESS)); err = hb_bp_read_from_mc_bridge(&fence_resp_pkt, HB_MC_FIFO_RX_RSP); if (err != HB_MC_SUCCESS) { @@ -399,6 +433,13 @@ int hb_mc_platform_fence(hb_mc_manycore_t *mc, long timeout) { is_vacant = fence_resp_pkt.response.data; } while ((credits_used != 0) || !is_vacant); + // We made sure there are no credits being used (TX FIFO queries are host packets and don't use the network) and + // the DPI TX FIFO is empty. Also every time we perform a transmit, we drain the Dromajo TX FIFO. But let's just + // check if this FIFO is empty as well. + do { + err = hb_bp_get_tx_fifo_entries(&num_tx_entries, HB_MC_FIFO_TX_REQ); + } while ((num_tx_entries != 0) || (err != HB_MC_SUCCESS)); + return HB_MC_SUCCESS; } diff --git a/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.cpp b/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.cpp index 78545d8d8..533d66be7 100644 --- a/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.cpp +++ b/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.cpp @@ -75,15 +75,6 @@ SimulationWrapper::~SimulationWrapper() { void SimulationWrapper::set_args(int argc, char **argv) { this->argc = argc; this->argv = argv; - - // Debugging code: - bsg_pr_info("Received arguments\n"); - bsg_pr_info("Number of arguments = %d\n", this->argc); - int debug_count = 0; - while (debug_count < this->argc) { - bsg_pr_info("Argument %d is %s\n", debug_count, this->argv[debug_count]); - debug_count++; - } } // Advances time to the next clock edge @@ -227,7 +218,7 @@ bool SimulationWrapper::dromajo_step() { } /* - * dromajo_transmit_packet + * dromajo_transmit_host_packet * Fetches data from the Dromajo->Manycore FIFO and if its a host packet, performs * the required host operations and pushes responses back on the response FIFO * @returns success on succesful transmission @@ -266,8 +257,8 @@ int SimulationWrapper::dromajo_transmit_host_packet(hb_mc_packet_t *dromajo_to_h } else { data = (data << (4 - num_characters) * 8); - bsg_pr_info("Data packet at the ends %x\n", data); this->char_index = 0; + break; } } } @@ -371,6 +362,52 @@ int SimulationWrapper::dromajo_transmit_host_packet(hb_mc_packet_t *dromajo_to_h return HB_MC_SUCCESS; } +/* + * dromajo_transmit_device_packet + * Fetches data from the Dromajo->Manycore FIFO and if its a device packet, forwards + * it to the Manycore DPI TX FIFO + * @returns success on succesful transmission + */ +int SimulationWrapper::dromajo_transmit_device_packet(hb_mc_packet_t *dromajo_to_device_packet) { + __m128i *pkt; + int err; + pkt = reinterpret_cast<__m128i *>(dromajo_to_device_packet); + + // Allows the DPI interface to track response FIFO capacity + bool expect_response = + (dromajo_to_device_packet->request.op_v2 != HB_MC_PACKET_OP_REMOTE_STORE) && + (dromajo_to_device_packet->request.op_v2 != HB_MC_PACKET_OP_REMOTE_SW) && + (dromajo_to_device_packet->request.op_v2 != HB_MC_PACKET_OP_CACHE_OP); + + // Attempt packet transmission + // Since we trigger a call to the transmit FIFOs only when all the 32-bit Dromajo + // FIFOs are full (i.e. a single 128-bit packet is ready), we need to wait until + // the DPI FIFOs are ready to receive before advancing to the next operation. + // This can prevent filling up of the FIFOs. However, not doing this can help in + // identifying situations that might create backpressure in actual hardware and + // provision for it. + do { + advance_time(); + err = dpi->tx_req(*pkt, expect_response); + } while (err != BSG_NONSYNTH_DPI_SUCCESS && + (err == BSG_NONSYNTH_DPI_NO_CREDITS || + err == BSG_NONSYNTH_DPI_NO_CAPACITY || + err == BSG_NONSYNTH_DPI_NOT_WINDOW || + err == BSG_NONSYNTH_DPI_BUSY || + err == BSG_NONSYNTH_DPI_NOT_READY)); + + if (err == BSG_NONSYNTH_DPI_SUCCESS) { + for (int i = 0;i < 4; i++) + host_to_mc_req_fifo->fifo[i].pop(); + } + else { + bsg_pr_err("%s: Packet transmission failed\n", __func__); + return HB_MC_FAIL; + } + + return HB_MC_SUCCESS; +} + /* * dromajo_transmit_packet * Fetches data from the Dromajo->Manycore FIFO and pushes it into the DPI FIFO @@ -378,7 +415,7 @@ int SimulationWrapper::dromajo_transmit_host_packet(hb_mc_packet_t *dromajo_to_h * @returns success on succesful transmission */ int SimulationWrapper::dromajo_transmit_packet() { - hb_mc_packet_t dromajo_to_mc_packet, host_to_dromajo_packet; + hb_mc_packet_t dromajo_to_mc_packet; int err; __m128i *pkt; @@ -401,51 +438,17 @@ int SimulationWrapper::dromajo_transmit_packet() { // This serves to return the error from the host function // It is also used to communicate the success code for successful program termination but this code is // not HB_MC_SUCCESS (maps to 0) but a positive number - return err; + if (err != HB_MC_SUCCESS) + return err; } else { - pkt = reinterpret_cast<__m128i *>(&dromajo_to_mc_packet); - - // Allows the DPI interface to track response FIFO capacity - bool expect_response = - (dromajo_to_mc_packet.request.op_v2 != HB_MC_PACKET_OP_REMOTE_STORE) && - (dromajo_to_mc_packet.request.op_v2 != HB_MC_PACKET_OP_REMOTE_SW) && - (dromajo_to_mc_packet.request.op_v2 != HB_MC_PACKET_OP_CACHE_OP); - - // Attempt packet transmission - // Since we trigger a call to the transmit FIFOs only when all the 32-bit Dromajo - // FIFOs are full (i.e. a single 128-bit packet is ready), we need to wait until - // the DPI FIFOs are ready to receive before advancing to the next operation. - // This can prevent filling up of the FIFOs. However, not doing this can help in - // identifying situations that might create backpressure in actual hardware and - // provision for it. - do { - advance_time(); - err = dpi->tx_req(*pkt, expect_response); - } while (err != BSG_NONSYNTH_DPI_SUCCESS && - (err == BSG_NONSYNTH_DPI_NO_CREDITS || - err == BSG_NONSYNTH_DPI_NO_CAPACITY || - err == BSG_NONSYNTH_DPI_NOT_WINDOW || - err == BSG_NONSYNTH_DPI_BUSY || - err == BSG_NONSYNTH_DPI_NOT_READY)); - - if (err == BSG_NONSYNTH_DPI_SUCCESS) { - for (int i = 0;i < 4; i++) - host_to_mc_req_fifo->fifo[i].pop(); - } - else { - bsg_pr_err("%s: Packet transmission failed\n", __func__); - return HB_MC_FAIL; - } + err = dromajo_transmit_device_packet(&dromajo_to_mc_packet); + if (err != HB_MC_SUCCESS) + return err; } is_empty = mc_is_fifo_empty(type); } while (!is_empty); - // Update the credits in dromajo - err = dromajo_update_credits(); - if (err != HB_MC_SUCCESS) - return err; - return HB_MC_SUCCESS; } @@ -538,18 +541,23 @@ int SimulationWrapper::eval(){ } // Advancing time is required for things to move around in hardware, however - // it adds a large overhead to the simulation time. Balance these values to - // hit that sweet spot. - if ((i % 10) == 0) - advance_time_cycles(10); + // it adds a large overhead to the simulation time. + advance_time();; + + // Update the credits in dromajo + // This might be a costly operation to do on every eval call + // because it is a DPI call, however it is required to update the + // credits for cases like in fences. + err = dromajo_update_credits(); + if (err != HB_MC_SUCCESS) + return err; // Check if transmit FIFO has an element and hence ready to transmit - // This operation is relatively low overhead since only a single FIFO's - // empty status is being checked. Hence, we can afford to do it every 100 - // iterations. - if (i % NUM_TX_FIFO_CHK_PER_TICK) { - mc_fifo_type_t type = FIFO_HOST_TO_MC_REQ; - bool is_empty = mc_is_fifo_empty(type); + // Every NUM_TX_FIFO_CHK_PER_TICK iterations or if there is an element + // in the TX FIFO, drain it immediately. + mc_fifo_type_t type = FIFO_HOST_TO_MC_REQ; + bool is_empty = mc_is_fifo_empty(type); + if ((i % NUM_TX_FIFO_CHK_PER_TICK == 0) || !is_empty) { if (!is_empty) { transmit = true; break; diff --git a/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.hpp b/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.hpp index ee7bf6d01..33eadfe59 100644 --- a/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.hpp +++ b/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.hpp @@ -117,6 +117,7 @@ class SimulationWrapper{ bool dromajo_step(); int dromajo_transmit_packet(); int dromajo_transmit_host_packet(hb_mc_packet_t *dromajo_to_host_packet); + int dromajo_transmit_device_packet(hb_mc_packet_t *dromajo_to_device_packet); int dromajo_receive_packet(); int dromajo_update_credits(); diff --git a/libraries/platforms/dromajo-vcs/execution.mk b/libraries/platforms/dromajo-vcs/execution.mk index 95549d9d6..ae8e961c9 100644 --- a/libraries/platforms/dromajo-vcs/execution.mk +++ b/libraries/platforms/dromajo-vcs/execution.mk @@ -43,7 +43,7 @@ SIM_ARGS += +ntb_random_seed_automatic # add the entire manycore binary somewhere for Dromajo/BlackParrot to load into the # DRAM. This is only a patch until we can do it the right way - use a filesystem %.log: $(BSG_MANYCORE_KERNELS) % - ./$(filter-out $<, $^) $(SIM_ARGS) +c_args="$(C_ARGS)" 2>&1 | tee $@ + ./$(filter %, $^) $(SIM_ARGS) +c_args="$(C_ARGS)" 2>&1 | tee $@ vanilla_stats.csv vcache_stats.csv router_stat.csv: % : %.profile.log diff --git a/libraries/platforms/dromajo-vcs/hb_bp_platform.h b/libraries/platforms/dromajo-vcs/hb_bp_platform.h index dbabba247..de336b117 100644 --- a/libraries/platforms/dromajo-vcs/hb_bp_platform.h +++ b/libraries/platforms/dromajo-vcs/hb_bp_platform.h @@ -82,10 +82,11 @@ extern "C" { #define MC_BASE_ADDR 0x500000 #define BP_TO_MC_REQ_FIFO_ADDR 0x1000 #define BP_TO_MC_REQ_CREDITS_ADDR 0x2000 -#define MC_TO_BP_RESP_FIFO_ADDR 0x3000 -#define MC_TO_BP_RESP_ENTRIES_ADDR 0x4000 -#define MC_TO_BP_REQ_FIFO_ADDR 0x5000 -#define MC_TO_BP_REQ_ENTRIES_ADDR 0x6000 +#define BP_TO_MC_REQ_ENTRIES_ADDR 0x3000 +#define MC_TO_BP_RESP_FIFO_ADDR 0x4000 +#define MC_TO_BP_RESP_ENTRIES_ADDR 0x5000 +#define MC_TO_BP_REQ_FIFO_ADDR 0x6000 +#define MC_TO_BP_REQ_ENTRIES_ADDR 0x7000 /**************************** Manycore Bridge helper functions ****************************/ // Use these functions to enable Dromajo/BlackParrot to write to the bridge. These functions @@ -105,10 +106,19 @@ int hb_bp_write_to_mc_bridge(hb_mc_packet_t *pkt); /* * Checks if the MC to BP FIFO contains any entries - * @param[in] type --> Type of FIFO to read from + * @param[in] entries --> Pointer to a location in memory that will hold the number of entries + * @param[in] type --> Type of FIFO to poll for entries * @returns number of entries in the MC to BP FIFO */ -int hb_bp_get_fifo_entries(int *entries, hb_mc_fifo_rx_t type); +int hb_bp_get_rx_fifo_entries(int *entries, hb_mc_fifo_rx_t type); + +/* + * Checks if the BP to MC FIFO contains any entries + * @param[in] entries --> Pointer to a location in memory that will hold the number of entries + * @param[in] type --> Type of FIFO to poll for entries + * @returns number of entries in the BP to MC FIFO + */ +int hb_bp_get_tx_fifo_entries(int *entries, hb_mc_fifo_tx_t type); /* * Reads the manycore bridge FIFOs in 32-bit chunks to form the 128-bit packet From a39f83bc56ec426994d52a9f6e3047471a45c9e6 Mon Sep 17 00:00:00 2001 From: sripathi-muralitharan Date: Sun, 8 Aug 2021 19:49:19 -0700 Subject: [PATCH 62/70] Fix pattern rule in execution.mk --- libraries/platforms/dromajo-vcs/execution.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/platforms/dromajo-vcs/execution.mk b/libraries/platforms/dromajo-vcs/execution.mk index ae8e961c9..ed4e89c4f 100644 --- a/libraries/platforms/dromajo-vcs/execution.mk +++ b/libraries/platforms/dromajo-vcs/execution.mk @@ -43,7 +43,7 @@ SIM_ARGS += +ntb_random_seed_automatic # add the entire manycore binary somewhere for Dromajo/BlackParrot to load into the # DRAM. This is only a patch until we can do it the right way - use a filesystem %.log: $(BSG_MANYCORE_KERNELS) % - ./$(filter %, $^) $(SIM_ARGS) +c_args="$(C_ARGS)" 2>&1 | tee $@ + ./$* $(SIM_ARGS) +c_args="$(C_ARGS)" 2>&1 | tee $@ vanilla_stats.csv vcache_stats.csv router_stat.csv: % : %.profile.log From c9fe26db64965e0783429df2b527447daeb54697 Mon Sep 17 00:00:00 2001 From: sripathi-muralitharan Date: Wed, 18 Aug 2021 18:55:17 -0700 Subject: [PATCH 63/70] Preparing for compiling for SPMD/CUDA-lite programs * Using a new linker script * CRT modifications for new linker script * Changing DRAM base for Dromajo --- libraries/platforms/dromajo-vcs/.gitignore | 1 + .../dromajo-vcs/bsg_manycore_simulator.cpp | 6 +- .../dromajo-vcs/bsg_manycore_simulator.hpp | 4 + libraries/platforms/dromajo-vcs/library.mk | 10 + libraries/platforms/dromajo-vcs/link.mk | 10 +- .../dromajo-vcs/software/linker_gen.py | 180 ++++++++++++++++++ .../platforms/dromajo-vcs/software/src/crt0.S | 8 +- 7 files changed, 212 insertions(+), 7 deletions(-) create mode 100644 libraries/platforms/dromajo-vcs/software/linker_gen.py diff --git a/libraries/platforms/dromajo-vcs/.gitignore b/libraries/platforms/dromajo-vcs/.gitignore index 46ac11709..c810f0d2b 100644 --- a/libraries/platforms/dromajo-vcs/.gitignore +++ b/libraries/platforms/dromajo-vcs/.gitignore @@ -1 +1,2 @@ lfs.cpp +software/linker diff --git a/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.cpp b/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.cpp index 533d66be7..9ebc8503d 100644 --- a/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.cpp +++ b/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.cpp @@ -189,17 +189,19 @@ int SimulationWrapper::dpi_init() { */ int SimulationWrapper::dromajo_init() { char dromajo_str[50]; + char dram_base_str[50]; char host_str[50]; char manycore_str[50]; char prog_str[50]; sprintf(dromajo_str, "dromajo"); + sprintf(dram_base_str, "--memory_addr=0x%d", BP_DRAM_BASE_ADDR); sprintf(host_str, "--host"); sprintf(manycore_str, "--manycore"); sprintf(prog_str, "main.elf"); - char* argv[] = {dromajo_str, host_str, manycore_str, prog_str}; - dromajo = dromajo_cosim_init(4, argv); + char* argv[] = {dromajo_str, dram_base_str, host_str, manycore_str, prog_str}; + dromajo = dromajo_cosim_init(5, argv); if (!dromajo) { bsg_pr_err("%s: Failed to initialize Dromajo instance!\n", __func__); return HB_MC_FAIL; diff --git a/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.hpp b/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.hpp index 33eadfe59..ee1c99ab7 100644 --- a/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.hpp +++ b/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.hpp @@ -59,6 +59,10 @@ declare_hb_mc_get_bits declare_bsg_printing +#ifndef BP_DRAM_BASE_ADDR +#error BlackParrot DRAM base address is undefined +#endif + #ifndef NUM_DROMAJO_INSTR_PER_TICK #define NUM_DROMAJO_INSTR_PER_TICK 1000 #endif diff --git a/libraries/platforms/dromajo-vcs/library.mk b/libraries/platforms/dromajo-vcs/library.mk index 19e8d167a..994c5a4e8 100644 --- a/libraries/platforms/dromajo-vcs/library.mk +++ b/libraries/platforms/dromajo-vcs/library.mk @@ -80,6 +80,15 @@ $(BSG_PLATFORM_PATH)/libbsg_manycore_runtime.a: AR = $(RV_AR) $(BSG_PLATFORM_PATH)/libbsgmc_cuda_legacy_pod_repl.a: AR = $(RV_AR) $(BSG_PLATFORM_PATH)/libbsg_manycore_regression.a: AR = $(RV_AR) +# Base addresses for various segments +# Ideally we want the manycore code at 0x80000000 and the BlackParrot code relocated elsewhere (at least > 0x81000000) since +# we know the manycore binary is expected to occupy 16 MB. However, Dromajo currently seems to have a requirement to have the +# start address to be 0x80000000. While, this is easly modified, there should be a better, more elegant way to achieve this. +# Dromajo suggests we load our own bootrom for this, which I believe should be a RISC-V binary file. +BP_DRAM_BASE_ADDR := 0x81000000 +HB_DRAM_BASE_ADDR := 0x80000000 +TOP_OF_STACK_ADDR := 0x8F000000 + # Make the litteFS file system $(BSG_PLATFORM_PATH)/lfs.cpp: MKLFS = $(BLACKPARROT_SDK_DIR)/install/bin/dramfs_mklfs 128 64 $(BSG_PLATFORM_PATH)/lfs.cpp: @@ -128,6 +137,7 @@ PLATFORM_DEFINES += -DBP_POD_X=0 -DBP_POD_Y=1 PLATFORM_DEFINES += -DNUM_DROMAJO_INSTR_PER_TICK=1000 PLATFORM_DEFINES += -DNUM_TX_FIFO_CHK_PER_TICK=100 PLATFORM_DEFINES += -DFIFO_MAX_ELEMENTS=$(BSG_MACHINE_IO_EP_CREDITS) +PLATFORM_DEFINES += -DBP_DRAM_BASE_ADDR=$(subst 0x,,$(BP_DRAM_BASE_ADDR)) PLATFORM_OBJECTS += $(patsubst %cpp,%o,$(PLATFORM_CXXSOURCES)) PLATFORM_OBJECTS += $(patsubst %c,%o,$(PLATFORM_CSOURCES)) diff --git a/libraries/platforms/dromajo-vcs/link.mk b/libraries/platforms/dromajo-vcs/link.mk index f7e9201db..f1a3cd5ec 100644 --- a/libraries/platforms/dromajo-vcs/link.mk +++ b/libraries/platforms/dromajo-vcs/link.mk @@ -109,6 +109,12 @@ TEST_CXXSOURCES += $(filter %.cpp,$(TEST_SOURCES)) TEST_OBJECTS += $(TEST_CXXSOURCES:.cpp=.o) TEST_OBJECTS += $(TEST_CSOURCES:.c=.o) +# Generate the linker +linker_gen: PYTHON := python3 +linker_gen: + mkdir -p $(BSG_PLATFORM_PATH)/software/linker + $(PYTHON) $(BSG_PLATFORM_PATH)/software/linker_gen.py $(BP_DRAM_BASE_ADDR) $(TOP_OF_STACK_ADDR) $(HB_DRAM_BASE_ADDR) > $(BSG_PLATFORM_PATH)/software/linker/riscv.ld + $(BSG_PLATFORM_PATH)/test.riscv: CC = $(RV_CC) $(BSG_PLATFORM_PATH)/test.riscv: CXX = $(RV_CXX) $(BSG_PLATFORM_PATH)/test.riscv: $(TEST_OBJECTS) @@ -116,7 +122,8 @@ $(BSG_PLATFORM_PATH)/test.riscv: $(BSG_PLATFORM_PATH)/lfs.o $(BSG_PLATFORM_PATH)/test.riscv: $(BSG_PLATFORM_PATH)/libbsg_manycore_runtime.a $(BSG_PLATFORM_PATH)/test.riscv: $(BSG_PLATFORM_PATH)/libbsgmc_cuda_legacy_pod_repl.a $(BSG_PLATFORM_PATH)/test.riscv: $(BSG_PLATFORM_PATH)/libbsg_manycore_regression.a -$(BSG_PLATFORM_PATH)/test.riscv: LDFLAGS := -T$(BLACKPARROT_SDK_DIR)/linker/riscv.ld -L$(BSG_PLATFORM_PATH) -static -nostartfiles -lstdc++ -lbsg_manycore_regression -lbsg_manycore_runtime +$(BSG_PLATFORM_PATH)/test.riscv: linker_gen +$(BSG_PLATFORM_PATH)/test.riscv: LDFLAGS := -T$(BSG_PLATFORM_PATH)/software/linker/riscv.ld -L$(BSG_PLATFORM_PATH) -static -nostartfiles -lstdc++ -lbsg_manycore_regression -lbsg_manycore_runtime $(BSG_PLATFORM_PATH)/test.riscv: LD = $(CXX) $(BSG_PLATFORM_PATH)/test.riscv: $(LD) -D_DRAMFS -o $@ $(BSG_PLATFORM_PATH)/software/src/crt0.o $(BSG_PLATFORM_PATH)/lfs.o $< $(LDFLAGS) @@ -169,5 +176,6 @@ platform.link.clean: rm -rf *.debug *.profile *.saifgen *.exec rm -rf *.elf rm -rf $(BSG_PLATFORM_PATH)/*.riscv + rm -rf $(BSG_PLATFORM_PATH)/software/linker link.clean: platform.link.clean ; diff --git a/libraries/platforms/dromajo-vcs/software/linker_gen.py b/libraries/platforms/dromajo-vcs/software/linker_gen.py new file mode 100644 index 000000000..0ed2235f0 --- /dev/null +++ b/libraries/platforms/dromajo-vcs/software/linker_gen.py @@ -0,0 +1,180 @@ +#!/usr/bin/python +from __future__ import print_function + +import argparse +import json + + +def print_linker(bp_dram_base, sp, hb_dram_base): + print( + """ + OUTPUT_ARCH( "riscv" ) + ENTRY(_start) + + SECTIONS {{ + + /*--------------------------------------------------------------------*/ + /* Code and read-only segment */ + /*--------------------------------------------------------------------*/ + + /* Begining of code and text segment */ + . = {_bp_dram_base}; + _ftext = .; + PROVIDE( eprol = . ); + + /* text: Program code section */ + .text : + {{ + *(.text.init) + *(.text.emu) + *(.text.amo) + *(.text) + *(.text.*) + *(.gnu.linkonce.t.*) + }} + + /* init: Code to execute before main (called by crt0.S) */ + .init : + {{ + KEEP( *(.init) ) + }} + + /* fini: Code to execute after main (called by crt0.S) */ + .fini : + {{ + KEEP( *(.fini) ) + }} + + /* rodata: Read-only data */ + .rodata : + {{ + *(.rdata) + *(.rodata) + *(.rodata.*) + *(.gnu.linkonce.r.*) + }} + + /* End of code and read-only segment */ + PROVIDE( etext = . ); + _etext = .; + + /*--------------------------------------------------------------------*/ + /* Global constructor/destructor segement */ + /*--------------------------------------------------------------------*/ + + .preinit_array : + {{ + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + }} + + .init_array : + {{ + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array )) + PROVIDE_HIDDEN (__init_array_end = .); + }} + + .fini_array : + {{ + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT(.fini_array.*))) + KEEP (*(.fini_array )) + PROVIDE_HIDDEN (__fini_array_end = .); + }} + + .eh_frame_hdr : {{ *(.eh_frame_hdr) *(.eh_frame_entry .eh_frame_entry.*) }} + .eh_frame : {{ KEEP (*(.eh_frame)) *(.eh_frame.*) }} + .gcc_except_table : {{ *(.gcc_except_table .gcc_except_table.*) }} + .gnu_extab : {{ *(.gnu_extab) }} + .exception_ranges : {{ *(.exception_ranges*) }} + .jcr : {{ KEEP (*(.jcr)) }} + + /*--------------------------------------------------------------------*/ + /* Initialized data segment */ + /*--------------------------------------------------------------------*/ + + /* Start of initialized data segment */ + . = ALIGN(16); + _fdata = .; + + /* data: Writable data */ + .data : + {{ + *(.data) + *(.data.*) + *(.gnu.linkonce.d.*) + }} + + /* Have _gp point to middle of sdata/sbss to maximize displacement range */ + . = ALIGN(16); + _gp = . + 0x800; + + /* Writable small data segment */ + .sdata : + {{ + *(.sdata) + *(.sdata.*) + *(.srodata.*) + *(.gnu.linkonce.s.*) + }} + + /* End of initialized data segment */ + PROVIDE( edata = . ); + _edata = .; + + /*--------------------------------------------------------------------*/ + /* Uninitialized data segment */ + /*--------------------------------------------------------------------*/ + + /* Start of uninitialized data segment */ + . = ALIGN(8); + _fbss = .; + + /* Writable uninitialized small data segment */ + .sbss : + {{ + *(.sbss) + *(.sbss.*) + *(.gnu.linkonce.sb.*) + }} + + /* bss: Uninitialized writeable data section */ + . = .; + _bss_start = .; + .bss : + {{ + *(.bss) + *(.bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + }} + + /* End of uninitialized data segment (used by syscalls.c for heap) */ + PROVIDE( end = . ); + _end = ALIGN(8); + + _sp = {_sp}; + + /* Manycore binary segment */ + . = {_hb_dram_base}; + .hb.bp.manycore : + {{ + *(*.manycore) + }} + }}""".format( + _bp_dram_base=bp_dram_base, _sp=sp, _hb_dram_base=hb_dram_base + ) + ) + + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument("bp_dram_base", help="The base address of DRAM for BlackParrot") + parser.add_argument("sp", help="The top of the stack") + parser.add_argument("hb_dram_base", help="The base address of DRAM for HammerBlade") + args = parser.parse_args() + + print_linker(args.bp_dram_base, args.sp, args.hb_dram_base) diff --git a/libraries/platforms/dromajo-vcs/software/src/crt0.S b/libraries/platforms/dromajo-vcs/software/src/crt0.S index 57ffd2419..d6d351bd0 100644 --- a/libraries/platforms/dromajo-vcs/software/src/crt0.S +++ b/libraries/platforms/dromajo-vcs/software/src/crt0.S @@ -5,7 +5,7 @@ # This assembly file mimics the BlackParrot perch library start.S # with minor modifications to allow arguments to be loaded into the -# argument registers for main +# argument registers for main as well as load the manycore binary .section ".text.init" .globl _start @@ -17,10 +17,10 @@ _start: la gp, _gp .option pop -# Setup stack pointers. Stacks start at 0x800F0000 +# Setup stack pointers. # We then subtract off 8K*coreID. The top 4K is for the core emulation stack -# the lower 4K is for the program TODO: Maybe larger stack value? - li sp, 0x800F0000 +# the lower 4K is for the program + la sp, _sp csrr t0, mhartid slli t0, t0, 13 sub sp, sp, t0 From e64201d2cf00648b6d7138c0a15d6b0a2cbe82b2 Mon Sep 17 00:00:00 2001 From: sripathi-muralitharan Date: Thu, 19 Aug 2021 21:33:57 -0700 Subject: [PATCH 64/70] Various updates * Argument parsing hacky fix to ignore the first argument; ARGP is just ughhhh * Copyright headers in some files * Refactoring placement of some make targets * Updates to comments --- libraries/platforms/dromajo-vcs/.gitignore | 2 +- libraries/platforms/dromajo-vcs/execution.mk | 2 +- libraries/platforms/dromajo-vcs/library.mk | 13 ++ libraries/platforms/dromajo-vcs/link.mk | 9 +- .../dromajo-vcs/software/linker_gen.py | 180 ------------------ .../platforms/dromajo-vcs/software/src/args.c | 28 ++- .../platforms/dromajo-vcs/software/src/crt0.S | 29 ++- 7 files changed, 69 insertions(+), 194 deletions(-) delete mode 100644 libraries/platforms/dromajo-vcs/software/linker_gen.py diff --git a/libraries/platforms/dromajo-vcs/.gitignore b/libraries/platforms/dromajo-vcs/.gitignore index c810f0d2b..9b1691cf0 100644 --- a/libraries/platforms/dromajo-vcs/.gitignore +++ b/libraries/platforms/dromajo-vcs/.gitignore @@ -1,2 +1,2 @@ lfs.cpp -software/linker +linker/riscv.ld diff --git a/libraries/platforms/dromajo-vcs/execution.mk b/libraries/platforms/dromajo-vcs/execution.mk index ed4e89c4f..a1d38794f 100644 --- a/libraries/platforms/dromajo-vcs/execution.mk +++ b/libraries/platforms/dromajo-vcs/execution.mk @@ -41,7 +41,7 @@ SIM_ARGS += +ntb_random_seed_automatic # Compile the manycore binary before building the rest of the library so that we can # add the entire manycore binary somewhere for Dromajo/BlackParrot to load into the -# DRAM. This is only a patch until we can do it the right way - use a filesystem +# DRAM. This is only a patch until we can do it the right way i.e. use a filesystem %.log: $(BSG_MANYCORE_KERNELS) % ./$* $(SIM_ARGS) +c_args="$(C_ARGS)" 2>&1 | tee $@ diff --git a/libraries/platforms/dromajo-vcs/library.mk b/libraries/platforms/dromajo-vcs/library.mk index 994c5a4e8..8e5f4cfeb 100644 --- a/libraries/platforms/dromajo-vcs/library.mk +++ b/libraries/platforms/dromajo-vcs/library.mk @@ -97,6 +97,19 @@ $(BSG_PLATFORM_PATH)/lfs.cpp: $(BSG_PLATFORM_PATH)/lfs.o: $(BSG_PLATFORM_PATH)/lfs.cpp $(CXX) $^ -c -o $@ $(CXXFLAGS) $(INCLUDES) +# Include the compiled manycore binary if one exists +# FIXME: Some caveats with this target --> You have to use it with the *.log target +# In the future we either move away from linking the manycore binary at compile time +# or have a better compilation strategy (requires changes in the test infrastructure) +$(BSG_PLATFORM_PATH)/mcbin.o: $(BSG_MANYCORE_KERNELS) +$(BSG_PLATFORM_PATH)/mcbin.o: CFLAGS := -march=rv64imafd -mabi=lp64 -mcmodel=medany +$(BSG_PLATFORM_PATH)/mcbin.o: INCLUDES := +$(BSG_PLATFORM_PATH)/mcbin.o: CC := $(RV_CC) +$(BSG_PLATFORM_PATH)/mcbin.o: + cp $(BSG_MANYCORE_KERNELS) manycore.riscv + sed "s|BSG_MANYCORE_KERNELS|\"manycore.riscv\"|g" $(BSG_PLATFORM_PATH)/mcbin.S > genmcbin.S + $(CC) -c -o $@ $(CFLAGS) $(DEFINES) $(INCLUDES) genmcbin.S + include $(LIBRARIES_PATH)/features/dma/simulation/dramsim3.mk include $(LIBRARIES_PATH)/features/dma/simulation/libdmamem.mk diff --git a/libraries/platforms/dromajo-vcs/link.mk b/libraries/platforms/dromajo-vcs/link.mk index f1a3cd5ec..304d253b3 100644 --- a/libraries/platforms/dromajo-vcs/link.mk +++ b/libraries/platforms/dromajo-vcs/link.mk @@ -112,8 +112,7 @@ TEST_OBJECTS += $(TEST_CSOURCES:.c=.o) # Generate the linker linker_gen: PYTHON := python3 linker_gen: - mkdir -p $(BSG_PLATFORM_PATH)/software/linker - $(PYTHON) $(BSG_PLATFORM_PATH)/software/linker_gen.py $(BP_DRAM_BASE_ADDR) $(TOP_OF_STACK_ADDR) $(HB_DRAM_BASE_ADDR) > $(BSG_PLATFORM_PATH)/software/linker/riscv.ld + $(PYTHON) $(BSG_PLATFORM_PATH)/software/linker/linker_gen.py $(BP_DRAM_BASE_ADDR) $(TOP_OF_STACK_ADDR) $(HB_DRAM_BASE_ADDR) > $(BSG_PLATFORM_PATH)/software/linker/riscv.ld $(BSG_PLATFORM_PATH)/test.riscv: CC = $(RV_CC) $(BSG_PLATFORM_PATH)/test.riscv: CXX = $(RV_CXX) @@ -122,11 +121,12 @@ $(BSG_PLATFORM_PATH)/test.riscv: $(BSG_PLATFORM_PATH)/lfs.o $(BSG_PLATFORM_PATH)/test.riscv: $(BSG_PLATFORM_PATH)/libbsg_manycore_runtime.a $(BSG_PLATFORM_PATH)/test.riscv: $(BSG_PLATFORM_PATH)/libbsgmc_cuda_legacy_pod_repl.a $(BSG_PLATFORM_PATH)/test.riscv: $(BSG_PLATFORM_PATH)/libbsg_manycore_regression.a +$(BSG_PLATFORM_PATH)/test.riscv: $(BSG_PLATFORM_PATH)/mcbin.o $(BSG_PLATFORM_PATH)/test.riscv: linker_gen $(BSG_PLATFORM_PATH)/test.riscv: LDFLAGS := -T$(BSG_PLATFORM_PATH)/software/linker/riscv.ld -L$(BSG_PLATFORM_PATH) -static -nostartfiles -lstdc++ -lbsg_manycore_regression -lbsg_manycore_runtime $(BSG_PLATFORM_PATH)/test.riscv: LD = $(CXX) $(BSG_PLATFORM_PATH)/test.riscv: - $(LD) -D_DRAMFS -o $@ $(BSG_PLATFORM_PATH)/software/src/crt0.o $(BSG_PLATFORM_PATH)/lfs.o $< $(LDFLAGS) + $(LD) -o $@ $(BSG_PLATFORM_PATH)/mcbin.o $(BSG_PLATFORM_PATH)/lfs.o $< $(LDFLAGS) cp $@ main.elf # VCS Generates an executable file by linking the TEST_OBJECTS with @@ -176,6 +176,7 @@ platform.link.clean: rm -rf *.debug *.profile *.saifgen *.exec rm -rf *.elf rm -rf $(BSG_PLATFORM_PATH)/*.riscv - rm -rf $(BSG_PLATFORM_PATH)/software/linker + rm -rf genmcbin.S manycore.riscv + rm -rf $(BSG_PLATFORM_PATH)/mcbin.o link.clean: platform.link.clean ; diff --git a/libraries/platforms/dromajo-vcs/software/linker_gen.py b/libraries/platforms/dromajo-vcs/software/linker_gen.py deleted file mode 100644 index 0ed2235f0..000000000 --- a/libraries/platforms/dromajo-vcs/software/linker_gen.py +++ /dev/null @@ -1,180 +0,0 @@ -#!/usr/bin/python -from __future__ import print_function - -import argparse -import json - - -def print_linker(bp_dram_base, sp, hb_dram_base): - print( - """ - OUTPUT_ARCH( "riscv" ) - ENTRY(_start) - - SECTIONS {{ - - /*--------------------------------------------------------------------*/ - /* Code and read-only segment */ - /*--------------------------------------------------------------------*/ - - /* Begining of code and text segment */ - . = {_bp_dram_base}; - _ftext = .; - PROVIDE( eprol = . ); - - /* text: Program code section */ - .text : - {{ - *(.text.init) - *(.text.emu) - *(.text.amo) - *(.text) - *(.text.*) - *(.gnu.linkonce.t.*) - }} - - /* init: Code to execute before main (called by crt0.S) */ - .init : - {{ - KEEP( *(.init) ) - }} - - /* fini: Code to execute after main (called by crt0.S) */ - .fini : - {{ - KEEP( *(.fini) ) - }} - - /* rodata: Read-only data */ - .rodata : - {{ - *(.rdata) - *(.rodata) - *(.rodata.*) - *(.gnu.linkonce.r.*) - }} - - /* End of code and read-only segment */ - PROVIDE( etext = . ); - _etext = .; - - /*--------------------------------------------------------------------*/ - /* Global constructor/destructor segement */ - /*--------------------------------------------------------------------*/ - - .preinit_array : - {{ - PROVIDE_HIDDEN (__preinit_array_start = .); - KEEP (*(.preinit_array)) - PROVIDE_HIDDEN (__preinit_array_end = .); - }} - - .init_array : - {{ - PROVIDE_HIDDEN (__init_array_start = .); - KEEP (*(SORT(.init_array.*))) - KEEP (*(.init_array )) - PROVIDE_HIDDEN (__init_array_end = .); - }} - - .fini_array : - {{ - PROVIDE_HIDDEN (__fini_array_start = .); - KEEP (*(SORT(.fini_array.*))) - KEEP (*(.fini_array )) - PROVIDE_HIDDEN (__fini_array_end = .); - }} - - .eh_frame_hdr : {{ *(.eh_frame_hdr) *(.eh_frame_entry .eh_frame_entry.*) }} - .eh_frame : {{ KEEP (*(.eh_frame)) *(.eh_frame.*) }} - .gcc_except_table : {{ *(.gcc_except_table .gcc_except_table.*) }} - .gnu_extab : {{ *(.gnu_extab) }} - .exception_ranges : {{ *(.exception_ranges*) }} - .jcr : {{ KEEP (*(.jcr)) }} - - /*--------------------------------------------------------------------*/ - /* Initialized data segment */ - /*--------------------------------------------------------------------*/ - - /* Start of initialized data segment */ - . = ALIGN(16); - _fdata = .; - - /* data: Writable data */ - .data : - {{ - *(.data) - *(.data.*) - *(.gnu.linkonce.d.*) - }} - - /* Have _gp point to middle of sdata/sbss to maximize displacement range */ - . = ALIGN(16); - _gp = . + 0x800; - - /* Writable small data segment */ - .sdata : - {{ - *(.sdata) - *(.sdata.*) - *(.srodata.*) - *(.gnu.linkonce.s.*) - }} - - /* End of initialized data segment */ - PROVIDE( edata = . ); - _edata = .; - - /*--------------------------------------------------------------------*/ - /* Uninitialized data segment */ - /*--------------------------------------------------------------------*/ - - /* Start of uninitialized data segment */ - . = ALIGN(8); - _fbss = .; - - /* Writable uninitialized small data segment */ - .sbss : - {{ - *(.sbss) - *(.sbss.*) - *(.gnu.linkonce.sb.*) - }} - - /* bss: Uninitialized writeable data section */ - . = .; - _bss_start = .; - .bss : - {{ - *(.bss) - *(.bss.*) - *(.gnu.linkonce.b.*) - *(COMMON) - }} - - /* End of uninitialized data segment (used by syscalls.c for heap) */ - PROVIDE( end = . ); - _end = ALIGN(8); - - _sp = {_sp}; - - /* Manycore binary segment */ - . = {_hb_dram_base}; - .hb.bp.manycore : - {{ - *(*.manycore) - }} - }}""".format( - _bp_dram_base=bp_dram_base, _sp=sp, _hb_dram_base=hb_dram_base - ) - ) - - -if __name__ == "__main__": - parser = argparse.ArgumentParser() - parser.add_argument("bp_dram_base", help="The base address of DRAM for BlackParrot") - parser.add_argument("sp", help="The top of the stack") - parser.add_argument("hb_dram_base", help="The base address of DRAM for HammerBlade") - args = parser.parse_args() - - print_linker(args.bp_dram_base, args.sp, args.hb_dram_base) diff --git a/libraries/platforms/dromajo-vcs/software/src/args.c b/libraries/platforms/dromajo-vcs/software/src/args.c index 55789f2b5..3081d2ff8 100644 --- a/libraries/platforms/dromajo-vcs/software/src/args.c +++ b/libraries/platforms/dromajo-vcs/software/src/args.c @@ -79,21 +79,35 @@ void hb_bp_init_args(void) { // Get the correct byte from the 4-byte data and then shift it // to the lowest byte byte = ((data & mask) >> (8 * (3 - i))); - if (byte != null_char) { - buffer[hb_bp_char_index++] = (char) byte; - mask >>= 8; + + // FIXME: Don't put the first argument (name of the program itself) in the buffer since the loader doesn't expect that + // Fix the loader or argp (more likely)! + if (hb_bp_arg_index != 0) { + if (byte != null_char) { + buffer[hb_bp_char_index++] = (char) byte; + mask >>= 8; + } + else { + buffer[hb_bp_char_index++] = ' '; + hb_bp_arg_index++; + break; + } } else { - buffer[hb_bp_char_index++] = ' '; - hb_bp_arg_index++; - break; + if (byte == null_char) { + hb_bp_arg_index++; + break; + } } } } else break; } - hb_bp_argc = hb_bp_arg_index; + + // FIXME: Don't put the first argument (name of the program itself) in the buffer since the loader doesn't expect that + // Fix the loader or argp (more likely)! + hb_bp_argc = hb_bp_arg_index - 1; // Convert a flat buffer into a 2-D array of pointers as argparse // expects it to be diff --git a/libraries/platforms/dromajo-vcs/software/src/crt0.S b/libraries/platforms/dromajo-vcs/software/src/crt0.S index d6d351bd0..f12d14427 100644 --- a/libraries/platforms/dromajo-vcs/software/src/crt0.S +++ b/libraries/platforms/dromajo-vcs/software/src/crt0.S @@ -1,3 +1,30 @@ +# Copyright (c) 2020, University of Washington All rights reserved. +# +# Redistribution and use in source and binary forms, with or without modification, +# are permitted provided that the following conditions are met: +# +# Redistributions of source code must retain the above copyright notice, this list +# of conditions and the following disclaimer. +# +# Redistributions in binary form must reproduce the above copyright notice, this +# list of conditions and the following disclaimer in the documentation and/or +# other materials provided with the distribution. +# +# Neither the name of the copyright holder nor the names of its contributors may +# be used to endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + # Start code # This file should be deprecated when the BlackParrot firmware is capable of @@ -5,7 +32,7 @@ # This assembly file mimics the BlackParrot perch library start.S # with minor modifications to allow arguments to be loaded into the -# argument registers for main as well as load the manycore binary +# argument registers for main. .section ".text.init" .globl _start From 9c6a5baf152ab62b21e715eaa0b30b8213a28a3c Mon Sep 17 00:00:00 2001 From: sripathi-muralitharan Date: Thu, 19 Aug 2021 21:36:58 -0700 Subject: [PATCH 65/70] Adding an assembly file to include the manycore binary; Incomplete --- libraries/platforms/dromajo-vcs/.gitignore | 2 +- libraries/platforms/dromajo-vcs/mcbin.S | 31 +++ .../dromajo-vcs/software/linker/linker_gen.py | 204 ++++++++++++++++++ 3 files changed, 236 insertions(+), 1 deletion(-) create mode 100644 libraries/platforms/dromajo-vcs/mcbin.S create mode 100644 libraries/platforms/dromajo-vcs/software/linker/linker_gen.py diff --git a/libraries/platforms/dromajo-vcs/.gitignore b/libraries/platforms/dromajo-vcs/.gitignore index 9b1691cf0..fbd4b459f 100644 --- a/libraries/platforms/dromajo-vcs/.gitignore +++ b/libraries/platforms/dromajo-vcs/.gitignore @@ -1,2 +1,2 @@ lfs.cpp -linker/riscv.ld +software/linker/riscv.ld diff --git a/libraries/platforms/dromajo-vcs/mcbin.S b/libraries/platforms/dromajo-vcs/mcbin.S new file mode 100644 index 000000000..00acaea81 --- /dev/null +++ b/libraries/platforms/dromajo-vcs/mcbin.S @@ -0,0 +1,31 @@ +# Copyright (c) 2020, University of Washington All rights reserved. +# +# Redistribution and use in source and binary forms, with or without modification, +# are permitted provided that the following conditions are met: +# +# Redistributions of source code must retain the above copyright notice, this list +# of conditions and the following disclaimer. +# +# Redistributions in binary form must reproduce the above copyright notice, this +# list of conditions and the following disclaimer in the documentation and/or +# other materials provided with the distribution. +# +# Neither the name of the copyright holder nor the names of its contributors may +# be used to endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# This assembly file includes the manycore binary if there is one + +.section ".manycore.text" +.incbin BSG_MANYCORE_KERNELS diff --git a/libraries/platforms/dromajo-vcs/software/linker/linker_gen.py b/libraries/platforms/dromajo-vcs/software/linker/linker_gen.py new file mode 100644 index 000000000..852178c9f --- /dev/null +++ b/libraries/platforms/dromajo-vcs/software/linker/linker_gen.py @@ -0,0 +1,204 @@ +# Copyright (c) 2020, University of Washington All rights reserved. +# +# Redistribution and use in source and binary forms, with or without modification, +# are permitted provided that the following conditions are met: +# +# Redistributions of source code must retain the above copyright notice, this list +# of conditions and the following disclaimer. +# +# Redistributions in binary form must reproduce the above copyright notice, this +# list of conditions and the following disclaimer in the documentation and/or +# other materials provided with the distribution. +# +# Neither the name of the copyright holder nor the names of its contributors may +# be used to endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#!/usr/bin/python +from __future__ import print_function + +import argparse +import json + + +def print_linker(bp_dram_base, sp, hb_dram_base): + print( + """ + OUTPUT_ARCH( "riscv" ) + ENTRY(_start) + + SECTIONS {{ + + /*--------------------------------------------------------------------*/ + /* Code and read-only segment */ + /*--------------------------------------------------------------------*/ + + /* Begining of code and text segment */ + . = {bp_dram_base}; + _ftext = .; + PROVIDE( eprol = . ); + + /* text: Program code section */ + .text : + {{ + *(.text.init) + *(.text.emu) + *(.text.amo) + *(.text) + *(.text.*) + *(.gnu.linkonce.t.*) + }} + + /* init: Code to execute before main (called by crt0.S) */ + .init : + {{ + KEEP( *(.init) ) + }} + + /* fini: Code to execute after main (called by crt0.S) */ + .fini : + {{ + KEEP( *(.fini) ) + }} + + /* rodata: Read-only data */ + .rodata : + {{ + *(.rdata) + *(.rodata) + *(.rodata.*) + *(.gnu.linkonce.r.*) + }} + + /* End of code and read-only segment */ + PROVIDE( etext = . ); + _etext = .; + + /*--------------------------------------------------------------------*/ + /* Global constructor/destructor segement */ + /*--------------------------------------------------------------------*/ + + .preinit_array : + {{ + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + }} + + .init_array : + {{ + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array )) + PROVIDE_HIDDEN (__init_array_end = .); + }} + + .fini_array : + {{ + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT(.fini_array.*))) + KEEP (*(.fini_array )) + PROVIDE_HIDDEN (__fini_array_end = .); + }} + + .eh_frame_hdr : {{ *(.eh_frame_hdr) *(.eh_frame_entry .eh_frame_entry.*) }} + .eh_frame : {{ KEEP (*(.eh_frame)) *(.eh_frame.*) }} + .gcc_except_table : {{ *(.gcc_except_table .gcc_except_table.*) }} + .gnu_extab : {{ *(.gnu_extab) }} + .exception_ranges : {{ *(.exception_ranges*) }} + .jcr : {{ KEEP (*(.jcr)) }} + + /*--------------------------------------------------------------------*/ + /* Initialized data segment */ + /*--------------------------------------------------------------------*/ + + /* Start of initialized data segment */ + . = ALIGN(16); + _fdata = .; + + /* data: Writable data */ + .data : + {{ + *(.data) + *(.data.*) + *(.gnu.linkonce.d.*) + }} + + /* Have _gp point to middle of sdata/sbss to maximize displacement range */ + . = ALIGN(16); + _gp = . + 0x800; + + /* Writable small data segment */ + .sdata : + {{ + *(.sdata) + *(.sdata.*) + *(.srodata.*) + *(.gnu.linkonce.s.*) + }} + + /* End of initialized data segment */ + PROVIDE( edata = . ); + _edata = .; + + /*--------------------------------------------------------------------*/ + /* Uninitialized data segment */ + /*--------------------------------------------------------------------*/ + + /* Start of uninitialized data segment */ + . = ALIGN(8); + _fbss = .; + + /* Writable uninitialized small data segment */ + .sbss : + {{ + *(.sbss) + *(.sbss.*) + *(.gnu.linkonce.sb.*) + }} + + /* bss: Uninitialized writeable data section */ + . = .; + _bss_start = .; + .bss : + {{ + *(.bss) + *(.bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + }} + + /* End of uninitialized data segment (used by syscalls.c for heap) */ + PROVIDE( end = . ); + _end = ALIGN(8); + + _sp = {_sp}; + + /* Manycore Binary Segment */ + . = {hb_dram_base}; + .manycore : + {{ + *(.manycore.*) + }} + }}""".format(bp_dram_base=bp_dram_base, _sp=sp, hb_dram_base=hb_dram_base) + ) + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument("bp_dram_base", help="BlackParrot DRAM Base Address") + parser.add_argument("sp", help="Top of the stack") + parser.add_argument("hb_dram_base", help="HammerBlade Manycore DRAM Base Address") + args = parser.parse_args() + + print_linker(args.bp_dram_base, args.sp, args.hb_dram_base) \ No newline at end of file From 397cf4e9b64e51e88c014861756482047f8114f6 Mon Sep 17 00:00:00 2001 From: sripathi-muralitharan Date: Sun, 22 Aug 2021 17:53:34 -0700 Subject: [PATCH 66/70] Validating existence of manycore binary in the appropriate locations --- libraries/platforms/dromajo-vcs/library.mk | 14 +++++++++----- libraries/platforms/dromajo-vcs/link.mk | 1 + libraries/platforms/dromajo-vcs/mcbin.S | 13 ++++++++++++- .../dromajo-vcs/software/linker/linker_gen.py | 1 - 4 files changed, 22 insertions(+), 7 deletions(-) diff --git a/libraries/platforms/dromajo-vcs/library.mk b/libraries/platforms/dromajo-vcs/library.mk index 8e5f4cfeb..9e3ea71b2 100644 --- a/libraries/platforms/dromajo-vcs/library.mk +++ b/libraries/platforms/dromajo-vcs/library.mk @@ -81,10 +81,14 @@ $(BSG_PLATFORM_PATH)/libbsgmc_cuda_legacy_pod_repl.a: AR = $(RV_AR) $(BSG_PLATFORM_PATH)/libbsg_manycore_regression.a: AR = $(RV_AR) # Base addresses for various segments -# Ideally we want the manycore code at 0x80000000 and the BlackParrot code relocated elsewhere (at least > 0x81000000) since -# we know the manycore binary is expected to occupy 16 MB. However, Dromajo currently seems to have a requirement to have the -# start address to be 0x80000000. While, this is easly modified, there should be a better, more elegant way to achieve this. -# Dromajo suggests we load our own bootrom for this, which I believe should be a RISC-V binary file. +# SM: For now let us assume the manycore code will fit into 16MB (I believe this is the requirement for the +# .text section of the manycore binary; but let's assume even data fits into this limit). The Dromajo codebase +# has a hardcoded parameter that start addresses should be one of 00x80000000, 0x8000000000 or 0xC000000000. +# Another entry for 0x81000000 has also been added. Remapping to a different start address requires the creation +# of a custom bootrom for Dromajo. BlackParrot should not face any such issue because of the presence of a +# base address register in the manycore which will get set to the correct base address during the NBF load stage. +# FIXME: Need a more elegant solution for relocating BlackParrot code to different pods or DRAM regions when +# running on Dromajo BP_DRAM_BASE_ADDR := 0x81000000 HB_DRAM_BASE_ADDR := 0x80000000 TOP_OF_STACK_ADDR := 0x8F000000 @@ -103,7 +107,7 @@ $(BSG_PLATFORM_PATH)/lfs.o: $(BSG_PLATFORM_PATH)/lfs.cpp # or have a better compilation strategy (requires changes in the test infrastructure) $(BSG_PLATFORM_PATH)/mcbin.o: $(BSG_MANYCORE_KERNELS) $(BSG_PLATFORM_PATH)/mcbin.o: CFLAGS := -march=rv64imafd -mabi=lp64 -mcmodel=medany -$(BSG_PLATFORM_PATH)/mcbin.o: INCLUDES := +$(BSG_PLATFORM_PATH)/mcbin.o: INCLUDES := -I$(shell pwd) $(BSG_PLATFORM_PATH)/mcbin.o: CC := $(RV_CC) $(BSG_PLATFORM_PATH)/mcbin.o: cp $(BSG_MANYCORE_KERNELS) manycore.riscv diff --git a/libraries/platforms/dromajo-vcs/link.mk b/libraries/platforms/dromajo-vcs/link.mk index 304d253b3..e06ab57c1 100644 --- a/libraries/platforms/dromajo-vcs/link.mk +++ b/libraries/platforms/dromajo-vcs/link.mk @@ -178,5 +178,6 @@ platform.link.clean: rm -rf $(BSG_PLATFORM_PATH)/*.riscv rm -rf genmcbin.S manycore.riscv rm -rf $(BSG_PLATFORM_PATH)/mcbin.o + rm -rf $(BSG_PLATFORM_PATH)/software/linker/riscv.ld link.clean: platform.link.clean ; diff --git a/libraries/platforms/dromajo-vcs/mcbin.S b/libraries/platforms/dromajo-vcs/mcbin.S index 00acaea81..2ba13ba70 100644 --- a/libraries/platforms/dromajo-vcs/mcbin.S +++ b/libraries/platforms/dromajo-vcs/mcbin.S @@ -27,5 +27,16 @@ # This assembly file includes the manycore binary if there is one -.section ".manycore.text" +.section .manycore.text +.globl manycore +.align 4 +.type manycore, @object + +manycore: .incbin BSG_MANYCORE_KERNELS + +.globl manycore_size +.type manycore_size, @object +.align 4 +manycore_size: +.int manycore_size - manycore \ No newline at end of file diff --git a/libraries/platforms/dromajo-vcs/software/linker/linker_gen.py b/libraries/platforms/dromajo-vcs/software/linker/linker_gen.py index 852178c9f..961e37a76 100644 --- a/libraries/platforms/dromajo-vcs/software/linker/linker_gen.py +++ b/libraries/platforms/dromajo-vcs/software/linker/linker_gen.py @@ -29,7 +29,6 @@ from __future__ import print_function import argparse -import json def print_linker(bp_dram_base, sp, hb_dram_base): From ee7687bff0846f8bee7a466443a20bb2f82e262a Mon Sep 17 00:00:00 2001 From: sripathi-muralitharan Date: Sat, 28 Aug 2021 23:30:53 -0700 Subject: [PATCH 67/70] Put manycore in RODATA instead; Updates to linker and name modifications --- .../dromajo-vcs/bsg_manycore_simulator.cpp | 2 +- .../dromajo-vcs/bsg_manycore_simulator.hpp | 2 +- libraries/platforms/dromajo-vcs/library.mk | 20 ++++++++----------- libraries/platforms/dromajo-vcs/link.mk | 2 +- libraries/platforms/dromajo-vcs/mcbin.S | 4 ++-- .../dromajo-vcs/software/linker/linker_gen.py | 13 +++--------- 6 files changed, 16 insertions(+), 27 deletions(-) diff --git a/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.cpp b/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.cpp index 9ebc8503d..5e78f2c63 100644 --- a/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.cpp +++ b/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.cpp @@ -195,7 +195,7 @@ int SimulationWrapper::dromajo_init() { char prog_str[50]; sprintf(dromajo_str, "dromajo"); - sprintf(dram_base_str, "--memory_addr=0x%d", BP_DRAM_BASE_ADDR); + sprintf(dram_base_str, "--memory_addr=0x%d", DRAM_BASE_ADDR); sprintf(host_str, "--host"); sprintf(manycore_str, "--manycore"); sprintf(prog_str, "main.elf"); diff --git a/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.hpp b/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.hpp index ee1c99ab7..e9be9e1f6 100644 --- a/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.hpp +++ b/libraries/platforms/dromajo-vcs/bsg_manycore_simulator.hpp @@ -59,7 +59,7 @@ declare_hb_mc_get_bits declare_bsg_printing -#ifndef BP_DRAM_BASE_ADDR +#ifndef DRAM_BASE_ADDR #error BlackParrot DRAM base address is undefined #endif diff --git a/libraries/platforms/dromajo-vcs/library.mk b/libraries/platforms/dromajo-vcs/library.mk index 9e3ea71b2..06d3f5e69 100644 --- a/libraries/platforms/dromajo-vcs/library.mk +++ b/libraries/platforms/dromajo-vcs/library.mk @@ -81,17 +81,13 @@ $(BSG_PLATFORM_PATH)/libbsgmc_cuda_legacy_pod_repl.a: AR = $(RV_AR) $(BSG_PLATFORM_PATH)/libbsg_manycore_regression.a: AR = $(RV_AR) # Base addresses for various segments -# SM: For now let us assume the manycore code will fit into 16MB (I believe this is the requirement for the -# .text section of the manycore binary; but let's assume even data fits into this limit). The Dromajo codebase -# has a hardcoded parameter that start addresses should be one of 00x80000000, 0x8000000000 or 0xC000000000. -# Another entry for 0x81000000 has also been added. Remapping to a different start address requires the creation -# of a custom bootrom for Dromajo. BlackParrot should not face any such issue because of the presence of a -# base address register in the manycore which will get set to the correct base address during the NBF load stage. -# FIXME: Need a more elegant solution for relocating BlackParrot code to different pods or DRAM regions when -# running on Dromajo -BP_DRAM_BASE_ADDR := 0x81000000 -HB_DRAM_BASE_ADDR := 0x80000000 -TOP_OF_STACK_ADDR := 0x8F000000 +DROMAJO_START_ADDR := 0x80000000 +# Dromajo requires that the entry point of the program and the Dromajo start address match +# This is hardcoded in Dromajo (src/riscv_machine.cpp) but can be overridden by providing +# a bootrom using the --bootrom option +BP_DRAM_BASE_ADDR := 0x80000000 +HB_DRAM_BASE_ADDR := 0x88000000 +TOP_OF_STACK_ADDR := 0x8F000000 # Make the litteFS file system $(BSG_PLATFORM_PATH)/lfs.cpp: MKLFS = $(BLACKPARROT_SDK_DIR)/install/bin/dramfs_mklfs 128 64 @@ -154,7 +150,7 @@ PLATFORM_DEFINES += -DBP_POD_X=0 -DBP_POD_Y=1 PLATFORM_DEFINES += -DNUM_DROMAJO_INSTR_PER_TICK=1000 PLATFORM_DEFINES += -DNUM_TX_FIFO_CHK_PER_TICK=100 PLATFORM_DEFINES += -DFIFO_MAX_ELEMENTS=$(BSG_MACHINE_IO_EP_CREDITS) -PLATFORM_DEFINES += -DBP_DRAM_BASE_ADDR=$(subst 0x,,$(BP_DRAM_BASE_ADDR)) +PLATFORM_DEFINES += -DDRAM_BASE_ADDR=$(subst 0x,,$(DROMAJO_START_ADDR)) PLATFORM_OBJECTS += $(patsubst %cpp,%o,$(PLATFORM_CXXSOURCES)) PLATFORM_OBJECTS += $(patsubst %c,%o,$(PLATFORM_CSOURCES)) diff --git a/libraries/platforms/dromajo-vcs/link.mk b/libraries/platforms/dromajo-vcs/link.mk index e06ab57c1..5401f8d58 100644 --- a/libraries/platforms/dromajo-vcs/link.mk +++ b/libraries/platforms/dromajo-vcs/link.mk @@ -112,7 +112,7 @@ TEST_OBJECTS += $(TEST_CSOURCES:.c=.o) # Generate the linker linker_gen: PYTHON := python3 linker_gen: - $(PYTHON) $(BSG_PLATFORM_PATH)/software/linker/linker_gen.py $(BP_DRAM_BASE_ADDR) $(TOP_OF_STACK_ADDR) $(HB_DRAM_BASE_ADDR) > $(BSG_PLATFORM_PATH)/software/linker/riscv.ld + $(PYTHON) $(BSG_PLATFORM_PATH)/software/linker/linker_gen.py $(BP_DRAM_BASE_ADDR) $(TOP_OF_STACK_ADDR) > $(BSG_PLATFORM_PATH)/software/linker/riscv.ld $(BSG_PLATFORM_PATH)/test.riscv: CC = $(RV_CC) $(BSG_PLATFORM_PATH)/test.riscv: CXX = $(RV_CXX) diff --git a/libraries/platforms/dromajo-vcs/mcbin.S b/libraries/platforms/dromajo-vcs/mcbin.S index 2ba13ba70..e447cb0d4 100644 --- a/libraries/platforms/dromajo-vcs/mcbin.S +++ b/libraries/platforms/dromajo-vcs/mcbin.S @@ -27,11 +27,11 @@ # This assembly file includes the manycore binary if there is one -.section .manycore.text +.section .rodata.manycore + .globl manycore .align 4 .type manycore, @object - manycore: .incbin BSG_MANYCORE_KERNELS diff --git a/libraries/platforms/dromajo-vcs/software/linker/linker_gen.py b/libraries/platforms/dromajo-vcs/software/linker/linker_gen.py index 961e37a76..9ce248d4b 100644 --- a/libraries/platforms/dromajo-vcs/software/linker/linker_gen.py +++ b/libraries/platforms/dromajo-vcs/software/linker/linker_gen.py @@ -31,7 +31,7 @@ import argparse -def print_linker(bp_dram_base, sp, hb_dram_base): +def print_linker(bp_dram_base, sp): print( """ OUTPUT_ARCH( "riscv" ) @@ -184,20 +184,13 @@ def print_linker(bp_dram_base, sp, hb_dram_base): _sp = {_sp}; - /* Manycore Binary Segment */ - . = {hb_dram_base}; - .manycore : - {{ - *(.manycore.*) - }} - }}""".format(bp_dram_base=bp_dram_base, _sp=sp, hb_dram_base=hb_dram_base) + }}""".format(bp_dram_base=bp_dram_base, _sp=sp) ) if __name__ == "__main__": parser = argparse.ArgumentParser() parser.add_argument("bp_dram_base", help="BlackParrot DRAM Base Address") parser.add_argument("sp", help="Top of the stack") - parser.add_argument("hb_dram_base", help="HammerBlade Manycore DRAM Base Address") args = parser.parse_args() - print_linker(args.bp_dram_base, args.sp, args.hb_dram_base) \ No newline at end of file + print_linker(args.bp_dram_base, args.sp) \ No newline at end of file From 274da739e09420bd51b215df2c099b4010af04fd Mon Sep 17 00:00:00 2001 From: sripathi-muralitharan Date: Tue, 31 Aug 2021 23:00:53 -0700 Subject: [PATCH 68/70] Modifying loader to directly read the location of the binary --- examples/spmd/loader.c | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/examples/spmd/loader.c b/examples/spmd/loader.c index fa1a5a486..4cf6a7213 100644 --- a/examples/spmd/loader.c +++ b/examples/spmd/loader.c @@ -33,13 +33,40 @@ #include #include -#include +//#include #include #include #include #include #include +// Reads the manycore binary from the program memory. The address to read from is a +// symbol in the program binary +static int read_program_binary(unsigned char **program, size_t *program_size) { + unsigned char *address; + unsigned char *data; + uint64_t size; + + // Read the address from the symbol table in the binary + __asm__ __volatile__ ("la %[manycore_start_addr], manycore" + : [manycore_start_addr] "=r" (address)); + + // The program size is already stored at a predefined location in the binary + __asm__ __volatile__ ("la t0, manycore_size\n\t" + "ld %[manycore_size], 0(t0)" + : [manycore_size] "=r" (size)); + + if (!(data = (unsigned char *) malloc(size))) { + bsg_pr_err("failed to allocate space for the manycore binary\n"); + return HB_MC_FAIL; + } + + *program_size = size; + *program = data; + + return HB_MC_SUCCESS; +} + static int read_program_file(const char *file_name, unsigned char **file_data, size_t *file_size) { struct stat st; @@ -97,7 +124,8 @@ int test_loader(int argc, char **argv) { // read in the program data from the file system - err = read_program_file(bin_path, &program_data, &program_size); + // err = read_program_file(bin_path, &program_data, &program_size); + err = read_program_binary(&program_data, &program_size); if (err != HB_MC_SUCCESS) return err; From c326d16ae3eb816232b073dd11fce649f08f0050 Mon Sep 17 00:00:00 2001 From: sripathi-muralitharan Date: Tue, 31 Aug 2021 23:01:13 -0700 Subject: [PATCH 69/70] Flow updates --- libraries/platforms/dromajo-vcs/library.mk | 5 ++-- libraries/platforms/dromajo-vcs/link.mk | 27 +++++++++++----------- 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/libraries/platforms/dromajo-vcs/library.mk b/libraries/platforms/dromajo-vcs/library.mk index 06d3f5e69..2bd0b1c7f 100644 --- a/libraries/platforms/dromajo-vcs/library.mk +++ b/libraries/platforms/dromajo-vcs/library.mk @@ -86,7 +86,6 @@ DROMAJO_START_ADDR := 0x80000000 # This is hardcoded in Dromajo (src/riscv_machine.cpp) but can be overridden by providing # a bootrom using the --bootrom option BP_DRAM_BASE_ADDR := 0x80000000 -HB_DRAM_BASE_ADDR := 0x88000000 TOP_OF_STACK_ADDR := 0x8F000000 # Make the litteFS file system @@ -101,7 +100,9 @@ $(BSG_PLATFORM_PATH)/lfs.o: $(BSG_PLATFORM_PATH)/lfs.cpp # FIXME: Some caveats with this target --> You have to use it with the *.log target # In the future we either move away from linking the manycore binary at compile time # or have a better compilation strategy (requires changes in the test infrastructure) -$(BSG_PLATFORM_PATH)/mcbin.o: $(BSG_MANYCORE_KERNELS) +kernel: + $(if $(BSG_MANYCORE_KERNELS),$(MAKE) $(BSG_PLATFORM_PATH)/mcbin.o,echo "BSG_MANYCORE_KERNELS not defined. Skipping...") + $(BSG_PLATFORM_PATH)/mcbin.o: CFLAGS := -march=rv64imafd -mabi=lp64 -mcmodel=medany $(BSG_PLATFORM_PATH)/mcbin.o: INCLUDES := -I$(shell pwd) $(BSG_PLATFORM_PATH)/mcbin.o: CC := $(RV_CC) diff --git a/libraries/platforms/dromajo-vcs/link.mk b/libraries/platforms/dromajo-vcs/link.mk index 5401f8d58..31cc2ec60 100644 --- a/libraries/platforms/dromajo-vcs/link.mk +++ b/libraries/platforms/dromajo-vcs/link.mk @@ -44,7 +44,7 @@ endif # platform specific hardware.mk file. include $(HARDWARE_PATH)/hardware.mk -# libraries.mk defines how to build libbsg_manycore_runtime.so, which is +# libraries.mk defines how to build libbsg_manycore_runtime.a, which is # pre-linked against all other simulation binaries. include $(LIBRARIES_PATH)/libraries.mk @@ -108,6 +108,8 @@ TEST_CSOURCES += $(filter %.c,$(TEST_SOURCES)) TEST_CXXSOURCES += $(filter %.cpp,$(TEST_SOURCES)) TEST_OBJECTS += $(TEST_CXXSOURCES:.cpp=.o) TEST_OBJECTS += $(TEST_CSOURCES:.c=.o) +TEST_OBJECTS += $(BSG_PLATFORM_PATH)/lfs.o +TEST_OBJECTS += $(if $(BSG_MANYCORE_KERNELS),$(BSG_PLATFORM_PATH)/mcbin.o) # Generate the linker linker_gen: PYTHON := python3 @@ -116,17 +118,16 @@ linker_gen: $(BSG_PLATFORM_PATH)/test.riscv: CC = $(RV_CC) $(BSG_PLATFORM_PATH)/test.riscv: CXX = $(RV_CXX) -$(BSG_PLATFORM_PATH)/test.riscv: $(TEST_OBJECTS) -$(BSG_PLATFORM_PATH)/test.riscv: $(BSG_PLATFORM_PATH)/lfs.o +$(BSG_PLATFORM_PATH)/test.riscv: LD = $(CXX) +$(BSG_PLATFORM_PATH)/test.riscv: linker_gen +$(BSG_PLATFORM_PATH)/test.riscv: kernel $(BSG_PLATFORM_PATH)/test.riscv: $(BSG_PLATFORM_PATH)/libbsg_manycore_runtime.a $(BSG_PLATFORM_PATH)/test.riscv: $(BSG_PLATFORM_PATH)/libbsgmc_cuda_legacy_pod_repl.a $(BSG_PLATFORM_PATH)/test.riscv: $(BSG_PLATFORM_PATH)/libbsg_manycore_regression.a -$(BSG_PLATFORM_PATH)/test.riscv: $(BSG_PLATFORM_PATH)/mcbin.o -$(BSG_PLATFORM_PATH)/test.riscv: linker_gen +$(BSG_PLATFORM_PATH)/test.riscv: $(TEST_OBJECTS) $(BSG_PLATFORM_PATH)/test.riscv: LDFLAGS := -T$(BSG_PLATFORM_PATH)/software/linker/riscv.ld -L$(BSG_PLATFORM_PATH) -static -nostartfiles -lstdc++ -lbsg_manycore_regression -lbsg_manycore_runtime -$(BSG_PLATFORM_PATH)/test.riscv: LD = $(CXX) $(BSG_PLATFORM_PATH)/test.riscv: - $(LD) -o $@ $(BSG_PLATFORM_PATH)/mcbin.o $(BSG_PLATFORM_PATH)/lfs.o $< $(LDFLAGS) + $(LD) -o $@ $(TEST_OBJECTS) $(LDFLAGS) cp $@ main.elf # VCS Generates an executable file by linking the TEST_OBJECTS with @@ -136,17 +137,17 @@ $(BSG_PLATFORM_PATH)/test.riscv: %.saifgen %.debug: VCS_VFLAGS += -debug_pp %.debug: VCS_VFLAGS += +plusarg_save +vcs+vcdpluson +vcs+vcdplusmemon +memcbk -%.debug %.profile: $(BSG_PLATFORM_PATH)/libbsg_manycore_platform.so $(BSG_PLATFORM_PATH)/test.riscv $(BSG_MACHINE_PATH)/$(BSG_PLATFORM)/vcs_simlibs/replicant_tb_top/AN.DB $(PLATFORM_OBJECTS) +%.debug %.profile: $(BSG_PLATFORM_PATH)/libbsg_manycore_platform.so $(BSG_PLATFORM_PATH)/test.riscv $(BSG_MACHINE_PATH)/$(BSG_PLATFORM)/vcs_simlibs/replicant_tb_top/AN.DB SYNOPSYS_SIM_SETUP=$(BSG_MACHINE_PATH)/$(BSG_PLATFORM)/synopsys_sim.setup \ - vcs -top replicant_tb_top $(PLATFORM_OBJECTS) $(VCS_FLAGS) -Mdirectory=$@.tmp -l $@.vcs.log -o $@ + vcs -top replicant_tb_top $(VCS_FLAGS) -Mdirectory=$@.tmp -l $@.vcs.log -o $@ -%.saifgen: $(BSG_PLATFORM_PATH)/libbsg_manycore_platform.so $(BSG_PLATFORM_PATH)/test.riscv $(BSG_MACHINE_PATH)/$(BSG_PLATFORM)/vcs_simlibs/replicant_tb_top_saifgen/AN.DB $(PLATFORM_OBJECTS) +%.saifgen: $(BSG_PLATFORM_PATH)/libbsg_manycore_platform.so $(BSG_PLATFORM_PATH)/test.riscv $(BSG_MACHINE_PATH)/$(BSG_PLATFORM)/vcs_simlibs/replicant_tb_top_saifgen/AN.DB SYNOPSYS_SIM_SETUP=$(BSG_MACHINE_PATH)/$(BSG_PLATFORM)/synopsys_sim.saifgen \ - vcs -top replicant_tb_top $(PLATFORM_OBJECTS) $(VCS_FLAGS) -Mdirectory=$@.tmp -l $@.vcs.log -o $@ + vcs -top replicant_tb_top $(VCS_FLAGS) -Mdirectory=$@.tmp -l $@.vcs.log -o $@ -%.exec: $(BSG_PLATFORM_PATH)/libbsg_manycore_platform.so $(BSG_PLATFORM_PATH)/test.riscv $(BSG_MACHINE_PATH)/$(BSG_PLATFORM)/vcs_simlibs/replicant_tb_top_exec/AN.DB $(PLATFORM_OBJECTS) +%.exec: $(BSG_PLATFORM_PATH)/libbsg_manycore_platform.so $(BSG_PLATFORM_PATH)/test.riscv $(BSG_MACHINE_PATH)/$(BSG_PLATFORM)/vcs_simlibs/replicant_tb_top_exec/AN.DB SYNOPSYS_SIM_SETUP=$(BSG_MACHINE_PATH)/$(BSG_PLATFORM)/synopsys_sim.exec \ - vcs -top replicant_tb_top $(PLATFORM_OBJECTS) $(VCS_FLAGS) -Mdirectory=$@.tmp -l $@.vcs.log -o $@ + vcs -top replicant_tb_top $(VCS_FLAGS) -Mdirectory=$@.tmp -l $@.vcs.log -o $@ .PRECIOUS:%.debug %.profile %.saifgen %.exec From 5eed2ebf5e3ef9043ed4f121b142b76d850b10bc Mon Sep 17 00:00:00 2001 From: sripathi-muralitharan Date: Tue, 31 Aug 2021 23:43:21 -0700 Subject: [PATCH 70/70] Cleaning up SPMD loader --- examples/spmd/loader.c | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/examples/spmd/loader.c b/examples/spmd/loader.c index 4cf6a7213..95ef48449 100644 --- a/examples/spmd/loader.c +++ b/examples/spmd/loader.c @@ -40,11 +40,14 @@ #include #include -// Reads the manycore binary from the program memory. The address to read from is a -// symbol in the program binary -static int read_program_binary(unsigned char **program, size_t *program_size) { +/* + * Reads manycore specific symbols from the program binary + * @param[out] program: Pointer to a memory location containing the address of the manycore binary + * @param[out] program_size: Pointer to the manycore binary size + * @returns HB_MC_SUCCESS + */ +static int read_symbols(unsigned char **program, size_t *program_size) { unsigned char *address; - unsigned char *data; uint64_t size; // Read the address from the symbol table in the binary @@ -56,13 +59,8 @@ static int read_program_binary(unsigned char **program, size_t *program_size) { "ld %[manycore_size], 0(t0)" : [manycore_size] "=r" (size)); - if (!(data = (unsigned char *) malloc(size))) { - bsg_pr_err("failed to allocate space for the manycore binary\n"); - return HB_MC_FAIL; - } - *program_size = size; - *program = data; + *program = address; return HB_MC_SUCCESS; } @@ -125,7 +123,7 @@ int test_loader(int argc, char **argv) { // read in the program data from the file system // err = read_program_file(bin_path, &program_data, &program_size); - err = read_program_binary(&program_data, &program_size); + err = read_symbols(&program_data, &program_size); if (err != HB_MC_SUCCESS) return err;