├── .github └── workflows │ └── docs.yml ├── .gitignore ├── .vscode ├── c_cpp_properties.json ├── devcontainer.json ├── launch.json ├── settings.json └── tasks.json ├── LICENSE ├── README.md ├── docker ├── gap9 │ ├── Dockerfile │ ├── Makefile │ └── build_gap9.sh └── pulp-open │ ├── Dockerfile │ ├── Makefile │ └── build_open.sh ├── docs ├── adapter.md ├── codegen.md ├── communication-example.md ├── converters.md ├── core.md ├── debugging.md ├── docker.md ├── examples │ ├── hello-world.md │ └── periodic-sensor.md ├── flow.md ├── functional-bus.md ├── getting-started.md ├── harvesters.md ├── how-to-build-docs.md ├── images │ ├── battery.pdf │ ├── battery.png │ ├── battery_circuit_model.png │ ├── battery_equivalent_circuit.png │ ├── core_functional.pdf │ ├── core_functional.png │ ├── debugging.png │ ├── functional_bus.pdf │ ├── functional_bus.png │ ├── logo.webp │ ├── messy_full_system_pv.pdf │ ├── messy_full_system_pv.png │ ├── messy_full_system_single_sensor.pdf │ ├── messy_full_system_single_sensor.png │ ├── messy_full_systemc_double_sensors.pdf │ ├── messy_full_systemc_double_sensors.png │ ├── power_bus.pdf │ ├── power_bus.png │ ├── pv_panel.pdf │ ├── pv_panel.png │ ├── sensor_functional.pdf │ ├── sensor_functional.png │ ├── sensor_power.pdf │ └── sensor_power.png ├── index.md ├── ipxact-parsing.md ├── ipxact.md ├── lut.md ├── messy.md ├── power-bus.md ├── resolution.md ├── sensors.md ├── simulink │ ├── messy_double_sensors.slx │ ├── messy_pv.slx │ └── messy_single_sensor.slx ├── timing.md ├── tracing.md └── what-is-messy.md ├── examples ├── .gitignore ├── helloworld │ ├── CMakeLists.txt │ ├── Kconfig │ ├── Makefile │ ├── README.rst │ ├── gaptest.yml │ ├── helloworld.c │ └── sdk.config ├── periodic_sensors │ ├── Makefile │ └── periodic_sensors.c ├── read_sensor │ ├── Makefile │ └── read_sensor.c ├── read_write_multiple_sensors │ ├── Makefile │ └── read_write_multiple_sensor.c └── read_write_sensor │ ├── Makefile │ └── read_write_sensor.c ├── messy ├── .gitignore ├── Makefile ├── code │ └── six_instructions_example.txt ├── codegen │ ├── codegen.py │ ├── codegen_ipxact.py │ ├── gap9.json │ ├── gap9_pv_panel.json │ ├── ipxact.py │ ├── ipxact │ │ └── pulp_open_pv_panel │ │ │ ├── pulp_open_battery_component.xml │ │ │ ├── pulp_open_battery_converter_component.xml │ │ │ ├── pulp_open_bus_component.xml │ │ │ ├── pulp_open_core_component.xml │ │ │ ├── pulp_open_core_converter_component.xml │ │ │ ├── pulp_open_design.xml │ │ │ ├── pulp_open_harvesters_component.xml │ │ │ ├── pulp_open_mic_sensor_component.xml │ │ │ ├── pulp_open_photovoltaic_component.xml │ │ │ ├── pulp_open_photovoltaic_converter_component.xml │ │ │ └── pulp_open_sensors_component.xml │ ├── pulp_open.json │ ├── pulp_open_double_sensor.json │ ├── pulp_open_pv_panel.json │ ├── pulp_open_pv_panel_indoor_1p1s.json │ ├── pulp_open_pv_panel_indoor_8p4s.json │ ├── pulp_open_pv_panel_outdoor_1p1s.json │ └── templates │ │ ├── .gitignore │ │ ├── include │ │ ├── adapters │ │ │ ├── adapter_gvsoc.hpp │ │ │ ├── adapter_gvsoc_gap9.hpp │ │ │ └── iss_adapter.hpp │ │ ├── config.hpp │ │ ├── converter │ │ │ ├── load_converter.hpp │ │ │ └── lut_converter.hpp │ │ ├── core.hpp │ │ ├── core_power.hpp │ │ ├── functional_bus.hpp │ │ ├── harvester.hpp │ │ ├── lut.hpp │ │ ├── messy_request.hpp │ │ ├── power_bus.hpp │ │ ├── sensor_functional.hpp │ │ └── sensor_power.hpp │ │ └── src │ │ ├── adapters │ │ ├── adapter_gvsoc.cpp │ │ └── adapter_gvsoc_gap9.cpp │ │ ├── converter │ │ ├── load_converter.cpp │ │ └── lut_converter.cpp │ │ ├── core.cpp │ │ ├── core_power.cpp │ │ ├── functional_bus.cpp │ │ ├── harvester.cpp │ │ ├── lut.cpp │ │ ├── main.cpp │ │ ├── messy_request.cpp │ │ ├── power_bus.cpp │ │ ├── sensor_functional.cpp │ │ └── sensor_power.cpp ├── input_files │ ├── gmonths.txt │ ├── gmonths_1sec_1day.txt │ ├── gmonths_raw.txt │ └── office_windows_1sec_1day.txt └── messy.py ├── mkdocs.yaml ├── requirements.txt └── utils ├── digitizer ├── edit_dataset_dialog.ui ├── mainwindow.ui ├── mpp_calculator.py ├── plot1.png ├── plotdigitizer.py ├── readme.md └── utils.py ├── plotter ├── plotter.py └── readme.md └── resolutioner ├── readme.md └── resolutioner.py /.github/workflows/docs.yml: -------------------------------------------------------------------------------- 1 | name: docs 2 | on: 3 | push: 4 | branches: 5 | - master 6 | - main 7 | permissions: 8 | contents: write 9 | jobs: 10 | deploy: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@v4 14 | - uses: actions/setup-python@v4 15 | with: 16 | python-version: 3.x 17 | - run: echo "cache_id=$(date --utc '+%V')" >> $GITHUB_ENV 18 | - uses: actions/cache@v3 19 | with: 20 | key: mkdocs-material-${{ env.cache_id }} 21 | path: .cache 22 | restore-keys: | 23 | mkdocs-material- 24 | - run: pip install mkdocs-material 25 | - run: mkdocs gh-deploy --force -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | *.o 3 | *.x 4 | *.o 5 | 6 | deps 7 | venv 8 | messy/src 9 | messy/include 10 | 11 | *BUILD/ 12 | doc_env/ -------------------------------------------------------------------------------- /.vscode/c_cpp_properties.json: -------------------------------------------------------------------------------- 1 | { 2 | "configurations": [ 3 | { 4 | "name": "Linux", 5 | "includePath": [ 6 | "${workspaceFolder}/**", 7 | "/systemc/include", 8 | "/systemc-ams/include", 9 | "/gap_sdk", 10 | "/gap_sdk/gvsoc/gvsoc/engine/include", 11 | "/gap_sdk/rtos/pmsis/os/freeRTOS/vendors/gwt/pmsis/include" 12 | ], 13 | "defines": [], 14 | "compilerPath": "/usr/bin/gcc", 15 | "cStandard": "c17", 16 | "cppStandard": "gnu++14", 17 | "intelliSenseMode": "linux-gcc-x64", 18 | "compilerArgs": [] 19 | } 20 | ], 21 | "version": 4 22 | } -------------------------------------------------------------------------------- /.vscode/devcontainer.json: -------------------------------------------------------------------------------- 1 | { 2 | "remoteUser": "docker_user", 3 | // Add bash as default shell 4 | "customizations": { 5 | "vscode": { 6 | "settings": { 7 | "terminal.integrated.shell.linux": "/bin/bash", 8 | "terminal.integrated.profiles.linux": { 9 | "bash": { 10 | "path": "/bin/bash", 11 | "icon": "terminal-bash" 12 | } 13 | }, 14 | "python.defaultInterpreterPath": "/usr/bin/python3" 15 | }, 16 | "extensions": [ 17 | "ms-python.python", 18 | "ms-vscode.cpptools", 19 | "ms-python.vscode-pylance", 20 | "ms-python.debugpy" 21 | ] 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": "codegen.py Debug", 9 | "type": "debugpy", 10 | "request": "launch", 11 | "cwd": "/messy/messy", 12 | "program": "codegen/codegen.py", 13 | "console": "integratedTerminal", 14 | "args": [ 15 | "-f", 16 | "codegen/pulp_open.json" 17 | ], 18 | }, 19 | { 20 | "name": "messy.py Debug", 21 | "type": "debugpy", 22 | "request": "launch", 23 | "program": "/messy/messy/messy.py", 24 | "console": "integratedTerminal", 25 | "args": [ 26 | "-f", 27 | "codegen/pulp-open.json", 28 | "-a", 29 | "/messy/examples/helloworld" 30 | ], 31 | }, 32 | { 33 | "name": "Executable Debug", 34 | "type": "cppdbg", 35 | "request": "launch", 36 | "program": "${workspaceFolder}/messy/bin/run", 37 | "args": [], 38 | "stopAtEntry": true, 39 | "cwd": "${workspaceFolder}/messy", 40 | "environment": [], 41 | "externalConsole": false, 42 | "MIMode": "gdb", 43 | "setupCommands": [ 44 | { 45 | "description": "Enable pretty-printing for gdb", 46 | "text": "-enable-pretty-printing", 47 | "ignoreFailures": true 48 | }, 49 | { 50 | "description": "Set Disassembly Flavor to Intel", 51 | "text": "-gdb-set disassembly-flavor intel", 52 | "ignoreFailures": true 53 | } 54 | ] 55 | } 56 | ] 57 | } -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.associations": { 3 | "array": "cpp", 4 | "atomic": "cpp", 5 | "strstream": "cpp", 6 | "bit": "cpp", 7 | "*.tcc": "cpp", 8 | "cctype": "cpp", 9 | "clocale": "cpp", 10 | "cmath": "cpp", 11 | "complex": "cpp", 12 | "cstdarg": "cpp", 13 | "cstddef": "cpp", 14 | "cstdint": "cpp", 15 | "cstdio": "cpp", 16 | "cstdlib": "cpp", 17 | "cstring": "cpp", 18 | "ctime": "cpp", 19 | "cwchar": "cpp", 20 | "cwctype": "cpp", 21 | "deque": "cpp", 22 | "map": "cpp", 23 | "set": "cpp", 24 | "unordered_map": "cpp", 25 | "vector": "cpp", 26 | "exception": "cpp", 27 | "algorithm": "cpp", 28 | "functional": "cpp", 29 | "iterator": "cpp", 30 | "memory": "cpp", 31 | "memory_resource": "cpp", 32 | "numeric": "cpp", 33 | "optional": "cpp", 34 | "random": "cpp", 35 | "string": "cpp", 36 | "string_view": "cpp", 37 | "system_error": "cpp", 38 | "tuple": "cpp", 39 | "type_traits": "cpp", 40 | "utility": "cpp", 41 | "fstream": "cpp", 42 | "initializer_list": "cpp", 43 | "iomanip": "cpp", 44 | "iosfwd": "cpp", 45 | "iostream": "cpp", 46 | "istream": "cpp", 47 | "limits": "cpp", 48 | "new": "cpp", 49 | "ostream": "cpp", 50 | "sstream": "cpp", 51 | "stdexcept": "cpp", 52 | "streambuf": "cpp", 53 | "cinttypes": "cpp", 54 | "typeindex": "cpp", 55 | "typeinfo": "cpp", 56 | "valarray": "cpp", 57 | "bitset": "cpp", 58 | "regex": "cpp", 59 | "future": "cpp", 60 | "variant": "cpp", 61 | "condition_variable": "cpp", 62 | "chrono": "cpp", 63 | "codecvt": "cpp", 64 | "compare": "cpp", 65 | "concepts": "cpp", 66 | "forward_list": "cpp", 67 | "list": "cpp", 68 | "unordered_set": "cpp", 69 | "ratio": "cpp", 70 | "source_location": "cpp", 71 | "mutex": "cpp", 72 | "numbers": "cpp", 73 | "semaphore": "cpp", 74 | "stop_token": "cpp", 75 | "thread": "cpp", 76 | "cfenv": "cpp", 77 | "shared_mutex": "cpp" 78 | } 79 | } -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "tasks": [ 3 | { 4 | "type": "cppbuild", 5 | "label": "C/C++: g++ build active file", 6 | "command": "/usr/bin/g++", 7 | "args": [ 8 | "-fdiagnostics-color=always", 9 | "-g", 10 | "-I. ", 11 | "-I$SYSTEMC_HOME/include ", 12 | "-I$AMS_HOME/include ", 13 | "-I./AMS_TEMPLATE/inc ", 14 | "-L. ", 15 | "-L$SYSTEMC_HOME/lib-linux64 ", 16 | "-L$AMS_HOME/lib-linux64", 17 | "${file}", 18 | "-o", 19 | "${fileDirname}/${fileBasenameNoExtension}" 20 | ], 21 | "options": { 22 | "cwd": "${fileDirname}" 23 | }, 24 | "problemMatcher": [ 25 | "$gcc" 26 | ], 27 | "group": { 28 | "kind": "build", 29 | "isDefault": true 30 | }, 31 | "detail": "Task generated by Debugger." 32 | } 33 | ], 34 | "version": "2.0.0" 35 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MESSY (Multi-layer Extra-functional Simulator in Systemc) 2 | 3 | drawing 4 | 5 | The availability of simulation platforms is a key ingredient for making RISC-V based hardware solutions pervasive. Simulators represent a cost-effective and scalable solution that enable rapid prototyping without the need for physical hardware. For these reasons, there is a growing availability of programs designed to simulate entire RISC-V chips. Some options include QEMU, Simulink, Renode, and GVSoC. However, these tools present some limitations. Most of them only simulate the computing core with scarce possibilities to perform system-level simulations. Moreover, they simulate only functional features, with poor support for extra-functional properties such as power consumption. This work tries to address these challenges by presenting a flexible simulator. 6 | 7 | Messy is an open-source framework that integrates functional RISC-V simulation (achieved with GVSoC) with SystemC-AMS (used to model extra-functional aspects, in detail power storage and distribution). The combination of GVSoC and SystemC-AMS in a single simulation framework allows to perform a DSE that is dependent on the mutual impact between functional and extra-functional aspects. 8 | 9 | # Reference 10 | 11 | If you enjoy and use Messy on your works, please acknowledge our paper: https://dl.acm.org/doi/10.1145/3637543.3652873 12 | ``` 13 | @inproceedings{10.1145/3637543.3652873, 14 | author = {Hamdi, Mohamed Amine and Pollo, Giovanni and Risso, Matteo and Haugou, Germain and Burrello, Alessio and Macii, Enrico and Poncino, Massimo and Vinco, Sara and Pagliari, Daniele Jahier}, 15 | title = {Integrating SystemC-AMS Power Modeling with a RISC-V ISS for Virtual Prototyping of Battery-operated Embedded Devices}, 16 | year = {2024}, 17 | isbn = {9798400704925}, 18 | url = {https://doi.org/10.1145/3637543.3652873}, 19 | doi = {10.1145/3637543.3652873}, 20 | booktitle = {Proceedings of the 21st ACM International Conference on Computing Frontiers: Workshops and Special Sessions}, 21 | keywords = {Design Space Exploration, Power, RISC-V, SystemC, Virtual Prototyping}, 22 | } 23 | ``` 24 | 25 | # Documentation 26 | 27 | To get started, please refer to the [Documentation](https://eml-eda.github.io/messy/) 28 | -------------------------------------------------------------------------------- /docker/gap9/Makefile: -------------------------------------------------------------------------------- 1 | SHELL := /bin/bash 2 | .SUFFIXES: 3 | .SUFFIXES: .cc .cpp .o 4 | .PHONY: clean ultraclean help 5 | 6 | CC := g++ 7 | OPT = 8 | DEBUG = 9 | OTHER := -Wall -O3 10 | 11 | # Use this CFLAGS definition if you need to see debug output 12 | # CFLAGS = -c -g -Wno-deprecated -Wall -D_DEBUG 13 | CFLAGS := -c -g -Wno-deprecated $(OTHER) 14 | 15 | #The Directories, Source, Includes, Objects, Binary and Resources 16 | SRCDIR := src 17 | INCDIR := include 18 | BUILDDIR := obj 19 | TARGETDIR := bin 20 | SRCEXT := cpp 21 | OBJEXT := o 22 | SYSTEMC_HOME := /usr/local/systemc 23 | AMS_HOME := /usr/local/systemc-ams 24 | GAP_SDK := /gap_sdk 25 | MODULE := run 26 | 27 | SOURCES := $(shell find $(SRCDIR) -type f -name *.$(SRCEXT)) 28 | OBJECTS := $(SOURCES:$(SRCDIR)/%.$(SRCEXT)=$(BUILDDIR)/%.$(OBJEXT)) 29 | 30 | # include Makefile.defs 31 | INCDIR = -I./include -I./src \ 32 | -I$(AMS_HOME)/include \ 33 | -I$(SYSTEMC_HOME)/include \ 34 | -I$(SYSTEMC_HOME)/src/sysc/libs \ 35 | -I$(SYSTEMC_HOME)/src/sysc/kernel \ 36 | -I$(GAP_SDK)/gvsoc/gvsoc/engine/include 37 | 38 | 39 | EXE := $(MODULE) 40 | 41 | $(BUILDDIR)/%.$(OBJEXT): $(SRCDIR)/%.$(SRCEXT) 42 | @echo "Compiling source $< into object $@" 43 | @mkdir -p '$(@D)' 44 | $(GCC_PATH)$(CC) $(CFLAGS) $(INCDIR) -std=c++14 $< -o $@ 45 | 46 | $(TARGETDIR)/$(EXE): $(OBJECTS) 47 | @echo "Building $@ from $<" 48 | @mkdir -p '$(@D)' 49 | $(GCC_PATH)$(CC) -g $(INCDIR) -std=c++14 -o $@ $(OBJECTS) -L$(GAP_SDK)/install/workstation/lib -lpulpvp \ 50 | $(AMS_HOME)/lib-linux64/libsystemc-ams.a \ 51 | $(SYSTEMC_HOME)/lib-linux64/libsystemc.a -lpthread 2>&1 | c++filt \ 52 | 53 | clean: 54 | echo "Cleaning up" 55 | rm -rf $(BUILDDIR) 56 | rm -rf $(TARGETDIR) 57 | rm -rf src 58 | rm -rf codegen/src 59 | rm -rf include 60 | rm -rf codegen/include 61 | rm -rf codegen/__pycache__ 62 | 63 | codegen: clean 64 | echo "Generating code" 65 | python3 codegen/codegen.py -f $(file) 66 | 67 | run: $(TARGETDIR)/$(EXE) 68 | @echo "Running $(EXE)" 69 | cd $(GAP_SDK);\ 70 | source sourceme.sh 1;\ 71 | $(TARGETDIR)/$(EXE) 72 | 73 | ultraclean: clean 74 | rm -f Makefile.deps 75 | rm -f tx_uart.log 76 | rm -f trace_file.txt 77 | rm -f power_trace.txt 78 | rm -f power_report.csv 79 | rm -f gvsoc_config.json 80 | rm -f functional_trace.txt 81 | rm -f flash.bin 82 | rm -f efuse_preload.data 83 | rm -f chip.soc.mram.bin 84 | 85 | Makefile.deps: 86 | $(GCC_PATH)$(CC) $(CFLAGS) $(INCDIR) -M $(SOURCES) $(SRCS_BUS) >> Makefile.deps 87 | 88 | application: 89 | cd /messy/messy;\ 90 | rm -r gvsoc_deps;\ 91 | mkdir gvsoc_deps;\ 92 | cd $(GAP_SDK);\ 93 | source sourceme.sh 1;\ 94 | cd $(app);\ 95 | echo "Building application";\ 96 | make all gvsoc.prepare platform=gvsoc runner_args="--vcd --event=.*";\ 97 | cp BUILD/GAP9_V2/GCC_RISCV_FREERTOS/gvsoc_config.json /messy/messy/gvsoc_deps/;\ 98 | cp BUILD/GAP9_V2/GCC_RISCV_FREERTOS/efuse_preload.data /messy/messy/gvsoc_deps/;\ 99 | cp BUILD/GAP9_V2/GCC_RISCV_FREERTOS/flash.bin /messy/messy/gvsoc_deps/;\ 100 | cp BUILD/GAP9_V2/GCC_RISCV_FREERTOS/chip.soc.mram.bin /messy/messy/gvsoc_deps/\ 101 | sed -i 's:"efuse_preload.data":"/messy/messy/gvsoc_deps/efuse_preload.data":g' /messy/messy/gvsoc_deps/gvsoc_config.json;\ 102 | sed -i 's:"chip.soc.mram.bin":"/messy/messy/gvsoc_deps/chip.soc.mram.bin":g' /messy/messy/gvsoc_deps/gvsoc_config.json;\ 103 | sed -i 's:"flash.bin":"/messy/messy/gvsoc_deps/flash.bin":g' /messy/messy/gvsoc_deps/gvsoc_config.json 104 | 105 | # include Makefile.deps 106 | 107 | help: 108 | @echo "Available targets:" 109 | @echo " all : Build the executable" 110 | @echo " clean : Remove build and generated files" 111 | @echo " codegen : Generate code" 112 | @echo " ultraclean: Perform a clean and remove additional files" 113 | @echo " run : Build the executable and run it" 114 | @echo " help : Display this help message" 115 | -------------------------------------------------------------------------------- /docker/gap9/build_gap9.sh: -------------------------------------------------------------------------------- 1 | if [ -n "${ZSH_VERSION:-}" ] 2 | then 3 | DIR="$(readlink -f -- "${(%):-%N}")" 4 | DIRNAME="$(dirname $DIR)" 5 | GAP_SDK_HOME=$(echo $DIRNAME) 6 | export GAP_SDK_HOME 7 | setopt shwordsplit 8 | else 9 | export GAP_SDK_HOME="$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")" 10 | fi 11 | 12 | EXCLUDE="clean.sh common.sh jlink.sh openocd.sh gap9_v2.sh" 13 | EXCLUDE_FILES= 14 | for i in $EXCLUDE 15 | do 16 | EXCLUDE_FILES="$EXCLUDE_FILES -not -iname *$i" 17 | done 18 | 19 | BOARDS=$(find $GAP_SDK_HOME/configs -maxdepth 1 -type f -iname "*.sh" $EXCLUDE_FILES | sort) 20 | 21 | n=0 22 | board= 23 | echo "Select the target : " 24 | for i in $BOARDS 25 | do 26 | n=$(($n+1)) 27 | board=$(basename $(echo $BOARDS | tr '[:lower:]' '[:upper:]' | cut -d ' ' -f $n) .SH) 28 | echo -e "\t$n - $board" 29 | done 30 | 31 | if [ "$#" -eq 1 ] 32 | then 33 | board=$1 34 | else 35 | read board 36 | fi 37 | 38 | if [ -z "$board" ] || [ "$board" -gt "$n" ] || [ "$board" -le 0 ] 39 | then 40 | source $GAP_SDK_HOME/configs/gap9_evk_audio.sh 41 | else 42 | board=$(echo $BOARDS | cut -d ' ' -f $board) 43 | source $board 44 | fi 45 | 46 | if [ -e $GAP_SDK_HOME/internal/scripts/environment/install_hooks.sh ]; then 47 | $GAP_SDK_HOME/internal/scripts/environment/install_hooks.sh 48 | fi 49 | 50 | echo The target board you have chosen is : $BOARD_NAME, $TARGET_CHIP. 51 | 52 | unset EXCLUDE EXCLUDE_FILES BOARDS board n 53 | -------------------------------------------------------------------------------- /docker/pulp-open/Makefile: -------------------------------------------------------------------------------- 1 | SHELL := /bin/bash 2 | .SUFFIXES: 3 | .SUFFIXES: .cc .cpp .o 4 | .PHONY: clean ultraclean help 5 | 6 | CC := g++ 7 | OPT = 8 | DEBUG = 9 | OTHER := -Wall -O3 10 | PULP_SDK := /pulp-sdk 11 | # Use this CFLAGS definition if you need to see debug output 12 | # CFLAGS = -c -g -Wno-deprecated -Wall -D_DEBUG 13 | CFLAGS := -c -g -Wno-deprecated $(OTHER) 14 | 15 | #The Directories, Source, Includes, Objects, Binary and Resources 16 | SRCDIR := src 17 | INCDIR := include 18 | BUILDDIR := obj 19 | TARGETDIR := bin 20 | SRCEXT := cpp 21 | OBJEXT := o 22 | SYSTEMC_HOME := /usr/local/systemc 23 | AMS_HOME := /usr/local/systemc-ams 24 | GAP_HOME := /gap_sdk 25 | MODULE := run 26 | 27 | SOURCES := $(shell find $(SRCDIR) -type f -name *.$(SRCEXT)) 28 | OBJECTS := $(SOURCES:$(SRCDIR)/%.$(SRCEXT)=$(BUILDDIR)/%.$(OBJEXT)) 29 | 30 | # include Makefile.defs 31 | INCDIR = -I./include -I./src \ 32 | -I$(AMS_HOME)/include \ 33 | -I$(SYSTEMC_HOME)/include \ 34 | -I$(SYSTEMC_HOME)/src/sysc/libs \ 35 | -I$(SYSTEMC_HOME)/src/sysc/kernel \ 36 | -I$(PULP_SDK)/tools/gvsoc/core/engine/include 37 | 38 | EXE := $(MODULE) 39 | 40 | $(BUILDDIR)/%.$(OBJEXT): $(SRCDIR)/%.$(SRCEXT) 41 | @echo "Compiling source $< into object $@" 42 | @mkdir -p '$(@D)' 43 | $(GCC_PATH)$(CC) $(CFLAGS) $(INCDIR) -std=c++14 $< -o $@ 44 | 45 | $(TARGETDIR)/$(EXE): $(OBJECTS) 46 | @echo "Building $@ from $<" 47 | @mkdir -p '$(@D)' 48 | $(GCC_PATH)$(CC) -g $(INCDIR) -std=c++14 -o $@ $(OBJECTS) -L$(PULP_SDK)/install/workstation/lib -lpulpvp \ 49 | $(AMS_HOME)/lib-linux64/libsystemc-ams.a \ 50 | $(SYSTEMC_HOME)/lib-linux64/libsystemc.a -lpthread 2>&1 | c++filt \ 51 | 52 | clean: 53 | echo "Cleaning up" 54 | rm -rf $(BUILDDIR) 55 | rm -rf $(TARGETDIR) 56 | rm -rf src 57 | rm -rf codegen/src 58 | rm -rf include 59 | rm -rf codegen/include 60 | rm -rf codegen/__pycache__ 61 | 62 | codegen: clean 63 | echo "Generating code" 64 | python3 codegen/codegen.py -f $(file) 65 | 66 | run: $(TARGETDIR)/$(EXE) 67 | @echo "Running $(EXE)" 68 | cd $(PULP_SDK);\ 69 | source configs/pulp-open.sh;\ 70 | cd /messy/messy;\ 71 | $(TARGETDIR)/$(EXE) 72 | 73 | ultraclean: clean 74 | rm -f Makefile.deps 75 | rm -f tx_uart.log 76 | rm -f trace_file.txt 77 | rm -f power_trace.txt 78 | rm -f power_report.csv 79 | rm -f gvsoc_config.json 80 | rm -f functional_trace.txt 81 | rm -f flash.bin 82 | rm -f efuse_preload.data 83 | rm -f chip.soc.mram.bin 84 | 85 | Makefile.deps: 86 | $(GCC_PATH)$(CC) $(CFLAGS) $(INCDIR) -M $(SOURCES) $(SRCS_BUS) >> Makefile.deps 87 | 88 | # include Makefile.deps 89 | 90 | application: 91 | cd /messy/messy;\ 92 | rm -r gvsoc_deps;\ 93 | mkdir gvsoc_deps;\ 94 | cd $(PULP_SDK);\ 95 | source configs/pulp-open.sh;\ 96 | cd $(app);\ 97 | echo "Building application";\ 98 | make all gvsoc.prepare platform=gvsoc runner_args="--vcd --event=.*";\ 99 | cp BUILD/PULP/GCC_RISCV/gvsoc_config.json /messy/messy/gvsoc_deps/;\ 100 | cp BUILD/PULP/GCC_RISCV/efuse_preload.data /messy/messy/gvsoc_deps/;\ 101 | cp BUILD/PULP/GCC_RISCV/flash.bin /messy/messy/gvsoc_deps/;\ 102 | cp BUILD/PULP/GCC_RISCV/chip.soc.mram.bin /messy/messy/gvsoc_deps/;\ 103 | cp BUILD/PULP/GCC_RISCV/spiflash.bin /messy/messy/gvsoc_deps/;\ 104 | cp BUILD/PULP/GCC_RISCV/hyperflash.bin /messy/messy/gvsoc_deps/;\ 105 | sed -i 's:"spiflash.bin":"/messy/messy/gvsoc_deps/spiflash.bin":g' /messy/messy/gvsoc_deps/gvsoc_config.json;\ 106 | sed -i 's:"efuse_preload.data":"/messy/messy/gvsoc_deps/efuse_preload.data":g' /messy/messy/gvsoc_deps/gvsoc_config.json;\ 107 | sed -i 's:"chip.soc.mram.bin":"/messy/messy/gvsoc_deps/chip.soc.mram.bin":g' /messy/messy/gvsoc_deps/gvsoc_config.json;\ 108 | sed -i 's:"flash.bin":"/messy/messy/gvsoc_deps/flash.bin":g' /messy/messy/gvsoc_deps/gvsoc_config.json;\ 109 | sed -i 's:"hyperflash.bin":"/messy/messy/gvsoc_deps/hyperflash.bin":g' /messy/messy/gvsoc_deps/gvsoc_config.json 110 | 111 | help: 112 | @echo "Available targets:" 113 | @echo " all : Build the executable" 114 | @echo " clean : Remove build and generated files" 115 | @echo " codegen : Generate code" 116 | @echo " ultraclean: Perform a clean and remove additional files" 117 | @echo " run : Build the executable and run it" 118 | @echo " help : Display this help message" 119 | -------------------------------------------------------------------------------- /docker/pulp-open/build_open.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | pip3 install -r /pulp-sdk/tools/gvsoc/requirements.txt 3 | pip3 install -r /pulp-sdk/tools/gvsoc/gapy/requirements.txt 4 | pip3 install -r /pulp-sdk/tools/gvsoc/core/requirements.txt 5 | cd /pulp_toolchain 6 | source sourceme.sh 7 | cd /pulp-sdk 8 | source configs/pulp-open.sh 9 | make build -j 4 -------------------------------------------------------------------------------- /docs/adapter.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eml-eda/messy/026551c39c4b89e32f853e50fcc8b89ac9725d6f/docs/adapter.md -------------------------------------------------------------------------------- /docs/codegen.md: -------------------------------------------------------------------------------- 1 | # Codegen 2 | 3 | This module will explain the codegen process with its characteristics. 4 | 5 | The codegen is a Python script that generates the code for the simulation. It is located in the `messy/codegen` folder. The codegen is composed of two files: 6 | 7 | - `codegen.py`: this is the main file of the codegen. It contains the call to specific functions that will generate the code of the components of the simulator. 8 | 9 | # Codegen explanation 10 | 11 | The `codegen.py` expect a JSON file as input, which contains the configuration for the simulator. 12 | 13 | An example of a JSON file is the following: 14 | 15 | ```JSON 16 | { 17 | "resolution":"SC_MS", 18 | "tracing":{ 19 | ... 20 | }, 21 | "bus":{ 22 | "vref":3.3 23 | }, 24 | "core":{ 25 | "vref":1.8, 26 | "iss":"gvsoc", 27 | "config":{ 28 | "path":"./gvsoc_config.json", 29 | "axi_path":"/chip/axi_proxy" 30 | }, 31 | ... 32 | }, 33 | "peripherals":{ 34 | "sensors" : { 35 | "mic_click": { 36 | ... 37 | } 38 | }, 39 | "harvesters":{ 40 | "battery" : { 41 | ... 42 | }, 43 | "photovoltaic" : { 44 | ... 45 | } 46 | } 47 | } 48 | } 49 | ``` 50 | 51 | In this case for example, we are describing a single sensor. The meaning of different fields is the following: 52 | 53 | - `resolution`: this is the simulation resolution using `sc_unit` values. For more details refer to [Resolution](resolution.md) 54 | - `tracing`: tracing is better described in [Tracing](tracing.md) 55 | - `bus`: the bus object contains all the relative informations about it, which currently resides only in its reference voltage in Volts. 56 | 57 | - `core`: definition of the simulated core (system), to define one we can use the following parameters 58 | - `vref`: reference voltage in Volts 59 | - `config`: configuration of the ISS, which considers path of files and address of the AXI currently 60 | 61 | - `converters`: Messy also supports converters. Read more at [Converters](converters.md) 62 | 63 | - `peripherals`: set of sensors (better described [Sensors](sensors.md)) and harvesters (better described in [Harvesters](harvesters.md)) 64 | 65 | -------------------------------------------------------------------------------- /docs/converters.md: -------------------------------------------------------------------------------- 1 | # Converters 2 | 3 | Converters are very important objects in electronics system, they are supported in MESSY currently by a [LUT](lut.md) approach, here an example of a converter: 4 | 5 | ```JSON 6 | "converter" : { 7 | "input_variable":"voltage", 8 | "out_dir":false, 9 | "lut":{ 10 | "input_values":[0.6559,0.7397,0.8363,0.9588,1.0941,1.1907,1.4291,1.7642,1.8544,1.9961,2.4278,2.5954,2.6534,2.7307,2.7758,2.7887,2.9691,3.1688,3.3428,3.5876,3.7874,3.9678,4.1353,4.3673,4.5928,4.7668,4.9729], 11 | "efficiency_values":[64.92,69.37,74.44,78.79,81.87,83.69,84.77,85.86,86.04,85.95,89.31,90.66,83.14,75.71,70.73,68.46,68.64,68.19,66.83,63.93,61.75,59.31,57.22,54.77,52.42,50.51,47.70] 12 | } 13 | } 14 | ``` 15 | 16 | The converter is described through the direction, set by `out_dir`, that we want to consider, the `input_variable` that we want to consider, that can be either voltage or current and finally the previously mentioned [LUT](lut.md), the [LUT](lut.md) second values for a converter are the `efficiency_values`, which are the efficiency percentages of a converter. 17 | 18 | The modeled converter can be described as a simple Buck DC-DC converter, but we want to support a wider variety of converters. -------------------------------------------------------------------------------- /docs/core.md: -------------------------------------------------------------------------------- 1 | The core, alongside the [adapter](adapter.md) is probably the most important component of the whole system. Inside it contains all the necessary functions used to run the simulation. Inside it contains an instance of the `iss_adapter`. 2 | 3 | Similarly to most of the other components, the core is composed of two separate instances: 4 | 5 | - **Functional**: this instance is responsible for defining the internal characteristics of the core. This instance interfaces with the core through a bus 6 | - **Power**: this instance controls the state of the core and exposes its current and voltage 7 | 8 | ## Functional Instance 9 | 10 | The functional instance is as follows: 11 | 12 | ![text](images/core_functional.png) 13 | 14 | ### Signals Summary 15 | 16 | A summary of the signals is shown in the table below: 17 | 18 | | Signal | Direction | Connected to | Description | 19 | | --- | --- | --- | --- | 20 | | request_go | input | [Functional Bus](functional-bus.md) | | 21 | | request_value | input | [Functional Bus](functional-bus.md) | | 22 | | idx_sensor | input | [Functional Bus](functional-bus.md) | | 23 | | request_address | output | [Functional Bus](functional-bus.md) | | 24 | | request_data | output | [Functional Bus](functional-bus.md) | | 25 | | request_size | output | [Functional Bus](functional-bus.md) | | 26 | | functional_bus_flag | output | [Functional Bus](functional-bus.md) | | 27 | | request_ready | output | [Functional Bus](functional-bus.md) | | 28 | | power_signal | output | Core Power| | 29 | 30 | ### Input Signals 31 | 32 | The input signals are: 33 | 34 | - **request_go**: This signal is a boolean. It comes from the [functional bus](functional-bus.md) and is used to signal the core when a request is completed. Initially, request_go is set to 0, and it means that the request is being processed. When the request is completed, the [functional bus](functional-bus.md) sets the request go to 1. The core then wakes up and set the request_ready signal to 0. The [functional bus](functional-bus.md) then frees the sensor and sets the request_go to 0 again. 35 | - **request_value**: This signal is a pointer. It comes from the [sensor](sensors.md), then goes through the [functional bus](functional-bus.md), and finally reaches the core. It contains the pointer to the data written to the sensor memory or read from it. When the request is a write this value is ignored 36 | - **idx_sensor**: This signal is an integer value. It comes from the [functional bus](functional-bus.md) and contains the index of the sensor that is being accessed 37 | 38 | ### Output Signals 39 | 40 | The output signals are: 41 | 42 | - **request_address**: This signal is an unsigned integer. It goes to the [functional bus](functional-bus.md) and contains the offset of the sensor memory that is being accessed. For example, if the sensor memory is contains 256 bytes and the request_address is set to 10 it means that we are accessing the 10th byte of the sensor memory. If the request has a size greater than 1, the request address will be the starting address of the memory block of the sensor. 43 | - **request_data**: This signal is a pointer. It goes to the [functional bus](functional-bus.md) and contains the pointer to the data that is being written to the sensor memory. In case of a read request, this value is ignored and not set. 44 | - **request_size**: this signal is an unsigned integer. It goes to the [functional bus](functional-bus.md) and contains the number of bytes that are being read from or written to the sensor memory. For example, if the request_size is set to 4 it means that we are reading or writing 4 elements of the sensor memory (since the sensor memory is byte-addressable). 45 | - **functional_bus_flag**: This signal is a boolean. It goes to the [functional bus](functional-bus.md) and it used to indicate if the request is a read or a write. If the flag is set to true it means that the request is a read, otherwise it is a write. 46 | - **request_ready**: This signal is a boolean. It goes to the [functional bus](functional-bus.md) and it is used to indicate that the request is ready to be processed by the [functional bus](functional-bus.md). In the [functional bus](functional-bus.md), in fact, the main loop is waiting for this signal to be set to true before forwarding the request to the sensor. 47 | - **power_signal**: This signal is a double. It is not used and should be removed 48 | 49 | ## Power Instance 50 | 51 | TODO -------------------------------------------------------------------------------- /docs/debugging.md: -------------------------------------------------------------------------------- 1 | # Debugging 2 | 3 | This guide explains how to debug the code. The provided configuration needs Visual Studio Code. For other IDEs, you need to adapt the configuration. 4 | The whole configuration is provided in the `.vscode` folder. Everything should work out of the box. 5 | 6 | You have to create a docker container first. See [Getting Started](getting-started.md) for more information. 7 | 8 | !!! Important 9 | After that you need to install the Visual Studio Code `Remote - Containers` and `C/C++` extensions. You can find them [here](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) and [here](https://marketplace.visualstudio.com/items?itemName=ms-vscode.cpptools) respectively. 10 | 11 | After that, you will find a docker icon in left bar. If you click it, it will show you the list of containers. You should see the container you created before. If you right click on it and select `Attach Visual Studio Code`, it will open a new window with the container attached. 12 | 13 | !!! important 14 | You have to install the `C/C++` extension in the container too. You find the link [here](https://marketplace.visualstudio.com/items?itemName=ms-vscode.cpptools). 15 | 16 | Then you can open the folder `/messy` and click on the debug icon (green circle in the picture below) in the left bar. You should see a list of debug configurations. The one we are interested in is called `gdb` (red circle in the picture below). If you click on it, it will start the debugger. You can set breakpoints and step through the code. 17 | 18 | ![debugging](images/debugging.png) -------------------------------------------------------------------------------- /docs/docker.md: -------------------------------------------------------------------------------- 1 | ## Requirements 2 | 3 | To build a Docker image, you need to have Docker installed on your machine. You can find the installation instructions [here](https://docs.docker.com/engine/install/). In addition to that you need to populate the `deps/` directory with the SystemC and SystemC-AMS `.tar` files. You can find them [here](https://www.accellera.org/downloads/standards/systemc) and [here](https://www.coseda-tech.com/systemc-ams-proof-of-concept). The Dockerfile expects the following files: 4 | 5 | - `systemc-x.x.x.tar` 6 | - `systemc-ams-x.x.x.tar` 7 | 8 | !!! warning 9 | The `x.x.x` at the end of the file name of the SystemC and SystemC-AMS files should be replaced by the downloaded version. After that check the `Dockerfile` to make sure to put the correct version in the `COPY` command. You need to change the `x.x.x` in the following line: 10 | 11 | ```Dockerfile 12 | COPY deps/systemc-2.3.3.tar /systemc.tar 13 | ... 14 | COPY deps/systemc-ams-2.3.4.tar /systemc-ams.tar 15 | ``` 16 | !!! important 17 | For compatibility reasons we suggest you to use the following version of SystemC and SystemC-AMS: 18 | 19 | 1. SystemC **2.3.3** 20 | 2. SystemC-AMS **2.3.4** 21 | 22 | 23 | ## Overview of the Dockerfile 24 | 25 | Each Dockerfile is based on the Ubuntu 22.04 image. It installs the following dependencies: 26 | 27 | - SystemC x.x.x ([https://systemc.org/](https://systemc.org/)) 28 | - Systemc-AMS x.x.x ([https://www.accellera.org/downloads/standards/systemc](https://www.accellera.org/downloads/standards/systemc)) 29 | - Core SDK 30 | - Core RISC-V 31 | - Make 32 | - CMake 33 | - g++ 34 | - python3 35 | - python3-pip 36 | 37 | ## Build the Docker image 38 | 39 | The first step is to build a Docker image. For example to build the `pulp-open` container the following command should be issued: 40 | 41 | ```bash 42 | docker build . -f docker/pulp-open/Dockerfile -t messy --build-arg USER_ID=$(id -u ${USER}) --build-arg GROUP_ID=$(id -g ${USER}) 43 | ``` 44 | 45 | The first time you run this command, it will take some time to build the image. Thanks to docker caching, the next time you run this command, it will be much faster. 46 | 47 | ## Run the Docker container 48 | 49 | Once the image is built, you can run the container with the following command: 50 | 51 | ```bash 52 | docker run -it --rm -v $(pwd):/messy messy:latest 53 | ``` 54 | 55 | This command will run the container and mount the current directory in the `/messy` directory of the container. This way, you can access the files from the container and the host. Now you should see the shell inside the container. 56 | -------------------------------------------------------------------------------- /docs/examples/hello-world.md: -------------------------------------------------------------------------------- 1 | ## How to run it 2 | 3 | Before running this example, you have launch the docker container. You can find the instructions in the [Docker](../docker.md) page of the documentation. 4 | 5 | When you are in the docker container, you have to go to the `messy` directory: 6 | 7 | ```bash 8 | cd /messy/messy/ 9 | ``` 10 | 11 | Then we can run python: 12 | 13 | ```bash 14 | python3 messy.py -f codegen/pulp_open.json -a /messy/examples/helloworld 15 | ``` 16 | The parameters are: 17 | 18 | 1. `-f` is the file name of the chosen system configuration 19 | 2. `-a` is the path of the folder of the application 20 | 21 | ## Explanation 22 | 23 | This code will build and execute the `helloworld` example. You should see the following output: 24 | 25 | ``` 26 | Entering main controller 27 | [31 0] Hello World! 28 | Cluster master core entry 29 | [0 7] Hello World! 30 | [0 6] Hello World! 31 | [0 5] Hello World! 32 | [0 4] Hello World! 33 | [0 3] Hello World! 34 | [0 2] Hello World! 35 | [0 0] Hello World! 36 | [0 1] Hello World! 37 | Cluster master core exit 38 | Bye ! 39 | ``` 40 | 41 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /docs/examples/periodic-sensor.md: -------------------------------------------------------------------------------- 1 | ## How to run it 2 | 3 | Before running this example, you have launch the docker container. You can find the instructions in the [Docker](../docker.md) page of the documentation. 4 | 5 | When you are in the docker container, you have to go to the `messy` directory: 6 | 7 | ```bash 8 | cd /messy/messy/ 9 | ``` 10 | 11 | Then we can run python: 12 | 13 | ```bash 14 | python3 messy.py -f codegen/pulp_open.json -a /messy/examples/periodic-sensor 15 | ``` 16 | The parameters are: 17 | 18 | 1. `-f` is the file name of the chosen system configuration 19 | 2. `-a` is the path of the folder of the application 20 | 21 | ## Explanation 22 | 23 | This example, as the name suggest, is a simple example that periodically writes a value to the sensor memory. This example is useful to understand how to interact with the sensor memory and how the flow of a write operation works. For more information about the write request, please refer to the [Communication Example](../communication-example.md) page. 24 | 25 | By adding some print statements inside the functional model of the sensor, we can see how the memory of the sensor is updated, each time a write occurs. 26 | 27 | ``` 28 | [ITER 0/2880] 0.00 Hours Elapsed 29 | [SENSOR] Writing data to register memory at address 0 30 | [SENSOR] Data written: 2 31 | [ITER 1/2880] 0.01 Hours Elapsed 32 | [SENSOR] Writing data to register memory at address 0 33 | [SENSOR] Data written: 4 34 | [ITER 2/2880] 0.02 Hours Elapsed 35 | [SENSOR] Writing data to register memory at address 0 36 | [SENSOR] Data written: 6 37 | [ITER 3/2880] 0.02 Hours Elapsed 38 | [SENSOR] Writing data to register memory at address 0 39 | [SENSOR] Data written: 8 40 | [ITER 4/2880] 0.03 Hours Elapsed 41 | [SENSOR] Writing data to register memory at address 0 42 | [SENSOR] Data written: 10 43 | [ITER 5/2880] 0.04 Hours Elapsed 44 | [SENSOR] Writing data to register memory at address 0 45 | [SENSOR] Data written: 12 46 | [ITER 6/2880] 0.05 Hours Elapsed 47 | [SENSOR] Writing data to register memory at address 0 48 | [SENSOR] Data written: 14 49 | .... 50 | ``` 51 | 52 | If we let this example run for enough time and inspect the `messy_trace.log` we can see the battery level decreasing over time. This is because the sensor is periodically writing to the memory, which in turn is consuming energy from the battery. This is a simple example to show how the sensor memory can be accessed and how the sensor can be used to interact with the system. -------------------------------------------------------------------------------- /docs/flow.md: -------------------------------------------------------------------------------- 1 | This file is intended for explaining the flow of MESSY and what each step does. The flow is divided into the following steps: 2 | 3 | ```mermaid 4 | graph TD 5 | A[JSON Configuration File] --> B[GVSoC Application] 6 | B --> MESSY 7 | subgraph MESSY 8 | D[Generation of the SystemC/AMS model] --> E[Compilation] 9 | E --> F[Execution of the simulation] 10 | end 11 | ``` 12 | 13 | ## Definition of the JSON configuration file 14 | 15 | This step is crucial because it defines the whole system. The JSON configuration file allows the user to define the components, such as the [core](core.md), the [sensors](sensors.md), the [harvesters](harvesters.md), the [functional bus](functional-bus.md), the [power bus](power-bus.md) etc. 16 | All these blocks have a predifined structure in terms of input and output signals. However, the user can define for example the power consumption and the delay of each state of a [sensor](sensors.md). 17 | 18 | ## Writing the application that will run on GVSoC 19 | 20 | This is another very important step because it defines the entrypoint of our simulation. Specifically it defines the code that will be executed by our system. The application is written in C. You can find some examples in the `examples` folder of the MESSY repository. 21 | 22 | ## Running the MESSY tool 23 | 24 | The next step is to run the MESSY tool. The entrypoint is the `messy.py` script. This script expects two arguments: 25 | 26 | - `-f`: the file name of the chosen JSON configuration file 27 | - `-a`: the path of the folder of the application 28 | 29 | This script will do the following: 30 | 31 | 1. [Generate the SystemC/SystemC-AMS model](#generation-of-the-systemcams-models) 32 | 2. [Compile the SystemC/SystemC-AMS model and the application](#compilation) 33 | 3. [Execute the simulation](#execution-of-the-simulation) 34 | 35 | ### Generation of the SystemC/AMS models 36 | 37 | The first step of the MESSY tool is to generate the SystemC and SystemC-AMS. The components defined in the JSON should match the available components defined in the `messy/codegen/templates` folder. The latter contains all the templates of the components that are supported by MESSY. 38 | 39 | As already mentioned, most of these templates have a predefined structure in terms of input and output signals. However, through the JSON configuration file, the user can define custom characteristics of the components, such as the power consumption and the delay of each state of a sensor. 40 | 41 | The JSON is then parsed by the python script and the templates are filled with the necessary information and saved in the `messy/codegen/src` and `messy/codegen/include` folders respectively. 42 | 43 | For more details on these steps, please refer to the [codegen](codegen.md) documentation. 44 | 45 | ### Compilation 46 | 47 | The following step of the `messy.py` script is to compile both the GVSoC application and the SystemC/SystemC-AMS models. 48 | 49 | The GVSoC application is compiled using the Makefile command `make application`. Everything happens automatically, since the `messy.py` script launches a subprocess that executes the command. Following the compilation of the GVSoC application, the SystemC/SystemC-AMS models are compiled using the Makefile command `make run`. This command compiles the models and runs the simulation. Everything, as before, happens automatically, since the `messy.py` script launches a subprocess that executes the command. 50 | 51 | ### Execution of the simulation 52 | 53 | The execution, as already explained, is done by the Makefile command `make run`. This command compiles the SystemC/SystemC-AMS models and runs the simulation. 54 | -------------------------------------------------------------------------------- /docs/getting-started.md: -------------------------------------------------------------------------------- 1 | # Getting Started 2 | 3 | This document will guide you through the steps to get started with the project. 4 | 5 | ## Clone the repository 6 | 7 | First, clone the repository to your local machine: 8 | 9 | ```bash 10 | git clone https://github.com/eml-eda/messy 11 | ``` 12 | 13 | ## Build the docker image 14 | 15 | For details on what the Dockerfile does and how to build the image, please refer to the [Docker](docker.md) file. 16 | 17 | ## Run some examples 18 | 19 | There are a few examples in `examples` folder. Try one of them: 20 | 21 | - [Hello World](examples/hello-world.md) 22 | - [Periodic Sensor](examples/periodic-sensor.md) -------------------------------------------------------------------------------- /docs/harvesters.md: -------------------------------------------------------------------------------- 1 | Harvesters in MESSY are viewed in 2 different categories, batteries and sources. Batteries are more complex and contain by default AMS level simulation, while sources are defined in a simpler way. 2 | 3 | Currently the power scheduling tries to use all the power generated by the sources to contain the system load and eccesses are handled uniformly by the batteries. 4 | 5 | In the future, this aspect could be analyzed more and bring more control over power scheduling algorithms, 6 | 7 | ## Batteries 8 | 9 | The batteries are the most complex harvester in MESSY. The block representing a battery is the following: 10 | 11 | ![alt text](images/battery.png) 12 | 13 | Internally, it is modeled as a first-order RC circuit using the ELN (Electrical Linear Network) model available in SystemC-AMS. 14 | 15 | ![alt text](images/battery_circuit_model.png) 16 | 17 | ### Signals Summary 18 | 19 | A summary of the signals is shown in the table below: 20 | 21 | | Signal | Direction | Connected to | Description | 22 | | --- | --- | --- | --- | 23 | | i | input | Battery Converter | Current | 24 | | v | output | Battery Converter | Voltage | 25 | | soc | output | - | State of Charge | 26 | 27 | ### Input Signals 28 | 29 | The input signals are: 30 | 31 | - **i**: This signal is a double. 32 | 33 | ### Output Signals 34 | 35 | The output signals are: 36 | 37 | - **v**: This signal is a double. It represents the voltage of the battery. 38 | - **soc**: This signal is a double and represents the State of Charge of the battery. It is an output of the whole system, since it should be read from the top level module. 39 | 40 | ### Definition in the JSON file 41 | A battery is defined through several parameters, following an example of a battery called `panasonic_batt`: 42 | 43 | ```JSON 44 | "panasonic_batt" : { 45 | "harvester_type":"battery", 46 | "tracing":{ 47 | ... 48 | }, 49 | "vref":3.8, 50 | "soc_init" : 100, 51 | "soc_end" : 0, 52 | "capacity":32, 53 | "self_discharge":{ 54 | "resolution":{ 55 | "unit":"SC_S", 56 | "mult":1 57 | }, 58 | "value":0.001 59 | }, 60 | "converter" : { 61 | ... 62 | } 63 | } 64 | ``` 65 | 66 | The firs parameter is the `harvester_type` one, this has to be set to battery, then tracing can be set as well. 67 | 68 | To continue a slate of battery related paramters are present, these are: 69 | 70 | - `vref`: reference voltage in Volts 71 | - `soc_init`: starting State of Charge of the battery 72 | - `soc_end`: battery State of Charge that should trigger the termination of the simulation 73 | - `capacity`: battery nominal capacity in mAh 74 | - `self_discharge`: object that represent the self dischargment of a battery, parametrized by a resolution object and a `value`, each resolution time the value will be discharged from the battery 75 | - `converter`: optionally MESSY allows harvesters to define a converter (better described in [Converters](converters.md)) 76 | 77 | ## Photovoltaic Panel 78 | 79 | Another type of harvester supported by MESSY is the Photovoltaic cell. It's block is as follows: 80 | 81 | ![alt text](images/pv_panel.png) 82 | 83 | ### Signals Summary 84 | 85 | A summary of the signals is shown in the table below: 86 | 87 | | Signal | Direction | Connected to | Description | 88 | | --- | --- | --- | --- | 89 | | i | output | Photovoltaic Converter | Current | 90 | | v | output | Photovoltaic Converter | Voltage | 91 | 92 | ### Output Signals 93 | 94 | The output signals are: 95 | 96 | - **i**: This signal is a double. It represents the current generated by the photovoltaic cell. 97 | - **v**: This signal is a double. It represents the voltage of the photovoltaic cell. 98 | 99 | 100 | ### Definition in the JSON file 101 | 102 | The sources are defined similarly, here is an example: 103 | 104 | ```JSON 105 | "photovoltaic" : { 106 | "harvester_type" :"source", 107 | "vref" :{ 108 | "input_file":"input_files/gmonths.txt", 109 | "lut":{ 110 | "input_values":[250,500,750,1000], 111 | "voltage_values":[2.9367,3.0710,3.1334,3.1689] 112 | } 113 | }, 114 | "iref":{ 115 | "input_file":"input_files/gmonths.txt", 116 | "lut":{ 117 | "input_values":[250,500,750,1000], 118 | "current_values":[13.4031,27.2251,41.8848,56.7245] 119 | } 120 | }, 121 | "converter" : { 122 | ... 123 | } 124 | } 125 | ``` 126 | 127 | The firs parameter is the `harvester_type` one, this has to be set to source, then tracing can be set as well as a converter. 128 | 129 | The specific parameters regards the enhanced input values such as `iref` and `vref`, these input values can be set statically, or to simulate more precisely natural conditions, they can be retrieved from an input file and generated by a [LUT](lut.md). -------------------------------------------------------------------------------- /docs/how-to-build-docs.md: -------------------------------------------------------------------------------- 1 | # Documentation 2 | Clone the repository 3 | 4 | ```bash 5 | git clone https://github.com/eml-eda/messy 6 | ``` 7 | 8 | Change into the directory 9 | 10 | ```bash 11 | cd messy 12 | ``` 13 | Open this folder in Visual Studio Code (or in the terminal) 14 | 15 | Create a python virtual environment 16 | 17 | ```bash 18 | python3 -m venv doc_env 19 | ``` 20 | 21 | Activate the virtual environment 22 | 23 | ```bash 24 | source doc_env/bin/activate 25 | ``` 26 | 27 | Install the dependencies 28 | 29 | ```bash 30 | pip3 install -r requirements.txt 31 | ``` 32 | 33 | Serve the documentation 34 | 35 | ```bash 36 | mkdocs serve 37 | ``` 38 | 39 | Now you see something like this: 40 | 41 | ``` 42 | Serving on http://127.0.0.1:8000/ 43 | ``` 44 | 45 | Visual Studio Code should automatically setup port forwarding. So you can simply open a browser and go to [http://127.0.0.1:8000](http://127.0.0.1:8000) to see the documentation. 46 | 47 | -------------------------------------------------------------------------------- /docs/images/battery.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eml-eda/messy/026551c39c4b89e32f853e50fcc8b89ac9725d6f/docs/images/battery.pdf -------------------------------------------------------------------------------- /docs/images/battery.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eml-eda/messy/026551c39c4b89e32f853e50fcc8b89ac9725d6f/docs/images/battery.png -------------------------------------------------------------------------------- /docs/images/battery_circuit_model.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eml-eda/messy/026551c39c4b89e32f853e50fcc8b89ac9725d6f/docs/images/battery_circuit_model.png -------------------------------------------------------------------------------- /docs/images/battery_equivalent_circuit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eml-eda/messy/026551c39c4b89e32f853e50fcc8b89ac9725d6f/docs/images/battery_equivalent_circuit.png -------------------------------------------------------------------------------- /docs/images/core_functional.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eml-eda/messy/026551c39c4b89e32f853e50fcc8b89ac9725d6f/docs/images/core_functional.pdf -------------------------------------------------------------------------------- /docs/images/core_functional.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eml-eda/messy/026551c39c4b89e32f853e50fcc8b89ac9725d6f/docs/images/core_functional.png -------------------------------------------------------------------------------- /docs/images/debugging.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eml-eda/messy/026551c39c4b89e32f853e50fcc8b89ac9725d6f/docs/images/debugging.png -------------------------------------------------------------------------------- /docs/images/functional_bus.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eml-eda/messy/026551c39c4b89e32f853e50fcc8b89ac9725d6f/docs/images/functional_bus.pdf -------------------------------------------------------------------------------- /docs/images/functional_bus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eml-eda/messy/026551c39c4b89e32f853e50fcc8b89ac9725d6f/docs/images/functional_bus.png -------------------------------------------------------------------------------- /docs/images/logo.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eml-eda/messy/026551c39c4b89e32f853e50fcc8b89ac9725d6f/docs/images/logo.webp -------------------------------------------------------------------------------- /docs/images/messy_full_system_pv.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eml-eda/messy/026551c39c4b89e32f853e50fcc8b89ac9725d6f/docs/images/messy_full_system_pv.pdf -------------------------------------------------------------------------------- /docs/images/messy_full_system_pv.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eml-eda/messy/026551c39c4b89e32f853e50fcc8b89ac9725d6f/docs/images/messy_full_system_pv.png -------------------------------------------------------------------------------- /docs/images/messy_full_system_single_sensor.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eml-eda/messy/026551c39c4b89e32f853e50fcc8b89ac9725d6f/docs/images/messy_full_system_single_sensor.pdf -------------------------------------------------------------------------------- /docs/images/messy_full_system_single_sensor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eml-eda/messy/026551c39c4b89e32f853e50fcc8b89ac9725d6f/docs/images/messy_full_system_single_sensor.png -------------------------------------------------------------------------------- /docs/images/messy_full_systemc_double_sensors.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eml-eda/messy/026551c39c4b89e32f853e50fcc8b89ac9725d6f/docs/images/messy_full_systemc_double_sensors.pdf -------------------------------------------------------------------------------- /docs/images/messy_full_systemc_double_sensors.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eml-eda/messy/026551c39c4b89e32f853e50fcc8b89ac9725d6f/docs/images/messy_full_systemc_double_sensors.png -------------------------------------------------------------------------------- /docs/images/power_bus.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eml-eda/messy/026551c39c4b89e32f853e50fcc8b89ac9725d6f/docs/images/power_bus.pdf -------------------------------------------------------------------------------- /docs/images/power_bus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eml-eda/messy/026551c39c4b89e32f853e50fcc8b89ac9725d6f/docs/images/power_bus.png -------------------------------------------------------------------------------- /docs/images/pv_panel.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eml-eda/messy/026551c39c4b89e32f853e50fcc8b89ac9725d6f/docs/images/pv_panel.pdf -------------------------------------------------------------------------------- /docs/images/pv_panel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eml-eda/messy/026551c39c4b89e32f853e50fcc8b89ac9725d6f/docs/images/pv_panel.png -------------------------------------------------------------------------------- /docs/images/sensor_functional.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eml-eda/messy/026551c39c4b89e32f853e50fcc8b89ac9725d6f/docs/images/sensor_functional.pdf -------------------------------------------------------------------------------- /docs/images/sensor_functional.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eml-eda/messy/026551c39c4b89e32f853e50fcc8b89ac9725d6f/docs/images/sensor_functional.png -------------------------------------------------------------------------------- /docs/images/sensor_power.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eml-eda/messy/026551c39c4b89e32f853e50fcc8b89ac9725d6f/docs/images/sensor_power.pdf -------------------------------------------------------------------------------- /docs/images/sensor_power.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eml-eda/messy/026551c39c4b89e32f853e50fcc8b89ac9725d6f/docs/images/sensor_power.png -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 | # MESSY (Multi-layer Extra-functional Simulator in Systemc) 2 | 3 | drawing 4 | 5 | The availability of simulation platforms is a key ingredient for making RISC-V based hardware solutions pervasive. Simulators represent a cost-effective and scalable solution that enable rapid prototyping without the need for physical hardware. For these reasons, there is a growing availability of programs designed to simulate entire RISC-V chips. Some options include QEMU, Simulink, Renode, and GVSoC. However, these tools present some limitations. Most of them only simulate the computing core with scarce possibilities to perform system-level simulations. Moreover, they simulate only functional features, with poor support for extra-functional properties such as power consumption. This work tries to address these challenges by presenting a flexible simulator. 6 | 7 | MESSY is an open-source framework that integrates functional RISC-V simulation (achieved with GVSoC for the PULP cores) with SystemC-AMS (used to model extra-functional aspects, in detail power storage and distribution). The combination of GVSoC and SystemC-AMS in a single simulation framework allows to perform a DSE that is dependent on the mutual impact between functional and extra-functional aspects. 8 | 9 | # Getting Started 10 | To get started, please refer to the [Getting Started](getting-started.md) -------------------------------------------------------------------------------- /docs/ipxact-parsing.md: -------------------------------------------------------------------------------- 1 | # IPXACT Parsing 2 | 3 | For the purpose of working with ipxact designs instead of json designs a separate script has been created. 4 | 5 | It utilizes functions from the `messy/codegen/ipxact.py` module 6 | 7 | ## Usage 8 | 9 | The script that will be used is called `messy/codegen/codegen_ipxact.py` and can be used like this: 10 | 11 | ```shell 12 | python codegen_ipxact.py -f ipxact/pulp_open_pv_panel/pulp_open_design.xml 13 | ``` 14 | 15 | The **-f** flag specifies a path to the IPXACT top-level design file. 16 | 17 | ## Structure 18 | 19 | The parsing script works as follows: 20 | 21 | 1. At first the design file is read 22 | 2. Then all the components are extracted from it (function ***read_ipxact_design(file_path)***) 23 | 3. Then in for a cycle the resulting dictionary (of the same format as json) is assembled 24 | 4. For each component it's XML representation is converted to JSON (function ***xml_to_json(element) and parse_element(element)***) 25 | 5. And then it's format is adjusted to match the initial JSON format (functions ***process_bus(), process_core() etc.***) 26 | 6. For each component the version, library and vendor are checked (function ***sanity_check()***) 27 | 28 | !!! Warning 29 | - Component filenaming convention is **component_name** + "_component.xml" 30 | - It is needed for the correct work of the script 31 | 32 | -------------------------------------------------------------------------------- /docs/lut.md: -------------------------------------------------------------------------------- 1 | # LUT 2 | 3 | LookUp Tables are used in a wide variety of applications, in MESSY they are used to help describe converters and input values files. 4 | 5 | A LUT is defined through a JSON object containing as following: 6 | 7 | ```JSON 8 | "lut":{ 9 | "input_values":[0.6559,...], 10 | "second_variable":[64.92,...] 11 | } 12 | ``` 13 | 14 | In this object the user shall set in `input_values` an array of values representing the input variable(tension, current, nits, torque etc.) and finally should call the second field (`efficiency_values`, `voltage_values` and `current_values`) with an array of the other values. -------------------------------------------------------------------------------- /docs/messy.md: -------------------------------------------------------------------------------- 1 | An example of the full system, with all the necessary blocks and connections, is the following: 2 | 3 | ![alt text](images/full-system.png) 4 | 5 | -------------------------------------------------------------------------------- /docs/power-bus.md: -------------------------------------------------------------------------------- 1 | The power bus is another key component of MESSY. It is the bus where all power components are connected to. Its structure is as follows: 2 | 3 | ![alt text](images/power_bus.png) 4 | 5 | ## Signals Summary 6 | 7 | A summary of the signals is shown in the table below: 8 | 9 | | Signal | Direction | Connected to | Description | 10 | | --- | --- | --- | --- | 11 | | core_current | input | Core Converter | Current | 12 | | core_voltage | input | Core Converter | Voltage | 13 | | voltage_sensor | input | Sensor Power | Voltage of the Sensor | 14 | | sensor_current | input | Sensor Converter | Current | 15 | | current_sources | input | Source Converter | Current | 16 | | current_batteries | output | Battery Converter | Current | 17 | 18 | ## Input Signals 19 | 20 | The input signals are: 21 | 22 | - **core_current**: This signal is a double. It comes from the Core converter and it indicates the current cosumed from the Core. 23 | - **core_voltage**: This signal is a double. It comes from the Power instance of the core and it indicates the voltage of the core. 24 | - **voltage_sensor**: This signal is an array of doubles. Its size is equal to the number of sensors. It comes from the each sensor power instance and it indicates the voltage of the corresponding sensor. 25 | - **sensor_current**: This signal is an array of doubles. Its size is equal to the number of sensors. It comes from the each sensor converter and it indicates the current consumed by the corresponding sensor. 26 | - **current_sources**: This signal is an array of double. Its size is equal to the number of sources. It comes from the each source converter and it indicates the current provided by the corresponding source. 27 | 28 | ## Output Signals 29 | 30 | The output signals are: 31 | 32 | - **current_batteries**: This signal is an array of double. Its size is equal to the number of batteries. It contains the sum of all the contributions of the currents consumed/produced by each sensor/source divided by the number of batteries. The code looks something like this: 33 | 34 | ```cpp 35 | void Power_bus::processing() { 36 | double tmp_i; 37 | total_current = 0; 38 | 39 | for (int i = 0; i < NUM_SENSORS; i++) { 40 | tmp_i = current_sensors[i].read(); 41 | total_current += tmp_i; //(1)! 42 | } 43 | 44 | tmp_i = core_current.read(); 45 | 46 | total_current += tmp_i; //(2)! 47 | 48 | #if NUM_SOURCES > 0 49 | for (int i = 0; i < NUM_SOURCES; i++) { 50 | tmp_i = current_sources[i].read(); 51 | total_current -= tmp_i; //(3)! 52 | } 53 | #endif 54 | 55 | #if NUM_BATTERIES > 0 56 | for (int i = 0; i < NUM_BATTERIES; i++) 57 | current_batteries[i].write(total_current / NUM_BATTERIES); //(4)! 58 | #endif 59 | } 60 | ``` 61 | 62 | 1. Sum all the current contributions from the sensors 63 | 2. Add the current from the core 64 | 3. Subtract from the total current the current provided by each source 65 | 4. Write the total current divided by the number of batteries to each battery converter 66 | 67 | 68 | ## Definition in the JSON file 69 | 70 | 71 | -------------------------------------------------------------------------------- /docs/resolution.md: -------------------------------------------------------------------------------- 1 | # Resolution 2 | 3 | A resolution object in MESSY is defined following SystemC timing units, a resolution is comprised of a unit measure (`SC_MS`, `SC_NS`, `SC_PS`) and a multiplier value, below an example that defines 30 seconds: 4 | 5 | ```JSON 6 | "resolution":{ 7 | "unit":"SC_S", 8 | "mult":30 9 | } 10 | ``` -------------------------------------------------------------------------------- /docs/simulink/messy_double_sensors.slx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eml-eda/messy/026551c39c4b89e32f853e50fcc8b89ac9725d6f/docs/simulink/messy_double_sensors.slx -------------------------------------------------------------------------------- /docs/simulink/messy_pv.slx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eml-eda/messy/026551c39c4b89e32f853e50fcc8b89ac9725d6f/docs/simulink/messy_pv.slx -------------------------------------------------------------------------------- /docs/simulink/messy_single_sensor.slx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eml-eda/messy/026551c39c4b89e32f853e50fcc8b89ac9725d6f/docs/simulink/messy_single_sensor.slx -------------------------------------------------------------------------------- /docs/timing.md: -------------------------------------------------------------------------------- 1 | This file is intended to describe how the timing between SystemC and GvSoC works. This is very important to understand, since it allows to grasp all the details about the communication between the two worlds. Everything mainly happens in the `core.cpp` and in the respective adapter (in this case `adapter_gvsoc.cpp`). The whole communication process is made possible thanks to some API that the chosen ISS (i.e GvSoC) exposes. Particularly the `step_until()` function is what actually advances the simulation inside GvSoc. This function executes the SoC functionality and returns the timestamp of the following event in the GVSoC queue. 2 | 3 | This function, has been wrapped in the `adapter_gvsoc.cpp` into a function called `exec_events_at(timestamp)`, which simply calls the `step_until()` function and returns the timestamp of the following event of the SoC. This is the function: 4 | 5 | ``` cpp 6 | int64_t AdapterGvsoc::exec_events_at(int64_t timestamp){ 7 | return gvsoc->step_until(timestamp); 8 | } 9 | ``` 10 | 11 | In the case you want to add a new ISS, you should implement the `exec_events_at(timestamp)` function in the respective adapter. This function should call a functionally equivalent method of the ISS you are using. 12 | 13 | The simulation advances in the following way: 14 | 15 | 1. Given the current SystemC timestamp, the `exec_events_at(timestamp)` function is called. This function advances the simulation in the ISS until the timestamp given as argument and returns the timestamp of the following event, that is called `next_timestamp`. 16 | 2. The `next_timestamp` is then used to advance the SystemC simulation until that timestamp. This is done by calling the `wait()` function of the SystemC kernel. 17 | 3. This process is repeated until the simulation ends. 18 | 19 | A view of the sequence diagram of the timing between SystemC and GvSoC is shown below: 20 | 21 | ```mermaid 22 | sequenceDiagram 23 | participant SystemC 24 | participant Adapter 25 | participant ISS 26 | SystemC->>Adapter: exec_events_at(timestamp) 27 | Adapter->>ISS: step_until(timestamp) 28 | ISS-->>Adapter: next_timestamp 29 | Adapter->>SystemC: wait(next_timestamp) 30 | ``` 31 | 32 | -------------------------------------------------------------------------------- /docs/tracing.md: -------------------------------------------------------------------------------- 1 | # Traces 2 | 3 | The system supports several traces, these can be defined in the initial part of the configuration and used by sensors, converters, core and harvesters later on. 4 | 5 | The initial configuration can be done as follows: 6 | 7 | ```JSON 8 | "tracing":{ 9 | "messy_trace":{ 10 | "filename":"messy_trace.log", 11 | "resolution":{ 12 | "unit":"SC_MS", 13 | "mult":1 14 | } 15 | } 16 | } 17 | ``` 18 | 19 | Here a trace(multiple can be set) of name `messy_trace` is defined, the `filename` parameters define where the trace will be saved and finally the `resolution` describes the logging frequency through a resolution object better described in [Resolution](resolution.md). 20 | 21 | To attach a trace to a sensor, harvester or what else during the configuration of that object the user shall set the `tracing` argument and describe for the related trace what to trace, for example below we want to trace the current of a sensor: 22 | 23 | ```JSON 24 | "tracing":{ 25 | "messy_trace":{ 26 | "mic_click_I":"current" 27 | } 28 | } 29 | ``` 30 | 31 | Here the tracing is set only for a trace called `messy_trace` and for this trace only one parameter of the sensor is logged, this is the current and is saved as `mic_click_I` on the log. 32 | 33 | Currently voltages, current and State of Charge values can be traced quite easily. -------------------------------------------------------------------------------- /docs/what-is-messy.md: -------------------------------------------------------------------------------- 1 | MESSY is an open-source framework that integrates functional RISC-V simulation (achieved with GVSoC for the PULP cores) with SystemC-AMS (used to model extra-functional aspects, in detail power storage and distribution). The combination of GVSoC and SystemC-AMS in a single simulation framework allows to perform a DSE that is dependent on the mutual impact between functional and extra-functional aspects. 2 | 3 | In simpler words, it allows the user to simulate a complete system that contains both the CPU and the sensors, batteries etc. This is useful to understand how the system behaves in different conditions and to optimize it. The modularity of MESSY allows to define the system using a JSON configuration file. 4 | Thanks to SystemC-AMS, it is possible to model the power consumption of each component of the system. 5 | 6 | A brief view of the system that can be generated thanks to MESSY is shown in the following image: 7 | 8 | -------------------------------------------------------------------------------- /examples/.gitignore: -------------------------------------------------------------------------------- 1 | chip.cluster.* 2 | chip.soc.* 3 | *view.gtkw 4 | debug_binary* 5 | nets -------------------------------------------------------------------------------- /examples/helloworld/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2022 GreenWaves Technologies SAS 2 | # All rights reserved. 3 | # 4 | # Redistribution and use in source and binary forms, with or without 5 | # modification, are permitted provided that the following conditions are met: 6 | # 7 | # 1. Redistributions of source code must retain the above copyright notice, 8 | # this list of conditions and the following disclaimer. 9 | # 2. Redistributions in binary form must reproduce the above copyright 10 | # notice, this list of conditions and the following disclaimer in the 11 | # documentation and/or other materials provided with the distribution. 12 | # 3. Neither the name of GreenWaves Technologies SAS nor the names of its 13 | # contributors may be used to endorse or promote products derived from 14 | # this software without specific prior written permission. 15 | # 16 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | # POSSIBILITY OF SUCH DAMAGE. 27 | 28 | cmake_minimum_required(VERSION 3.19) 29 | 30 | ############################################################################### 31 | # Panel Control 32 | ############################################################################### 33 | set(TARGET_NAME "helloworld") 34 | set(TARGET_SRCS helloworld.c) 35 | 36 | ############################################################################### 37 | # CMake pre initialization 38 | ############################################################################### 39 | 40 | set(CONFIG_GAP_SDK_HOME $ENV{GAP_SDK_HOME}) 41 | include($ENV{GAP_SDK_HOME}/utils/cmake/setup.cmake) 42 | 43 | project(${TARGET_NAME} C ASM) 44 | add_executable(${TARGET_NAME} ${TARGET_SRCS}) 45 | 46 | # For validation purposes 47 | if (DEFINED USE_CUSTOM_XIP) 48 | if (${USE_CUSTOM_XIP} EQUAL 1) 49 | set(CONFIG_XIP y) 50 | set(CONFIG_XIP_VIRTUAL_ADDRESS 0x20000000) 51 | set(CONFIG_XIP_PAGE_SIZE 2) 52 | set(CONFIG_XIP_PAGE_NUMBER 12) 53 | endif() 54 | endif() 55 | 56 | ############################################################################### 57 | # CMake post initialization 58 | ############################################################################### 59 | setupos(${TARGET_NAME}) 60 | -------------------------------------------------------------------------------- /examples/helloworld/Kconfig: -------------------------------------------------------------------------------- 1 | source "$(GAP_SDK_HOME)/utils/kconfig/Kconfig" 2 | -------------------------------------------------------------------------------- /examples/helloworld/Makefile: -------------------------------------------------------------------------------- 1 | # User Test 2 | #------------------------------------ 3 | APP = test 4 | # App sources 5 | APP_SRCS = helloworld.c 6 | # App includes 7 | APP_INC = 8 | # Compiler flags 9 | APP_CFLAGS = 10 | # Linker flags 11 | APP_LDFLAGS = 12 | 13 | # Custom linker 14 | APP_LINK_SCRIPT = 15 | 16 | include $(RULES_DIR)/pmsis_rules.mk 17 | -------------------------------------------------------------------------------- /examples/helloworld/README.rst: -------------------------------------------------------------------------------- 1 | Hello World 2 | =========== 3 | 4 | Requirements 5 | ------------ 6 | 7 | No specific requirement. This example should run without issue on all chips/boards/OSes. 8 | 9 | Description 10 | ----------- 11 | 12 | This example is a classic Hello World. 13 | It prints an hello world string on all available cores. 14 | 15 | How to run 16 | ---------- 17 | 18 | .. tabs:: 19 | 20 | .. tab:: Makefile 21 | 22 | .. tabs:: 23 | 24 | .. tab:: Real board 25 | 26 | .. code-block:: bash 27 | 28 | make clean all run platform=board 29 | 30 | .. tab:: GVSoC 31 | 32 | .. code-block:: bash 33 | 34 | make clean all run platform=gvsoc 35 | 36 | .. tab:: CMake 37 | 38 | .. tabs:: 39 | 40 | .. tab:: Real board 41 | 42 | .. code-block:: bash 43 | 44 | cmake -B build 45 | cmake --build build --target menuconfig # Select your board in the menu 46 | cmake --build build --target run 47 | 48 | .. tab:: GVSoC 49 | 50 | .. code-block:: bash 51 | 52 | cmake -B build 53 | cmake --build build --target menuconfig # Select GVSoC in the menu 54 | cmake --build build --target run 55 | 56 | Results 57 | ------- 58 | 59 | You should have an output looking like this (order may vary): 60 | 61 | .. code-block:: 62 | 63 | *** PMSIS HelloWorld *** 64 | 65 | Entering main controller 66 | [32 0] Hello World! 67 | Cluster master core entry 68 | [0 2] Hello World! 69 | [0 0] Hello World! 70 | [0 1] Hello World! 71 | [0 3] Hello World! 72 | [0 4] Hello World! 73 | [0 5] Hello World! 74 | [0 6] Hello World! 75 | [0 7] Hello World! 76 | Cluster master core exit 77 | Bye ! 78 | 79 | Code 80 | ---- 81 | 82 | .. tabs:: 83 | 84 | .. tab:: C 85 | 86 | .. literalinclude:: helloworld.c 87 | :language: c 88 | 89 | .. tab:: Makefile 90 | 91 | .. literalinclude:: Makefile 92 | :language: Makefile 93 | 94 | .. tab:: CMakelist 95 | 96 | .. literalinclude:: CMakeLists.txt 97 | :language: CMake 98 | 99 | .. tab:: KConfig 100 | 101 | .. literalinclude:: Kconfig 102 | :language: KConfig 103 | -------------------------------------------------------------------------------- /examples/helloworld/gaptest.yml: -------------------------------------------------------------------------------- 1 | name: helloworld 2 | variants: 3 | gvsoc: 4 | chip: gap9 5 | board: gap9evk 6 | platform: gvsoc 7 | os: freertos 8 | builder: cmake 9 | flags: ~ 10 | 11 | board: 12 | chip: gap9 13 | board: gap9evk 14 | platform: board 15 | os: freertos 16 | builder: cmake 17 | flags: ~ 18 | 19 | gvsoc_xip: 20 | chip: gap9 21 | board: gap9evk 22 | platform: gvsoc 23 | os: freertos 24 | builder: cmake 25 | flags: 26 | - CONFIG_XIP=1 27 | 28 | gvsoc_custom_xip: 29 | chip: gap9 30 | board: gap9evk 31 | platform: gvsoc 32 | os: freertos 33 | builder: cmake 34 | flags: 35 | - USE_CUSTOM_XIP=1 36 | 37 | board_custom_xip: 38 | chip: gap9 39 | board: gap9evk 40 | platform: board 41 | os: freertos 42 | builder: cmake 43 | flags: 44 | - USE_CUSTOM_XIP=1 45 | 46 | gap10_gvsoc: 47 | chip: gap10 48 | board: gap10virtual 49 | platform: gvsoc 50 | os: freertos 51 | builder: cmake 52 | flags: ~ 53 | -------------------------------------------------------------------------------- /examples/helloworld/helloworld.c: -------------------------------------------------------------------------------- 1 | /* PMSIS includes */ 2 | #include "pmsis.h" 3 | 4 | /* Task executed by cluster cores. */ 5 | void cluster_helloworld(void *arg) 6 | { 7 | uint32_t core_id = pi_core_id(), cluster_id = pi_cluster_id(); 8 | printf("[%d %d] Hello World!\n", cluster_id, core_id); 9 | } 10 | 11 | /* Cluster main entry, executed by core 0. */ 12 | void cluster_delegate(void *arg) 13 | { 14 | printf("Cluster master core entry\n"); 15 | /* Task dispatch to cluster cores. */ 16 | pi_cl_team_fork(pi_cl_cluster_nb_cores(), cluster_helloworld, arg); 17 | printf("Cluster master core exit\n"); 18 | } 19 | 20 | /* Program Entry. */ 21 | int main(void) 22 | { 23 | printf("\n\n\t *** PMSIS HelloWorld ***\n\n"); 24 | printf("Entering main controller\n"); 25 | 26 | uint32_t errors = 0; 27 | uint32_t core_id = pi_core_id(), cluster_id = pi_cluster_id(); 28 | printf("[%d %d] Hello World!\n", cluster_id, core_id); 29 | 30 | struct pi_device cluster_dev; 31 | struct pi_cluster_conf cl_conf; 32 | 33 | /* Init cluster configuration structure. */ 34 | pi_cluster_conf_init(&cl_conf); 35 | cl_conf.id = 0; /* Set cluster ID. */ 36 | // Enable the special icache for the master core 37 | //cl_conf.icache_conf = PI_CLUSTER_MASTER_CORE_ICACHE_ENABLE | 38 | // // Enable the prefetch for all the cores, it's a 9bits mask (from bit 2 to bit 10), each bit correspond to 1 core 39 | // PI_CLUSTER_ICACHE_PREFETCH_ENABLE | 40 | // // Enable the icache for all the cores 41 | // PI_CLUSTER_ICACHE_ENABLE; 42 | 43 | /* Configure & open cluster. */ 44 | pi_open_from_conf(&cluster_dev, &cl_conf); 45 | if (pi_cluster_open(&cluster_dev)) 46 | { 47 | printf("Cluster open failed !\n"); 48 | pmsis_exit(-1); 49 | } 50 | 51 | /* Prepare cluster task and send it to cluster. */ 52 | struct pi_cluster_task cl_task; 53 | 54 | pi_cluster_send_task_to_cl(&cluster_dev, pi_cluster_task(&cl_task, cluster_delegate, NULL)); 55 | 56 | pi_cluster_close(&cluster_dev); 57 | 58 | printf("Bye !\n"); 59 | 60 | return errors; 61 | } 62 | -------------------------------------------------------------------------------- /examples/helloworld/sdk.config: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /examples/periodic_sensors/Makefile: -------------------------------------------------------------------------------- 1 | # User Test 2 | #------------------------------------ 3 | APP = test 4 | # App sources 5 | APP_SRCS = periodic_sensors.c 6 | # App includes 7 | APP_INC = 8 | # Compiler flags 9 | APP_CFLAGS = 10 | # Linker flags 11 | APP_LDFLAGS = 12 | 13 | # Custom linker 14 | APP_LINK_SCRIPT = 15 | 16 | include $(RULES_DIR)/pmsis_rules.mk 17 | -------------------------------------------------------------------------------- /examples/periodic_sensors/periodic_sensors.c: -------------------------------------------------------------------------------- 1 | /* PMSIS includes */ 2 | #include "pmsis.h" 3 | #ifdef GAP_SDK 4 | #define AXI_BASE 0x80000000 5 | #else 6 | #define AXI_BASE 0x20000000 7 | #endif 8 | 9 | #define NUM_ITERS 2880 // 1 day 10 | #define PERIOD_US 3000000 // 30 sec 11 | #define PERIOD_HR 0.00833333 12 | 13 | /* Program Entry. */ 14 | int main(void) 15 | { 16 | printf("\n\n\t *** PMSIS HelloWorld ***\n\n"); 17 | printf("Entering main controller\n"); 18 | 19 | uint32_t errors = 10; 20 | uint32_t core_id = pi_core_id(), cluster_id = pi_cluster_id(); 21 | 22 | int *mic_click_sensor = (volatile int *)AXI_BASE + 0x0; 23 | for (int i = 0; i < NUM_ITERS; i++) 24 | { 25 | printf("[ITER %d/%d] %.2f Hours Elapsed\n", i, NUM_ITERS, i * PERIOD_HR); 26 | 27 | // Random placeholder computation 28 | *mic_click_sensor = (i + 1) * 2; 29 | 30 | // Periodic Wait 31 | pi_time_wait_us(PERIOD_US); 32 | } 33 | 34 | return errors; 35 | } -------------------------------------------------------------------------------- /examples/read_sensor/Makefile: -------------------------------------------------------------------------------- 1 | # User Test 2 | #------------------------------------ 3 | APP = test 4 | # App sources 5 | APP_SRCS = read_sensor.c 6 | # App includes 7 | APP_INC = 8 | # Compiler flags 9 | APP_CFLAGS = 10 | # Linker flags 11 | APP_LDFLAGS = 12 | 13 | # Custom linker 14 | APP_LINK_SCRIPT = 15 | 16 | include $(RULES_DIR)/pmsis_rules.mk 17 | -------------------------------------------------------------------------------- /examples/read_sensor/read_sensor.c: -------------------------------------------------------------------------------- 1 | /* PMSIS includes */ 2 | #include "pmsis.h" 3 | #ifdef GAP_SDK 4 | #define AXI_BASE 0x80000000 5 | #else 6 | #define AXI_BASE 0x20000000 7 | #endif 8 | #define MEMORY_SENSOR_SIZE 256 9 | #define ITER_SIZE 128 10 | 11 | typedef struct messy_ex_t{ 12 | uint8_t idx; 13 | uint64_t val; 14 | }messy_ex; 15 | 16 | int main(void) 17 | { 18 | printf("\n\n\t *** PMSIS HelloWorld ***\n\n"); 19 | printf("Entering main controller\n"); 20 | 21 | uint32_t errors = 10; 22 | uint32_t core_id = pi_core_id(), cluster_id = pi_cluster_id(); 23 | printf("[%d %d] Hello World!\n", cluster_id, core_id); 24 | 25 | uint8_t* sensor_addr = AXI_BASE+0x0; 26 | printf("\n\nMessy uint8 sensor test, there should be %d iters\n\n",MEMORY_SENSOR_SIZE); 27 | for(int i=0;iidx,messy_sensor->val); 48 | messy_sensor++; 49 | } 50 | 51 | return errors; 52 | } 53 | -------------------------------------------------------------------------------- /examples/read_write_multiple_sensors/Makefile: -------------------------------------------------------------------------------- 1 | # User Test 2 | #------------------------------------ 3 | APP = test 4 | # App sources 5 | APP_SRCS = read_write_multiple_sensor.c 6 | # App includes 7 | APP_INC = 8 | # Compiler flags 9 | APP_CFLAGS = 10 | # Linker flags 11 | APP_LDFLAGS = 12 | 13 | # Custom linker 14 | APP_LINK_SCRIPT = 15 | 16 | include $(RULES_DIR)/pmsis_rules.mk 17 | -------------------------------------------------------------------------------- /examples/read_write_multiple_sensors/read_write_multiple_sensor.c: -------------------------------------------------------------------------------- 1 | /* PMSIS includes */ 2 | #include "pmsis.h" 3 | #ifdef GAP_SDK 4 | #define AXI_BASE 0x80000000 5 | #else 6 | #define AXI_BASE 0x20000000 7 | #endif 8 | #define NUM_ITERS 10 9 | /* Program Entry. */ 10 | int main(void) 11 | { 12 | printf("\n\n\t *** PMSIS HelloWorld ***\n\n"); 13 | printf("Entering main controller\n"); 14 | 15 | uint32_t errors = 10; 16 | uint32_t core_id = pi_core_id(), cluster_id = pi_cluster_id(); 17 | printf("[%d %d] Hello World!\n", cluster_id, core_id); 18 | 19 | int* mic_click_sensor = (volatile int *)AXI_BASE+0x0; 20 | int* mic_click_sensor2 = (volatile int *)AXI_BASE+256; 21 | 22 | for(int i=0;i 2 | 5 | 6 | POLITO 7 | pulp_open 8 | battery 9 | 1.0 10 | 11 | 12 | 13 | tlms-interface 14 | system-c 15 | pulp_open 16 | battery 17 | 18 | 19 | harvester_type 20 | battery 21 | 22 | 23 | vref 24 | 3.8 25 | 26 | 27 | soc_init 28 | 100 29 | 30 | 31 | soc_end 32 | 0 33 | 34 | 35 | capacity 36 | 32 37 | 38 | 39 | 40 | 41 | fs-core-interface 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | SC_S 51 | 1 52 | 53 | 0.001 54 | 55 | harvester 56 | battery 57 | 58 | 59 | SoC 60 | 61 | 62 | 63 | 64 | 65 | 66 | En 67 | 68 | In 69 | 70 | 71 | 72 | V 73 | 74 | provides 75 | 76 | 77 | double 78 | interface 79 | 80 | 81 | 82 | 83 | 84 | I 85 | 86 | requires 87 | 88 | 89 | double 90 | interface 91 | 92 | 93 | 94 | 95 | 96 | SOC 97 | 98 | provides 99 | 100 | 101 | double 102 | interface 103 | 104 | 105 | 106 | 107 | 108 | 109 | -------------------------------------------------------------------------------- /messy/codegen/ipxact/pulp_open_pv_panel/pulp_open_battery_converter_component.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | POLITO 6 | pulp_open 7 | battery_converter 8 | 1.0 9 | 10 | 11 | 12 | interface 13 | tlm-interface 14 | 15 | 16 | 17 | 18 | 19 | tlms-interface 20 | system-c 21 | pulp_open 22 | battery_converter 23 | 24 | 25 | input_variable 26 | current 27 | 28 | 29 | out_dir 30 | true 31 | 32 | 33 | 34 | 35 | fs-battery-converter-interface 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | V_in 46 | 47 | requires 48 | 49 | 50 | double 51 | interface 52 | 53 | 54 | 55 | 56 | 57 | 58 | I_in 59 | 60 | requires 61 | 62 | 63 | double 64 | interface 65 | 66 | 67 | 68 | 69 | 70 | 71 | V_out 72 | 73 | provides 74 | 75 | 76 | double 77 | interface 78 | 79 | 80 | 81 | 82 | 83 | 84 | I_out 85 | 86 | provides 87 | 88 | 89 | double 90 | interface 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 200, 300, 400] 105 | 106 | 107 | [88.0165, 90.9091, 91.1157, 92.1488, 92.7686, 92.7686, 93.595, 93.8017, 92.9752, 93.1818, 93.595, 94.2149, 94.4215, 94.6281, 94.4215, 94.4215, 94.4215, 94.4215, 94.6281, 94.4215, 94.6281, 96.6942] 108 | 109 | 110 | 111 | 112 | 113 | 114 | -------------------------------------------------------------------------------- /messy/codegen/ipxact/pulp_open_pv_panel/pulp_open_core_component.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | POLITO 6 | pulp_open 7 | core 8 | 1.0 9 | 10 | 11 | 12 | interface 13 | tlm-interface 14 | 15 | 16 | 17 | 18 | 19 | tlms-interface 20 | system-c 21 | pulp_open 22 | core 23 | 24 | 25 | vref 26 | 1.8 27 | 28 | 29 | iss 30 | gvsoc 31 | 32 | 33 | 34 | 35 | fs-core-interface 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | V 46 | 47 | provides 48 | 49 | 50 | double 51 | interface 52 | 53 | 54 | 55 | 56 | 57 | 58 | I 59 | 60 | provides 61 | 62 | 63 | double 64 | interface 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | current 78 | 79 | 80 | 81 | ./gvsoc_deps/gvsoc_config.json 82 | 83 | 84 | /chip/axi_proxy 85 | 86 | 87 | core 88 | 89 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /messy/codegen/ipxact/pulp_open_pv_panel/pulp_open_mic_sensor_component.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | POLITO 6 | pulp_open 7 | mic_sensor 8 | 1.0 9 | 10 | 11 | 12 | interface 13 | tlm-interface 14 | 15 | 16 | 17 | 18 | 19 | tlms-interface 20 | system-c 21 | pulp_open 22 | mic_sensor 23 | 24 | 25 | vref 26 | 3.3 27 | 28 | 29 | power 30 | true 31 | 32 | 33 | register_memory 34 | 256 35 | 36 | 37 | 38 | 39 | fs-mic_sensor-interface 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | V 50 | 51 | provides 52 | 53 | 54 | double 55 | interface 56 | 57 | 58 | 59 | 60 | 61 | 62 | I 63 | 64 | provides 65 | 66 | 67 | double 68 | interface 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 0.12 84 | 30 85 | 86 | 87 | 88 | 89 | 0.16 90 | 30 91 | 92 | 93 | 94 | 95 | 0.002 96 | 97 | 98 | 99 | load 100 | 101 | 102 | 103 | 104 | -------------------------------------------------------------------------------- /messy/codegen/ipxact/pulp_open_pv_panel/pulp_open_photovoltaic_component.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | POLITO 7 | pulp_open 8 | photovoltaic 9 | 1.0 10 | 11 | 12 | 13 | tlms-interface 14 | system-c 15 | pulp_open 16 | photovoltaic 17 | 18 | 19 | harvester_type 20 | source 21 | 22 | 23 | 24 | 25 | fs-core-interface 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | input_files/gmonths.txt 34 | 35 | [250,500,750,1000] 36 | [2.9367,3.0710,3.1334,3.1689] 37 | 38 | 39 | 40 | input_files/gmonths.txt 41 | 42 | [250,500,750,1000] 43 | [13.4031,27.2251,41.8848,56.7245] 44 | 45 | 46 | 47 | 48 | 49 | 50 | En 51 | 52 | In 53 | 54 | 55 | 56 | V 57 | 58 | provides 59 | 60 | 61 | double 62 | interface 63 | 64 | 65 | 66 | 67 | 68 | I 69 | 70 | provides 71 | 72 | 73 | double 74 | interface 75 | 76 | 77 | 78 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /messy/codegen/ipxact/pulp_open_pv_panel/pulp_open_photovoltaic_converter_component.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | POLITO 6 | pulp_open 7 | photovoltaic_converter 8 | 1.0 9 | 10 | 11 | 12 | interface 13 | tlm-interface 14 | 15 | 16 | 17 | 18 | 19 | tlms-interface 20 | system-c 21 | pulp_open 22 | battery_converter 23 | 24 | 25 | input_variable 26 | voltage 27 | 28 | 29 | out_dir 30 | false 31 | 32 | 33 | 34 | 35 | fs-battery-converter-interface 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | V_in 46 | 47 | requires 48 | 49 | 50 | double 51 | interface 52 | 53 | 54 | 55 | 56 | 57 | 58 | I_in 59 | 60 | requires 61 | 62 | 63 | double 64 | interface 65 | 66 | 67 | 68 | 69 | 70 | V_out 71 | 72 | provides 73 | 74 | 75 | double 76 | interface 77 | 78 | 79 | 80 | 81 | 82 | 83 | I_out 84 | 85 | provides 86 | 87 | 88 | double 89 | interface 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | [0.6559,0.7397,0.8363,0.9588,1.0941,1.1907,1.4291,1.7642,1.8544,1.9961,2.4278,2.5954,2.6534,2.7307,2.7758,2.7887,2.9691,3.1688,3.3428,3.5876,3.7874,3.9678,4.1353,4.3673,4.5928,4.7668,4.9729] 104 | 105 | 106 | [64.92,69.37,74.44,78.79,81.87,83.69,84.77,85.86,86.04,85.95,89.31,90.66,83.14,75.71,70.73,68.46,68.64,68.19,66.83,63.93,61.75,59.31,57.22,54.77,52.42,50.51,47.70] 107 | 108 | 109 | 110 | 111 | 112 | 113 | -------------------------------------------------------------------------------- /messy/codegen/ipxact/pulp_open_pv_panel/pulp_open_sensors_component.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | POLITO 6 | pulp_open 7 | sensors 8 | 1.0 9 | 10 | 11 | 12 | interface 13 | tlm-interface 14 | 15 | 16 | 17 | 18 | 19 | tlms-interface 20 | system-c 21 | pulp_open 22 | sensors 23 | 24 | 25 | fs-harvesters-interface 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | V_out 36 | 37 | provides 38 | 39 | 40 | double 41 | interface 42 | 43 | 44 | 45 | 46 | 47 | 48 | I_out 49 | 50 | provides 51 | 52 | 53 | double 54 | interface 55 | 56 | 57 | 58 | 59 | 60 | 61 | V_in 62 | 63 | requires 64 | 65 | 66 | double 67 | interface 68 | 69 | 70 | 71 | 72 | 73 | 74 | I_in 75 | 76 | requires 77 | 78 | 79 | double 80 | interface 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | -------------------------------------------------------------------------------- /messy/codegen/pulp_open.json: -------------------------------------------------------------------------------- 1 | { 2 | "resolution":"SC_MS", 3 | "tracing":{ 4 | "messy_trace":{ 5 | "filename":"messy_trace.log", 6 | "resolution":{ 7 | "unit":"SC_MS", 8 | "mult":1 9 | } 10 | } 11 | }, 12 | "bus":{ 13 | "vref":3.3 14 | }, 15 | "core":{ 16 | "vref":1.8, 17 | "iss":"gvsoc", 18 | "config":{ 19 | "path":"./gvsoc_deps/gvsoc_config.json", 20 | "axi_path":"/chip/axi_proxy" 21 | }, 22 | "tracing":{ 23 | "messy_trace":{ 24 | "core_I":"current" 25 | } 26 | }, 27 | "converter":{ 28 | "input_variable":"current", 29 | "out_dir":false, 30 | "lut":{ 31 | "input_values":[ 32 | 0.001, 0.002, 0.003, 0.004, 0.005, 0.006, 0.007, 0.008, 0.009, 0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.07, 0.08, 0.09, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 200, 300, 400 33 | ], 34 | "efficiency_values":[ 35 | 42.7039, 50.2146, 64.1631, 64.8069, 71.6738, 73.8197, 74.4635, 75.3219, 77.0386, 77.897, 82.4034, 84.1202, 84.7639, 85.4077, 86.0515, 86.2661, 86.2661, 86.4807, 86.9099, 87.7682, 87.7682, 87.9828, 87.9828, 88.1974, 87.9828, 88.1974, 88.1974, 88.1974, 88.412, 88.6266, 87.5536, 87.5536, 87.7682, 88.6266, 88.8412, 88.8412, 89.0558, 90.1288, 90.3433, 90.5579, 90.5579, 90.7725, 90.7725, 91.2017, 90.7725, 90.7725, 90.1288, 88.412, 84.9785 36 | ] 37 | } 38 | } 39 | }, 40 | "peripherals":{ 41 | "sensors" : { 42 | "mic_click": { 43 | "power": true, 44 | "tracing":{ 45 | "messy_trace":{ 46 | "mic_click_I":"current" 47 | } 48 | }, 49 | "vref": 3.3, 50 | "register_memory" : 256, 51 | "states":{ 52 | "read" : { 53 | "current" : "0.12", 54 | "delay" : "30" 55 | }, 56 | "write": { 57 | "current" : "0.16", 58 | "delay" : "30" 59 | }, 60 | "idle":{ 61 | "current" : "0.002" 62 | } 63 | } 64 | } 65 | }, 66 | "harvesters":{ 67 | "battery" : { 68 | "harvester_type":"battery", 69 | "tracing":{ 70 | "messy_trace":{ 71 | "battery":"SoC" 72 | } 73 | }, 74 | "vref":3.8, 75 | "soc_init" : 100, 76 | "soc_end" : 0, 77 | "capacity":32, 78 | "self_discharge":{ 79 | "resolution":{ 80 | "unit":"SC_S", 81 | "mult":1 82 | }, 83 | "value":0.001 84 | }, 85 | "converter" : { 86 | "input_variable":"current", 87 | "out_dir":true, 88 | "lut":{ 89 | "input_values":[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 200, 300, 400], 90 | "efficiency_values":[88.0165, 90.9091, 91.1157, 92.1488, 92.7686, 92.7686, 93.595, 93.8017, 92.9752, 93.1818, 93.595, 94.2149, 94.4215, 94.6281, 94.4215, 94.4215, 94.4215, 94.4215, 94.6281, 94.4215, 94.6281, 96.6942] 91 | } 92 | } 93 | } 94 | } 95 | } 96 | } -------------------------------------------------------------------------------- /messy/codegen/pulp_open_double_sensor.json: -------------------------------------------------------------------------------- 1 | { 2 | "resolution":"SC_MS", 3 | "tracing":{ 4 | "messy_trace":{ 5 | "filename":"messy_trace.log", 6 | "resolution":{ 7 | "unit":"SC_MS", 8 | "mult":1 9 | } 10 | } 11 | }, 12 | "bus":{ 13 | "vref":3.3 14 | }, 15 | "core":{ 16 | "vref":1.8, 17 | "iss":"gvsoc", 18 | "config":{ 19 | "path":"./gvsoc_deps/gvsoc_config.json", 20 | "axi_path":"/chip/axi_proxy" 21 | }, 22 | "tracing":{ 23 | "messy_trace":{ 24 | "core_I":"current" 25 | } 26 | }, 27 | "converter":{ 28 | "input_variable":"current", 29 | "out_dir":false, 30 | "lut":{ 31 | "input_values":[ 32 | 0.001, 0.002, 0.003, 0.004, 0.005, 0.006, 0.007, 0.008, 0.009, 0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.07, 0.08, 0.09, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 200, 300, 400 33 | ], 34 | "efficiency_values":[ 35 | 42.7039, 50.2146, 64.1631, 64.8069, 71.6738, 73.8197, 74.4635, 75.3219, 77.0386, 77.897, 82.4034, 84.1202, 84.7639, 85.4077, 86.0515, 86.2661, 86.2661, 86.4807, 86.9099, 87.7682, 87.7682, 87.9828, 87.9828, 88.1974, 87.9828, 88.1974, 88.1974, 88.1974, 88.412, 88.6266, 87.5536, 87.5536, 87.7682, 88.6266, 88.8412, 88.8412, 89.0558, 90.1288, 90.3433, 90.5579, 90.5579, 90.7725, 90.7725, 91.2017, 90.7725, 90.7725, 90.1288, 88.412, 84.9785 36 | ] 37 | } 38 | } 39 | }, 40 | "peripherals":{ 41 | "sensors" : { 42 | "mic_click": { 43 | "power": true, 44 | "tracing":{ 45 | "messy_trace":{ 46 | "mic_click_I":"current" 47 | } 48 | }, 49 | "vref": 3.3, 50 | "register_memory" : 256, 51 | "states":{ 52 | "read" : { 53 | "current" : "0.12", 54 | "delay" : "30" 55 | }, 56 | "write": { 57 | "current" : "0.16", 58 | "delay" : "30" 59 | }, 60 | "idle":{ 61 | "current" : "0.002" 62 | } 63 | } 64 | }, 65 | "mic_click2": { 66 | "power": true, 67 | "tracing":{ 68 | "messy_trace":{ 69 | "mic_click_I":"current" 70 | } 71 | }, 72 | "vref": 3.3, 73 | "register_memory" : 256, 74 | "states":{ 75 | "read" : { 76 | "current" : "0.12", 77 | "delay" : "30" 78 | }, 79 | "write": { 80 | "current" : "0.16", 81 | "delay" : "30" 82 | }, 83 | "idle":{ 84 | "current" : "0.002" 85 | } 86 | } 87 | } 88 | }, 89 | "harvesters":{ 90 | "battery" : { 91 | "harvester_type":"battery", 92 | "tracing":{ 93 | "messy_trace":{ 94 | "battery":"SoC" 95 | } 96 | }, 97 | "vref":3.8, 98 | "soc_init" : 100, 99 | "soc_end" : 0, 100 | "capacity":32, 101 | "self_discharge":{ 102 | "resolution":{ 103 | "unit":"SC_S", 104 | "mult":1 105 | }, 106 | "value":0.001 107 | }, 108 | "converter" : { 109 | "input_variable":"current", 110 | "out_dir":true, 111 | "lut":{ 112 | "input_values":[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 200, 300, 400], 113 | "efficiency_values":[88.0165, 90.9091, 91.1157, 92.1488, 92.7686, 92.7686, 93.595, 93.8017, 92.9752, 93.1818, 93.595, 94.2149, 94.4215, 94.6281, 94.4215, 94.4215, 94.4215, 94.4215, 94.6281, 94.4215, 94.6281, 96.6942] 114 | } 115 | } 116 | } 117 | } 118 | } 119 | } -------------------------------------------------------------------------------- /messy/codegen/pulp_open_pv_panel.json: -------------------------------------------------------------------------------- 1 | { 2 | "resolution":"SC_MS", 3 | "tracing":{ 4 | "messy_trace":{ 5 | "filename":"messy_trace.log", 6 | "resolution":{ 7 | "unit":"SC_MS", 8 | "mult":1 9 | } 10 | } 11 | }, 12 | "bus":{ 13 | "vref":3.3 14 | }, 15 | "core":{ 16 | "vref":1.8, 17 | "iss":"gvsoc", 18 | "config":{ 19 | "path":"./gvsoc_deps/gvsoc_config.json", 20 | "axi_path":"/chip/axi_proxy" 21 | }, 22 | "tracing":{ 23 | "messy_trace":{ 24 | "core_I":"current" 25 | } 26 | }, 27 | "converter":{ 28 | "input_variable":"current", 29 | "out_dir":false, 30 | "lut":{ 31 | "input_values":[ 32 | 0.001, 0.002, 0.003, 0.004, 0.005, 0.006, 0.007, 0.008, 0.009, 0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.07, 0.08, 0.09, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 200, 300, 400 33 | ], 34 | "efficiency_values":[ 35 | 42.7039, 50.2146, 64.1631, 64.8069, 71.6738, 73.8197, 74.4635, 75.3219, 77.0386, 77.897, 82.4034, 84.1202, 84.7639, 85.4077, 86.0515, 86.2661, 86.2661, 86.4807, 86.9099, 87.7682, 87.7682, 87.9828, 87.9828, 88.1974, 87.9828, 88.1974, 88.1974, 88.1974, 88.412, 88.6266, 87.5536, 87.5536, 87.7682, 88.6266, 88.8412, 88.8412, 89.0558, 90.1288, 90.3433, 90.5579, 90.5579, 90.7725, 90.7725, 91.2017, 90.7725, 90.7725, 90.1288, 88.412, 84.9785 36 | ] 37 | } 38 | } 39 | }, 40 | "peripherals":{ 41 | "sensors" : { 42 | "mic_click": { 43 | "power": true, 44 | "tracing":{ 45 | "messy_trace":{ 46 | "mic_click_I":"current" 47 | } 48 | }, 49 | "vref": 3.3, 50 | "register_memory" : 256, 51 | "states":{ 52 | "read" : { 53 | "current" : "0.12", 54 | "delay" : "30" 55 | }, 56 | "write": { 57 | "current" : "0.16", 58 | "delay" : "30" 59 | }, 60 | "idle":{ 61 | "current" : "0.002" 62 | } 63 | } 64 | } 65 | }, 66 | "harvesters":{ 67 | "battery" : { 68 | "harvester_type":"battery", 69 | "tracing":{ 70 | "messy_trace":{ 71 | "battery":"SoC" 72 | } 73 | }, 74 | "vref":3.8, 75 | "soc_init" : 100, 76 | "soc_end" : 0, 77 | "capacity":32, 78 | "self_discharge":{ 79 | "resolution":{ 80 | "unit":"SC_S", 81 | "mult":1 82 | }, 83 | "value":0.001 84 | }, 85 | "converter" : { 86 | "input_variable":"current", 87 | "out_dir":true, 88 | "lut":{ 89 | "input_values":[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 200, 300, 400], 90 | "efficiency_values":[88.0165, 90.9091, 91.1157, 92.1488, 92.7686, 92.7686, 93.595, 93.8017, 92.9752, 93.1818, 93.595, 94.2149, 94.4215, 94.6281, 94.4215, 94.4215, 94.4215, 94.4215, 94.6281, 94.4215, 94.6281, 96.6942] 91 | } 92 | } 93 | }, 94 | "photovoltaic" : { 95 | "harvester_type" :"source", 96 | "vref" :{ 97 | "input_file":"input_files/gmonths.txt", 98 | "lut":{ 99 | "input_values":[250,500,750,1000], 100 | "voltage_values":[2.9367,3.0710,3.1334,3.1689] 101 | } 102 | }, 103 | "iref":{ 104 | "input_file":"input_files/gmonths.txt", 105 | "lut":{ 106 | "input_values":[250,500,750,1000], 107 | "current_values":[13.4031,27.2251,41.8848,56.7245] 108 | } 109 | }, 110 | "converter" : { 111 | "input_variable":"voltage", 112 | "out_dir":false, 113 | "lut":{ 114 | "input_values":[0.6559,0.7397,0.8363,0.9588,1.0941,1.1907,1.4291,1.7642,1.8544,1.9961,2.4278,2.5954,2.6534,2.7307,2.7758,2.7887,2.9691,3.1688,3.3428,3.5876,3.7874,3.9678,4.1353,4.3673,4.5928,4.7668,4.9729], 115 | "efficiency_values":[64.92,69.37,74.44,78.79,81.87,83.69,84.77,85.86,86.04,85.95,89.31,90.66,83.14,75.71,70.73,68.46,68.64,68.19,66.83,63.93,61.75,59.31,57.22,54.77,52.42,50.51,47.70] 116 | } 117 | } 118 | } 119 | } 120 | } 121 | } -------------------------------------------------------------------------------- /messy/codegen/templates/.gitignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eml-eda/messy/026551c39c4b89e32f853e50fcc8b89ac9725d6f/messy/codegen/templates/.gitignore -------------------------------------------------------------------------------- /messy/codegen/templates/include/adapters/adapter_gvsoc_gap9.hpp: -------------------------------------------------------------------------------- 1 | #ifndef __ADAPTER_GVSOC_H 2 | #define __ADAPTER_GVSOC_H 3 | 4 | #include 5 | #include 6 | // vtable issues? how to build abstract class? 7 | // #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #define LOG_REQUESTS 1 14 | #ifdef LOG_REQUESTS 15 | #include 16 | #endif 17 | 18 | class AdapterGvsocGap9 : public gv::Io_user, public vp::Notifier { 19 | public: 20 | int64_t exec_events_at(int64_t timestamp); 21 | double get_power_at(int64_t timestamp); 22 | void close(); 23 | void startup(); 24 | void custom_reply(MessyRequest *req); 25 | void access(gv::Io_request *req); 26 | void grant(gv::Io_request *req); 27 | void reply(gv::Io_request *req); 28 | void notify_stop(int64_t time); 29 | void notify_run(int64_t time); 30 | MessyRequest *get_messy_request_from_gvsoc(gv::Io_request *req); 31 | AdapterGvsocGap9(); 32 | //~AdapterGvsocGap9() {}; 33 | bool finished = false; 34 | 35 | private: 36 | int closed = 0; 37 | gv::Io_binding *axi; 38 | Gvsoc_launcher *gvsoc; 39 | #ifdef LOG_REQUESTS 40 | std::ofstream request_addresses; 41 | std::ofstream request_sizes; 42 | #endif 43 | }; 44 | 45 | #endif -------------------------------------------------------------------------------- /messy/codegen/templates/include/adapters/iss_adapter.hpp: -------------------------------------------------------------------------------- 1 | #ifndef __ISS_ADAPTER_H 2 | #define __ISS_ADAPTER_H 3 | 4 | #include 5 | #include 6 | 7 | /** 8 | * @class ISS_Adapter 9 | * @brief Abstract base class for an ISS (Instruction Set Simulator) adapter. 10 | * 11 | * The ISS_Adapter class provides an interface for interacting with an ISS. It includes 12 | * methods for executing events, retrieving power consumption, handling requests, and 13 | * managing the simulation state. 14 | */ 15 | class ISS_Adapter { 16 | public: 17 | /** 18 | * @brief Executes events at the specified timestamp. 19 | * 20 | * This function advances the ISS simulation to the specified timestamp. 21 | * 22 | * @param timestamp The timestamp at which to execute events. 23 | * @return The next timestamp at which events should be executed. 24 | */ 25 | virtual int64_t exec_events_at(int64_t timestamp); 26 | 27 | /** 28 | * @brief Closes the ISS adapter. 29 | * 30 | * This function performs any necessary cleanup and closes the ISS adapter. 31 | */ 32 | virtual void close(); 33 | 34 | /** 35 | * @brief Destructor for ISS_Adapter. 36 | * 37 | * This virtual destructor ensures that derived classes can clean up resources properly. 38 | */ 39 | virtual ~ISS_Adapter() {}; 40 | 41 | /** 42 | * @brief Starts up the ISS adapter. 43 | * 44 | * This function initializes and starts up the ISS adapter. 45 | */ 46 | virtual void startup(); 47 | 48 | /** 49 | * @brief Custom reply handler for MessyRequest. 50 | * 51 | * This function handles the reply for a MessyRequest. 52 | * 53 | * @param req Pointer to the MessyRequest to be handled. 54 | */ 55 | virtual void custom_reply(MessyRequest *req); 56 | 57 | /** 58 | * @brief Retrieves the power consumption at the specified timestamp. 59 | * 60 | * This function retrieves the power consumption from the ISS simulation at the specified timestamp. 61 | * 62 | * @param timestamp The timestamp at which to retrieve power consumption. 63 | * @return The power consumption at the specified timestamp. 64 | */ 65 | virtual double get_power_at(int64_t timestamp); 66 | 67 | bool finished = false; /**< Flag indicating whether the ISS simulation has finished */ 68 | }; 69 | 70 | #endif -------------------------------------------------------------------------------- /messy/codegen/templates/include/config.hpp: -------------------------------------------------------------------------------- 1 | #ifndef __CONFIG__H__ 2 | #define __CONFIG__H__ 3 | 4 | /** 5 | * @brief Reference voltage for the bus. 6 | */ 7 | #define VREF_BUS ${bus["vref"]} 8 | 9 | /** 10 | * @brief Number of sensors available in the system. 11 | */ 12 | #define NUM_SENSORS ${len(peripherals["sensors"])} 13 | 14 | /** 15 | * @brief Number of sources in the harvester peripherals. 16 | */ 17 | #define NUM_SOURCES ${len([harv_name for harv_name,harv in peripherals["harvesters"].items() if harv["harvester_type"]=="source"])} 18 | 19 | /** 20 | * @brief Number of batteries in the harvester peripherals. 21 | */ 22 | #define NUM_BATTERIES ${len([harv_name for harv_name,harv in peripherals["harvesters"].items() if harv["harvester_type"]=="battery"])} 23 | 24 | /** 25 | * @brief Total number of harvesters in the system. 26 | */ 27 | #define NUM_HARVESTERS ${len(peripherals["harvesters"])} 28 | 29 | /** 30 | * @brief Resolution of the simulation. 31 | * 32 | * The resolution of the simulation should be compliant with what SystemC can handle. The allowed values are: 33 | * 34 | * - SC_SEC: 1s 35 | * - SC_MS: 1ms 36 | * 37 | * The preferred value is SC_MS, as it provides a good trade-off between simulation time and accuracy. 38 | */ 39 | #define SIM_RESOLUTION ${resolution} 40 | 41 | /** 42 | * @brief Length of the simulation. The measurement unit is defined by SIM_RESOLUTION. 43 | */ 44 | #define SIM_LEN 1000000 45 | 46 | % for sensor_name,sensor in peripherals["sensors"].items(): 47 | 48 | /** 49 | * @brief Base address for the ${sensor_name} sensor. 50 | */ 51 | #define ${sensor_name}_BASE_ADDRESS ${sensor["base"]} 52 | 53 | /** 54 | * @brief Enum defining the states for the ${sensor_name} sensor. 55 | */ 56 | typedef enum { 57 | ${sensor_name}_OFF__, 58 | % for s_state_name in sensor["states"]: 59 | ${sensor_name}_${s_state_name}, 60 | % endfor 61 | } ${sensor_name}_states; 62 | % endfor 63 | 64 | #endif -------------------------------------------------------------------------------- /messy/codegen/templates/include/converter/load_converter.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /** 5 | * @class Load_converter 6 | * @brief SystemC-AMS module representing a load converter. 7 | * 8 | * The Load_converter module models a converter that takes current and voltage inputs 9 | * and outputs the current delivered to the power bus. It includes methods for setting 10 | * attributes, initialization, processing, and setting the efficiency factor. 11 | */ 12 | SCA_TDF_MODULE(Load_converter) { 13 | // Input Port 14 | sca_tdf::sca_in current_in; /**< Input current from the power instance */ 15 | sca_tdf::sca_in voltage_in; /**< Input voltage from the power instance */ 16 | 17 | // Output Port 18 | sca_tdf::sca_out current_out; /**< Output current to the power bus */ 19 | 20 | /** 21 | * @brief Constructor for Load_converter. 22 | * 23 | * Initializes the input and output ports with their respective names. 24 | */ 25 | SCA_CTOR(Load_converter) : current_in("Current_from_power_instance"), 26 | voltage_in("Voltage_from_power_instance"), 27 | current_out("Current_to_power_bus") {} 28 | 29 | void set_attributes(); 30 | void initialize(); 31 | void processing(); 32 | 33 | /** 34 | * @brief Sets the efficiency factor of the converter. 35 | * 36 | * This function sets the efficiency factor used in the conversion process. 37 | * 38 | * @param k The efficiency factor to be set. 39 | */ 40 | void set_efficency(double k); 41 | 42 | Load_converter() {} 43 | 44 | private: 45 | double efficency_factor = 1.0; /**< Efficiency factor for the conversion process */ 46 | }; -------------------------------------------------------------------------------- /messy/codegen/templates/include/converter/lut_converter.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | /** 6 | * @def SIZE_CONV_DCDC_${name} 7 | * @brief Defines the size of the lookup table for the converter. 8 | */ 9 | #define SIZE_CONV_DCDC_${name} ${len(lut["input_values"])} 10 | 11 | /** 12 | * @brief Lookup table for input values of the converter. 13 | * 14 | * This static array contains the input values for the converter's lookup table. 15 | */ 16 | static const double ${input_variable}_CONV_${name}[SIZE_CONV_DCDC_${name}] = {${str(lut["input_values"])[1:len(str(lut["input_values"]))-1]}}; 17 | 18 | /** 19 | * @brief Lookup table for efficiency values of the converter. 20 | * 21 | * This static array contains the efficiency values corresponding to the input values 22 | * for the converter's lookup table. 23 | */ 24 | static const double ETA_CONV_${name}[SIZE_CONV_DCDC_${name}] = {${str(lut["efficiency_values"])[1:len(str(lut["efficiency_values"]))-1]}}; 25 | 26 | 27 | /** 28 | * @class ${name}_converter 29 | * @brief SystemC-AMS module representing a converter. 30 | * 31 | * The ${name}_converter module models a converter that takes current and voltage inputs 32 | * from the ${name} and outputs the current delivered to the BUS. It uses lookup tables 33 | * to determine the efficiency of the conversion process, and in fact it contains a LUT object as a private variable. 34 | */ 35 | SCA_TDF_MODULE(${name}_converter) 36 | { 37 | // Input Ports 38 | sca_tdf::sca_in current_in; /**< Input current from the ${'core_power' if name == 'core' else 'power_bus' if name == 'battery' else 'unknown_source'}. ${'The input current is the current coming from the power_bus that should go to charge or discharge the battery, but before going to the battery, it passes through the battery_converter.' if name == 'battery' else ''} */ 39 | sca_tdf::sca_in voltage_in; ///< Input voltage from the ${'core_power' if name == 'core' else name} 40 | 41 | // Output Port 42 | sca_tdf::sca_out current_out; /**< Output current to the ${'power_bus' if name == 'core' else 'battery' if name == 'battery' else 'unknown_source'} */ 43 | 44 | /** 45 | * @brief Constructor for ${name}_converter. 46 | * 47 | * Initializes the input and output ports with their respective names. 48 | */ 49 | SCA_CTOR(${name}_converter): current_in("current_in"), 50 | voltage_in("voltage_in"), 51 | current_out("current_out") {}; 52 | 53 | void set_attributes(); 54 | void initialize(); 55 | void processing(); 56 | 57 | /** 58 | * @brief Constructor for ${name}_converter. 59 | * 60 | * Initializes the input and output ports with their respective names. 61 | */ 62 | ${name}_converter(){} 63 | 64 | private: 65 | /** 66 | * @brief Lookup table for efficiency values. 67 | * 68 | * This LUT object is used to store and retrieve efficiency values based on the input values. 69 | */ 70 | LUT lut_eta = LUT(${input_variable}_CONV_${name}, ETA_CONV_${name}, SIZE_CONV_DCDC_${name}); 71 | }; 72 | -------------------------------------------------------------------------------- /messy/codegen/templates/include/core.hpp: -------------------------------------------------------------------------------- 1 | #ifndef __MESSY_CORE_H__ 2 | #define __MESSY_CORE_H__ 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | class Core : public sc_module { 11 | public: 12 | // Input Ports 13 | sc_core::sc_in request_go; /**< Flag indicating if the request can proceed */ 14 | sc_core::sc_in request_value; /**< Value of the request */ 15 | sc_core::sc_in idx_sensor; /**< Index of the sensor */ 16 | 17 | // Output Ports 18 | sc_core::sc_out request_address; /**< Address of the request */ 19 | sc_core::sc_out request_data; /**< Data of the request */ 20 | sc_core::sc_out request_size; /**< Size of the request */ 21 | sc_core::sc_out functional_bus_flag; /**< Flag for the functional bus */ 22 | sc_core::sc_out request_ready; /**< Flag indicating if the request is ready */ 23 | 24 | 25 | // Power Port 26 | sc_core::sc_out power_signal; /**< Power signal output */ 27 | 28 | // Variables 29 | int simulation_iters = 0; /**< Number of simulation iterations. It gets incremented every time the continue_messy method is executed */ 30 | double tot_power = 0.0; /**< Total power consumed. It gets accumulated every time the continue_messy is executed, by summing to the total power the instant power returned by gvsoc */ 31 | 32 | /** 33 | * @brief Runs the core functionality. 34 | */ 35 | void run(); 36 | 37 | /** 38 | * @brief Closes the core functionality and the SystemC simulation. 39 | */ 40 | void close(); 41 | 42 | /** 43 | * @brief Runs the next SystemC process. 44 | */ 45 | void run_next_sc(); 46 | 47 | /** 48 | * @brief Continues the messy process. 49 | * 50 | * @param handle_req_queue Flag indicating whether to handle the request queue. 51 | */ 52 | void continue_messy(bool handle_req_queue); 53 | 54 | /** 55 | * @brief Handles the request queue. 56 | */ 57 | void handle_req_queue(); 58 | 59 | /** 60 | * @brief Requests a delay. 61 | * 62 | * @param start_time The start time of the delay. 63 | * @param time_to_skip The amount of time to skip. 64 | * @param resolution The resolution of the delay. 65 | */ 66 | void request_delay(double start_time, int time_to_skip, sc_core::sc_time_unit resolution); 67 | 68 | /** 69 | * @brief Handles a request. 70 | * 71 | * @param req Pointer to the MessyRequest to be handled. 72 | */ 73 | void handle_req(MessyRequest *req); 74 | 75 | /** 76 | * @brief Handles an access request from the gvsoc side. It gets called when an access from the gvsoc side is reaching us. 77 | * 78 | * @param req Pointer to the MessyRequest to be accessed. 79 | */ 80 | void access_request(MessyRequest *req); 81 | 82 | /** 83 | * @brief Handles a granted request. It gets called when one of our access gets granted. 84 | * 85 | * @param req Pointer to the MessyRequest that was granted. 86 | */ 87 | void grant_req(MessyRequest *req); 88 | 89 | 90 | /** 91 | * @brief Handles a response to a request. It gets called when one of our access gets its response. 92 | * 93 | * @param req Pointer to the MessyRequest that received a response. 94 | */ 95 | void reply_to_req(MessyRequest *req); 96 | 97 | /** 98 | * @brief Constructor for Core. 99 | * 100 | * Initializes the input and output ports with their respective names. 101 | */ 102 | SC_CTOR(Core) : request_address("Address_From_Core_to_Func_Bus"), 103 | request_data("Data_From_Core_to_Func_Bus"), 104 | functional_bus_flag("Flag_From_Core_to_Func_Bus"), 105 | request_ready("Master_Ready_to_Func_Bus"), 106 | request_go("Master_GO_to_Func_Bus"), 107 | request_value("Data_form_Bus_to_Master"), 108 | power_signal("Func_to_Power_signal"), 109 | idx_sensor("selected_sensor_of_request") { 110 | iss_adapter = (${adapter_class}*) new ${adapter_class}(); 111 | SC_THREAD(run); 112 | sensitive << request_go; 113 | } 114 | 115 | ~Core() { 116 | delete iss_adapter; 117 | } 118 | 119 | private: 120 | int64_t next_timestamp = 0; /**< The next timestamp for scheduling events in the simulation */ 121 | int64_t sc_timestamp = 0; /**< The current SystemC timestamp */ 122 | ${adapter_class} *iss_adapter; /**< Pointer to the ISS (Instruction Set Simulator) adapter */ 123 | }; 124 | #endif -------------------------------------------------------------------------------- /messy/codegen/templates/include/core_power.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #define V_CORE ${vref} 7 | 8 | 9 | /** 10 | * @class Core_power 11 | * @brief This module models the power consumption of the core in a SystemC-AMS environment. 12 | * 13 | * This TDF module calculates the voltage and current states of the core based on functional signals 14 | * and sends the results to the power bus. It interacts with the functional core model through the 15 | * input `func_signal` and produces the `voltage_state` and `current_state` outputs. 16 | */ 17 | SCA_TDF_MODULE(Core_power) 18 | { 19 | Core* core; 20 | //Data from Functional Instance 21 | sca_tdf::sc_in func_signal; 22 | //Data to Power Bus 23 | sca_tdf::sca_out voltage_state; 24 | sca_tdf::sca_out current_state; 25 | //sca_tdf::sc_out power_to_therm; 26 | 27 | /** 28 | * @brief Constructor for the Core_power module. 29 | * 30 | * Initializes the input and output signal names for tracing and connecting to other modules. 31 | */ 32 | SCA_CTOR(Core_power): 33 | func_signal("State_of_Power_From_Functional"), 34 | voltage_state("Voltage_trace_to_Power_Bus"), 35 | current_state("Current_trace_to_Power_Bus") 36 | {} 37 | 38 | void set_attributes(); 39 | void initialize(); 40 | void processing(); 41 | 42 | Core_power(){} 43 | }; -------------------------------------------------------------------------------- /messy/codegen/templates/include/functional_bus.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /** 5 | * @class Functional_bus 6 | * @brief SystemC module representing a functional bus. 7 | * 8 | * The Functional_bus module handles communication between a master and multiple sensors. 9 | * It processes requests from the master and routes data to and from the sensors. 10 | */ 11 | SC_MODULE(Functional_bus) { 12 | 13 | // Input Port 14 | sc_core::sc_in request_address; /**< Address of the request from the master */ 15 | sc_core::sc_in request_data; /**< Data of the request from the master */ 16 | sc_core::sc_in flag_from_core; /**< Flag indicating the type of request from the master */ 17 | sc_core::sc_in request_ready; /**< Flag indicating if the request is ready */ 18 | sc_core::sc_in request_size; /**< Size of the request from the master */ 19 | sc_core::sc_in data_input_sensor[NUM_SENSORS]; /**< Data input from sensors */ 20 | sc_core::sc_in go_sensors[NUM_SENSORS]; /**< Size of the request from the master */ 21 | 22 | // Output Port 23 | sc_core::sc_out request_value; /**< Data of the response to the master */ 24 | sc_core::sc_out request_go; /**< Flag indicating if the bus is ready to process the request */ 25 | sc_core::sc_out idx_sensor; /**< Index of the selected sensor */ 26 | sc_core::sc_out address_out_sensor[NUM_SENSORS]; /**< Address output to sensors */ 27 | sc_core::sc_out data_out_sensor[NUM_SENSORS]; /**< Data output to sensors */ 28 | sc_core::sc_out size_out_sensor[NUM_SENSORS]; /**< Size of the data output to sensors */ 29 | sc_core::sc_out flag_out_sensor[NUM_SENSORS]; /**< Flags indicating the type of data output to sensors */ 30 | sc_core::sc_out ready_sensor[NUM_SENSORS]; /**< Flags indicating if sensors are ready */ 31 | 32 | 33 | /** 34 | * @brief Constructor for Functional_bus. 35 | * 36 | * Initializes the input and output ports and sets up the sensitivity list for the SC_THREAD. 37 | */ 38 | SC_CTOR(Functional_bus) : request_address("Address_from_Master_to_Bus"), 39 | request_data("Data_from_Master_to_Bus"), 40 | flag_from_core("Flag_from_Master_to_Bus"), 41 | request_ready("Ready_from_Master_to_Bus"), 42 | request_value("Data_from_Bus_to_Master"), 43 | request_go("Go_from_Bus_to_Master"), 44 | idx_sensor("selected_sensor_from_request") { 45 | SC_THREAD(processing_data); 46 | sensitive << request_ready; 47 | for (int i = 0; i < NUM_SENSORS; i++) { 48 | sensitive << go_sensors[i]; 49 | } 50 | } 51 | 52 | /** 53 | * @brief Thread for processing data. 54 | * 55 | * This function is responsible for processing the data received from the master 56 | * and routing it to the appropriate sensor. 57 | */ 58 | void processing_data(); 59 | 60 | /** 61 | * @brief Function for handling responses. 62 | * 63 | * This function is responsible for handling the responses from the sensors 64 | * and sending them back to the master. 65 | */ 66 | void response(); 67 | 68 | private: 69 | int selected_sensor = 0; /**< Index of the currently selected sensor */ 70 | 71 | Functional_bus() {} 72 | }; -------------------------------------------------------------------------------- /messy/codegen/templates/include/lut.hpp: -------------------------------------------------------------------------------- 1 | #ifndef LUT_H 2 | #define LUT_H 3 | 4 | /** 5 | * @class LUT 6 | * @brief A class that implements a lookup table (LUT) for querying values based on keys. 7 | */ 8 | class LUT 9 | { 10 | public: 11 | /** 12 | * @brief Constructor for the LUT class. 13 | * 14 | * Initializes the lookup table with the given key and value arrays. 15 | * 16 | * @param k A pointer to an array of keys. 17 | * @param v A pointer to an array of corresponding values. 18 | * @param sz The number of key-value pairs in the lookup table. 19 | */ 20 | LUT(const double* k, const double* v, int sz); 21 | 22 | /** 23 | * @brief Destructor for the LUT class. 24 | * 25 | * Cleans up any dynamically allocated memory used by the LUT. 26 | */ 27 | ~LUT(); 28 | 29 | /** 30 | * @brief Retrieves the value corresponding to a given query key. 31 | * 32 | * @param query The key for which the corresponding value is to be found. 33 | * @return The value associated with the query key, or a default value if the key is not found. 34 | */ 35 | double get_val(double query); 36 | 37 | private: 38 | double* key; ///< Pointer to the array of keys. 39 | double* val; ///< Pointer to the array of values. 40 | int size; ///< The size of the lookup table (number of key-value pairs). 41 | }; 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /messy/codegen/templates/include/messy_request.hpp: -------------------------------------------------------------------------------- 1 | #ifndef __MESSY_REQUEST__H__ 2 | #define __MESSY_REQUEST__H__ 3 | 4 | #include 5 | 6 | /** 7 | * @class MessyRequest 8 | * @brief Represents a request with address, data, read/write flag, handle, and size. 9 | * 10 | * The MessyRequest class encapsulates the details of a request that includes 11 | * an address, a pointer to the data, a flag indicating whether it is a read 12 | * request, a pointer to a handle, and the size of the request. This class is 13 | * used to manage and process requests in a system that handles multiple 14 | * requests, such as a memory management system or a network request handler. 15 | */ 16 | class MessyRequest { 17 | public: 18 | long long int addr; /**< Address of the request */ 19 | unsigned int *data; /**< Pointer to the data */ 20 | bool read_req; /**< Flag indicating if it's a read request */ 21 | unsigned int *handle_c; /**< Pointer to the handle */ 22 | unsigned int size; /**< Size of the request */ 23 | 24 | /** 25 | * @brief Constructor for MessyRequest. 26 | * 27 | * This constructor initializes a MessyRequest object with the given 28 | * parameters. It sets the address, data pointer, read request flag, 29 | * handle pointer, and size of the request. 30 | * 31 | * @param address_t Address of the request. 32 | * @param data_t Pointer to the data. 33 | * @param read_req_t Flag indicating if it's a read request. 34 | * @param handle_c_t Pointer to the handle. 35 | * @param size_t Size of the request. 36 | */ 37 | MessyRequest(long long int address_t, unsigned int *data_t, bool read_req_t, unsigned int *handle_c_t, unsigned int size_t) { 38 | addr = address_t; 39 | data = data_t; 40 | read_req = read_req_t; 41 | handle_c = handle_c_t; 42 | size = size_t; 43 | }; 44 | }; 45 | 46 | /** 47 | * @brief Vector to store core requests. 48 | * 49 | * This static vector is used to store pointers to MessyRequest objects. It 50 | * acts as a queue for managing the requests that need to be processed. 51 | */ 52 | static std::vector core_requests; 53 | 54 | /** 55 | * @brief Adds a request to the core requests. 56 | * 57 | * This function takes a pointer to a MessyRequest object and adds it to the 58 | * core_requests vector. The core_requests vector is used to store all the 59 | * requests that need to be processed. 60 | * 61 | * @param req Pointer to the MessyRequest to be added. 62 | */ 63 | void add_request(MessyRequest *req); 64 | 65 | /** 66 | * @brief Gets the request at a specific index. 67 | * 68 | * This function returns a pointer to the MessyRequest object at the specified 69 | * index in the core_requests vector. It allows access to individual requests 70 | * based on their position in the vector. 71 | * 72 | * @param i Index of the request. 73 | * @return Pointer to the MessyRequest at the specified index. 74 | */ 75 | MessyRequest *get_request_at(int i); 76 | 77 | /** 78 | * @brief Deletes a number of requests from the core requests. 79 | * 80 | * This function removes a specified number of requests from the beginning of 81 | * the core_requests vector. It is useful for clearing out processed requests 82 | * from the queue. 83 | * 84 | * @param size Number of requests to delete. 85 | */ 86 | void delete_n_requests(int size); 87 | 88 | /** 89 | * @brief Gets the size of the request queue. 90 | * 91 | * This function returns the number of requests currently stored in the 92 | * core_requests vector. It provides a way to check how many requests are 93 | * pending processing. 94 | * 95 | * @return Size of the request queue. 96 | */ 97 | int request_queue_size(); 98 | 99 | #endif -------------------------------------------------------------------------------- /messy/codegen/templates/include/power_bus.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | /** 6 | * @brief Power bus module for managing and aggregating power-related signals. 7 | * 8 | * The Power_bus module models the power consumption of a system by aggregating 9 | * current and voltage values from various components such as the CPU, sensors, 10 | * and power sources. The module is triggered every 1 ms to update the power states. 11 | */ 12 | SCA_TDF_MODULE(Power_bus) { 13 | // Time resolution is set to 1 ms, meaning the module is triggered every 1 ms 14 | 15 | // Input Ports 16 | sca_tdf::sca_in core_current; ///< Input port for the current consumed by the CPU core. 17 | sca_tdf::sca_in core_voltage; ///< Input port for the voltage supplied to the CPU core. 18 | sca_tdf::sca_in voltage_sensors[NUM_SENSORS]; ///< Array of input ports for the voltages supplied to the sensors. 19 | sca_tdf::sca_in current_sensors[NUM_SENSORS]; ///< Array of input ports for the currents consumed by the sensors. 20 | 21 | #if NUM_SOURCES > 0 22 | sca_tdf::sca_in current_sources[NUM_SOURCES]; //< Array of input ports for the currents supplied by external power sources (i.e. photovoltailc panels). 23 | #endif 24 | #if NUM_BATTERIES > 0 25 | sca_tdf::sca_out current_batteries[NUM_BATTERIES]; //< Array of output ports for the currents drawn from batteries. 26 | #endif 27 | 28 | /** 29 | * @brief Constructor for the Core_power module. 30 | * 31 | * Initializes the input and output signal names for tracing and connecting to other modules. 32 | */ 33 | SCA_CTOR(Power_bus) : core_current("Current_of_CPU"), 34 | core_voltage("Voltage_of_CPU") {} 35 | 36 | void set_attributes(); 37 | void initialize(); 38 | void processing(); 39 | 40 | private: 41 | double total_current = 0; 42 | 43 | // Default constructor is private to prevent its use, ensuring that 44 | // the module must be initialized using the public constructor above. 45 | Power_bus() {} 46 | }; -------------------------------------------------------------------------------- /messy/codegen/templates/include/sensor_functional.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | /** 6 | * @brief Functional module for the ${sensor_name} sensor. 7 | * 8 | * This module handles the functional behavior of the ${sensor_name} sensor. It processes data from input ports, controls sensor operations through internal logic, and interacts with power and thermal models. 9 | * 10 | * The module includes the following ports: 11 | * - Input Ports: 12 | * - enable: Input port for enabling the sensor. 13 | * - address: Input port for the memory address. When writing, this is the address to write to; when reading, this is the address to read from. 14 | * - data_in: Input port for incoming data to be written to the sensor's memory. 15 | * - req_size: Input port for the size of the request. 16 | * - flag_wr: Input port for the write/read flag (true for read, false for write). 17 | * - ready: Input port indicating if the sensor is ready to be used. 18 | * - Output Ports: 19 | * - data_out: Output port for the data read from the sensor's memory. 20 | * - go: Output port for signaling the sensor to proceed with the operation. 21 | * - power_signal: Output port for the power state signal 22 | */ 23 | SC_MODULE(Sensor_${sensor_name}_functional) { 24 | Core *core; 25 | 26 | // Input Port 27 | sc_core::sc_in enable; ///< Input port for enabling the sensor. 28 | sc_core::sc_in address; ///< Input port for the memory address. When writing this is the address to write to, when reading this is the address to read from. 29 | sc_core::sc_in data_in; ///< Input port for incoming data to be written to the sensor's memory. 30 | sc_core::sc_in req_size; ///< Input port for the size of the request. It must be coehrent with the size of the data_in. 31 | sc_core::sc_in flag_wr; ///< Input port for the write/read flag (true for read, false for write). 32 | sc_core::sc_in ready; ///< Input port indicating if the system is ready. 33 | 34 | // Output Port 35 | sc_core::sc_out data_out; ///< Output port for the data read from the sensor's memory. 36 | sc_core::sc_out go; ///< Output port for signaling the sensor to proceed with the operation. 37 | 38 | // Power Port 39 | sc_core::sc_out power_signal; ///< Output port for the power state signal. 40 | 41 | // Thermal Port 42 | // sc_core::sc_out thermal_signal; 43 | 44 | 45 | /** 46 | * @brief Constructor for the Sensor_${sensor_name}_functional module. 47 | * 48 | * Initializes input and output ports and sets up the sensor logic thread. 49 | * It also allocates memory for the sensor's register map. 50 | */ 51 | SC_CTOR(Sensor_${sensor_name}_functional) : enable("Enable_signal"), 52 | address("Address"), 53 | data_in("Data_in"), 54 | flag_wr("Flag"), 55 | ready("Ready"), 56 | data_out("Data_out"), 57 | go("Go"), 58 | power_signal("Func_to_Power_signal") { 59 | // printf("SENSOR :: systemc constructor"); 60 | 61 | register_memory = new uint8_t[${register_memory}]; ///< Allocate memory for the sensor's register map. 62 | 63 | // Declare the sensor logic thread and make it sensitive to the 'ready' signal. 64 | SC_THREAD(sensor_logic); 65 | sensitive << ready; 66 | } 67 | 68 | 69 | /** 70 | * @brief Thread that implements the sensor logic. 71 | * 72 | * This function controls the internal sensor operations based on the input signals 73 | * and manages the interaction between data, address, and control flags. 74 | */ 75 | void sensor_logic(); 76 | 77 | /** 78 | * @brief Default constructor for Sensor_${sensor_name}_functional. 79 | * 80 | * A placeholder constructor 81 | */ 82 | Sensor_${sensor_name}_functional() { 83 | // printf("SENSOR :: constructor"); 84 | } 85 | 86 | /** 87 | * @brief Destructor for Sensor_${sensor_name}_functional. 88 | * 89 | * Frees the dynamically allocated memory for the sensor's register map. 90 | */ 91 | ~Sensor_${sensor_name}_functional() { 92 | delete[] register_memory; 93 | } 94 | 95 | // Register Map 96 | private: 97 | uint8_t *register_memory; ///< Pointer to the sensor's register memory. 98 | int register_memory_size = ${register_memory}; ///< Size of the sensor's register memory. 99 | }; -------------------------------------------------------------------------------- /messy/codegen/templates/include/sensor_power.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #define ${sensor_name}_VREF ${vref} 5 | 6 | /** 7 | * @brief Sensor power module class for ${sensor_name}. 8 | * 9 | * This module models the power consumption of the ${sensor_name} sensor. It reads 10 | * a functional signal and outputs the corresponding voltage and current state 11 | * to the power bus. 12 | */ 13 | SCA_TDF_MODULE(Sensor_${sensor_name}_power) 14 | { 15 | 16 | sca_tdf::sc_in func_signal; //< Input port for receiving data from the functional instance. 17 | sca_tdf::sca_out voltage_state; //< Output port for sending voltage state to the power bus. 18 | sca_tdf::sca_out current_state; //< Output port for sending current state to the power bus. 19 | 20 | /** 21 | * @brief Constructor for the Sensor_${sensor_name}_power module. 22 | * 23 | * Initializes the port names for power state signals. 24 | */ 25 | SCA_CTOR(Sensor_${sensor_name}_power): 26 | func_signal("State_of_Power_From_Functional"), 27 | voltage_state("Voltage_trace_to_Power_Bus"), 28 | current_state("Current_trace_to_Power_Bus") 29 | {} 30 | 31 | void set_attributes(); 32 | void initialize(); 33 | void processing(); 34 | 35 | Sensor_${sensor_name}_power(){} 36 | }; -------------------------------------------------------------------------------- /messy/codegen/templates/src/adapters/adapter_gvsoc_gap9.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | AdapterGvsocGap9::AdapterGvsocGap9() 4 | { 5 | #ifdef LOG_REQUESTS 6 | request_addresses.open("./request_adresses.log"); 7 | request_sizes.open("./request_sizes.log"); 8 | #endif 9 | } 10 | void AdapterGvsocGap9::startup(){ 11 | string gvsoc_config_path="${config['path']}"; 12 | gv::GvsocConf conf; 13 | conf.config_path=gvsoc_config_path; 14 | conf.api_mode=gv::Api_mode::Api_mode_sync; 15 | conf.proxy_socket=-1; 16 | gvsoc = (Gvsoc_launcher*) gv::gvsoc_new(&conf); 17 | gvsoc->open(); 18 | // register this core as an executor notifier 19 | gvsoc->register_exec_notifier(this); 20 | 21 | // Get a connection to the main soc AXI. This will allow us to inject accesses 22 | // and could also be used to received accesses from simulated test 23 | // to a certain mapping corresponding to the external devices. 24 | this->axi = gvsoc->io_bind(this, "${config['axi_path']}", ""); 25 | if (this->axi == NULL) 26 | { 27 | fprintf(stderr, "Couldn't find AXI proxy\n"); 28 | return; 29 | } 30 | 31 | gvsoc->start(); 32 | } 33 | 34 | MessyRequest* AdapterGvsocGap9::get_messy_request_from_gvsoc(gv::Io_request* req){ 35 | #ifdef LOG_REQUESTS 36 | request_addresses << req->addr << std::endl; 37 | request_sizes << req->size << std::endl; 38 | #endif 39 | return (MessyRequest*)new MessyRequest((long long)req->addr,(unsigned int*)req->data,(bool)req->type==gv::Io_request_read,(unsigned int*)req->handle,req->size); 40 | } 41 | 42 | int64_t AdapterGvsocGap9::exec_events_at(int64_t timestamp){ 43 | int64_t next_event_time=gvsoc->step_until(timestamp); 44 | finished=this->gvsoc->top_get()->time_engine->finished_get(); 45 | return next_event_time; 46 | } 47 | 48 | double AdapterGvsocGap9::get_power_at(int64_t timestamp){ 49 | double x=0,y=0; 50 | double inst_power=this->gvsoc->get_instant_power(x,y); 51 | return inst_power; 52 | } 53 | 54 | void AdapterGvsocGap9::close(){ 55 | if(!closed){ 56 | int retval = gvsoc->join(); 57 | gvsoc->stop(); 58 | gvsoc->close(); 59 | closed=1; 60 | } 61 | } 62 | 63 | void AdapterGvsocGap9::access(gv::Io_request* req){ 64 | add_request(this->get_messy_request_from_gvsoc(req)); 65 | } 66 | 67 | void AdapterGvsocGap9::custom_reply(MessyRequest* req){ 68 | vp::io_req *vp_req = (vp::io_req *)req->handle_c; 69 | vp_req->get_resp_port()->resp(vp_req); 70 | delete req; 71 | } 72 | 73 | void AdapterGvsocGap9::grant(gv::Io_request *req) 74 | { 75 | 76 | } 77 | 78 | void AdapterGvsocGap9::reply(gv::Io_request *req) 79 | { 80 | 81 | } 82 | 83 | void AdapterGvsocGap9::notify_stop(int64_t time) 84 | { 85 | if(!this->gvsoc->retain_count()) 86 | this->gvsoc->release(); 87 | } 88 | 89 | void AdapterGvsocGap9::notify_run(int64_t time) 90 | { 91 | if(!this->gvsoc->retain_count()) 92 | this->gvsoc->retain(); 93 | } -------------------------------------------------------------------------------- /messy/codegen/templates/src/converter/load_converter.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void Load_converter::set_attributes() { 4 | 5 | current_in.set_rate(1); 6 | current_in.set_timestep(1, SIM_RESOLUTION); 7 | voltage_in.set_rate(1); 8 | voltage_in.set_timestep(1, SIM_RESOLUTION); 9 | } 10 | 11 | void Load_converter::initialize() {} 12 | 13 | /** 14 | * @warning This function is called by the SystemC-AMS kernel. Do not call it manually. 15 | * 16 | * @brief Processes the data. 17 | * 18 | * This function is responsible for processing the input data and generating 19 | * the output data. It reads the current and voltage inputs, calculates the 20 | * output current based on the efficiency factor and input values, and writes 21 | * the output current to the current_out port. 22 | */ 23 | void Load_converter::processing() { 24 | double v_tmp; /**< Temporary variable to store the input voltage */ 25 | double i_tmp; /**< Temporary variable to store the input current */ 26 | double i_out; /**< Variable to store the calculated output current */ 27 | 28 | // Read input quantities 29 | v_tmp = voltage_in.read(); /**< Read the voltage input from the port */ 30 | i_tmp = current_in.read(); /**< Read the current input from the port */ 31 | 32 | // Compute the output current (Psensor * efficiency / Vbus) 33 | if (v_tmp == 0) { 34 | i_out = 0.0; /**< Set output current to 0 if input voltage is 0 */ 35 | } else { 36 | i_out = ( (v_tmp * i_tmp) * efficency_factor ) / VREF_BUS; /**< Calculate the output current based on input values and efficiency factor */ 37 | } 38 | 39 | current_out.write(i_out); /**< Write the calculated output current to the port */ 40 | } 41 | 42 | /** 43 | * @brief Sets the efficiency factor of the converter. 44 | * 45 | * This function sets the efficiency factor used in the conversion process. 46 | * 47 | * @param k The efficiency factor to be set. 48 | */ 49 | void Load_converter::set_efficency(double k) { 50 | efficency_factor = k; 51 | } -------------------------------------------------------------------------------- /messy/codegen/templates/src/converter/lut_converter.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | 4 | void ${name}_converter::set_attributes() 5 | { 6 | current_out.set_timestep(1, SIM_RESOLUTION); 7 | current_out.set_delay(1); 8 | } 9 | 10 | void ${name}_converter::initialize() {} 11 | 12 | 13 | /** 14 | * @warning This function is called by the SystemC-AMS scheduler. Do not call it manually. 15 | * 16 | * @brief Processes the data. 17 | * 18 | * This function is responsible for processing the input data and generating 19 | * the output data. It reads the current and voltage inputs, calculates the 20 | * efficiency using the lookup table, and computes the current output based 21 | * on the efficiency and input values. 22 | */ 23 | void ${name}_converter::processing() 24 | { 25 | double ideal_power; /**< Variable to store the ideal power */ 26 | double eta; /**< Variable to store the efficiency */ 27 | double i_tmp; /**< Temporary variable to store the input current */ 28 | double v_tmp; /**< Read the voltage input from the port */ 29 | 30 | // Read input quantities 31 | i_tmp = current_in.read(); /**< Read the current input from the port */ 32 | v_tmp = voltage_in.read(); /**< Read the voltage input from the port */ 33 | 34 | // Get efficiency 35 | eta = lut_eta.get_val(${"v_tmp" if input_variable=="voltage" else "i_tmp"}) / 100; /**< Get the efficiency from the lookup table */ 36 | 37 | % if not out_dir: 38 | /** 39 | * The efficiency of this converter is defined as: 40 | * eta = Pin / Pout 41 | * where Pin = i_tmp * v_tmp and Pout = current_out * VREF_BUS 42 | * Therefore, the output current is: 43 | * current_out = eta * (i_tmp * VREF_BUS) / v_tmp 44 | */ 45 | current_out.write(i_tmp * v_tmp / (VREF_BUS*eta)); 46 | % else: 47 | /** 48 | * 49 | * The efficiency of this converter is defined as: 50 | * eta = Pout / Pin 51 | * where Pin = i_tmp * VREF_BUS and Pout = current_out * v_tmp 52 | * Therefore, the output current is: 53 | * current_out = (eta * (i_tmp * VREF_BUS)) / v_tmp 54 | * 55 | */ 56 | current_out.write((eta * (i_tmp * VREF_BUS)) / v_tmp); 57 | % endif 58 | } 59 | -------------------------------------------------------------------------------- /messy/codegen/templates/src/core_power.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /** 4 | * @warning This function should not be called directly. It is called by the SystemC-AMS kernel. 5 | * 6 | * @brief Sets the attributes of the `func_signal` port. 7 | * 8 | * This function sets the rate and timestep of the `func_signal` port. Check the SystemC-AMS documentation for more details on the `set_rate` and `set_timestep` functions. 9 | */ 10 | void Core_power::set_attributes() { 11 | func_signal.set_rate(1); ///< Set the number of samples that have to be read on the port per execution. Check SystemC-AMS documentation for more details on the set_rate function. 12 | func_signal.set_timestep(1, SIM_RESOLUTION); //< Set how often the module is triggered (sampling period). Check SystemC-AMS documentation for more details on the set_timestep function. 13 | } 14 | 15 | void Core_power::initialize() {} 16 | 17 | /** 18 | * @warning This function should not be called directly. It is called by the SystemC-AMS kernel. 19 | * 20 | * @brief Main processing function for the Core_power module. 21 | * 22 | * This function calculates the voltage and current states based on the functional signal. 23 | * If the core has not performed any simulation iterations, it writes 0.0 to the voltage and 24 | * current outputs. Otherwise, it calculates the current state based on the total power 25 | * consumed and the number of simulation iterations, and resets the power-related parameters. 26 | */ 27 | void Core_power::processing() { 28 | // If no simulation iterations have been performed, set voltage and current to 0. 29 | if (!core->simulation_iters) { 30 | voltage_state.write(0.0); 31 | current_state.write(0.0); 32 | return; 33 | } 34 | 35 | // Calculate and write the current state based on total power and number of iterations. 36 | voltage_state.write(V_CORE); 37 | current_state.write(((core->tot_power / core->simulation_iters) * 1000) / V_CORE); 38 | 39 | // Reset the core's simulation iteration count and total power. 40 | core->simulation_iters = 0; 41 | core->tot_power = 0; 42 | } 43 | -------------------------------------------------------------------------------- /messy/codegen/templates/src/functional_bus.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /** 5 | * @brief Thread for processing data. 6 | * 7 | * This function is responsible for processing the data received from the master 8 | * and routing it to the appropriate sensor. It reads the request details such as 9 | * address, data, size, and flag from the master, and determines which sensor the 10 | * request is intended for. If the request is valid, it sets the appropriate output 11 | * signals to the sensor. If the request is invalid, it logs an error and sets the 12 | * response to indicate failure. 13 | */ 14 | void Functional_bus::processing_data(){ 15 | unsigned int add_s; /**< Local variable to store the request address */ 16 | uint8_t* data_s; /**< Local variable to store the request data */ 17 | unsigned int reg_s; /**< Local variable to store the register address within the sensor */ 18 | unsigned int size_s; /**< Local variable to store the size of the request */ 19 | bool flag_s; /**< Local variable to store the request flag */ 20 | 21 | while (true){ 22 | // Check if the request is ready 23 | if (request_ready.read() == true) { 24 | // Read the request details from the input ports 25 | add_s = request_address.read(); 26 | flag_s = flag_from_core.read(); 27 | size_s = request_size.read(); 28 | 29 | // Iterate over the sensors to find the matching address range 30 | % for idx,(sensor_name,sensor) in enumerate(peripherals["sensors"].items()): 31 | % if idx == 0: 32 | if 33 | % else: 34 | else if 35 | % endif 36 | (${sensor_name}_BASE_ADDRESS <= add_s && add_s < (${sensor_name}_BASE_ADDRESS + ${sensor["register_memory"]})) 37 | { 38 | // Check if the request exceeds the sensor's memory range 39 | if(add_s+size_s > (${sensor_name}_BASE_ADDRESS + ${sensor["register_memory"]})){ 40 | fprintf(stderr,"\n[MESSY]\tRead/Write at %d of %d bytes exceeds ${sensor_name} memory\n",add_s,size_s); 41 | selected_sensor=-1; 42 | request_value.write(0x0); 43 | request_go.write(true); 44 | } 45 | else{ 46 | // Calculate the register address within the sensor 47 | reg_s = add_s - ${sensor_name}_BASE_ADDRESS; 48 | data_s = request_data.read(); 49 | // Set the output signals to the sensor 50 | size_out_sensor[${idx}].write(size_s); 51 | address_out_sensor[${idx}].write(reg_s); 52 | data_out_sensor[${idx}].write(data_s); 53 | flag_out_sensor[${idx}].write(flag_s); 54 | selected_sensor = ${idx}; 55 | ready_sensor[selected_sensor].write(true); 56 | } 57 | } 58 | % endfor 59 | else{ 60 | // Log an error if the address does not match any sensor 61 | fprintf(stderr,"\n[MESSY]\tAddress %d not found by functional bus\n", add_s); 62 | selected_sensor=-1; 63 | request_value.write(0x0); 64 | request_go.write(true); 65 | } 66 | // Write the index of the selected sensor to the output port 67 | idx_sensor.write(selected_sensor); 68 | } 69 | 70 | // Wait for the next event 71 | wait(); 72 | 73 | if(selected_sensor>=0){ 74 | // Check if a valid sensor was selected 75 | response(); 76 | // Wait until the sensor and request are no longer ready 77 | while (go_sensors[selected_sensor].read() != false && request_ready.read() != false) { 78 | wait(); 79 | } 80 | // Indicate that the request processing is complete 81 | request_go.write(false); 82 | } 83 | 84 | } 85 | } 86 | 87 | /** 88 | * @brief Function for handling responses. 89 | * 90 | * This function is responsible for handling the responses from the sensors 91 | * and sending them back to the master. It reads the data from the selected 92 | * sensor and writes it to the request_value output port. It also updates the 93 | * ready_sensor and request_go flags accordingly. 94 | */ 95 | void Functional_bus::response(){ 96 | // Check if the selected sensor is ready 97 | if (go_sensors[selected_sensor].read() == true) { 98 | // Write the sensor data to the request_value output port 99 | request_value.write(data_input_sensor[selected_sensor].read()); 100 | // Indicate that the response is ready 101 | request_go.write(true); 102 | // Reset the ready flag for the selected sensor 103 | ready_sensor[selected_sensor].write(false); 104 | } 105 | } -------------------------------------------------------------------------------- /messy/codegen/templates/src/harvester.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | % if harvester_type!="battery": 3 | void Harvester_${harvester_name}::set_attributes() 4 | { 5 | i.set_timestep(1, SIM_RESOLUTION); 6 | v.set_timestep(1, SIM_RESOLUTION); 7 | } 8 | 9 | void Harvester_${harvester_name}::initialize() 10 | { 11 | % if vref and type(vref)==dict: 12 | // Open file with simulation 13 | vref_input_file.open("${vref['input_file']}"); 14 | if(!vref_input_file) 15 | { 16 | cout << "couldn't open ${vref['input_file']} file.\n" << endl; 17 | exit(-1); 18 | } 19 | % endif 20 | 21 | % if iref and type(iref)==dict: 22 | // Open file with simulation 23 | iref_input_file.open("${iref['input_file']}"); 24 | if(!iref_input_file) 25 | { 26 | cout << "couldn't open ${iref['input_file']} file.\n" << endl; 27 | exit(-1); 28 | } 29 | % endif 30 | } 31 | 32 | void Harvester_${harvester_name}::processing() 33 | { 34 | // sensing of irradiance takes place every TRACE_PERIOD s. 35 | % if vref and type(vref)==dict: 36 | double vref_input=0.0; 37 | vref_input_file >> vref_input; 38 | v.write(lut_v.get_val(vref_input)); 39 | % endif 40 | 41 | % if iref and type(iref)==dict: 42 | double iref_input=0.0; 43 | iref_input_file >> iref_input; 44 | i.write(lut_i.get_val(iref_input)); 45 | % endif 46 | 47 | } 48 | % else: 49 | /** 50 | * @warning This function is called by the SystemC kernel before the simulation starts. It should not be called by the user. 51 | * 52 | * @brief Sets the attributes of the battery-based harvester. 53 | * 54 | * This function configures the timestep and delay for the open-circuit voltage (v_oc), series resistance (r_s), and state of charge (soc) outputs. 55 | */ 56 | void Harvester_${harvester_name}_battery_voc::set_attributes() 57 | { 58 | v_oc.set_timestep(1, SIM_RESOLUTION); 59 | r_s.set_timestep(1, SIM_RESOLUTION); 60 | soc.set_timestep(1, SIM_RESOLUTION); 61 | r_s.set_delay(1); 62 | soc.set_delay(1); 63 | } 64 | 65 | /** 66 | * @warning This function is called by the SystemC kernel before the simulation starts. It should not be called by the user. 67 | * 68 | * @brief Initializes the battery harvester. 69 | * 70 | * This function initializes the temporary state of charge (tmpsoc) based on the provided initial SOC value. 71 | */ 72 | void Harvester_${harvester_name}_battery_voc::initialize() { 73 | tmpsoc = ${soc_init/100}f; 74 | } 75 | 76 | /** 77 | * @warning This function is called by the SystemC kernel during the simulation. It should not be called by the user. 78 | * 79 | * @brief Processing method for the battery-based harvester. 80 | * 81 | * This function computes the state of charge (SOC), battery open-circuit voltage (Voc), 82 | * and series resistance (R_s) based on the current and SOC relationships. If SOC drops below 83 | * a threshold, the simulation is stopped. 84 | */ 85 | void Harvester_${harvester_name}_battery_voc::processing(){ 86 | double tmpcurrent = i.read(); ///< Read the battery current. If negative, the battery is charging. 87 | 88 | /** 89 | * Compute actual state-of-charge solving the integral: 90 | * SOC_t = SOC_{t-1} - \int^{t}_{-inf} i(\tau) / C d\tau 91 | */ 92 | // TODO: Quickfix for scaling resulution 93 | int scaling_factor_resulution; 94 | if (SIM_RESOLUTION == SC_MS) 95 | { 96 | // MS 97 | scaling_factor_resulution = 1000; 98 | } 99 | else 100 | { 101 | // SEC 102 | scaling_factor_resulution = 1; 103 | } 104 | tmpsoc -= (((tmpcurrent + prev_i_batt) * 1) / (2 * (3600) * c_nom * scaling_factor_resulution)); 105 | prev_i_batt = tmpcurrent; // Update 106 | 107 | // Output the battery SOC 108 | if(tmpsoc >= 1) // Not let the SOC overflow 109 | { 110 | soc.write(1); ///< Since the battery is full, the SOC is set to 1. 111 | tmpsoc = 1; 112 | } 113 | else 114 | { 115 | soc.write(tmpsoc); ///< Output the current SOC 116 | } 117 | 118 | // SOC and battery Voc relationship 119 | // val(x) = p1*x^4 + p2*x^3 + p3*x^2 + p4*x + p5 120 | double v_p1=-13.26, v_p2=27.4, v_p3=-17.99, v_p4=4.496, v_p5=3.45; 121 | v_oc.write((v_p1 * tmpsoc * tmpsoc * tmpsoc * tmpsoc) + (v_p2 * tmpsoc * tmpsoc * tmpsoc) + (v_p3 * tmpsoc * tmpsoc) + (v_p4 * tmpsoc) + v_p5); // Place interpolated funct here 122 | 123 | // SOC and battery internal resistance relationship 124 | // val(x) = p1*x^4 + p2*x^3 + p3*x^2 + p4*x + p5 125 | double r_p1=-0.1055, r_p2=0.1968, r_p3=-0.1119, r_p4=0.01607, r_p5=0.003117; 126 | r_s.write((r_p1 * tmpsoc * tmpsoc * tmpsoc * tmpsoc) + (r_p2 * tmpsoc * tmpsoc * tmpsoc) + (r_p3 * tmpsoc * tmpsoc) + (r_p4 * tmpsoc) + r_p5); // Place interpolated funct here 127 | 128 | // When the battery SOC decreases under 5% of starting voc, the simulation stops. 129 | if(tmpsoc <= ${soc_end/100}) 130 | { 131 | cout << "SOC is less than or equal to {{starting_voc-perc_voc}}/100%:" << " @" << sc_time_stamp() << " ; it is "<< tmpsoc << endl; 132 | sc_stop(); 133 | } 134 | } 135 | % endif 136 | -------------------------------------------------------------------------------- /messy/codegen/templates/src/lut.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /** 4 | * @brief Constructor for the LUT class. 5 | * 6 | * Initializes the lookup table by copying the key and value arrays and storing the size. 7 | * 8 | * @param k A pointer to the array of keys. 9 | * @param v A pointer to the array of corresponding values. 10 | * @param sz The number of key-value pairs. 11 | */ 12 | LUT::LUT(const double *k, const double *v, int sz) { 13 | key = new double[sz]; ///< Dynamically allocate memory for keys. 14 | val = new double[sz]; ///< Dynamically allocate memory for values. 15 | int i; 16 | 17 | // Initialize the key-value pairs 18 | for (i = 0; i < sz; i++) { 19 | this->key[i] = k[i]; ///< Copy each key into the LUT. 20 | this->val[i] = v[i]; ///< Copy each value into the LUT. 21 | } 22 | this->size = sz; ///< Store the size of the lookup table. 23 | } 24 | 25 | /** 26 | * @brief Destructor for the LUT class. 27 | * 28 | * Frees the memory allocated for keys and values. 29 | */ 30 | LUT::~LUT() { 31 | delete[] key; 32 | delete[] val; 33 | } 34 | 35 | /** 36 | * @brief Retrieves the interpolated value for a given query key. 37 | * 38 | * Performs a linear interpolation between the two closest key-value pairs if the query 39 | * key falls between them. 40 | * 41 | * @param query The key for which the corresponding value is to be interpolated. 42 | * @return The interpolated value based on the query key. 43 | */ 44 | double LUT::get_val(double query) { 45 | int i; 46 | double dx; 47 | double dy; 48 | 49 | // Find i, such that key[i] <= query < key[i+1] 50 | for (i = 0; i < size - 1; i++) // TODO: Use Binary Search here instead 51 | { 52 | if (key[i + 1] > query) { 53 | break; 54 | } 55 | } 56 | 57 | // Interpolate 58 | dx = key[i + 1] - key[i]; 59 | dy = val[i + 1] - val[i]; 60 | return val[i] + (query - key[i]) * dy / dx; 61 | } -------------------------------------------------------------------------------- /messy/codegen/templates/src/messy_request.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /** 4 | * @brief Adds a request to the core requests. 5 | * 6 | * This function takes a pointer to a MessyRequest object and adds it to the 7 | * core_requests vector. The core_requests vector is used to store all the 8 | * requests that need to be processed. 9 | * 10 | * @param req Pointer to the MessyRequest to be added. 11 | */ 12 | void add_request(MessyRequest *req) { core_requests.emplace_back(req); } 13 | 14 | /** 15 | * @brief Gets the request at a specific index. 16 | * 17 | * This function returns a pointer to the MessyRequest object at the specified 18 | * index in the core_requests vector. It allows access to individual requests 19 | * based on their position in the vector. 20 | * 21 | * @param i Index of the request. 22 | * @return Pointer to the MessyRequest at the specified index. 23 | */ 24 | MessyRequest *get_request_at(int i) { return core_requests[i]; } 25 | 26 | /** 27 | * @brief Deletes a number of requests from the core requests. 28 | * 29 | * This function removes a specified number of requests from the beginning of 30 | * the core_requests vector. It is useful for clearing out processed requests 31 | * from the queue. 32 | * 33 | * @param size Number of requests to delete. 34 | */ 35 | void delete_n_requests(int size) { core_requests.erase(core_requests.begin(), core_requests.begin() + size); } 36 | 37 | /** 38 | * @brief Gets the size of the request queue. 39 | * 40 | * This function returns the number of requests currently stored in the 41 | * core_requests vector. It provides a way to check how many requests are 42 | * pending processing. 43 | * 44 | * @return Size of the request queue. 45 | */ 46 | int request_queue_size() { return core_requests.size(); } -------------------------------------------------------------------------------- /messy/codegen/templates/src/power_bus.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void Power_bus::set_attributes() {} 4 | 5 | void Power_bus::initialize() {} 6 | 7 | /** 8 | * @warning This function should not be called directly. It is called by the SystemC-AMS kernel. 9 | * 10 | * @brief This function calculates and updates the total current on the power bus. 11 | * 12 | * It reads the current values from the sensors, the core, and the sources. 13 | * It sums the current from all sensors and core, and then subtracts the 14 | * current from the power sources. If there are any batteries, the calculated 15 | * total current is divided equally among the batteries and written to each 16 | * battery. 17 | * 18 | * The function performs the following steps: 19 | * - Initializes the `total_current` to 0. 20 | * - Loops through the current sensors to read and accumulate their current values. 21 | * - Reads the current from the core and adds it to `total_current`. 22 | * - If there are any current sources, their values are read and subtracted from `total_current`. The current sources are assumed to be supplying current to the system, so they are subtracted from the total current. 23 | * - If there are any batteries, the total current is divided by the number of batteries, 24 | * and the value is written to each battery, representing the current drawn from each battery. 25 | * 26 | * @note The number of sensors, sources, and batteries is determined by the constants 27 | * `NUM_SENSORS`, `NUM_SOURCES`, and `NUM_BATTERIES` respectively. 28 | * 29 | * @warning If `NUM_SOURCES` or `NUM_BATTERIES` is 0, the respective section of code 30 | * will not be executed. 31 | * 32 | */ 33 | void Power_bus::processing() { 34 | double tmp_i; 35 | total_current = 0; 36 | 37 | for (int i = 0; i < NUM_SENSORS; i++) { 38 | tmp_i = current_sensors[i].read(); 39 | total_current += tmp_i; 40 | } 41 | 42 | tmp_i = core_current.read(); 43 | 44 | total_current += tmp_i; 45 | 46 | #if NUM_SOURCES > 0 47 | for (int i = 0; i < NUM_SOURCES; i++) { 48 | tmp_i = current_sources[i].read(); 49 | total_current -= tmp_i; 50 | } 51 | #endif 52 | 53 | #if NUM_BATTERIES > 0 54 | for (int i = 0; i < NUM_BATTERIES; i++) 55 | current_batteries[i].write(total_current / NUM_BATTERIES); 56 | #endif 57 | } -------------------------------------------------------------------------------- /messy/codegen/templates/src/sensor_functional.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /** 4 | * @brief Main logic for the ${sensor_name} sensor. 5 | * 6 | * This function implements the core logic of the sensor, handling both read and 7 | * write operations. It also manages power signals based on the sensor's current state, 8 | * such as reading, writing, or idling. The hierarchy of the sensor logic is as follows: 9 | * - enable: Checks if the sensor is enabled. If true, proceeds to the next step, else idles (writes 0 to the power signal). 10 | * - ready: This is the following step if the enable signal is true. If the sensor is also ready (ready signal is true), the sensor proceeds to the next step, else writes false to the go signal. 11 | * - flag_wr: If the sensor is ready, it checks the flag_wr signal. If true, the sensor performs a read operation, else a write operation. 12 | * 13 | * 14 | * The read and write operations are modeled using the following concept. In the configuration file, the user can specify the delay and the power consumption for each operation. To mimic this behaviour, the sensor logic waits for the specified delay time before proceeding to the next operation. During the read/write operation, the power signal is set to the corresponding state (read/write) and then switched back to idle after the operation is complete. This allows the power model to accurately simulate the power consumption of the sensor. 15 | */ 16 | void Sensor_${sensor_name}_functional::sensor_logic() { 17 | % if memory_init: 18 | % for idx,val in enumerate(memory_init): 19 | register_memory[idx]=val; 20 | % endfor 21 | % endif 22 | while (true) { 23 | if (enable.read() == true) { 24 | if (ready.read() == true) { 25 | if (flag_wr.read() == true) { 26 | // Read operation 27 | unsigned int add = address.read(); ///< Get the address from the input 28 | 29 | // Perform read operation 30 | data_out.write(register_memory + add); ///< Send the pointer to the data in the register memory to the output. 31 | 32 | // Reading power consumption state 33 | power_signal.write(${sensor_name}_read); ///< Signal that the sensor is in reading state 34 | 35 | // Request delay for the read operation 36 | double start_time = sc_time_stamp().to_double(); ///< Get the current simulation time 37 | core->request_delay(start_time, ${states["read"]["delay"]}, SIM_RESOLUTION); 38 | 39 | // Switch to idle power consumption state 40 | power_signal.write(${sensor_name}_idle); 41 | go.write(true); ///< Indicate that the operation is complete. 42 | } else { 43 | // Write operation 44 | unsigned int add = address.read(); ///< Get the address from the input 45 | 46 | // Prepare address and data for writing 47 | unsigned int req_size_val = req_size.read(); ///< Get the size of the write request 48 | uint8_t *req_core_val_addr = data_in.read(); ///< Get the data to be written to the register memory 49 | 50 | // Write data to the register memory 51 | for (unsigned int i = 0; i < req_size_val; i++) 52 | register_memory[i + add] = req_core_val_addr[i]; 53 | 54 | data_out.write(register_memory + add); ///< Send the pointer to the data in the register memory to the output 55 | 56 | // Writing power consumption state 57 | power_signal.write(${sensor_name}_write); 58 | 59 | // Request delay for the write operation 60 | double start_time = sc_time_stamp().to_double(); ///< Get the current simulation time 61 | core->request_delay(start_time, ${states["write"]["delay"]}, SIM_RESOLUTION); 62 | 63 | // Switch to idle power consumption state 64 | power_signal.write(${sensor_name}_idle); 65 | go.write(true); ///< Indicate that the operation is complete. 66 | } 67 | } else { 68 | go.write(false); 69 | } 70 | 71 | } else { 72 | power_signal.write(0); 73 | } 74 | wait(); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /messy/codegen/templates/src/sensor_power.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void Sensor_${sensor_name}_power::set_attributes() 4 | { 5 | func_signal.set_rate(1); 6 | func_signal.set_timestep(1, SIM_RESOLUTION); 7 | } 8 | 9 | void Sensor_${sensor_name}_power::initialize() {} 10 | 11 | /** 12 | * @warning This function should not be called directly. It is called by the SystemC-AMS kernel. 13 | * 14 | * @brief Process the functional signal and output voltage and current state. 15 | * 16 | * This method reads the current functional state of the sensor and updates 17 | * the voltage and current values accordingly. The voltage and current values 18 | * are based on predefined states and associated current consumption. 19 | * 20 | * The available states are: 21 | % for state_name,state in states.items(): 22 | * ${sensor_name}_${state_name} : Voltage = ${sensor_name}_VREF, Current = ${state["current"]} 23 | % endfor 24 | */ 25 | void Sensor_${sensor_name}_power::processing() 26 | { 27 | % for state_name,state in states.items(): 28 | if(func_signal.read() == ${sensor_name}_${state_name} ){ 29 | voltage_state.write(${sensor_name}_VREF); 30 | current_state.write(${state["current"]}); 31 | return; 32 | } 33 | % endfor 34 | if(func_signal.read() == 0){ 35 | voltage_state.write(0.0); 36 | current_state.write(0.0); 37 | return; 38 | } 39 | } -------------------------------------------------------------------------------- /messy/messy.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | import subprocess 3 | from pathlib import Path 4 | from typing import List 5 | 6 | 7 | def run_messy( 8 | config_filename: Path = None, application: Path = None, skip: List[str] = [] 9 | ): 10 | """ 11 | Run the messy toolchain with the given configuration file and application 12 | 13 | Args: 14 | config_filename: Path to the JSON input simulation settings 15 | application: Path to the application to simulate 16 | skip: List of steps to skip in the build process 17 | 18 | Returns: 19 | None 20 | """ 21 | if "clean" not in skip: 22 | subprocess.run(["make","clean"]) 23 | if "codegen" not in skip and config_filename.suffix == ".json": 24 | subprocess.run(["make","codegen",f"file={Path(config_filename).absolute()}"]) 25 | subprocess.run(["make", "format"]) 26 | if "codegen_ipxact" not in skip and config_filename.suffix == ".xml": 27 | subprocess.run(["make","codegen_ipxact",f"file={Path(config_filename).absolute()}"]) 28 | if "application" not in skip: 29 | subprocess.run(["make", "application", f"app={Path(application).absolute()}"]) 30 | subprocess.run(["make", "run"]) 31 | 32 | 33 | if __name__ == "__main__": 34 | # Create an argument parser with a description 35 | parser = argparse.ArgumentParser(description="Generate src code") 36 | 37 | # Add an argument for the input file path 38 | parser.add_argument( 39 | "-f", 40 | "--filename", 41 | type=str, 42 | default="codegen/pulp-open.json", 43 | metavar="PATH", 44 | help="Path to JSON input simulation settings", 45 | ) 46 | 47 | parser.add_argument( 48 | "-a", 49 | "--application", 50 | type=str, 51 | default="/messy/examples/helloworld", 52 | metavar="PATH", 53 | help="Path to the application to simulate", 54 | ) 55 | 56 | parser.add_argument( 57 | "--skip_clean", 58 | action="store_true", 59 | help="Skip the cleaning of the current build", 60 | ) 61 | 62 | parser.add_argument( 63 | "--skip_codegen", 64 | action="store_true", 65 | help="Skip the codegen part of the current build", 66 | ) 67 | 68 | parser.add_argument( 69 | "--skip_application", 70 | action="store_true", 71 | help="Skip the application regeneration part of the current build", 72 | ) 73 | 74 | # Parse the command line arguments 75 | args = parser.parse_args() 76 | 77 | config_filename = args.filename 78 | application = args.application 79 | 80 | # Convert the input file path to a Path object 81 | if args.filename: 82 | config_filename = Path(args.filename) 83 | if args.application: 84 | application = Path(args.application) 85 | 86 | skips = [] 87 | if args.skip_application: 88 | skips.append("application") 89 | if args.skip_codegen: 90 | skips.append("codegen") 91 | skips.append("codegen_ipxact") 92 | if args.skip_clean: 93 | skips.append("clean") 94 | run_messy(config_filename=config_filename, application=application, skip=skips) 95 | -------------------------------------------------------------------------------- /mkdocs.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2020 ETH Zurich and University of Bologna. 2 | # Licensed under the Apache License, Version 2.0, see LICENSE for details. 3 | # SPDX-License-Identifier: Apache-2.0 4 | 5 | site_name: MESSY 6 | repo_url: https://github.com/eml-eda/messy 7 | repo_name: eml-eda/messy 8 | theme: 9 | name: material 10 | features: 11 | - content.code.copy 12 | - content.code.annotate 13 | icon: 14 | admonition: 15 | note: octicons/tag-16 16 | abstract: octicons/checklist-16 17 | info: octicons/info-16 18 | tip: octicons/squirrel-16 19 | success: octicons/check-16 20 | question: octicons/question-16 21 | warning: octicons/alert-16 22 | failure: octicons/x-circle-16 23 | danger: octicons/zap-16 24 | bug: octicons/bug-16 25 | example: octicons/beaker-16 26 | quote: octicons/quote-16 27 | icon: 28 | repo: fontawesome/brands/github 29 | palette: 30 | # Palette toggle for light mode 31 | - scheme: default 32 | toggle: 33 | icon: material/brightness-7 34 | name: Switch to dark mode 35 | # Palette toggle for dark mode 36 | - scheme: slate 37 | toggle: 38 | icon: material/brightness-4 39 | name: Switch to light mode 40 | markdown_extensions: 41 | - admonition 42 | - pymdownx.details 43 | - attr_list 44 | - md_in_html 45 | - pymdownx.superfences: 46 | custom_fences: 47 | - name: mermaid 48 | class: mermaid 49 | format: !!python/name:pymdownx.superfences.fence_code_format 50 | 51 | nav: 52 | - Home: index.md 53 | - "What is MESSY": what-is-messy.md 54 | - "Getting started": getting-started.md 55 | - "Examples": 56 | - "Hello World": examples/hello-world.md 57 | - "Periodic Sensor": examples/periodic-sensor.md 58 | - "Flow": 59 | - "Flow": flow.md 60 | - "Codegen": codegen.md 61 | - "Timing and Communication": 62 | - "GVSoC - SystemC Timing": timing.md 63 | - "SystemC Modules Timing": communication-example.md 64 | - "IPXACT": 65 | - "IPXACT": ipxact.md 66 | - "IPXACT-Parsing": ipxact-parsing.md 67 | - "Building Blocks": 68 | - "Core": core.md 69 | - "Functional Bus": functional-bus.md 70 | - "Power Bus": power-bus.md 71 | - "Sensors": sensors.md 72 | - "Adapter": adapter.md 73 | - "Harvesters": harvesters.md 74 | - "Converters": converters.md 75 | - "LUT": lut.md 76 | - Others: 77 | - "Docker": docker.md 78 | - "Resolution": resolution.md 79 | - "Debugging": debugging.md 80 | - "Tracing": tracing.md 81 | - "How to build the documentation": how-to-build-docs.md 82 | 83 | 84 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | mkdocs-material==9.5.28 2 | Mako==1.3.9 3 | numpy==2.2.3 4 | pandas==2.2.3 5 | matplotlib==3.8.4 6 | argcomplete==3.5.3 7 | six==1.17.0 8 | rich==13.9.4 9 | pyelftools==0.32 10 | prettytable==3.15.1 -------------------------------------------------------------------------------- /utils/digitizer/mpp_calculator.py: -------------------------------------------------------------------------------- 1 | import os 2 | import pandas as pd 3 | import matplotlib.pyplot as plt 4 | import sys 5 | 6 | # Create the 'out' folder if it doesn't exist 7 | output_folder = 'out' 8 | os.makedirs(output_folder, exist_ok=True) 9 | 10 | # Get the CSV filename from command-line argument or use default 'digitized_data.csv' 11 | if len(sys.argv) > 1: 12 | csv_filename = sys.argv[1] 13 | else: 14 | csv_filename = 'digitized_data.csv' 15 | 16 | # Read the CSV file containing X and Y values 17 | data = pd.read_csv(csv_filename, header=None, names=['X', 'Y']) 18 | 19 | # Compute (X * Y) for each row 20 | data['X_times_Y'] = data['X'] * data['Y'] 21 | 22 | # Find the maximum power point (MPP) 23 | max_power_point = data.loc[data['X_times_Y'].idxmax()] 24 | 25 | # Save MPP data to a separate CSV file 26 | mpp_data = pd.DataFrame({'Voltage': [max_power_point['X']], 'Current': [max_power_point['Y']], 'Power': [max_power_point['X_times_Y']]}) 27 | mpp_data.to_csv(os.path.join(output_folder, 'mpp.csv'), index=False) 28 | 29 | # Generate a plot with only the maximum power point 30 | plt.plot(data['X'], data['Y']) 31 | plt.scatter(max_power_point['X'], max_power_point['Y'], color='red', label='MPP') 32 | plt.xlabel('Voltage (V)') 33 | plt.ylabel('Current (mA)') 34 | plt.legend() 35 | plt.grid(True) 36 | plt.savefig(os.path.join(output_folder, 'original_plot.png')) 37 | plt.close() 38 | 39 | # Generate a plot with V on the x-axis and P on the y-axis 40 | plt.plot(data['X'], data['X_times_Y']) 41 | plt.scatter(max_power_point['X'], max_power_point['X_times_Y'], color='red', label='MPP') 42 | plt.xlabel('Voltage (V)') 43 | plt.ylabel('Power (mW)') 44 | plt.legend() 45 | plt.grid(True) 46 | plt.savefig(os.path.join(output_folder, 'mpp_plot.png')) 47 | plt.close() 48 | 49 | print("Maximum power point data saved to 'out/mpp.csv'") 50 | print("Original plot with maximum power point saved as 'out/original_plot.png'") 51 | print("Plot of Voltage vs Power saved as 'out/mpp_plot.png'") 52 | -------------------------------------------------------------------------------- /utils/digitizer/plot1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eml-eda/messy/026551c39c4b89e32f853e50fcc8b89ac9725d6f/utils/digitizer/plot1.png -------------------------------------------------------------------------------- /utils/digitizer/readme.md: -------------------------------------------------------------------------------- 1 | # MPP Calculator 2 | 3 | This is a Maximum Power Point (MPP) calculator designed for Voltage vs Current plots of harvester units. It includes a plot digitizer, forked from [PythonPlotDigitizer](https://github.com/sjgallagher2/PythonPlotDigitizer). 4 | 5 | ## Python Plot Digitizer 6 | 7 | This is a plot digitizer written in Python using PyQt5 and Matplotlib. With an interface inspired partly by [WebPlotDigitizer](https://automeris.io/WebPlotDigitizer/), this app (with only 2 source files!) can handle multiple datasets with different plotting options, and can save the data, sorted, to csv. Linear, semi-log, and log-log plots are supported. 8 | 9 | 10 | 11 | ### Quick Guide 12 | 13 | Using the Python Plot Digitizer goes like this: 14 | 15 | * Start up, and load the image using "Browse Image" 16 | * Choose any 3 points (preferably on the axes and far apart) with their associated plot coordinates. Coordinates are entered "x,y" with the comma. Left click adds the next point, right click resets the previous point. Use the arrow keys to nudge points around. 17 | * After the coordinate system is set, the transformation is calculated, and you can start adding datapoints. Left-click adds new datapoints, right-click removes the last datapoint, and the arrow keys nudge the most recent datapoint. 18 | * You can change the dataset settings to customize the label, marker type, and marker color. You can also add new datasets. 19 | 20 | 21 | 22 | #### Features Not Yet Implemented 23 | 24 | The following are not yet implemented: 25 | 26 | * Load CSV Data - Loads a dataset onto the current image from a csv file 27 | * Edit Datapoints - Select, move, or delete datapoints 28 | * Redo - Use Ctrl-R to re-add a datapoint after deletion 29 | * Help - A help window to remind you how to use the application 30 | 31 | ## MPP Calculator 32 | 33 | The MPP Calculator is a tool designed to analyze Voltage vs Current plots of harvester units and identify their Maximum Power Point (MPP). It is built upon the Python Plot Digitizer, which facilitates the digitization of plots for further analysis. 34 | 35 | ### Features 36 | 37 | - Analyzes voltage-current plots to determine the MPP. 38 | - Provides visualization of the plot with the identified MPP highlighted. 39 | - Outputs the MPP data in a CSV file format for further analysis. 40 | 41 | ### Usage 42 | 43 | To use the MPP Calculator: 44 | 1. Provide the Voltage vs Current plot data. 45 | 2. Run the calculator script, specifying the CSV filename as a command-line argument if necessary. 46 | Example: `python mpp_calculator.py my_plot_data.csv` 47 | 3. Obtain the MPP data and visual representation of the plot with MPP highlighted for analysis. 48 | 49 | If no CSV filename is provided, the calculator will default to using 'digitized_data.csv'. 50 | -------------------------------------------------------------------------------- /utils/plotter/plotter.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import pandas as pd 3 | import matplotlib.pyplot as plt 4 | 5 | def plot_data(data, scale_factor=10): 6 | # Extract timestamp and values 7 | timestamp = data.iloc[:, 0] 8 | values = data.iloc[:, 1:] 9 | 10 | # Scale the first curve 11 | scaled_values = values.copy() 12 | scaled_values.iloc[:, 2] *= scale_factor 13 | 14 | # Plotting 15 | plt.figure(figsize=(10, 6)) 16 | plt.plot(timestamp, scaled_values.iloc[:, 2], label=f"{values.columns[2]} (scaled by {scale_factor})") 17 | plt.plot(timestamp, values.iloc[:, 3], label=values.columns[3]) 18 | plt.xlabel('Timestamp') 19 | plt.ylabel('Values') 20 | plt.title('Data Visualization') 21 | plt.legend() 22 | plt.grid(True) 23 | plt.xticks(rotation=45) 24 | plt.tight_layout() 25 | plt.show() 26 | 27 | if __name__ == "__main__": 28 | # Check if a filename is provided as command line argument 29 | if len(sys.argv) != 2: 30 | print("Usage: python plotter.py ") 31 | sys.exit(1) 32 | 33 | # Read the data file 34 | filename = sys.argv[1] 35 | try: 36 | with open(filename, 'r') as f: 37 | # Skip the first character 38 | f.read(1) 39 | # Read the remaining content of the file 40 | data = pd.read_csv(f, sep='\s+', skipinitialspace=True, comment='%') 41 | except FileNotFoundError: 42 | print("File not found!") 43 | sys.exit(1) 44 | except pd.errors.ParserError: 45 | print("Error parsing the file!") 46 | sys.exit(1) 47 | 48 | # Check if the file contains at least two columns 49 | if len(data.columns) < 2: 50 | print("File must contain at least two columns (timestamp and one value)!") 51 | sys.exit(1) 52 | 53 | # Plot the data with the first curve scaled 54 | plot_data(data) 55 | -------------------------------------------------------------------------------- /utils/plotter/readme.md: -------------------------------------------------------------------------------- 1 | # PLOTTER: A Data Plotting Script 2 | 3 | ## Overview 4 | This script is designed to read a data file, extract relevant information, and generate a visualization plot of the data. The script is written in Python and utilizes the Pandas library for data manipulation and Matplotlib for plotting. 5 | 6 | ## Requirements 7 | - Python 3.x 8 | - Pandas 9 | - Matplotlib 10 | 11 | ## Usage 12 | To run the script, use the following command: 13 | 14 | ```bash 15 | python plotter.py 16 | ``` 17 | 18 | ### Arguments 19 | - ``: The path to the data file you wish to visualize. The data file should be formatted as a space-separated values file with a timestamp in the first column and at least one additional column of values. 20 | 21 | ### Example 22 | ```bash 23 | python plotter.py sample_data.txt 24 | ``` 25 | 26 | ## Data File Format 27 | The data file should be formatted as follows: 28 | - Space-separated values 29 | - First column: Timestamps 30 | - Subsequent columns: Data values 31 | 32 | Comments in the file should start with the `%` character. The script expects the first character in the file to be skipped (e.g., a leading comment character). 33 | 34 | ### Sample Data File 35 | ``` 36 | % Sample Data 37 | timestamp value1 value2 value3 38 | 2021-01-01 10 20 30 39 | 2021-01-02 15 25 35 40 | 2021-01-03 20 30 40 41 | ``` 42 | 43 | ## Features 44 | - Reads a space-separated data file 45 | - Skips the first character of the file (useful for skipping a leading comment character) 46 | - Parses the file and checks for at least two columns 47 | - Plots three specific columns of data against the timestamp (Currently: columns 2 and 3. Could be modified according to necessities) 48 | -------------------------------------------------------------------------------- /utils/resolutioner/readme.md: -------------------------------------------------------------------------------- 1 | # PV Panel Trace File Reading Frequency Workaround 2 | 3 | ## Overview 4 | 5 | The current photovoltaic (PV) panel simulator reads one line from the PV panel trace file based on the system resolution set in the configuration file. If the resolution is set to seconds, each value in the trace file must represent samplings taken at one-second intervals. To match a different resolution, a workaround involves repeating each value in the trace file to achieve the desired resolution. 6 | 7 | ## Script: resolutioner.py 8 | 9 | ### Description 10 | 11 | `resolutioner.py` is a simple Python script designed to adjust the sampling resolution of a PV panel trace file by repeating each line a specified number of times. The argument `` should be calculated as: 12 | 13 | ``` 14 | num_repeats = old_resolution / new_resolution 15 | ``` 16 | 17 | ### Usage 18 | 19 | 1. Ensure you have Python installed on your system. 20 | 2. Open your terminal or command prompt. 21 | 3. Run the script with the following command: 22 | 23 | ```bash 24 | python resolutioner.py 25 | ``` 26 | 27 | - : The path to the PV panel trace file. 28 | - : The path to the output file where the adjusted resolution trace will be saved. 29 | - : The number of times each line should be repeated to match the desired resolution. 30 | 31 | #### Example 32 | If the original resolution is 1 second and you want to change it to 0.1 seconds, you would set num_repeats to 10: 33 | 34 | ```bash 35 | python resolutioner.py trace_file.txt adjusted_trace_file.txt 10 36 | ``` 37 | -------------------------------------------------------------------------------- /utils/resolutioner/resolutioner.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | def repeat_lines(input_file, output_file, num_repeats): 4 | try: 5 | with open(input_file, 'r') as file: 6 | lines = file.readlines() 7 | 8 | total_lines = len(lines) 9 | with open(output_file, 'w') as file: 10 | for i, line in enumerate(lines): 11 | for _ in range(num_repeats): 12 | file.write(line) 13 | print(f"Progress: {((i+1)/total_lines)*100:.2f}%") 14 | except FileNotFoundError: 15 | print(f"The file {input_file} does not exist.") 16 | except Exception as e: 17 | print(f"An error occurred: {e}") 18 | 19 | if __name__ == "__main__": 20 | if len(sys.argv) != 4: 21 | print("Usage: python resolutioner.py ") 22 | else: 23 | input_file = sys.argv[1] 24 | output_file = sys.argv[2] 25 | num_repeats = int(sys.argv[3]) 26 | repeat_lines(input_file, output_file, num_repeats) 27 | --------------------------------------------------------------------------------