├── .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 |
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 | 
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 | 
--------------------------------------------------------------------------------
/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 | 
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 | 
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 | 
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 |
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 | 
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 | 
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 |
--------------------------------------------------------------------------------