diff --git a/.readthedocs.yaml b/.readthedocs.yaml new file mode 100644 index 00000000..81a18992 --- /dev/null +++ b/.readthedocs.yaml @@ -0,0 +1,35 @@ +# Read the Docs configuration file for Sphinx projects +# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details + +# Required +version: 2 + +# Set the OS, Python version and other tools you might need +build: + os: ubuntu-22.04 + tools: + python: "3.12" + # You can also specify other tool versions: + # nodejs: "20" + # rust: "1.70" + # golang: "1.20" + +# Build documentation in the "docs/" directory with Sphinx +sphinx: + configuration: docs/conf.py + # You can configure Sphinx to use a different builder, for instance use the dirhtml builder for simpler URLs + # builder: "dirhtml" + # Fail on all warnings to avoid broken references + # fail_on_warning: true + +# Optionally build your docs in additional formats such as PDF and ePub +formats: + - pdf +# - epub + +# Optional but recommended, declare the Python requirements required +# to build your documentation +# See https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html +python: + install: + - requirements: docs/requirements.txt \ No newline at end of file diff --git a/docs/conf.py b/docs/conf.py index 8afcd2c4..b062bafc 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -30,7 +30,7 @@ # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. -extensions = ['sphinx.ext.autosectionlabel', 'sphinx_panels', 'sphinx_copybutton', ] +extensions = ['sphinx.ext.autosectionlabel', 'sphinx_design', 'sphinx_copybutton', 'sphinx.ext.graphviz'] copybutton_prompt_text = r">>> |\.\.\. |\$ |In \[\d*\]: | {2,5}\.\.\.: | {5,8}: " copybutton_prompt_is_regexp = True diff --git a/docs/diagrams/AtomBones.drawio b/docs/diagrams/AtomBones.drawio new file mode 100644 index 00000000..89aaf8bc --- /dev/null +++ b/docs/diagrams/AtomBones.drawio @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/diagrams/AtomBones.png b/docs/diagrams/AtomBones.png new file mode 100644 index 00000000..969aba99 Binary files /dev/null and b/docs/diagrams/AtomBones.png differ diff --git a/docs/diagrams/HydrogenSoC.drawio b/docs/diagrams/HydrogenSoC.drawio index c02cce34..cbd7a18c 100644 --- a/docs/diagrams/HydrogenSoC.drawio +++ b/docs/diagrams/HydrogenSoC.drawio @@ -1 +1,178 @@ -7Vrbcts2EP0aPSZDghdRj7IsN53W006cjt2nDkRAJGqIUEAokvL1BUWAN8C27JC2rPRFQxxcCJ7dPbugOPJmq90vHK7Ta4YwHQEH7Ube5QiAKIzkbwHsS8AfOyWQcIJKyK2BG/IdK1AP2xCE89ZAwRgVZN0GY5ZlOBYtDHLOtu1hS0bbd13DBBvATQypid4SJFL1WIFT458wSVJ9Z9dRPSuoBysgTyFi2wbkzUfejDMmyqvVboZpwZ3mpZx39UBvtTGOM3HMhN/+EIw7t5er++9zN5he4a/z9Qfgl8t8g3SjnljtVuw1BZxtMoSLVdyRd7FNicA3axgXvVtpc4mlYkVVN+SxMqInWwjmaTVT3QlzgXcPPoNbMSM9CrMVFnwvh+gJE0Wm8ibd3Nam8UOFpU2z6IFQuUNSLV0zJi8Uac8g0HsOf87T/C0JpTNGGT/M9ZbLJYhjieeCs3vc6EHhIgzCfmj1QJvWyokbvLpWXr2heHVNHjGSkamajIuUJSyDdF6jF22m6zG/M7ZW/P6LhdgrD4Ubwdrs4x0Rd43rv4ulPgaqdblTKx8ae93I5PPeNRuNWUWznnZo6Xm5gFxMC4mSQExhnpNYw1eE6i2VhtfaAyqDF2w8bm5JHtvwGD/GslJUyBMsHhkX2t2HYwoF+dbeR/+uYITYVLDVCIRUbvliweVVUlzNGMf9Bl8UY3vwLaLAD5yegi/sBB8wgy+yxF40VOiZKeGW5OmCZZJd51aStsbc4Fk+v2iT2SYtK6a3GVYQpCTJihCQfMmFvYuCTSIz8FR1rAhCh/C2Wa9t3z7M4bfNAWxaCCz2AINJoWuwfXZSOKDGBUdq3ANu8ToaFwxbRmAXBXhsU7JJOPZgX2WE21EyzwwdW+SEg0WOd/6R8/ZFRHhkgEVvWkT45+8KJ2DjyQ/a+DBV+jPcNwasGclE3lj5zwKodSfoHl/Czkn4ifEgcDr+Ve6g9rbqUV7ugOE5KHz19uZkFN4xWPw/rI8P6/GRYR28pXSPjcj59Xp+3Wv0IIijpfWkF8YRXiz7iZ7qKHEqJ73IYPbyfTIbBCfGrDs5HV0CjwtTq4RUZ/Jm/WiKkNuvCPVSMxhJPuykKpkIP0bOJACe+m0vWEqgWqNj/B6yPzihPDV+hj8ce6Q43CFDHTeSSMOJ3p/LdMuWgZ1kYsjxX9PPX8wXndcMbWi/rzpl8Rgh3ybTEVh4YU/lY1emgaV8tMm0P5RM60doUP7lziTcRD7fGfSfzRtQIwx800q+xUqDvQAFtrNTaZElOwRwbYbw64bpjg/5QRincoAbrHd1p2FXDXzaI84SnN2wme6TO150x0usvLGGT9IV+v7ztVu+2vzidd+MA/NoYKbZOivVycywTCuPveB012NuAw8ktwbLgYVkjf1gDnS7J3y3Y7xy/0YONBeaPLHQ0BWXebh5/77hOW/qG91/Krv10Yt9o/sZwdC+YVZaMb3/h/wkQu4e8bnHqyZ4bf6GPXgufl57WN5e9GQP2ay/OCvDqf5sz5v/Bw== \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/diagrams/HydrogenSoC.png b/docs/diagrams/HydrogenSoC.png index b2c5aae4..548687af 100644 Binary files a/docs/diagrams/HydrogenSoC.png and b/docs/diagrams/HydrogenSoC.png differ diff --git a/docs/diagrams/RISCVAtom_arch.drawio b/docs/diagrams/RISCVAtom_arch.drawio new file mode 100644 index 00000000..0f2934d1 --- /dev/null +++ b/docs/diagrams/RISCVAtom_arch.drawio @@ -0,0 +1,635 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/diagrams/RISCVAtom_arch.png b/docs/diagrams/RISCVAtom_arch.png new file mode 100644 index 00000000..32292edf Binary files /dev/null and b/docs/diagrams/RISCVAtom_arch.png differ diff --git a/docs/diagrams/memory_map.drawio b/docs/diagrams/memory_map.drawio index 08ab7f92..32f6f010 100644 --- a/docs/diagrams/memory_map.drawio +++ b/docs/diagrams/memory_map.drawio @@ -1 +1,232 @@ -7Vptc5s4EP41nul1Jh1ABuOPjtNLO3O5dpoP9/JNRmujCSAq5Njurz8JhA2IujRB47RXZ8aRVmKRnmdZ7a6ZoGW6v+U4j+8YgWTiOWQ/QTcTzwuDUH4rwaESuP7MqSQbTomWnQT39AtoYT1tSwkUrYmCsUTQvC2MWJZBJFoyzDnbtaetWdK+a443YAjuI5yY0r8oEbHel++c5O+AbuL6zq6jR1JcT9aCIsaE7Roi9HaClpwxUbXS/RISBV6NS3Xd718ZPS6MQyaGXLC7XTLnLkeP+N8/0Z27+Lx4/8eV1vKIk63e8JuVWlG1YnGoYeBsmxFQmpwJut7FVMB9jiM1upPES1ks0kT2XNlc0yRZsoTx8lq09tWfkrNMNOTVR8rNndTLAi5g3xDpnd0CS0Hwg5xSjwYaZW1nKNT93Yk0t2YibhBWy7C2k81R9QlK2dBofgeynonsozRQufkxsQWX+DCzhGFwaQyRiaHcy7jWSTCE68gOgt58IIIzWwhOTQQ5I1jgcTH0ISRTSxj6AzGc2sLQNzEcHcH1GoLIkhW6Q59jawgGPadMUYwM4NqzBqB3aQBnBoAxSECeBSDBRVzOVZ0Nx4RC63ieAQ7AOeMwC8HZAzRGgiiE1doOB0M9KbJFQWhQUAgcPdjlYD4jzmx2xuEaHITeCgVBQ9sN5TLsoCyT4xnjCrxR+bkYIXODkPEcSsYysGPHV9OBuB0vHB24OrU6hxxkZKGyJ9mLElwUNGqDBXsq/la4vvF17x+Nsmrf7Judg+58Fc2CbXkE33Z/QFq5mol5A1O/B9JaxiHBgj62M7w+mPUdPjIqV3yk1HP6XVOtodqOvqiZkHX1eG093SBQYL4BYegpOT9u+hlmYOZ+I5mBa8kMwhdlBmjaps8fyQy6emybgZmoTrwgETpfb9lD8HnL6oGroqzVLOQE1833JbH1uGxt1H9n7+hPrVIusdJaTTAMrkzvWibWPuG0Y+7x1TihG3XGRdKsQMqvlY+mEU4WeiClhKjb9J4D7ZOidSyr9eq6lOuOcyjM24yjnuAm6DsSrJ0IZqI9tg24v2zgvA3MLm0DZqngSTbQbwDuD+4ExifcvfhDb2blYxI+/UV4J/J3L024WUU4F/BphFuodFLXj1hI1LNS4jnoyFv9Swn6Htf5QsK6bjhmFHWeGtcZxNoO7MyKBZWKmMH50ysWXW6NasQq9Kd+Tw1pHUZgq1o3OMO2Vq1DfZ61A3oR41w1oy1PDtccRw8gvo3+iaoS/oTm74ZSoeNwW3UO1EmKj0lyg4X+346ssTDA3f20LFwOddPrfFrcScErN3j47fULPfotxPcItR+InnBv2suMLWLMeumnDyUxwfT/RUz3XL40M/XNnhGIz/vicMmpU1EsJThV4FbfSl4+k0pBMVHvqih8VqBEKS5XTCCXsSDNNrK9zVmmNpHmCaQSeFz+nPBDxfY27GjI6xJ9geoT4g7ZPb0oVAWIp9et0Nv/AA== \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/diagrams/memory_map.png b/docs/diagrams/memory_map.png index 42f00ad0..bd3613d1 100644 Binary files a/docs/diagrams/memory_map.png and b/docs/diagrams/memory_map.png differ diff --git a/docs/index.rst b/docs/index.rst index de60d188..7117968c 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -11,15 +11,15 @@ RISC-V Atom Documentation & User Manual **************************************** +Welcome to RISC-V Atom Documentation and User Manual! Please follow the :doc:`getting started guide` +to setup an environment to build and test the RISC-V Atom project. Please feel free file a bug report in github. + .. toctree:: :maxdepth: 1 :caption: Overview pages/overview/introduction.rst - pages/overview/components.rst pages/overview/directory_structure.rst - pages/overview/performance.rst - pages/overview/fpga_results.rst .. toctree:: @@ -28,18 +28,25 @@ RISC-V Atom Documentation & User Manual pages/getting_started/prerequisites.rst pages/getting_started/building.rst + pages/getting_started/docker.rst pages/getting_started/examples.rst .. toctree:: - :maxdepth: 2 + :maxdepth: 1 :caption: Documentation & User Manual - pages/documentation/riscv_atom/riscv_atom.rst + pages/documentation/riscv_atom.rst pages/documentation/soc_targets.rst + pages/documentation/memory_map.rst + pages/documentation/bootloader.rst pages/documentation/atomsim/atomsim.rst pages/documentation/scar.rst pages/documentation/convelf.rst + pages/documentation/libcatom.rst + pages/documentation/build_flow.rst + pages/documentation/performance.rst + pages/documentation/fpga_results.rst Indices and tables diff --git a/docs/pages/documentation/atomsim/adding_target.rst b/docs/pages/documentation/atomsim/adding_target.rst deleted file mode 100644 index 020bb8b3..00000000 --- a/docs/pages/documentation/atomsim/adding_target.rst +++ /dev/null @@ -1,4 +0,0 @@ -Adding a New Target to AtomSim -############################### - -This is a placeholder \ No newline at end of file diff --git a/docs/pages/documentation/atomsim/atomsim.rst b/docs/pages/documentation/atomsim/atomsim.rst index b000014b..2cd27ee5 100644 --- a/docs/pages/documentation/atomsim/atomsim.rst +++ b/docs/pages/documentation/atomsim/atomsim.rst @@ -2,26 +2,54 @@ AtomSim: A simulation tool for Atom based SoCs ############################################### AtomSim is an interactive RTL simulator for Atom based SoCs. It provides an interface which is similar to the RISC-V -Spike simulator, but simulates the actual RTL in the backend. Atomsim is a modular and flexible simulaion solution -based on Verilator, due to which it can achieve a very high simulation rate. AtomSim is a feature rich tool which makes -it very powerful for debugging code on the Atom CPU. +Spike simulator, but simulates the actual RTL in the backend. AtomSim is a feature rich tool which makes it very powerful +for debugging code on the Atom CPU. Key Features of AtomSim are listed below: #. Achieves a high simulation rate due to use of Verilator. #. Target Configurable, can be easily extended for new SoC designs. #. In-built debug mode similar to spike. -#. External Debug Support using OpenOCD & GDB ``[TODO]``. +#. External Debug Support using OpenOCD & GDB **[TODO]**. #. Supports VCD trace generation. #. Supports memory dumps. #. Compatible with RISC-V compliance tests framework. #. Compatible with SCAR framework. -The following figure depicts the architecture of atomsim. +.. tip:: + See :doc:`../../getting_started/building` for info on how to build AtomSim. + +The following figure depicts the architecture of AtomSim. .. image:: ../../../diagrams/atomsim_arch.png -See :doc:`../../getting_started/building` for info on how to build atomsim. +.. _atomsim_arch: + +AtomSim Architecture +********************* +AtomSim is designed in a modular fashion with a clear API between the layers. There are 3 main layers in AtomSim, +1) frontend, 2) middle-end, and 3) backend. + +Frontend +========= +Frontend is the interactive part of the simulator. User can interact with AtomSim in the following two modes of operation. + +#. :ref:`Normal Mode ` +#. :ref:`Debug Mode ` + + +Middle-end +=========== +Middle-end contains references to signals and states of the CPU. These states and signal values are set by the backend +and read by the frontend to display information. + + +Backend +======== +Backend is the part which probes the signal values and CPU state from the RTL. All backends extend from the ``Backend`` +class. + + To view available command line options, use: @@ -30,15 +58,6 @@ To view available command line options, use: $ atomsim --help -Modes of Operation -******************* -Atomsim supports two modes of operation: - -.. toctree:: - :maxdepth: 1 - - debug_mode.rst - normal_mode.rst AtomSim Topics @@ -46,7 +65,6 @@ AtomSim Topics .. toctree:: :maxdepth: 1 - cli_args.rst - code_structure.rst - adding_target.rst + atomsim_modes.rst + atomsim_developers_guide.rst diff --git a/docs/pages/documentation/atomsim/atomsim_developers_guide.rst b/docs/pages/documentation/atomsim/atomsim_developers_guide.rst new file mode 100644 index 00000000..3a04a4d2 --- /dev/null +++ b/docs/pages/documentation/atomsim/atomsim_developers_guide.rst @@ -0,0 +1,31 @@ +AtomSim Developer's Guide +########################## + +AtomSim Code Structure +======================= + +AtomSim is designed in a modular fashion to allow portability across platforms not just limited to RISC-V Atom. Checkout +:ref:`AtomSim architecture`. The source code for atomsim is located under ``RVATOM/sim`` folder. Atomsim +comprises of an interactive frontend (implemented in ``interactive.cpp``), middle-end (implemented in ``simstate.cpp``) +and a backends for different *soctargets* (implemened in ``backend_.cpp``). All AtomSim backends are +implemented as a child-class of the *Backend* template class (implemented in ``backend.hpp``). The backend class +implements the RTL facing side of AtomSim and is responsible for reading register values and driving any signals through +the *Testbench* class (implemented in ``testbench.hpp``). + +Adding a New Backend to AtomSim +================================ + +- Adding new backend involves adding a new backend class that extends the *Backend* class (in ``backend.hpp``). +- All soctarget backends must override all the methods marked with ``[** OVERRIDE **]`` comment in the *Backend* class + (parent) as bare-minimum. +- The methods marked with ``[** MAY OVERRIDE **]`` can optionally be overriden in child classes depending on the intended + functionality. +- To allow AtomSim to *peek* and *poke* into SoC memory, user must override the ``fetch()`` and ``store()`` methods. +- The backend may optioanlly use the testbench class from (``testbench.hpp``) to implement the low-level RTL facing + functionality. +- Users can use the *BitbangUART* class is provided in the ``bitbang_uart.cpp`` to emulate a UART device being connected + to SoC. Additioanlly, the *Vuart* class is provided in ``vuart.cpp`` can be used to interface with linux serial ports. +- Users may intend to not simulate the whole SoC in RTL and therefore they can create their own C++ modules to emulate + some functionality and call them from their backends. One example of this is the :ref:`AtomBones` + soctarget which only simulates the processor in RTL, everything else like memories (implemented in ``memory.cpp``), + uart, etc. is emulated in C++. \ No newline at end of file diff --git a/docs/pages/documentation/atomsim/atomsim_modes.rst b/docs/pages/documentation/atomsim/atomsim_modes.rst new file mode 100644 index 00000000..0192b70e --- /dev/null +++ b/docs/pages/documentation/atomsim/atomsim_modes.rst @@ -0,0 +1,98 @@ +AtomSim Simulation Modes +######################### + +.. _atomsim_normal_mode: + +AtomSim can be run in 2 modes, normal and interactive mode. + +Normal Mode +************ +In this mode of simulation, no debug information is printed. Optionally user can enable printing of UART traffic to +stdout using ``--enable-uart-dump / -u`` CLI option while invoking atomsim. Using ``--verbose / -v`` flag shows +additional useful information. Checkout :doc:`cli_args` for information on CLI options. + +.. code-block:: bash + + $ atomsim sw/examples/banner/banner.elf -v + ___ __ _____ + / _ |/ /____ __ _ / __(_)_ _ + / __ / __/ _ \/ ' \_\ \/ / ' \ + /_/ |_\__/\___/_/_/_/___/_/_/_/_/ v2.2 + soctarget: hydrogensoc + Initializing ram + Initialization complete! + EBreak hit at 0x2000007c + Exiting.. + + +.. _atomsim_debug_mode: + +Debug/Interactive Mode +*********************** +Debug/Interactive mode of AtomSim presents a console interface to the user, allowing them to interact with the simulation +in real-time. The console is similar to the GDB console and inherits many features from it like stepping, breakpoints etc. + +To invoke AtomSim in interactive debug mode, invoke atomsim with ``--debug / -d`` flag. + +.. code-block:: bash + + ___ __ _____ + / _ |/ /____ __ _ / __(_)_ _ + / __ / __/ _ \/ ' \_\ \/ / ' \ + /_/ |_\__/\___/_/_/_/___/_/_/_/_/ v2.2 + [ 1] PC: 0x00000000, IR: 0x00000013, _ + atomsim> + + +As shown above, AtomSim will display the current cycle count, PC value, Instruction Register value and its disassembly +respectively. To see register file contents, users can use the ``info / i`` command in the AtomSim console. + +Alternatively, If invoked with both ``--debug / -d`` and ``--verbose / -v`` CLI options, AtomSim presents a more verbose +interface with register file contents in each cycle. + +.. code-block:: bash + + ___ __ ____ + / _ |/ /____ __ _ / __(_)_ _ + / __ / __/ _ \/ ' \_\ \/ / ' \ + /_/ |_\__/\___/_/_/_/___/_/_/_/_/ v2.2 + soctarget: hydrogensoc + Initializing ram + Initialization complete! + ┌─[ 1]─────────────────────────────────────────────┐ + │ PC: 0x00000000 PC_f: 0x00010000 ( +65536 ) │ + │ IR: 0x00000013 _ │ + └──────────────────────────────────────────────────────────┘ + x0 (zero) : 0x00000000 x16 (a6) : 0x00000000 + x1 (ra) : 0x00000000 x17 (a7) : 0x00000000 + x2 (sp) : 0x00000000 x18 (s2) : 0x00000000 + x3 (gp) : 0x00000000 x19 (s3) : 0x00000000 + x4 (tp) : 0x00000000 x20 (s4) : 0x00000000 + x5 (t0) : 0x00000000 x21 (s5) : 0x00000000 + x6 (t1) : 0x00000000 x22 (s6) : 0x00000000 + x7 (t2) : 0x00000000 x23 (s7) : 0x00000000 + x8 (s0/fp): 0x00000000 x24 (s8) : 0x00000000 + x9 (s1) : 0x00000000 x25 (s9) : 0x00000000 + x10 (a0) : 0x00000000 x26 (s10) : 0x00000000 + x11 (a1) : 0x00000000 x27 (s11) : 0x00000000 + x12 (a2) : 0x00000000 x28 (t3) : 0x00000000 + x13 (a3) : 0x00000000 x29 (t4) : 0x00000000 + x14 (a4) : 0x00000000 x30 (t5) : 0x00000000 + x15 (a5) : 0x00000000 x31 (t6) : 0x00000000 + atomsim> + +Try the ``help`` command to checkout the commands available in AtomSim console. + +Tips for using AtomSim in interactive mode +=========================================== +- If simulation is run in normal mode, pressing :kbd:`ctrl` + :kbd:`c` returns AtomSim to interactive mode and pressing + :kbd:`ctrl` + :kbd:`c` in interactive mode terminates the simulation. +- AtomSim has shorter aliases for most of the command names which can be seen in command help. +- AtomSim console is based on the linux readline library which allows user to press :kbd:`up` / :kbd:`down` arrow keys + to cycle between previously entered commands. +- If user presses :kbd:`enter` without entering a command, AtomSim executes the last executed command. +- When entering numeric values in console such as addresses, users can specify in decimal, hexadecimal (by prefixing + the value with **0x**), or binary (by prefixng the value with **0b**). +- Register names can be specified as physical register names (*x0, x1, x2 ...*) or their ABI names (*zero, ra, sp...*) +- Some of effects of CLI arguments can be overridden in the AtomSim console, like enabling/disabling trace, verbosity etc. +- Lastly, refer to the ``help`` command to find most up-to-date information related to the AtomSim console. diff --git a/docs/pages/documentation/atomsim/cli_args.rst b/docs/pages/documentation/atomsim/cli_args.rst index 36137a07..a338ae6d 100644 --- a/docs/pages/documentation/atomsim/cli_args.rst +++ b/docs/pages/documentation/atomsim/cli_args.rst @@ -1,29 +1,66 @@ AtomSim CLI Argument Reference ############################### -The following are the arguments that may be passed to the AtomSim executable. +Following are the arguments that may be passed to the AtomSim executable. -.. code-block:: text - - Usage: - $ atomsim [OPTION...] input_file ++--------+---------------------+------------------------------------------------+----------------------------------------+ +| Option | Long Option | Function | Default value | ++========+=====================+================================================+========================================+ +| **General Options** | ++--------+---------------------+------------------------------------------------+----------------------------------------+ +| -h | --help | Show this message | | ++--------+---------------------+------------------------------------------------+----------------------------------------+ +| | --version | Show version information | | ++--------+---------------------+------------------------------------------------+----------------------------------------+ +| | --soctarget | Show current AtomSim SoC target | | ++--------+---------------------+------------------------------------------------+----------------------------------------+ +| | --no-color | Don't show colored output | | ++--------+---------------------+------------------------------------------------+----------------------------------------+ +| | --no-banner | Don't show banner | | ++--------+---------------------+------------------------------------------------+----------------------------------------+ +| -i | --input arg | Specify an input file | | ++--------+---------------------+------------------------------------------------+----------------------------------------+ +| **Debugging Options** | ++--------+---------------------+------------------------------------------------+----------------------------------------+ +| -v | --verbose | Turn on verbose output | | ++--------+---------------------+------------------------------------------------+----------------------------------------+ +| -d | --debug | Start in debug mode | | ++--------+---------------------+------------------------------------------------+----------------------------------------+ +| -t | --trace | Enable VCD tracing | | ++--------+---------------------+------------------------------------------------+----------------------------------------+ +| | --trace-file arg | Specify trace file | trace.vcd | ++--------+---------------------+------------------------------------------------+----------------------------------------+ +| | --dump-file arg | Specify dump file | dump.txt | ++--------+---------------------+------------------------------------------------+----------------------------------------+ +| | --ebreak-dump | Enable processor state dump at hault | | ++--------+---------------------+------------------------------------------------+----------------------------------------+ +| | --signature arg | Enable signature dump at hault | | +| | | (Used for riscv compliance tests) | "" | ++--------+---------------------+------------------------------------------------+----------------------------------------+ +| **Sim Config Options** | ++--------+---------------------+------------------------------------------------+----------------------------------------+ +| | --maxitr arg | Specify maximum simulation iterations | 1000000 | ++--------+---------------------+------------------------------------------------+----------------------------------------+ +| **Backend Config Options (Common)** | ++--------+---------------------+------------------------------------------------+----------------------------------------+ +| -u | --enable-uart-dump | Enable dumping UART data (from soc) to stdout | | ++--------+---------------------+------------------------------------------------+----------------------------------------+ +| -p | --vuart-port arg | serial port for virtual UART | "" | ++--------+---------------------+------------------------------------------------+----------------------------------------+ +| -b | --vuart-baud arg | serial baud rate for virtual UART | 115200 | ++--------+---------------------+------------------------------------------------+----------------------------------------+ +| **Backend Config Options (AtomBones)** | ++--------+---------------------+------------------------------------------------+----------------------------------------+ +| | --bootrom-size arg | Specify size of bootrom to simulate (in KB) | 8 | ++--------+---------------------+------------------------------------------------+----------------------------------------+ +| | --bootrom-image arg | Specify bootrom hex image | ${RVATOM}/sw/bootloader/bootloader.hex | ++--------+---------------------+------------------------------------------------+----------------------------------------+ +| | --ram-size arg | Specify size of RAM memory to simulate (in KB) | 81920 | ++--------+---------------------+------------------------------------------------+----------------------------------------+ +| **Backend Config Options (HydrogenSoC)** | ++--------+---------------------+------------------------------------------------+----------------------------------------+ +| | --bootmode arg | Specify bootmode signal | 1 | ++--------+---------------------+------------------------------------------------+----------------------------------------+ - Config options: - --maxitr arg Specify maximum simulation iterations (default: 10000000) - --vuart arg use provided virtual uart port (default: Null) - --vuart-baud arg Specify virtual uart port baudrate (default: 9600) - Debug options: - -v, --verbose Turn on verbose output - -d, --debug Start in debug mode - -t, --trace Enable VCD tracing - --trace-dir arg Specify trace directory (default: build/trace) - --dump-dir arg Specify dump directory (default: build/trace) - --ebreak-dump Enable processor state dump at hault - --signature arg Enable signature sump at hault (Used for riscv - compliance tests) (default: "") - - General options: - -h, --help Show this message - --version Show version information - --simtarget Show current AtomSim Target - -i, --input arg Specify an input file +.. note:: + For most up-to-date information, run ``atomsim --help`` command. diff --git a/docs/pages/documentation/atomsim/code_structure.rst b/docs/pages/documentation/atomsim/code_structure.rst deleted file mode 100644 index 927af680..00000000 --- a/docs/pages/documentation/atomsim/code_structure.rst +++ /dev/null @@ -1,4 +0,0 @@ -AtomSim Code Structure -####################### - -This is a Placeholder \ No newline at end of file diff --git a/docs/pages/documentation/atomsim/debug_mode.rst b/docs/pages/documentation/atomsim/debug_mode.rst deleted file mode 100644 index 41237068..00000000 --- a/docs/pages/documentation/atomsim/debug_mode.rst +++ /dev/null @@ -1,149 +0,0 @@ -Debug/Interactive Mode -####################### -In this mode of simulation, Contents of Program counter (in both stages), Instruction register, instruction disassembly and contents of registers (if verbosity is set) are printed to stdout. A console with symbol ``:`` is also displayed at the bottom if screen for user to enter various commands to control the simulation. To step through one clock cycle, user can simply press :kbd:`enter` key (without entering anything in console). - -To invoke interactive debug mode, invoke atomsim with `-d` & `-v` flag: - -:: - - $ ./build/bin/atomsim hello.elf -d -v - Segments found : 2 - Loading Segment 0 @ 0x00000000 --- done - Loading Segment 1 @ 0x00010000 --- done - Entry point : 0x00000000 - Initialization complete! - : - -< 1 >-------------------------------------------- - F-STAGE | pc : 0x00000034 (+4) () - E-STAGE V pc : 0x00000000 ir : 0x00010517 [addi x1, 0x33f] - --------------------------------------------------- - x0 (zero) : 0x00000000 x16 (a6) : 0x00000000 - x1 (ra) : 0x00000000 x17 (a7) : 0x00000000 - x2 (sp) : 0x00000000 x18 (s2) : 0x00000000 - x3 (gp) : 0x00000000 x19 (s3) : 0x00000000 - x4 (tp) : 0x00000000 x20 (s4) : 0x00000000 - x5 (t0) : 0x00000000 x21 (s5) : 0x00000000 - x6 (t1) : 0x00033000 x22 (s6) : 0x00000400 - x7 (t2) : 0x00000000 x23 (s7) : 0x00000000 - x8 (s0/fp): 0x00000000 x24 (s8) : 0x00000000 - x9 (s1) : 0x00000000 x25 (s9) : 0x00000000 - x10 (a0) : 0x00000000 x26 (s10) : 0x00000000 - x11 (a1) : 0x00000000 x27 (s11) : 0x00000000 - x12 (a2) : 0x00000000 x28 (t3) : 0x00000000 - x13 (a3) : 0x00000000 x29 (t4) : 0x00000000 - x14 (a4) : 0x00000000 x30 (t5) : 0x00000000 - x15 (a5) : 0x00000000 x31 (t6) : 0x00000000 - : - - -Interacting With Debug Console -******************************* - -Displaying contents of a register -================================== -Contents of register can be displayed simply typing its name (abi names are also supported) on the -console. ex: - -:: - - : reg x0 - x0 = 0x000045cf - : reg ra - ra = 0x0000301e - -Use ':' to display a range of registers. ex: - -:: - - : x0 : x1 - - -Displaying Contents of a memory location -======================================== -:: - - : m
- -Address can be specified in hex or decimal. -Use sizetag to specify the size of data to be fetched, b for byte, h for half-word and w for word -(default is word). - -:: - - : m 0x30 b - mem[0x30] = 01 - -Use ':' to display contents of memory in a range. ex: - -:: - - : m 0x32:0x38 w - mem[0x30] = 01 30 cf 21 - mem[0x38] = 11 70 ab cf - - -Generating VCD traces -===================== -Tracing can be enabled by: - -:: - - : trace out.vcd - Trace enabled : "./out.vcd" opened for output. - -or by passing --trace option while invoking atomsim. - -Tracing can be disabled by: - -:: - - :notrace - Trace disabled - - -Controlling execution -===================== -You can advance the simulation by one clock cycle by pressing the enter-key. You can also execute -until a desired equality is reached: - -1. until value of a register becomes - :: - - : until - -2. until value of a memory address
becomes - :: - - : until
- -3. while is true - :: - - : while - -4. Execute for specified number of ticks - :: - - : for - -5. You can continue execution indefinitely by: - :: - - : r - -6. To end the simulation from the debug prompt: - :: - - : q - - or - - :: - - : quit - - .. note:: - At any point during execution (even without -d), you can enter the interactive debug mode with :kbd:`ctrl` + :kbd:`c`. - -7. Miscellaneous - verbose-on & verbose off commands can be used to turn on /off verbosity. diff --git a/docs/pages/documentation/atomsim/normal_mode.rst b/docs/pages/documentation/atomsim/normal_mode.rst deleted file mode 100644 index 010341b6..00000000 --- a/docs/pages/documentation/atomsim/normal_mode.rst +++ /dev/null @@ -1,29 +0,0 @@ -Normal Mode -############ - -In this mode of simulation, no debug information is printed. Only serial data recieved from the system is printed to the stdout. Using ``--verbose / -v`` flag shows additional useful information. - -.. code-block:: bash - - $ atomsim sw/examples/banner/banner.elf -v - Input File: hello-asm/hello.elf - Resetting.. - Relaying uart-rx to stdout (Note: This mode does not support uart-tx) - Initialization complete! - Hello World! - -- from Assembly - - Haulting @ tick 931 - -Redierecting AtomSim Output -**************************** -All verbose information is printed on **stderror** stream while the output of the program is printed on the **stdout**. Therefore one can easily redirect them to two different files if needed. This can be done as follows: - -.. code-block:: - - $ atomsim sw/examples/banner/banner.elf -v 1> output.log 2> sim.log - - -Reverting to Debug Mode from Normal Mode -***************************************** -During a program's execution on atomsim, if user presses :kbd:`ctrl` + :kbd:`c` atomsim quits by default. This behaviour can be changed by invoking AtomSim with ``___to_be_added____`` options. With this option, anytime during the simulation, it is possible to revert to debug mode from normal mode by pressing :kbd:`ctrl` + :kbd:`c`. To quit AtomSim, press :kbd:`ctrl` + :kbd:`c` twice or press :kbd:`ctrl` + :kbd:`c` once and then use the *quit* command on debug console. \ No newline at end of file diff --git a/docs/pages/documentation/bootloader.rst b/docs/pages/documentation/bootloader.rst new file mode 100644 index 00000000..94228af8 --- /dev/null +++ b/docs/pages/documentation/bootloader.rst @@ -0,0 +1,66 @@ +RISC-V Atom Bootloader +####################### + +The RISC-V Atom bootloader is a **stage-0** bootloader. It is loaded in the BootROM and executable as the first thing +after reset. The source code for Atom bootloader is located in ``RVATOM/sw/bootloader`` subdirectory. The bootloader can +be built manually using the following *make* command. + +.. code-block:: + + $ cd sw/bootloader + $ make soctarget=hydrogensoc + +During run-time, the bootloader uses RAM to implement stack. it includes code for platform initialization, loading +executable and control transfer. Bootloader provides various *bootmodes* to the user allowing the user to control the +boot process. + +Following is a list of actions that are performed step-by-step during the boot process: + +#. Upon reset the control is transferred to reset vector, which by default points to start of BootROM. +#. CPU starts executing the stage-0 bootloader. + #. Bootloader performs common initialization. + #. Bootloader then performs any platform specific initializations. + #. Bootloader reads the *bootmode* pins and decides the bootmode. + #. Actions are performed according to bootmode, which includes loading the executable into RAM from correct source. + #. Finally, the control is transferred to User program. + + +Bootmodes +********** + +RISC-V Atom bootloader mainly supports 4 boot modes: + ++----------+---------------+----------------------------------------------------------------------+ +| Pinval | Bootmode | Function | ++==========+===============+======================================================================+ +| ``0b00`` | FLASHBoot | Loads a binary image into RAM from FLASH memory using SPI | ++----------+---------------+----------------------------------------------------------------------+ +| ``0b01`` | Jump to RAM | Jumps to RAM, without memory initialization | ++----------+---------------+----------------------------------------------------------------------+ +| ``0b10`` | UARTBoot | Loads a binary image into RAM from UART stream using XMODEM protocol | ++----------+---------------+----------------------------------------------------------------------+ +| ``0b11`` | Infinite Loop | Executes an infinite loop | ++----------+---------------+----------------------------------------------------------------------+ + +FLASHBoot +========== +In this bootmode, user must write the binary image for the program directly in FLASH memory at a predefined offset value. +During boot, this binary image will be copied as it is to the RAM and will be executed. FLASHBoot requires the SPI IP to +communicate with FLASH memory and will give an boot-panic error if its missing. + +UARTBoot +========= +In this mode, the bootloader obtains the program binary image from UART using the +`XMODEM protocol `_. It supports XMODEM CRC16 with default packet size of 128 bytes. + +Transferring files over UART +----------------------------- +RISC-V Atom project provides the ``xmsend.py`` python script that can be used to transmit binary files over UART. *xmsend* +can be used as follows. + +.. code-block:: bash + + $ xmsend.py -b 115200 -p /dev/ttyUSB0 firmware.bin + +.. tip:: + Make sure that no other process (like screen) is using the serial port before invoking the xmsend script. diff --git a/docs/pages/documentation/build_flow.rst b/docs/pages/documentation/build_flow.rst new file mode 100644 index 00000000..630b30ef --- /dev/null +++ b/docs/pages/documentation/build_flow.rst @@ -0,0 +1,28 @@ +RISC-V Atom Build Flow +####################### + +RISC-V Atom project uses a Make base build flow, assisted by the ``cfgparse.py`` script and JSON config files located +under ``rtl/config`` directory. There exists a JSON config file for each / a group of RTL components which specifies +how to compile them, any required flags, macros etc. This implies, each soctarget or a variation of an soctarget has a +JSON which is used to build it. + +This approach has many advantages over a static approach of incorporating everything in the Makefiles. The ``cfgparse.py`` +is used to parse the json files and extract all the necessary information to build a target like compiler flags, source +files etc. Not only that, cfgparse script allows JSON files to include dependency information on other JSON files, variable +substitution and polymorphism. + +Some Information on the Structure of JSON config files +******************************************************* + +#. One JSON file can depend on one or more JSON files (specified in ``includes`` attribute), allowing all of them to be + parsed together. +#. A JSON file can specify parameters in the ``params`` attribute which can be used as variables in conditional statements + throughout the script. +#. Parameters in the included JSON files can be overridden by the parameters in the JSON file which included it. +#. A conditional statement can be specified as ``[?:]``, where if the condition is true, ``A`` is + substituted in the string, else ``B`` is substituted in the string. Users are free to omit A, B, or both depending on + the requirement. +#. JSON config files support basic polymorphism. They can inherit attributes from the another JSON file using the + ``extends`` attribute. This is useful when users want to specify a special configuration of an existing configuration + without duplicating the contents of the original file. +#. Parameters in the *child* config files override parameters in the parent *config* file. diff --git a/docs/pages/overview/fpga_results.rst b/docs/pages/documentation/fpga_results.rst similarity index 100% rename from docs/pages/overview/fpga_results.rst rename to docs/pages/documentation/fpga_results.rst diff --git a/docs/pages/documentation/libcatom.rst b/docs/pages/documentation/libcatom.rst new file mode 100644 index 00000000..9038d4fd --- /dev/null +++ b/docs/pages/documentation/libcatom.rst @@ -0,0 +1,26 @@ +Libcatom: C standard library for RISC-V Atom +############################################# + +Libcatom is a minimal C standard library for RISCV-Atom. It consists of startup code, basic stdio library, heap allocator, +soc-specific libraries such as drivers for peripherals such as GPIO, UART, SPI etc. and linker scripts. The soc-specific +sources (such as drivers) are located inside the corresponding folder. ``platform.h`` header defines most of the +platform-specific macros for libcatom. Libcatom does not define the software multiply and soft floating point operations +and therefore uses the standard library provided with the compiler. + +Building Libcatom +****************** +Libcatom can be built as follows. + + +.. code-block:: bash + + $ make soctarget=hydrogensoc sim=1 + + +.. tip:: + You don't need to build Libcatom separately in most cases as it will be built automatically (with correct soc target) + while building AtomSim. + +.. note:: + You must use ``sim=1`` option to build the library for simulation. If you see framing errors in UART output during + simulation, most likely you haven't built the library and anything that uses it with ``sim=1``. \ No newline at end of file diff --git a/docs/pages/documentation/memory_map.rst b/docs/pages/documentation/memory_map.rst new file mode 100644 index 00000000..86b73916 --- /dev/null +++ b/docs/pages/documentation/memory_map.rst @@ -0,0 +1,45 @@ +Memory Map and Boot Flow +######################### + +Memory Map +*********** + +The following image shows the memory map of Atom-based SoCs. + +.. image:: /diagrams/memory_map.png + +The column **C** shows the memory map template for all RISC-V Atom based SoCs. Column **D** and **E** show the memory map +for AtomBones and HydrogenSoC respectively. + +Boot Flow +********** +Upon reset, the core jumps to the reset vector (default: ``0x10000``) which points to the start of BootROM. RISC-V Atom +BootROM includes a **stage-0 bootloader** that is automatically built and included when building the AtomSim or running FPGA +builds. The stage-0 bootloader uses RAM for stack. It initializes the platform, loads the user program in RAM and finally +transfers control to the user program. The user program often includes a **stage-1 bootloader** which sets up the runtime +environment and standard library before executing the application. + +.. graphviz:: + + digraph G { + rankdir=LR; + reset_vec [label="Reset Vector", shape=rect, style=filled, fillcolor=white]; + subgraph cluster_0 { + style=filled; + fillcolor=gray; + label="BootROM"; + stage0_bl [label="Stage-0\nBootloader", shape=rect, style=filled, fillcolor=yellow]; + } + subgraph cluster_1 { + style=filled; + fillcolor=gray; + label="RAM"; + stage1_bl [label="Stage-1\nBootloader", shape=rect, style=filled, fillcolor=orange]; + prog [shape=rect, label="User Program", style=filled, fillcolor=cyan]; + stage1_bl -> prog [label="launch"]; + } + reset_vec -> stage0_bl; + stage0_bl -> stage1_bl; + } + +To know more about the stage-0 bootloader, see :doc:`this` page. \ No newline at end of file diff --git a/docs/pages/overview/performance.rst b/docs/pages/documentation/performance.rst similarity index 100% rename from docs/pages/overview/performance.rst rename to docs/pages/documentation/performance.rst diff --git a/docs/pages/documentation/riscv_atom.rst b/docs/pages/documentation/riscv_atom.rst new file mode 100644 index 00000000..cf785668 --- /dev/null +++ b/docs/pages/documentation/riscv_atom.rst @@ -0,0 +1,132 @@ +RISC-V Atom CPU +################ +Atom is an open-source 32-bit soft-core processor written in Verilog. It is an embedded class processor +architecture that implements the open-source RISC-V instruction set architecture (RV32IC), as described +in the RISC-V unprivileged spec. Atom contains a two stage pipeline inspired from arm cortex m0+. + +The following diagram showcases the architecture of RISC-V Atom core. + +.. image:: /diagrams/RISCVAtom_arch.png + +Atom Pipeline Stages +********************* +The pipeline is divided into two stages. These are explained below. + +Stage-1: Fetch +=============== + +Fetch unit is responsible for fetching instructions from instruction memory through the IPort. It uses a 32-bit Program +Counter (PC) to keep track of the address of the instruction being fetched. After the instruction is successfully fetched, +Program counter is incremented by either 4 or 2 (in case of compressed instruction). Fetch stage also includes pipeline +control logic which controls pipeline stalls and flushes. If compressed extension in enables, Fetch stage includes +RISC-V Compressed Aligner which aligns all the memory requests to 4 byte boundary. It also includes RISC-V Compressed +instruction decoder, which decodes 16-bit compressed instructions to their 32-bit equivalents. + +Stage-2: Decode, Execute & Write-back +====================================== + +In this stage, the instruction from Instruction Register (IR) is decoded and executed. First, the decode unit decodes the +instruction and sets all the control signals in order to configure the data-path to execute the instruction. Parallelly, +operand registers are fetched and 32-bit immediate value is generated. Next, ALU/Comparator does the necessary +computation/comparison and the results are written back to register file. In case current instruction invokes a memory +request, stage-2 is stalled until response is received. Memload module is used extract the correct data from the received +memory response. If CSR extension is enabled, CSR Unit is included in this stage. CSR Unit provides Control and status +registers which perform various special functions. SR Unit also includes exceptions and interrupt handling logic if Exceptions +and interrupts are enabled. Branch calculation also happens in this stage and if branch is taken, a signal is sent to +the pipeline control logic to flush the pipeline. + +Atom Interface +*************** +Atom module is defined in the file ``RVATOM/rtl/core/atomRV.v``. It has has two independent ports (IPort & DPort) +which it uses to access memory. Both the ports use a generic ready-valid handshaking protocol to transfer data. We also +provide wrappers to the core to convert the generic handshaking protocol to standard bus protocols such as Wishbone. +These wrappers are specified in the following files. + +#. Wishbone-B4 Wrapper with separate instruction and data port: ``RVATOM/rtl/core/atomRV_wb.v`` + + +Atom Configuration operations +****************************** + ++----------------+------------------------------------------------------+ +| Macro | Function | ++================+======================================================+ +| ``EN_RVC`` | Enables support for RISC-V Compressed Extension | ++----------------+------------------------------------------------------+ +| ``EN_RVZICSR`` | Enables Control and Status Registers (CSRs) | ++----------------+------------------------------------------------------+ +| ``EN_EXCEPT`` | Enables support for RISC-V interrupts and exceptions | ++----------------+------------------------------------------------------+ +| ``DPI_LOGGER`` | Enable DPI Logger | ++----------------+------------------------------------------------------+ + + +RISC-V Atom RTL +**************** +RISC-V Atom is written in Verilog. The RTL specification for Atom is divided into 3 categories, *core*, *uncore* and *soc*, +all of which reside in the ``rtl`` directory. + +Core Directory +============== +The ``rtl/core`` subdirectory contains the the *core* components of the CPU such as register file, ALU, decode unit etc. +It also contains Verilog header files like ``Defs.vh`` and ``Utils.vh``. ``Defs.vh`` contain various signal enumerations +and other parameters internal to the processor. ``Utils.vh`` defines some useful utility macros. + + +Uncore Directory +================ +The ``rtl/uncore`` subdirectory contains the SoC peripheral components such as UART, GPIO, memories, etc. It also +contains the wishbone wrappers of some non-wishbone components. SoC implementations of the Atom processor usually +instantiate these hardware modules in their implementations. + + +SoC directory +============== +The top level Verilog modules for SoCs (such as AtomBones & HydrogenSoC) are present in the ``rtl/soc`` directory in the +corresponding subdirectories. Each of these top level modules are configured by their respective configuration headers +(_Config.vh file). These configuration headers contain the macros used in the top-module definitions to control the +generation of SoC, various sub-components and their parameters. + + +RTL Features +************* + +DPI Logger +=========== +DPI Logger is a System Verilog DPI based logging mechanism provided with the RTL. It can be used to dump useful run-time +debug information such as PC values, Jump addresses, Loads and Stores, etc. into a log file. This module is present in +the ``rtl/dpi`` subdirectory. + +To enable DPI Logger simply define ``DPI_LOGGER`` macro in the top-module or in the CLI as ``-DDPI_LOGGER``. This will +trigger the inclusion of the ``rtl/dpi/util_dpi.vh`` header in ``rtl/core/Utils.vh``. User is free include the +``rtl/core/Utils.vh`` header file in any Verilog file that needs to be debugged. + +To log information, user first needs to call the ``dpi_trace_start()`` function somewhere in the rtl as following. + +.. code-block:: verilog + + initial begin + dpi_trace_start(); + end + +Then the ``dpi_trace()`` function can be used to dump information. Its syntax is exactly same as the Verilog ``$display`` +system function. Example of logging the jumps during code execution is provided in the ``AtomRV.v`` file and is also +shown below. + +.. code-block:: verilog + + `ifdef DPI_LOGGER + initial begin + dpi_logger_start(); // begin logging + end + `endif + + `ifdef LOG_RVATOM_JUMP + always @(posedge clk_i) begin + if(jump_decision) // on some trigger condition + dpi_logger("Jump address=0x%x\n", {alu_out[31:1], 1'b0}); // dump information + end + `endif + +For logging the Jumps, user must also define the ``LOG_ATOMRV_JUMP`` macro in a similar way. This will generate a ``run.log`` +file in the current directory containing all the dumped information. diff --git a/docs/pages/documentation/riscv_atom/riscv_atom.rst b/docs/pages/documentation/riscv_atom/riscv_atom.rst deleted file mode 100644 index a953d167..00000000 --- a/docs/pages/documentation/riscv_atom/riscv_atom.rst +++ /dev/null @@ -1,56 +0,0 @@ -RISC-V Atom (Core) -################### -Atom is an open-source 32-bit soft-core processor written in Verilog. It is an embedded class processor -architecture that implements the open-source RISC-V instruction set architecture (RV32I), as described -in the RISC-V unprivileged spec. Atom contains a two stage pipeline inspired from arm cortex m0+. - -The following diagram showcases the architecture of RISC-V Atom core. - -.. image:: ../../../diagrams/atom_architecture_diagram.png - -Processor Pipeline Stages -************************** -The pipeline is divided into two stages. These are explained below. - -Stage-1: Fetch -=============== - -Fetch unit is responsible for fetching instructions from instruction memory through the IBUS. It uses a -32-bit register called "Program counter" to keep track of the address of the instruction being fetched. -After the instruction is successfully fetched, Program counter is incremented by 4. - -Stage-2: Decode, Execute & Write-back -====================================== - -In this stage, the instruction is decoded, all the signal are assigned in order to configure -data-path to execute the instruction. & registers are fetched. A 32 bit immediate is generated by the -ImmGen unit. ALU then execute the instruction which is followed by write-back into the register file. -Branch calculation also happens in this stage and if branch is taken, the pipeline is flushed. Comparator -module in this stage is used for all the instructions that involve comparison like slt, slti, beq, bltu etc. - -Processor Interface -******************** -RISCV-Atom module is defined in the file ``RVATOM/rtl/core/atomRV.v``. It has has two independent ports -which it uses to access memory. - -#. Instruction port & -#. Data port - -Both the ports use a generic ready-valid handshaking protocol to transfer data. - -We also provide wrappers to the core to convert the generic handshaking protocol to standard bus protocols such -as Wishbobne. These wrappers are specified in the following files. - -#. Wishbobne-B4 Wrapper with separate instruction and data port: ``RVATOM/rtl/core/atomRV_wb.v`` - - - - - - -.. toctree:: - :maxdepth: 1 - :caption: Related Topics - - rtl.rst - \ No newline at end of file diff --git a/docs/pages/documentation/riscv_atom/rtl.rst b/docs/pages/documentation/riscv_atom/rtl.rst deleted file mode 100644 index 10d6974c..00000000 --- a/docs/pages/documentation/riscv_atom/rtl.rst +++ /dev/null @@ -1,71 +0,0 @@ -RISC-V Atom RTL -################ -RISC-V Atom is written in Verilog. Its RTL is divided into 2 categories, core and uncore, -both of which reside in the `rtl` directory in `core` and `uncore` subdirectories respectively. - -Rtl directory -************** -The top level verilog modules (atombones & hydrogensoc) are present in the `rtl` directory. Each -of these top level modules are configured by their respective configure headers (_Config.vh file). -These configuration headers contain the macros used in the top-module definitions to control the -generation of various sub-components and their parameters. - - -Core directory -============== -`core` directory contains the the *core* components of the CPU such as register file, alu, -decode unit etc. It also contains verilog header files like `Defs.vh` and `Utils.vh`. `Defs.vh` -defines various signal eunumerations and other parameters internal to the processor. `Utils.vh` -defines some useful utility macros. - - -Uncore directory -================ -The `uncore` subdirectory contains all the peripheral components such as uart, gpio, ram, rom etc. -This also includes the wishbone wrappers of some non-wishbone components. SoC implementations of the -Atom processor usually instantiate these hardware modules in their implementations. - -RTL Features -************* - -DPI Logger -=========== -DPI Logger is a SystemVerilog DPI based logging mechanism provided with the RTL. It can be used to -dump useful run-time debug information such as PC values, Jump addresses, Loads and Stores, etc. -into a log file. This module is present in the `rtl/dpi` subdirectory. - -To enable DPI Logger simply define `DPI_LOGGER` macro in the topmodule or in the Makefile VFLAGS variable -as `-DDPI_LOGGER`. This will trigger the inclusion of the `rtl/dpi/util_dpi.vh` header in `rtl/core/Utils.vh`. -User is free include the `rtl/core/Utils.vh` header file in any verilog file that needs to be debugged. - -To log information, user first needs to call the `dpi_trace_start()` function somewhere in the rtl as following. - -.. code-block:: verilog - - initial begin - dpi_trace_start(); - end - -Then the `dpi_trace()` function can be used to dump information. Its syntax is exactly same as the verilog -`$display` system funciton. Example of logging the jump is provided in the `AtomRV.v` file and is also shown -below. - -.. code-block:: verilog - - `ifdef DPI_LOGGER - initial begin - dpi_logger_start(); // begin logging - end - `endif - - `ifdef LOG_RVATOM_JUMP - always @(posedge clk_i) begin - if(jump_decision) // on some trigger condition - dpi_logger("Jump address=0x%x\n", {alu_out[31:1], 1'b0}); // dump information - end - `endif - -For logging the Jumps, user must also define the `LOG_ATOMRV_JUMP` macro in a similar way. This will generate a -"run.log" file in the current directory containt all the dumped information. - - diff --git a/docs/pages/documentation/scar.rst b/docs/pages/documentation/scar.rst index 69f5cb9c..98319cca 100644 --- a/docs/pages/documentation/scar.rst +++ b/docs/pages/documentation/scar.rst @@ -1,62 +1,86 @@ SCAR: Search Compile Assert Run ################################ -SCAR is a processor verification framework in python. SCAR performs a set of assembly level tests to verify the processor implementation. Each assembly test checks for one particular functionality of the processor. SCAR does this by examining a state dump file after the processor is done with executing a test code. This state dump file then checked assuming a set of assertions in the form of expected register values. These assertions are provided in the assembly file itself. SCAR is also used to verify the ISA-compliance. +SCAR is a processor verification framework in python. SCAR performs a set of assembly level tests to verify the processor +implementation. Each assembly test checks for one particular functionality of the processor. SCAR does this by examining +a state dump file after the processor is done with executing a test code. This state dump file then checked assuming a +set of assertions in the form of expected register values. These assertions are provided in a separate assertion file. +SCAR is also used to verify the ISA-compliance. + +SCAR is located in ``RVATOM/test/scar`` directory. SCAR Workflow ************** +As the name suggests: + +#. **Search:** SCAR searches for all the available assembly level tests specified in a config JSON file. The config JSON + file also specifies the corresponding assertion files. +#. **Compile:** SCAR then compiles all the tests with a user-defined linker script. +#. **Execute:** In this step, The elf files are executed on the target simulator with a special flag which creates a + state dump file after execution terminates. SCAR createsa ``work`` directory to store all the outputs. +#. **Verify:** Finally, Assertions are read from the assertion file and are then used to verify the register values in + the generated state dump file. + +Once you're finished building the RISC-V Atom project, SCAR can be invoked from the ``RVATOM`` directory itself using the +``scar`` target in the Makefile (see make help). Following is a demo output of a run of SCAR framework on hydrogensoc. + +.. code-block:: bash + + +------------------------------------------------------------------------------+ + | SCAR Verification Report | + +------------------------------------------------------------------------------+ + Date: 2024-02-04 19:23:21 + + 0). add64 - Passed All Assertions Passed + 1). addi - Passed All Assertions Passed + 2). add - Passed All Assertions Passed + 3). andi - Passed All Assertions Passed + 4). and - Passed All Assertions Passed + 5). auipc - Passed All Assertions Passed + 6). beq - Passed All Assertions Passed + 7). bge - Passed All Assertions Passed + 8). bgeu - Passed All Assertions Passed + 9). blt - Passed All Assertions Passed + 10). bltu - Passed All Assertions Passed + 11). bne - Passed All Assertions Passed + 12). function_call - Passed All Assertions Passed + 13). jalr - Passed All Assertions Passed + 14). jal - Passed All Assertions Passed + 15). li - Passed All Assertions Passed + 16). load_store_byte - Passed All Assertions Passed + 17). load_store_hw - Passed All Assertions Passed + 18). lui - Passed All Assertions Passed + 19). lw - Passed All Assertions Passed + 20). mv - Passed All Assertions Passed + 21). ori - Passed All Assertions Passed + 22). or - Passed All Assertions Passed + 23). slli - Passed All Assertions Passed + 24). sll - Passed All Assertions Passed + 25). slti - Passed All Assertions Passed + 26). sltiu - Passed All Assertions Passed + 27). slt - Passed All Assertions Passed + 28). sltu - Passed All Assertions Passed + 29). srai - Passed All Assertions Passed + 30). sra - Passed All Assertions Passed + 31). srli - Passed All Assertions Passed + 32). srl - Passed All Assertions Passed + 33). stack - Passed All Assertions Passed + 34). storew - Passed All Assertions Passed + 35). sub - Passed All Assertions Passed + 36). sw - Passed All Assertions Passed + 37). xori - Passed All Assertions Passed + 38). xor - Passed All Assertions Passed + ================================================================================ + Passed tests : 39 / 39 + Ignored tests : 0 / 39 + Failed tests : 0 / 39 -#. **Search:** SCAR searches for all the available assembly level test in the directory and makes a list -#. **Compile:** It then compiles all the found tests with a user-defined linker script. -#. **Execute:** In this step, The elf files are executed on the target simulator which creates a state dump file after execution. -#. **Verify:** Finally, Assertions are read from the assembly file containing the test. These are then used to check for mismatches in the generated state dump file. - - -Assembly test format -********************* -The assembly file must satisfy the following criteria: - -#. File must have a ``_start`` label before the start of code. -#. File must have a ``ebreak`` instraction after the end of code. -#. File must have an assertion section at the bottom with the following format. - -Assertion Section Format -======================== -The assembly file must contain a set of assertions at the bottom in the following format: - -:: - - .global _start - _start: - - li t0, 0x00d01010 - li t1, 0x1ddc1044 - li t2, 0xdeadbeef - li t3, 0x22101301 - li t4, 0xfaf01569 - li t5, 0x078b102a - li t6, 0xdae013c0 - - add a0, t0, t1 - add a1, t1, t2 - add a2, t2, t3 - add a3, t3, t4 - add a4, t4, t5 - add a5, t5, t6 - - nop - nop - ebreak - - # $-ASSERTIONS-$ - # eq a0 0x1eac2054 - # eq a1 0xfc89cf33 - # eq a2 0x00bdd1f0 - # eq a3 0x1d00286a - # eq a4 0x027b2593 - # eq a5 0xe26b23ea - - -State-Dump file format -======================= -[TODO] \ No newline at end of file +How to Create Your Own Tests? +****************************** +#. Assembly file containing the test source code must have a ``_start`` label before the start of code. +#. Assembly file must have a ``ebreak`` instraction after the end of code, this triggers the simulation to terminate. +#. Each test file must have a corresponding assertion file (``*.asrt``) both of which need to be specified in the JSON + config file. +#. The assertion file uses a python like syntax to specify one expressions per line; which could use physical register + names (x0, x1, x2...) or ABI names (zero, ra, sp) as variables. +#. State dump file generated by simulator must have one key value pair per line. diff --git a/docs/pages/documentation/soc_targets.rst b/docs/pages/documentation/soc_targets.rst index 2ccb4a04..dee36804 100644 --- a/docs/pages/documentation/soc_targets.rst +++ b/docs/pages/documentation/soc_targets.rst @@ -1,16 +1,38 @@ -RISC-V Atom SoC Targets -######################## -SoC Targets are systems that use the RISC-V atom core alongside different peripherals. From a -complexity and functionality point-of-view, SoC Targets can be as simple as a wrapper to the core -interface (e.g. AtomBones) and as complex as multi-core fully-fledged SOCs. +SoC Targets +############ + +SoC Targets are RISC-V Atom based SoCs. These contain one or more Atom cores, peripheral IPs, crossbars memories etc. +From a complexity and functionality point-of-view, SoC Targets can be as simple as a wrapper to the core interface +(e.g. AtomBones) and as complex as multi-core SOCs. + +.. _soctarget-atombones: AtomBones ********** +AtomBones is a stub-target that consists of a single atom core only. All other peripherals like memories and serial port +are simulated in C++. It is meant to be used for simulation and debugging of the core because of its faster simulation +rate. Unlike FPGA SoC targets, AtomBones provides larger memories for experimenting with the programs without being +constrained by physical memory size. + +The following figure shows the architecture of AtomBones. -.. image:: ../../../diagrams/AtomBones.png +.. image:: /diagrams/AtomBones.png + :width: 600 +AtomBones backend implements the C++ simulation of SoC peripherals. In each cycle, the backend listens to IPort and DPort +for any requests and responds to them by bit-banging. The backend provides the ``fetch()`` and ``store()`` API that are +used to access these memory mapped peripherals. + +.. _soctarget-hydrogensoc: HydrogenSoC ************ +HydrogenSoC is a full SoC implementation that contains a single Atom core along with Memories, and peripheral IPs like +UART, GPIOs, timers, etc. All the peripherals are connected to the CPU using a Wishbone-B4 bus. Users have the flexibility +to disable/enable core features, add/remove IPs, and set memory maps through a config JSON file. HydrogenSoC is proven on +multiple FPGA platforms. + +The following diagram shows the architecture of HydrogenSoC. -.. image:: ../../diagrams/HydrogenSoC.png \ No newline at end of file +.. image:: /diagrams/HydrogenSoC.png + :width: 600 diff --git a/docs/pages/getting_started/building.rst b/docs/pages/getting_started/building.rst index da46ed09..59062d0d 100644 --- a/docs/pages/getting_started/building.rst +++ b/docs/pages/getting_started/building.rst @@ -3,6 +3,7 @@ Building RISC-V Atom Clone the repository ********************* +First let's clone the repository as follows. .. code-block:: bash @@ -10,55 +11,51 @@ Clone the repository $ cd riscv-atom # switch to riscv-atom directory -.. note:: All the commands are executed from the root directory unless explicitly mentioned. We'll refer to this root directory as ``RVATOM``. +.. note:: + All the commands are executed from the root directory unless explicitly mentioned. We'll refer to this root + directory as ``RVATOM``. -Edit Config.mk -*************** -Edit Config.mk file and provide paths appropriately - - -RISC-V Atom environment variables -********************************** +Setting up the environment +*************************** #. ``RVATOM`` environment variable must point to root of riscv-atom directory for the tools & scripts to work properly. -#. ``RVATOM_LIB`` environment variable must point to the ``RVATOM/sw/lib`` folder. This variable is used by the compile scripts to locate *libcatom*. +#. ``RVATOM_LIB`` environment variable must point to the ``RVATOM/sw/lib`` folder. This variable is used by the compile + scripts to locate *libcatom*. -For convenience, ``RVATOM/sourceme`` script is provided that you can source everytime you work with the project. -This can be done as follows: +For convenience, ``RVATOM/sourceme`` script is provided that you can source as follows: .. code-block:: bash $ source sourceme -With this method, everytime you open a new terminal, you have to source the ``sourceme`` file. You can optionally append the aforementioned -to your ``.bashrc`` to source it automatically everytime you open a new terminl. +.. tip:: + With this method, every time you open a new terminal, you have to source the ``sourceme`` file. You can optionally + append the aforementioned to your ``.bashrc`` to source it automatically every time you open a new terminal. -.. code-block:: bash + .. code-block:: bash - $ echo "source /sourceme" >> ~/.bashrc - -In the above command replace ``rvatom-path`` with the path to your RISC-V atom directory. + $ echo "source /sourceme" >> ~/.bashrc + + Replace ``rvatom-path`` with the path to your RISC-V atom directory. -Building the Simulator -*********************** -Let's build AtomSim simulator for ``atombones`` target. +Building AtomSim +***************** +:doc:`AtomSim` is the interactive RTL simulator for RISC-V Atom. Let's build AtomSim for :ref:`AtomBones ` target. .. code-block:: bash - $ make soctarget=atombones + $ make soctarget=atombones sim=1 -This will create ``RVATOM/sim/build`` and ``RVATOM/sim/run`` directories for Atomsim build files and runtime files respectively. -You can find the Atomsim executable in the former directory. +Optionally, to speed up builds, you can specify the number of parallel jobs to run using ``-j `` flag in the above +command. This will create ``RVATOM/sim/build`` directory for AtomSim build files. You can find the Atomsim executable in +``RVATOM/sim/build/bin`` directory. -Assuming you've sourced the ``RVATOM/sourceme`` file, try the following command to verify the build. +Assuming you've sourced the ``RVATOM/sourceme`` file, try the following command to check if the build was successful. .. code-block:: bash - $ atomsim --help - AtomSim v_._ - Interactive RTL Simulator for Atom based systems [ atombones ] - Usage: - atomsim [OPTION...] input + $ atomsim --version + v2.2 [ atombones ] ... \ No newline at end of file diff --git a/docs/pages/getting_started/docker.rst b/docs/pages/getting_started/docker.rst new file mode 100644 index 00000000..392e94ad --- /dev/null +++ b/docs/pages/getting_started/docker.rst @@ -0,0 +1,38 @@ +RISC-V Atom Development in Docker +################################## + +Alternative to previous approach, you can also use the provided `Dockerfile `_ +to build a Docker image containing all the necessary tools to checkout the RISC-V Atom project. As a prerequisite, you +must have Docker installed on your system. You can install Docker by following the `official Docker guide `_. + +Once you have installed Docker, you can clone the RISC-V Atom repository and build the Docker image as follows. + +.. code-block:: bash + + $ git clone https://github.com/saursin/riscv-atom.git + $ cd riscv-atom # switch to riscv-atom directory + $ docker build . -t rvatom-dev # we'll name this image rvatom-dev + +Once the build is finished you should be able to see the image using the following command: + +.. code-block:: bash + + $ docker images + REPOSITORY TAG IMAGE ID CREATED SIZE + rvatom-dev latest a9cab48034fc 24 hours ago 475MB + +To run an instance of this docker image (also called container), you can run the following command. + +.. code-block:: bash + + $ docker run -it -v .:/home/riscv-atom rvatom-dev + > Setting environment variables... + *** Welcome to the riscv-atom container! *** + root@7110d3ddecd7:/home/riscv-atom# + +The above command should launch the container and attach to it, and you should have a familiar linux prompt! It will +also mount the riscv-atom directory on host machine to ``/home/riscv-atom`` directory in the container, and +automatically set-up the environment variables for RISC-V Atom development. + +.. tip:: + Checkout this `cheatsheet `_ to learn more about Docker CLI syntax. \ No newline at end of file diff --git a/docs/pages/getting_started/examples.rst b/docs/pages/getting_started/examples.rst index 4d2784e1..51d2eed9 100644 --- a/docs/pages/getting_started/examples.rst +++ b/docs/pages/getting_started/examples.rst @@ -1,8 +1,8 @@ Running Examples on AtomSim ############################ -The RISC-V Atom project consists of a wide range of examples programs out-of-the-box to test. These examples programs reside -in `RVATOM/sw/examples` directory. +The RISC-V Atom project consists of a wide range of examples programs out-of-the-box to test. These examples programs +reside in `RVATOM/sw/examples` directory. Switch to examples directory @@ -14,22 +14,48 @@ Lets run the classical "hello World!" example first! Hello World Example ******************** -The source code for the *hello-world* example resides in the ``hello-asm`` directory. You can have a look at the source code. First we need to compile the hello world example with our RISC-V gcc cross-compiler. For this purpose, use the provided makefile as following. +The source code for the *hello-world* example resides in the ``hello-asm`` directory. You can have a look at the source +code. First we need to compile the hello world example with our RISC-V gcc cross-compiler. For this purpose, use the +provided makefile as following. .. code-block:: bash - $ make soctarget=atombones ex=hello-asm compile + $ make soctarget=atombones ex=hello-asm sim=1 compile -The above command should generate a ``hello.elf`` file in the ``hello-asm`` directory. Now fire up atomsim and -provide the generated elf file as argument. +The above command should generate a ``hello.elf`` file in the ``hello-asm`` directory. + +.. tip:: + ``soctarget=atombones`` in the above command can be skipped if AtomSim is already built. The SoC target will be automatically detected from + the AtomSim executable. + +Now fire up AtomSim and provide the generated elf file as argument. .. code-block:: bash - $ atomsim hello-asm/hello.elf + $ atomsim -u hello-asm/hello.elf + ___ __ _____ + / _ |/ /____ __ _ / __(_)_ _ + / __ / __/ _ \/ ' \_\ \/ / ' \ + /_/ |_\__/\___/_/_/_/___/_/_/_/_/ v2.2 + ----------8<-----------8<-----------8<-----------8<--------- + + **** RISC-V Atom Bootloader **** + bootmode: 0x1 + Jumping to RAM + -------------------------------- Hello World! - -- from Assembly + -- from Assembly + + EBreak hit at 0x2000014a + Exiting.. -Alternatively, use make run to run the example. +You should see *Hello world* message on the screen. + +.. note:: + Make sure to use ``-u`` flag to direct UART output from SoC to stdout. You can also use ``-t`` flag to generate a VCD + trace of the simulation. + +Alternatively, use ``make run`` to run the example as follows .. code-block:: bash @@ -40,7 +66,7 @@ We can compile other examples also in the similar fashion by using the following .. code-block:: bash - $ make soctarget= ex= compile + $ make soctarget= ex= sim=1 compile $ make soctarget= ex= run .. note:: @@ -52,95 +78,133 @@ Banner Example .. code-block:: bash $ make target=atombones ex=banner compile - $ atomsim banner/banner.elf - - -Output: - -.. code-block:: text - - .';,. ....;;;. - .ll,:o, ':c,. - .dd;co' .cl, - .:o:;,. 'o: - co. .oc - ,o' .coddoc. 'd, - lc .lXMMMMMMXl. ll - .o: ;KMMMMMMMMK, :o. - .o: 'OMMMMMMMMO. :o. - co. .o0XNNX0o. .oc - .o: ..''.. :o. - 'o: :o' - .lc. .ll. - ,lc' 'cl, - 'cc:,.. ..,:c:' - .;::::;;;;::::;. - .... - ____ _________ _______ __ __ - / __ \/ _/ ___// ____/ | / / ____ _/ /_____ ____ ___ - / /_/ // / \__ \/ / | | / / / __ `/ __/ __ \/ __ `__ \ - / _, _// / ___/ / /___ | |/ / / /_/ / /_/ /_/ / / / / / / - /_/ |_/___//____/\____/ |___/ \__,_/\__/\____/_/ /_/ /_/ - /=========By: Saurabh Singh (saurabh.s99100@gmail.com)====/ - - ROM size: xxxxx bytes (xx KB) - RAM size: xxxxx bytes (xx KB) - exiting... - -The Runexamples Script -*********************** -Instead of testing all examples one-by-one, we can use the provided ``atomsim-runexamples`` script to -automatically compile and simulate all examples. - -Simply invoke the script as following - -.. code-block:: bash +.. code-block:: + + $ atomsim -u banner/banner.elf + ___ __ _____ + / _ |/ /____ __ _ / __(_)_ _ + / __ / __/ _ \/ ' \_\ \/ / ' \ + /_/ |_\__/\___/_/_/_/___/_/_/_/_/ v2.2 + ----------8<-----------8<-----------8<-----------8<--------- + + **** RISC-V Atom Bootloader **** + bootmode: 0x1 + Jumping to RAM + -------------------------------- + + .';,. ....;;;. + .ll,:o, ':c,. + .dd;co' .cl, + .:o:;,. 'o: + co. .oc + ,o' .coddoc. 'd, + lc .lXMMMMMMXl. ll + .o: ;KMMMMMMMMK, :o. + .o: 'OMMMMMMMMO. :o. + co. .o0XNNX0o. .oc + .o: ..''.. :o. + 'o: :o' + .lc. .ll. + ,lc' 'cl, + 'cc:,.. ..,:c:' + .;::::;;;;::::;. + .... + ____ _________ _______ __ __ + / __ \/ _/ ___// ____/ | / / ____ _/ /_____ ____ ___ + / /_/ // / \__ \/ / | | / / / __ `/ __/ __ \/ __ `__ \ + / _, _// / ___/ / /___ | |/ / / /_/ / /_/ /_/ / / / / / / + /_/ |_/___//____/\____/ |___/ \__,_/\__/\____/_/ /_/ /_/ + /=========By: Saurabh Singh (saurabh.s99100@gmail.com)====/ + + CPU : RISC-V Atom @ 50000000 Hz + Arch : RV32IC - little endian + CODE RAM : 0x20000000 (40960 bytes) + DATA RAM : 0x2000a000 (8192 bytes) + Exiting... + EBreak hit at 0x2000007c + Exiting.. - $ atomsim-runexamples -atomsim-runexamples script internally uses the same makefile that we used earlier, with the run-all target. -Therefore we can alternatively get the same result by using the make command (in ``RVATOM/sw/examples`` directory). +How to compile and run all examples? +************************************* +Instead of testing all examples one-by-one, we can compile and run all examples as follows. .. code-block:: bash $ make soctarget=atombones run-all - Using Atomsim Vuart ******************** -By default AtomSim relays the output of the running application on stdout. But, in this mode of operation, user cannot provide any input to the running program. Alternatively, Atomsim can estabilish a two-way communication with AtomSim through a linux serial port. This functionality is provided by the Vuart module in Atomsim. +When using ``-u`` flag, AtomSim relays the output of the running application on stdout. But, in this mode of operation, +user cannot provide any input to the running program. AtomSim provides Virtual UART to work around this problem. Virtual +UART is an inbuilt class in AtomSim that can attach the stdin, stdout streams of the simulation to a linux serial port. + + +.. graphviz:: + + digraph G { + rankdir=LR; + subgraph cluster_0 { + style=filled; + fillcolor=lightgrey; + label="Pair of pseudo serial ports using socat as relay"; + Userport [shape=rect, style=filled, fillcolor=orange]; + Simport [shape=rect, style=filled, fillcolor=orange]; + Socat [shape=ellipse, style=filled, fillcolor=yellow]; + Userport -> Socat -> Simport [dir=both]; + } + subgraph cluster_1 { + style=filled; + fillcolor=cyan; + label="AtomSim"; + VUART [shape=rect, style=filled, fillcolor=gray]; + RTL [shape=rect, label="RTL\nSimulation", style=filled, fillcolor=gray]; + VUART -> RTL [dir=both, label="UART traffic"]; + } + Screen [shape=rect, style=filled, fillcolor=cyan]; + ttyUSB [shape=rect, style=filled, fillcolor=orange]; + FPGA [shape=box3d, style=filled, fillcolor=green]; + Screen -> Userport [label=attach]; + Simport -> VUART [dir=back, label=attach]; + Screen -> ttyUSB [label=attach]; + ttyUSB -> FPGA [label=USB]; + } -Generating virtual serial ports +| + +Generating Pseudo Serial Ports ================================ -A pair of connected serial ports can be generated by usng the provided ``atomsim-gen-vports`` script as following. +A pair of connected pseudo serial ports can be generated by using the provided ``atomsim-gen-vports`` script as following. .. code-block:: bash $ atomsim-gen-vports -This will generate a pair of new virtual serial ports in ``/dev/pts`` and links them together using the -``socat`` linux command. This means that whatever is sent to port-1 is recieved at port-2 and vice versa. +This will generate a pair of new pseudo serial ports in ``/dev/pts`` and links them together using the +``socat`` linux command. This means that whatever is sent to port-1 is received at port-2 and vice-versa. Further, this script also generates symlinks to these generated ports in the ``RVATOM`` directory as ``simport`` and ``userport``. -Interacting with Stdout and Stdin over virtual ports -===================================================== +Interacting with Stdout and Stdin over Pseudo Serial Ports +========================================================== Open a new terminal (say terminal-2) and run the screen command as following .. code-block:: bash - $ screen $RVATOM/userport 9600 + $ screen $RVATOM/userport 115200 And on the other terminal (terminal-1) run atomsim as following .. code-block:: bash - $ atomsim hello-asm/hello.s --vuart=$RVATOM/simport + $ atomsim hello-asm/hello.s -p $RVATOM/simport -b 115200 You should now be able to see the output on the terminal-2. -To close the screen command press ``ctrl+a``, type ``:quit`` and press ``enter``. +.. tip:: + To close *screen* first press :kbd:`ctrl` + :kbd:`a`, then press :kbd:`k` followed by :kbd:`y`. To clear the *screen* window, + press :kbd:`ctrl` + :kbd:`a`, then press :kbd:`shift` + :kbd:`c`. Adding New Examples @@ -150,14 +214,14 @@ To add a new example to the existing framework, simply create a directory under .. code-block:: bash - $ mkdir newexample + $ mkdir myexample Next, put your source files under this directory. .. code-block:: c - $ cat newexample.c + $ cat myexample.c #include void main() { @@ -174,10 +238,9 @@ executable file as follows. .. code-block:: bash $ cat Makefile.include - src_files = newexample.c - executable = newexample.elf + src_files = myexample.c + executable = myexample.elf That's it! Now you can use the same compile and run commands as discussed earlier to run this example. - diff --git a/docs/pages/getting_started/prerequisites.rst b/docs/pages/getting_started/prerequisites.rst index 3e725136..87d4ec36 100644 --- a/docs/pages/getting_started/prerequisites.rst +++ b/docs/pages/getting_started/prerequisites.rst @@ -1,60 +1,37 @@ Prerequisites ############### - -This page discusses how to set up your system in order to get riscv-atom up and running. +This page discusses how to set up your system in order to get RISC-V Atom up and running. Required Packages ****************** .. note:: - RISC-V Atom project has been developed and tested on ubuntu 20.04. - However, It should work just fine on any other version of ubuntu with no or few additional packages. - - -Run apt update -================ -This step is needed to make sure the apt package list is up to date. - -.. code-block:: bash - - $ sudo apt update - + RISC-V Atom project has been developed and tested on **Ubuntu 20.04**. + However, It should work just fine on any other linux based distribution with relevant packages. Install git, make, python3, gcc & other tools ============================================== -GNU C/C++ compilers and Make and other essential build tools are conveniently packaged as ``build-essential`` meta package. +RISC-V Atom uses *Make* for all builds. *GNU C/C++ compilers*, *Make* and other essential build tools are conveniently +packaged as ``build-essential`` meta package in Ubuntu. RISC-V Atom uses the GNU Readline library to implement the +interactive console in AtomSim. We also want to install GTKWave to view VCD waveforms and screen to connect to serial ports. .. code-block:: bash - $ sudo apt install git python3 build-essential + $ sudo apt-get update + $ sudo apt-get install git python3 python3-pip build-essential libreadline8 libreadline-dev socat + $ sudo apt-get install gtkwave screen + $ pip install -r requirements.txt Install Verilator ================== -Verilator will be used By Atomsim to *Verilate* Verilog RTL into C++. We recommend installing latest stable verilator version using `git quick install method `_ - -Install GTK Wave -================== -GTKwave is a GUI tool to view waveforms stored as Value Change Dump (VCD) files. - -.. code-block:: bash - - $ sudo apt install gtkwave - - -Install Screen -================== -Screen is a command line utility that can be used to connect to serial ports on linux. -It will be used to estabilish a two-way serial communication with the AtomSim. - -.. code-block:: bash - - $ sudo apt install screen +Verilator will be used By AtomSim to *Verilate* Verilog RTL into C++. We recommend installing the latest stable +Verilator version (>=5.006) using `git quick install method `_. Install RISC-V GNU Toolchain ============================= -We will be installing the RV64-Multilib toolchain +We will be installing the **RISC-V 64-bit Multilib** toolchain Further install instructions can be found `here `_. We recommend using the provided ``install_toolchain.sh`` script to install the proper toolchain. @@ -63,23 +40,41 @@ We recommend using the provided ``install_toolchain.sh`` script to install the p $ chmod +x install_toolchain.sh $ ./install_toolchain.sh +Allow user to access serial ports +================================= +To allow current linux user to access serial ports and usb devices (such as JTAG), the user must be added to +the ``dialout`` and ``plugdev`` groups respectively. ----------------- +.. code-block:: bash -| + $ sudo usermod -aG dialout $USER + $ sudo usermod -aG plugdev $USER + +.. note:: + This takes effect after user logs out and logs back in. + +OpenFPGAloader +============== +We use openFPGAloader to load bitstreams on FPGA. you are free to use vendor tools instead. To install openFPGAloader +follow `this `_ guide. + +---------------- Optional Packages ****************** -.. note:: The following packages are optional and are only required for generating documentation using doxygen & sphinx +.. note:: + The following packages are optional and are only required for generating documentation using + Doxygen & Sphinx Install Doxygen ================ -Doxygen a tool is used to generate C++ cource code documentation from =documentation comments= inside the C++ source files. +Doxygen a tool is used to generate C++ source code documentation from comments inside the C++ source files. .. code-block:: bash - $ sudo apt install doxygen + $ sudo apt-get install doxygen + Install Latex Related packages =============================== @@ -92,10 +87,10 @@ These packages are essential for generating Latex documentation using Doxygen. Install sphinx & other python dependencies =========================================== -Sphinx is used to generate the RISC-V Atom Documentation and User-Manual in PDF & HTML. +Sphinx is used to generate the RISC-V Atom Documentation and User-Manual in PDF & HTML. To install the packages to +generate sphinx documentation, run the following command in ``docs`` directory under riscv-atom repository. .. code-block:: bash - $ cd docs/ && pip install -r requirements.txt - - + $ pip install -r docs/requirements.txt + $ sudo apt install graphviz # Graphviz is for flow diagrams in sphinx documentation diff --git a/docs/pages/overview/components.rst b/docs/pages/overview/components.rst deleted file mode 100644 index 8724c2b9..00000000 --- a/docs/pages/overview/components.rst +++ /dev/null @@ -1,61 +0,0 @@ -Components -########### - -This page gives a high-level overview of various components of the RISC-V Atom project. - -RISC-V Atom Core -***************** - -Atom is a 32-bit embedded-class softcore processor written in Verilog HDL. It is designed to cater to embedded class applications. It is fully compliant with the open-source RISC-V Instruction Set Architecture (RV32I) and passes all official RISC-V compliance tests. Atom is based on a two-stage pipelined architecture inspired by the ARM cortex m0+ processor. It is aimed towards implementation on FPGAs. - - -.. link-button:: RISC-V Atom (Core) - :type: ref - :text: Click here for in-depth documentation - :classes: btn-outline-primary btn-block - - -SoC Targets -************ - -* **AtomBones**: It is a stub-target that consists of a single atom core only. The instruction memory, data memory, and serial port are simulated in C++. It is should be used for simulation and debugging purposes only. - -* **HydrogenSoC**: It is a basic SoC implementation that contains a single Atom core along with instruction memory, data memory, serial ports, GPIO pins, etc. All the peripherals are connected with the CPU using a Wishbone-B4 bus. - -.. link-button:: RISC-V Atom SoC Targets - :type: ref - :text: Click here for in-depth documentation - :classes: btn-outline-primary btn-block - - -AtomSim -******** - -AtomSim is a Spike-like simulator written in C++. In contrast to Spike, AtomSim Simulates the actual RTL in the backend. AtomSim provides a hardware-software co-simulation environment for developing applications and extensions on the Atom platform. It uses the Verilator tool to compile the RTL into a shared object which then gets linked with the C++ based simulator frontend to simulate the system. AtomSim also features a command-line interface to control various aspects of the simulation like start, stop, step, run indefinitely, run for a specified number of cycles, enable/disable vcd tracing, etc. It also supports run-time instruction disassembly with the help of the RISC-V objdump tool. - -.. link-button:: AtomSim: A simulation tool for Atom based SoCs - :type: ref - :text: Click here for in-depth documentation - :classes: btn-outline-primary btn-block - - -SCAR -***** - -SCAR (Search, Compile Assert, and Run) is a processor verification framework written in python. It performs a set of assembly-level tests to verify the processor implementation. Each assembly test usually checks for one particular function of the processor. SCAR does this by examining a state dump after the processor is done with executing a test code. This state dump is then checked assuming a set of assertions in the form of expected register values. These assertions are provided in the assembly file itself. SCAR is also used to verify the RISC-V ISA compliance in this project. - -.. link-button:: SCAR: Search Compile Assert Run - :type: ref - :text: Click here for in-depth documentation - :classes: btn-outline-primary btn-block - - -ConvELF -******** - -ConvELF is a python script that is used to convert an ELF executable file to verilog friendly memory initialization files. These files can be in either `hex` or `bin` format and can be used to initialize a verilog memory with the help of `$readmemh` & `readmemb` functions. ConvELF is a flexible program configured by a memory map specified as a python dictionary. It can even fragment an elf file into multiple memory initialization files depending on the memory map provided. - -.. link-button:: ConvELF: A Utility Tool for ELF Conversion - :type: ref - :text: Click here for in-depth documentation - :classes: btn-outline-primary btn-block diff --git a/docs/pages/overview/directory_structure.rst b/docs/pages/overview/directory_structure.rst index 0d9d79d0..a71f49a1 100644 --- a/docs/pages/overview/directory_structure.rst +++ b/docs/pages/overview/directory_structure.rst @@ -6,38 +6,41 @@ Directory Structure riscv-atom : root directory | ├─ docs : RISCV-Atom documentation & user manual - | ├─ diagrams : executable binaries - | └─ pages : reStructuredText sources | ├─ rtl : RISCV-Atom Verilog Sources + | ├─ common : Common headers + | ├─ config : SoC target config files (JSON) | ├─ core : RISCV-Atom core components - | ├─ uncore : RISCV-Atom non-core components (SoC peripherals) - | └─ dpi : SystemVerilog DPI sources + | ├─ dpi : SystemVerilog DPI sources + | ├─ soc : SoC RTL files + | ├─ tb : Verilog testbenches + | └─ uncore : RISCV-Atom non-core components (SoC peripherals) | - ├─ scripts : scripts for commonly used commands + ├─ scripts : Commonly used python and bash scripts | ├─ sim : Atomsim source code | ├─ build : AtomSim build files (autogenerated) | ├─ docs : AtomSim Source Documentation (Doxygen) - | ├─ include : Third party Libraries for AtomSim - | └─ run : Atomsim run logs, dumps and VCD traces (autogenerated) + | └─ include : Third party Libraries for AtomSim | - ├─ sw : Atomsim source code - | ├─ examples : example programs - | └─ lib : libc for RISCV-Atom (libcatom) - | ├─ include : libcatom headers - | ├─ libcatom : libcatom sources + ├─ sw : Software sources + | ├─ bootloader : RISC-V Atom bootloader + | ├─ examples : Example programs + | └─ lib : Libc for RISCV-Atom (libcatom) + | ├─ include : Libcatom headers + | ├─ libcatom : Libcatom sources | └─ link : Linker scripts | ├─ synth : RISC-V Atom Synthesis - | ├─ xilinx : Synthesis project for xilinx FPGAs - | └─ yosys : Yosys synthesis scripts + | ├─ altera : Synthesis project for Altera FPGAs + | ├─ xilinx : Synthesis project for Xilinx FPGAs + | └─ yosys : Synthesis project for Yosys | ├─ test : RISCV Atom tests | ├─ riscv-target : Official RISC-V compliance test files | └─ scar : SCAR tests directory | - └─ tools : utility tools - └─ elfdump : elfdump utility + └─ tools : Utility tools + └─ elfdump : Elfdump utility diff --git a/docs/pages/overview/introduction.rst b/docs/pages/overview/introduction.rst index 70dd8903..bb0e67ab 100644 --- a/docs/pages/overview/introduction.rst +++ b/docs/pages/overview/introduction.rst @@ -12,23 +12,53 @@ Introduction ############## -**RISC-V Atom** is an open-source soft-core processor platform targeted for FPGAs. It is based on the open-source loyality-free RISC-V ISA. It is complete hardware prototyping and software development environment based around the :doc:`Atom` CPU. RISC-V Atom is a customizable processor platform which is easy to learn, use and tinker even for a begineer. It also provides a wide variety of software examples for testing, a rich documentation and a comprehensive guide for getting stated. +**RISC-V Atom** is an open-source soft-core processor platform targeted for FPGAs. It is complete hardware prototyping +and software development environment based around **Atom**, which is a 32-bit embedded-class processor based on the +`RISC-V `_ Instruction Set Architecture (ISA). Key Highlights *************** +Key highlights of the RISC-V Atom projects are are listed below: -#. Based around :doc:`Atom`: A 32-bit 2-stage pipelined RISC-V CPU. -#. Provides multiple SoC configurations. -#. Provides an interactive feature-rich RTL simulation frontend called **AtomSim**. -#. Features a python based processor verification framework called *SCAR*. -#. RISC-V GCC is used as default toolchain (prebuilt toolchains are also provided) -#. A rich documentation & getting started guide. -#. An array of software examples to run & test. -#. A rich software framework with a C library **libcatom** for all SoC peripherals. -#. Customizable, Easy to learn and tinker. -#. Open-Sources under MIT License. - -.. note:: - Although significant efforts have been and will be made towards optimizing the RTL for LUT consumption & timing on FPGAs, however, the **codebase is not recommended for any production use as of now**. - -To get started, Check out the getting started guide :doc:`/pages/getting_started/prerequisites`. +#. Atom implements ``RV32IC_Zicsr`` ISA as defined in the `RISC-V unprivileged ISA manual `_. +#. Simple 2-stage pipelined architecture, ideal for smaller FPGAs. +#. Optional support for RISC-V exceptions and interrupts. +#. Wishbone ready CPU interface. +#. Interactive RTL simulator - :doc:`AtomSim`. +#. In-house verification framework - :doc:`SCAR`. +#. Multiple SoC configurations. +#. Tiny libc like standard library - :doc:`Libcatom`. +#. Wide range of example programs. +#. Open source under `MIT License `_. + +.. tip:: + To get started, Check out the :doc:`getting started guide`. + + +Components +*********** +Following is list of various components of the RISC-V Atom project. + +.. card:: RISC-V Atom CPU + :link-type: doc + :link: /pages/documentation/riscv_atom + + A simple 32-bit RISC-V processor. + +.. card:: SoC Targets + :link-type: doc + :link: /pages/documentation/soc_targets + + RISC-V Atom project provides several configurable SoC targets that can be built around the Atom CPU. + +.. card:: AtomSim + :link-type: doc + :link: /pages/documentation/atomsim/atomsim + + AtomSim is the interactive RTL simulator for RISC-V Atom SoCs. + +.. card:: SCAR + :link-type: doc + :link: /pages/documentation/scar + + SCAR (Search, Compile Assert, and Run) is an in-house processor verification framework written in python. diff --git a/docs/requirements.txt b/docs/requirements.txt index 277e92d7..bbb8fcbb 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,4 +1,4 @@ -sphinx==4.5.0 # not using latest due to compatibility issues with with sphinx-panels +sphinx==5.0 # not using latest due to compatibility issues with with sphinx-panels sphinx-rtd-theme sphinx-copybutton -sphinx-panels +sphinx-design diff --git a/rtl/uncore/spi/README.md b/rtl/uncore/spi/README.md index 01653e62..1dc948e0 100644 --- a/rtl/uncore/spi/README.md +++ b/rtl/uncore/spi/README.md @@ -70,7 +70,7 @@ SPI IP with Wishbone B-4 Interface. | **Range** | **Access** | **RstVal** | **Name** | **Description** |-----------|------------|------------|----------|----------------- -| [31:24] | RW | - | ACS | Active Chip Select +| [31:24] | RW | 0x1 | ACS | Active Chip Select | [23:2] | - | - | - | Reserved | [1:0] | RW | 0x0 | CSMODE | CS Mode diff --git a/rtl/uncore/spi/SPI_wb.v b/rtl/uncore/spi/SPI_wb.v index a9ada835..f63a7338 100644 --- a/rtl/uncore/spi/SPI_wb.v +++ b/rtl/uncore/spi/SPI_wb.v @@ -85,7 +85,7 @@ always @(posedge wb_clk_i) begin rg_sctrl_pol <= 1'b0; rg_sctrl_spien <= 1'b0; - rg_csctrl_acs <= 0; + rg_csctrl_acs <= 1; rg_csctrl_csmode <= 2'b00; rg_dctrl_prcshd <= DEFAULT_DCTRL_PRECSHD; diff --git a/scripts/atomsim-gen-vports b/scripts/atomsim-gen-vports index a4904002..c732e9a0 100755 --- a/scripts/atomsim-gen-vports +++ b/scripts/atomsim-gen-vports @@ -9,15 +9,8 @@ SIMPORT=$RVATOM/simport if [[ $1 != -s ]] then - echo "simport : $SIMPORT" - echo "userport: $USERPORT" - - echo -n "Generating Virtual UART Ports... " + printf "\033[0;36m$SIMPORT\033[0m <--\033[0;33m socat \033[0m--> \033[0;36m$USERPORT\033[0m\n" fi socat pty,link=$USERPORT,echo=0 pty,link=$SIMPORT,echo=0 & - -if [[ $1 != -s ]] -then - echo " Done!" -fi \ No newline at end of file +echo "Socat PID: $!" \ No newline at end of file diff --git a/scripts/atomsim-runexamples b/scripts/atomsim-runexamples deleted file mode 100755 index 62647a1a..00000000 --- a/scripts/atomsim-runexamples +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/bash - -# Detect current directory -curr_dir=$(pwd) -echo -e "current directory: $currdir" - -example_dir=$RVATOM/sw/examples/ - -cd ${example_dir} -make run-all $* -cd ${curr_dir} \ No newline at end of file diff --git a/sourceme b/sourceme index b4198ed2..236bc479 100644 --- a/sourceme +++ b/sourceme @@ -1,4 +1,4 @@ -########## RISCV-ATOM Environment Setup ########## +echo "***** RISC-V Atom Environment Setup *****" # Uncomment if using environment modules # module load verilator/5.006 diff --git a/sw/examples/Makefile b/sw/examples/Makefile index 14a48de4..8ecdce72 100644 --- a/sw/examples/Makefile +++ b/sw/examples/Makefile @@ -77,7 +77,7 @@ ifeq ($(__check_soctarget), true) ABI:=$(shell $(RVATOM)/scripts/cfgparse.py $(RVATOM)/rtl/config/$(soctarget).json -a abi) endif -CFLAGS += -march=$(ISA) -mabi=$(ABI) -nostartfiles -ffreestanding -Os +CFLAGS += -march=$(ISA) -mabi=$(ABI) -nostartfiles -ffreestanding -Os -fdata-sections -ffunction-sections CFLAGS += -I $(RVATOM_LIB)/include -L $(RVATOM_LIB) LFLAGS := -T $(LINKERSCRIPT) -lcatom -Wl,--gc-sections diff --git a/sw/examples/sdcard/Makefile.include b/sw/examples/sdcard/Makefile.include new file mode 100644 index 00000000..40a13b5e --- /dev/null +++ b/sw/examples/sdcard/Makefile.include @@ -0,0 +1,2 @@ +src_files = sdcard.c +executable = sdcard.elf \ No newline at end of file diff --git a/sw/examples/sdcard/sdcard.c b/sw/examples/sdcard/sdcard.c new file mode 100644 index 00000000..af1d6e88 --- /dev/null +++ b/sw/examples/sdcard/sdcard.c @@ -0,0 +1,79 @@ +#include "platform.h" +#include +#include +#include + + +int main(){ + serial_init(UART_BAUD_115200); + + struct SPI_Config cfg = { + cfg.base_addr = SPI_ADDR, + cfg.enable = true, + cfg.pha = false, + cfg.pol = false, + cfg.lsb_first = false, + cfg.baudrate = 1000000, + cfg.device_num = 0, + cfg.cs_mode = CSMODE_DISABLE, + cfg.post_cs_low_delay = 1, + cfg.pre_cs_high_delay = 1, + cfg.loopback_enable=false + }; + + uint8_t rc = sd_init(&cfg); + if(rc != SD_SUCCESS) + return 1; + + printf("read Sector 0\n"); + uint8_t rbuf[512], res[5], token; + + res[0] = sdc_read_block(&cfg, 0x00000000, rbuf, &token); + + + // print response + if(SD_RESP1_NO_ERROR(res[0]) && (token == SD_START_TOKEN)) { + dumphexbuf((char*)rbuf, 512, 0x00000000); + } + else { + puts("Error reading sector\n"); + return 1; + } + + + // initialize buffer + uint8_t wbuf[512]; + for(uint16_t i = 0; i < 512; i++) wbuf[i] = 0x55; + + res[0] = sdc_write_block(&cfg, 0x00000000, wbuf, &token); + // print response + if(SD_RESP1_NO_ERROR(res[0]) && (token == SD_DATA_ACCEPTED)) { + puts("Write OK\n"); + } + else { + puts("Error writing\n"); + return 1; + } + + + // read again + res[0] = sdc_read_block(&cfg, 0x00000000, rbuf, &token); + if(SD_RESP1_NO_ERROR(res[0]) && (token == SD_START_TOKEN)) { + dumphexbuf((char*)rbuf, 512, 0x00000000); + } + else { + puts("Error reading sector\n"); + return 1; + } + + // verify + for(int i=0; i<512; i++){ + if(rbuf[i] != wbuf[i]){ + printf("TEST FAIL! @ i=%d\n", i); + return 1; + } + } + + puts("TEST PASSED!\n"); + return 0; +} \ No newline at end of file diff --git a/sw/lib/include/assert.h b/sw/lib/include/assert.h index 2e3a5563..5ab58475 100644 --- a/sw/lib/include/assert.h +++ b/sw/lib/include/assert.h @@ -6,6 +6,6 @@ #define assert(x) \ if(!(x)) { \ - puts("[ERROR]: Assert Failed:" EXPAND_AND_STRINGIFY(__FILE__) EXPAND_AND_STRINGIFY(__LINE__)); \ + puts("[ERROR]: Assert Failed: " __FILE__ ":" EXPAND_AND_STRINGIFY(__LINE__) "\n"); \ exit(1); \ } diff --git a/sw/lib/include/sd.h b/sw/lib/include/sd.h new file mode 100644 index 00000000..479b1289 --- /dev/null +++ b/sw/lib/include/sd.h @@ -0,0 +1,48 @@ +#pragma once +#include +#include + +// Error codes +#define SD_SUCCESS 0 +#define SD_ERR_UNKNOWN_CARD 1 +#define SD_ERR_MAYBE_VER1CARD 2 + +#define SD_DATA_ACCEPTED 0x05 +#define SD_DATA_REJECTED_CRC 0x0B +#define SD_DATA_REJECTED_WRITE 0x0D + +#define SD_RESP1_NO_ERROR(x) ((x) == 0) + +#define SD_START_TOKEN 0xFE +#define SD_ERROR_TOKEN 0x00 +#define SD_BLOCK_LEN 512 + +/** + * @brief Initialize SDCARD + * + * @param cfg SPI config + * @return uint8_t resp1 + */ +uint8_t sd_init(struct SPI_Config *cfg); + +/** + * @brief Read a block from SDCARD + * + * @param cfg SPI config + * @param addr block address + * @param buf buffer + * @param token response token + * @return uint8_t resp1 + */ +uint8_t sdc_read_block(struct SPI_Config *cfg, uint32_t addr, uint8_t *buf, uint8_t *token); + +/** + * @brief Write a block to SDCard + * + * @param cfg SPI Config + * @param addr block address + * @param buf buffer + * @param token response token + * @return uint8_t resp1 + */ +uint8_t sdc_write_block(struct SPI_Config *cfg, uint32_t addr, uint8_t *buf, uint8_t *token); diff --git a/sw/lib/include/stdlib.h b/sw/lib/include/stdlib.h index e7e43949..58017404 100644 --- a/sw/lib/include/stdlib.h +++ b/sw/lib/include/stdlib.h @@ -88,7 +88,7 @@ char *memset(char *dptr, int x, int len); * @param block_size size of block to be allocated (in bytes) * @return void* pointer to the allocated block of memory */ -void *malloc(size_t block_size); +void *malloc(unsigned block_size); /** @@ -98,3 +98,14 @@ void *malloc(size_t block_size); */ void free(void* ptr); + +/** + * @brief Defragments heap + */ +void heap_defrag(); + + +/** + * @brief Displays heap blocks and overall status + */ +void heap_status(); diff --git a/sw/lib/libcatom/heap.c b/sw/lib/libcatom/heap.c new file mode 100644 index 00000000..b21629ca --- /dev/null +++ b/sw/lib/libcatom/heap.c @@ -0,0 +1,146 @@ +#include +#include +#include + +extern int _start_heap[2]; // specified as array to prevent a bounds warning + +#define HEAP_START &_start_heap +#ifndef HEAP_SIZE + #define HEAP_SIZE 2048 +#endif + +struct heapblock{ + struct heapblock * next; + unsigned size; +}; +typedef struct heapblock HeapBlock; + +// Free list +static HeapBlock * _freelist = NULL; + + +void heap_init() { + _freelist = (HeapBlock *) HEAP_START; + _freelist->next = NULL; + _freelist->size = HEAP_SIZE - sizeof(HeapBlock); +} + + +void * malloc(unsigned nbytes) { + // First Fit + if(nbytes == 0 ) + return NULL; + + HeapBlock * curr = _freelist; + HeapBlock * prev = NULL; + + while(curr != NULL){ + if(curr->size >= nbytes){ + if(curr->size > sizeof(HeapBlock) + nbytes){ + // split + HeapBlock *newblk = (HeapBlock *)(((uint8_t*)curr) + sizeof(HeapBlock) + nbytes); + newblk->next = curr->next; + newblk->size = curr->size - (sizeof(HeapBlock) + nbytes); + curr->next = newblk; + curr->size = nbytes; + } + + // allocate current block (remove from list & return chunk pointer) + if(prev == NULL) { + // first block + _freelist = curr->next; + } + else { + prev->next = curr->next; + } + + // printf("Allocating [0x%08x: 0x%08x, 0x%d]\n", (uint32_t)curr, (uint32_t)curr->next, curr->size); + return (void *)(((uint8_t*)curr) + sizeof(HeapBlock)); + } + prev = curr; + curr = curr->next; + } + + // No suitable block found + return NULL; +} + + +void free(void * chunk){ + if(chunk == NULL) + return; + + HeapBlock * blk = (HeapBlock *)(((uint8_t*)chunk) - sizeof(HeapBlock)); + // printf("Freeing [0x%08x: 0x%08x, 0x%d]\n", (uint32_t)blk, (uint32_t)blk->next, blk->size); + + HeapBlock * curr = _freelist; + HeapBlock * prev = NULL; + + // march till we reach location of blk + while(curr != NULL && curr < blk){ + prev = curr; + curr = curr->next; + } + + // Insert block + if (prev == NULL) { + _freelist = blk; + } else { + prev->next = blk; + } + blk->next = curr; + + // // merge with previous + // // only if prev and current are adjascent (which means both are free) + // if(prev != NULL && ((uint8_t*)prev + sizeof(HeapBlock) + prev->size) == (uint8_t*)blk) { + // prev->size += sizeof(HeapBlock) + blk->size; + // prev->next = blk->next; + // } + + // // merge with next + // // only if current and next are adjascent (which means both are free) + // if(curr != NULL && ((uint8_t*)blk + sizeof(HeapBlock) + blk->size) == (uint8_t*)curr) { + // blk->size += sizeof(HeapBlock) + curr->size; + // blk->next = curr->next; + // } +} + + +void heap_defrag(){ + HeapBlock * curr = _freelist; + HeapBlock * prev = NULL; + + while(curr != NULL){ + // merge if prev blk & curr blk are contigous (both free) + if(prev != NULL && (uint8_t*)prev+sizeof(HeapBlock)+prev->size == (uint8_t*)curr){ + prev->size += sizeof(HeapBlock) + curr->size; + prev->next = curr->next; + curr = prev->next; + continue; + } + prev = curr; + curr = curr->next; + } +} + + +void heap_status(){ + unsigned total_sz = 0; + unsigned blk_cnt = 0; + unsigned largest_blk_sz = 0; + HeapBlock * currblk = _freelist; + while(currblk != NULL) { + printf("Block [addr=0x%08x: next=0x%08x, size=%d]\n", (uint32_t)currblk, (uint32_t)currblk->next, currblk->size); + total_sz += currblk->size; + if(currblk->size > largest_blk_sz){ + largest_blk_sz = currblk->size; + } + currblk = currblk->next; + blk_cnt ++; + } + printf("Chunks: %d\n", blk_cnt); + printf("Avail: %d/%d bytes\n", total_sz, HEAP_SIZE); + + // see: https://cpp4arduino.com/2018/11/06/what-is-heap-fragmentation.html + printf("Frag: %.2f %%\n", (1.0 - ((float)largest_blk_sz/(float)HEAP_SIZE)) * 100); +} diff --git a/sw/lib/libcatom/hydrogensoc/sd.c b/sw/lib/libcatom/hydrogensoc/sd.c new file mode 100644 index 00000000..96747674 --- /dev/null +++ b/sw/lib/libcatom/hydrogensoc/sd.c @@ -0,0 +1,414 @@ +#include +#include +#include +#include + +#include + +#ifdef SDCARD_SILENT_INIT + #define SD_DBG(x) +#else + #define SD_DBG(x) x +#endif + +// Configuration +#define SD_NUM_ATTEMPTS 10 +#define SD_SPI_INIT_BAUD 200000 + +//FIXME: change these to time based timeout values +#define SD_MAX_READ_ATTEMPTS 1563 +#define SD_MAX_WRITE_ATTEMPTS 3907 + +// Helper Macros +#define R1_CHECK_CARD_RDY(X) ((X) == 0) +#define R1_CHECK_MSB_ERROR(X) ((X) & 0b10000000) +#define R1_CHECK_PARAM_ERROR(X) ((X) & 0b01000000) +#define R1_CHECK_ADDR_ERROR(X) ((X) & 0b00100000) +#define R1_CHECK_ERASE_SEQ_ERROR(X) ((X) & 0b00010000) +#define R1_CHECK_CRC_ERROR(X) ((X) & 0b00001000) +#define R1_CHECK_ILLEGAL_CMD(X) ((X) & 0b00000100) +#define R1_CHECK_ERASE_RESET(X) ((X) & 0b00000010) +#define R1_CHECK_IN_IDLE(X) ((X) & 0b00000001) + +#define R7_GET_CMD_VER(X) ((X >> 4) & 0xF0) +#define R7_GET_VOL_ACC(X) (X & 0x1F) +#define R7_VOLTAGE_ACC_27_33 0b00000001 +#define R7_VOLTAGE_ACC_LOW 0b00000010 +#define R7_VOLTAGE_ACC_RES1 0b00000100 +#define R7_VOLTAGE_ACC_RES2 0b00001000 + +#define R3_POWER_UP_STATUS(X) ((X) & 0x40) +#define R3_CCS_VAL(X) ((X) & 0x40) +#define R3_VDD_2728(X) ((X) & 0b10000000) +#define R3_VDD_2829(X) ((X) & 0b00000001) +#define R3_VDD_2930(X) ((X) & 0b00000010) +#define R3_VDD_3031(X) ((X) & 0b00000100) +#define R3_VDD_3132(X) ((X) & 0b00001000) +#define R3_VDD_3233(X) ((X) & 0b00010000) +#define R3_VDD_3334(X) ((X) & 0b00100000) +#define R3_VDD_3435(X) ((X) & 0b01000000) +#define R3_VDD_3536(X) ((X) & 0b10000000) + + +uint8_t sdc_read_res1(struct SPI_Config *cfg); +void sdc_read_res3_or_7(struct SPI_Config *cfg, uint8_t *res); +void sdc_powerup_seq(struct SPI_Config *cfg); + +/////////////////////////////////////////////////////////////////////////////// +static void __print_buf(uint8_t *buf, unsigned buflen) { + puts("{ "); + for(unsigned i=0; i 1) return; + + printf("- Cmd Version: 0x%x\n", R7_GET_CMD_VER(res[1])); + puts("- Voltage Accepted: "); + switch(R7_GET_VOL_ACC(res[3])){ + case R7_VOLTAGE_ACC_27_33: puts("2.7-3.6V"); break; + case R7_VOLTAGE_ACC_LOW: puts("Low Voltage"); break; + case R7_VOLTAGE_ACC_RES1: + case R7_VOLTAGE_ACC_RES2: puts("Reserved"); break; + default: puts("Not Defined"); break; + } + putchar('\n'); + printf("- Check pattern: 0x%x\n", res[4]); +} + +void sd_print_r3_resp(uint8_t *res) { + puts("Res3:"); __print_buf(res, 5); putchar('\n'); + + sd_print_r1_resp(res[0]); + if(res[0] > 1) return; + + puts("- Card Power Up Status: "); + if(R3_POWER_UP_STATUS(res[1])) { + puts("Ready\n"); + printf("- CCS Status: %c\n", R3_CCS_VAL(res[1]) ? '1' : '0'); + } + else { + puts("Busy\n"); + } + + puts("- VDD Window: "); + if(R3_VDD_2728(res[3])) puts("2.7-2.8, "); + if(R3_VDD_2829(res[2])) puts("2.8-2.9, "); + if(R3_VDD_2930(res[2])) puts("2.9-3.0, "); + if(R3_VDD_3031(res[2])) puts("3.0-3.1, "); + if(R3_VDD_3132(res[2])) puts("3.1-3.2, "); + if(R3_VDD_3233(res[2])) puts("3.2-3.3, "); + if(R3_VDD_3334(res[2])) puts("3.3-3.4, "); + if(R3_VDD_3435(res[2])) puts("3.4-3.5, "); + if(R3_VDD_3536(res[2])) puts("3.5-3.6"); + puts("\n"); +} + +enum SDRespType { + RESP1, + RESP3, + RESP7 +}; + +typedef struct { + uint8_t cmd; + uint32_t arg; + uint8_t crc; + enum SDRespType resp_type; +} SDCmd_attr; + +typedef enum { + SD_CMD0 = 0, + SD_CMD8 = 1, + SD_CMD17 = 2, + SD_CMD24 = 3, + SD_CMD41 = 4, + SD_CMD55 = 5, + SD_CMD58 = 6 +} SDCmd; + +const SDCmd_attr sdcmds[7] = { + /* SD_CMD0 */ {.cmd=0, .arg=0x00000000, .crc=0x94, .resp_type=RESP1}, + /* SD_CMD8 */ {.cmd=8, .arg=0x000001AA, .crc=0x86, .resp_type=RESP7}, + /* SD_CMD17 */ {.cmd=17, .arg=0x00000000, .crc=0x00, .resp_type=RESP1}, + /* SD_CMD24 */ {.cmd=24, .arg=0x00000000, .crc=0x00, .resp_type=RESP1}, + /* SD_CMD41 */ {.cmd=41, .arg=0x40000000, .crc=0x00, .resp_type=RESP1}, + /* SD_CMD55 */ {.cmd=55, .arg=0x00000000, .crc=0x00, .resp_type=RESP1}, + /* SD_CMD58 */ {.cmd=58, .arg=0x00000000, .crc=0x00, .resp_type=RESP3} +}; + +#define _spi_select(cfg) \ + spi_transfer(cfg, 0xFF); \ + spi_select(cfg); \ + spi_transfer(cfg, 0xFF); + +#define _spi_deselect(cfg) \ + spi_transfer(cfg, 0xFF); \ + spi_deselect(cfg); \ + spi_transfer(cfg, 0xFF); \ + +void sdc_cmd(struct SPI_Config *cfg, SDCmd cmd, uint8_t * resp) { + // send command + spi_transfer(cfg, sdcmds[cmd].cmd | 0x40); + + // send arg + spi_transfer(cfg, sdcmds[cmd].arg >> 24); + spi_transfer(cfg, sdcmds[cmd].arg >> 16); + spi_transfer(cfg, sdcmds[cmd].arg >> 8); + spi_transfer(cfg, sdcmds[cmd].arg); + + // send CRC + spi_transfer(cfg, sdcmds[cmd].crc | 0x1); + + // read response + switch(sdcmds[cmd].resp_type) { + case RESP1: + resp[0] = sdc_read_res1(cfg); + break; + + case RESP3: + case RESP7: + sdc_read_res3_or_7(cfg, resp); + break; + + default: + resp[0] = sdc_read_res1(cfg); + break; + } +} + +uint8_t sdc_read_res1(struct SPI_Config *cfg) { + unsigned ntry = 8; + uint8_t resp; + do { + resp = spi_transfer(cfg, 0xFF); + } while((resp == 0xff) & (ntry-- > 0)); + return resp; +} + +void sdc_read_res3_or_7(struct SPI_Config *cfg, uint8_t *res) { + // read R1 + res[0] = sdc_read_res1(cfg); + + // if error reading R1, return + if(res[0] > 1) return; + + // read remaining bytes + res[1] = spi_transfer(cfg, 0x0); + res[2] = spi_transfer(cfg, 0x0); + res[3] = spi_transfer(cfg, 0x0); + res[4] = spi_transfer(cfg, 0x0); +} + +void sdc_powerup_seq(struct SPI_Config *cfg) { + // deselect SPI + spi_deselect(cfg); + + // wait for some time + sleep_ms(1); + + // send 80 clock cycles to synchronize + for(int i=0; i<80; i+=8) + spi_transfer(cfg, 0xff); +} + +uint8_t sd_init(struct SPI_Config *cfg) +{ + cfg->cs_mode = CSMODE_DISABLE; + cfg->baudrate = SD_SPI_INIT_BAUD; + spi_init(cfg); + + uint8_t res[5]; + uint8_t ntries = 0; + + // Step - 1: Power UP Sequence + SD_DBG(puts("SDC: Powering up\n");) + sdc_powerup_seq(cfg); + + + // Step - 2: goto IDLE + SD_DBG(puts("SDC: Sending CMD0..\n");) + ntries = SD_NUM_ATTEMPTS; + do { + _spi_select(cfg) + sdc_cmd(cfg, SD_CMD0, res); + _spi_deselect(cfg) + } while ((res[0] != 0x01) && (ntries-- > 0)); + + if(ntries==0) + return SD_ERR_UNKNOWN_CARD; + + + // Step - 3: Send interface conditions + SD_DBG(puts("SDC: Sending CMD8..\n");) + _spi_select(cfg) + sdc_cmd(cfg, SD_CMD8, res); + _spi_deselect(cfg) + SD_DBG(sd_print_r7_resp(res);) + + // check idle + if(res[0] != 0x01) + return SD_ERR_MAYBE_VER1CARD; + // check echo pattern + if(res[4] != 0xAA) + return SD_ERR_UNKNOWN_CARD; + + + // Step - 4: Initialization + SD_DBG(puts("SDC: Initializing..\n");) + ntries = 0; + do { + if(ntries > SD_NUM_ATTEMPTS) { + return SD_ERR_UNKNOWN_CARD; + } + + // send app cmd + SD_DBG(printf("SDC: Sending CMD55... (Try:%d)\n", ntries);) + _spi_select(cfg) + sdc_cmd(cfg, SD_CMD55, res); + _spi_deselect(cfg) + SD_DBG(sd_print_r1_resp(res[0]);) + + // if no error in response + if(res[0] < 2) + { + SD_DBG(puts("SDC: Sending ACMD41...\n");) + _spi_select(cfg) + sdc_cmd(cfg, SD_CMD41, res); + _spi_deselect(cfg) + SD_DBG(sd_print_r1_resp(res[0]);) + } + + // wait + sleep_ms(10); + ntries++; + } while(!R1_CHECK_CARD_RDY(res[0])); + + // Step - 5: read OCR + SD_DBG(puts("SDC: Send CMD58 (Read OCR)..\n");) + _spi_select(cfg) + sdc_cmd(cfg, SD_CMD58, res); + _spi_deselect(cfg) + SD_DBG(sd_print_r3_resp(res);) + + // check card is ready + SD_DBG(puts("SDC: Initialization ");) + + if(!(res[1] & 0x80)) { + SD_DBG(puts("FAILED\n");) + return SD_ERR_UNKNOWN_CARD; + } + + SD_DBG(puts("SUCCESS\n");) + return SD_SUCCESS; +} + +uint8_t sdc_read_block(struct SPI_Config *cfg, uint32_t addr, uint8_t *buf, uint8_t *token) { + uint8_t res1, read; + uint16_t readAttempts; + + // set token to none + *token = 0xFF; + + _spi_select(cfg); + + // send command 17 + sdc_cmd(cfg, SD_CMD17, &res1); + + // if response received from card + if(res1 != 0xFF) + { + // wait for a response token (timeout = 100ms) + readAttempts = 0; + while(++readAttempts != SD_MAX_READ_ATTEMPTS) + if((read = spi_transfer(cfg, 0xFF)) != 0xFF) break; + + // if response token is 0xFE + if(read == SD_START_TOKEN) + { + // read 512 byte block + for(uint16_t i = 0; i < SD_BLOCK_LEN; i++) + *buf++ = spi_transfer(cfg, 0xFF); + + // read (& discard) 16-bit CRC + spi_transfer(cfg, 0xFF); + spi_transfer(cfg, 0xFF); + } + + // set token to card response + *token = read; + } + + // deassert chip select + _spi_deselect(cfg); + return res1; +} + +uint8_t sdc_write_block(struct SPI_Config *cfg, uint32_t addr, uint8_t *buf, uint8_t *token) +{ + uint8_t res1, readAttempts, read; + + // set token to none + *token = 0xFF; + + // assert chip select + _spi_select(cfg) + + // send CMD24 + sdc_cmd(cfg, SD_CMD24, &res1); + + // if no error + if(R1_CHECK_CARD_RDY(res1)) + { + // send start token + spi_transfer(cfg, SD_START_TOKEN); + + // write buffer to card + for(uint16_t i = 0; i < SD_BLOCK_LEN; i++) + spi_transfer(cfg, buf[i]); + + // wait for a response (timeout = 250ms) + readAttempts = 0; + while(++readAttempts != SD_MAX_WRITE_ATTEMPTS) + if((read = spi_transfer(cfg, 0xFF)) != 0xFF) { *token = 0xFF; break; } + + // if data accepted + if((read & 0x1F) == 0x05) + { + // set token to data accepted + *token = 0x05; + + // wait for write to finish (timeout = 250ms) + readAttempts = 0; + while(spi_transfer(cfg, 0xFF) == 0x00) { + if(++readAttempts == SD_MAX_WRITE_ATTEMPTS) { + *token = 0x00; + break; + } + } + } + } + + // deassert chip select + _spi_deselect(cfg) + return res1; +} diff --git a/sw/lib/libcatom/start.S b/sw/lib/libcatom/start.S index ff9b57c4..d012e630 100644 --- a/sw/lib/libcatom/start.S +++ b/sw/lib/libcatom/start.S @@ -31,6 +31,9 @@ _start: sub a2, t0, a0 // size = _sbss - _sbss jal memset + // Initialize heap + jal heap_init + /* Disable and clear all interrupt sources */ li a3, -1 csrc mie, a3 diff --git a/synth/altera/de0-cv/HydrogenSoC.tcl b/synth/altera/de0-cv/HydrogenSoC.tcl index 57cf2c89..18daa27e 100644 --- a/synth/altera/de0-cv/HydrogenSoC.tcl +++ b/synth/altera/de0-cv/HydrogenSoC.tcl @@ -160,14 +160,26 @@ if {$make_assignments} { set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to gpio_io[29] set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to gpio_io[30] set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to gpio_io[31] - set_location_assignment PIN_G13 -to spi_cs_o[0] - set_location_assignment PIN_G12 -to spi_mosi_o - set_location_assignment PIN_J17 -to spi_miso_i - set_location_assignment PIN_K16 -to spi_sck_o + + # SDCARD Slot + set_location_assignment PIN_C11 -to spi_cs_o[0] + set_location_assignment PIN_H11 -to spi_sck_o + set_location_assignment PIN_B11 -to spi_mosi_o + set_location_assignment PIN_K9 -to spi_miso_i set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to spi_cs_o[0] + set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to spi_sck_o set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to spi_mosi_o set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to spi_miso_i - set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to spi_sck_o + + # GPIO - SDCARD ELA + # set_location_assignment PIN_G13 -to ela_spi_cs_o + # set_location_assignment PIN_G12 -to ela_spi_sck_o + # set_location_assignment PIN_J17 -to ela_spi_mosi_o + # set_location_assignment PIN_K16 -to ela_spi_miso_o + # set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to ela_spi_cs_o[0] + # set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to ela_spi_sck_o + # set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to ela_spi_mosi_o + # set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to ela_spi_miso_o set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top @@ -175,25 +187,6 @@ if {$make_assignments} { export_assignments } -load_package flow - -# Synthesize the design -puts "Synthesizing the design..." -execute_module -tool map - -# Place and route -puts "Performing place and route..." -execute_module -tool fit - -# Generate programming files (Bitstream) -puts "Generating bitstream..." -execute_module -tool asm - -# Generate Timing Analysis Report -puts "Generating timing analysis report..." -execute_module -tool sta - -puts "Bitstream generation completed." # Load necessary package load_package flow