OpenCores
URL https://opencores.org/ocsvn/neorv32/neorv32/trunk

Subversion Repositories neorv32

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /neorv32/trunk
    from Rev 5 to Rev 6
    Reverse comparison

Rev 5 → Rev 6

/.ci/hw_check.sh
7,67 → 7,13
homedir="$( cd "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )"
homedir=$homedir/..
 
# The directories of the hw source files
srcdir_core=$homedir/rtl/core
srcdir_top_templates=$homedir/rtl/top_templates
srcdir_sim=$homedir/sim
 
# Show GHDL version
ghdl -v
 
# List files
echo ""
echo "Simulation source files:"
ls -al $srcdir_core
ls -al $srcdir_top_templates
ls -al $srcdir_sim
 
# Analyse sources; libs and images at first!
ghdl -a --work=neorv32 $srcdir_core/neorv32_package.vhd
ghdl -a --work=neorv32 $srcdir_core/neorv32_application_image.vhd
ghdl -a --work=neorv32 $srcdir_core/neorv32_bootloader_image.vhd
#
ghdl -a --work=neorv32 $srcdir_core/neorv32_boot_rom.vhd
ghdl -a --work=neorv32 $srcdir_core/neorv32_clic.vhd
ghdl -a --work=neorv32 $srcdir_core/neorv32_cpu.vhd
ghdl -a --work=neorv32 $srcdir_core/neorv32_cpu_alu.vhd
ghdl -a --work=neorv32 $srcdir_core/neorv32_cpu_bus.vhd
ghdl -a --work=neorv32 $srcdir_core/neorv32_cpu_control.vhd
ghdl -a --work=neorv32 $srcdir_core/neorv32_cpu_cp_muldiv.vhd
ghdl -a --work=neorv32 $srcdir_core/neorv32_cpu_decompressor.vhd
ghdl -a --work=neorv32 $srcdir_core/neorv32_cpu_regfile.vhd
ghdl -a --work=neorv32 $srcdir_core/neorv32_devnull.vhd
ghdl -a --work=neorv32 $srcdir_core/neorv32_dmem.vhd
ghdl -a --work=neorv32 $srcdir_core/neorv32_gpio.vhd
ghdl -a --work=neorv32 $srcdir_core/neorv32_imem.vhd
ghdl -a --work=neorv32 $srcdir_core/neorv32_mtime.vhd
ghdl -a --work=neorv32 $srcdir_core/neorv32_pwm.vhd
ghdl -a --work=neorv32 $srcdir_core/neorv32_spi.vhd
ghdl -a --work=neorv32 $srcdir_core/neorv32_top.vhd
ghdl -a --work=neorv32 $srcdir_core/neorv32_trng.vhd
ghdl -a --work=neorv32 $srcdir_core/neorv32_twi.vhd
ghdl -a --work=neorv32 $srcdir_core/neorv32_uart.vhd
ghdl -a --work=neorv32 $srcdir_core/neorv32_wdt.vhd
ghdl -a --work=neorv32 $srcdir_core/neorv32_wishbone.vhd
#
ghdl -a --work=neorv32 $srcdir_top_templates/*.vhd
#
ghdl -a --work=neorv32 $srcdir_sim/*.vhd
 
# Prepare simulation output files
touch neorv32.testbench_uart.out
chmod 777 neorv32.testbench_uart.out
touch neorv32.devnull.out
chmod 777 neorv32.devnull.out
 
# Run simulation
ghdl -e --work=neorv32 neorv32_tb
ghdl -r --work=neorv32 neorv32_tb --stop-time=5ms --ieee-asserts=disable --assert-level=error
sh $homedir/sim/ghdl/ghdl_sim.sh --stop-time=5ms
 
# Check output
echo "Checking NEORV32.DEVNULL output. Should contain:"; cat $homedir/check_reference.out
echo "Checking NEORV32.DEVNULL text output. Should contain:"; cat $homedir/check_reference.out
echo ""
echo "Checking NEORV32.DEVNULL output. NEORV32.DEVNULL output is:"
echo "Checking NEORV32.DEVNULL text output. NEORV32.DEVNULL text output is:"
cat neorv32.devnull.out
 
# Check if reference can be found in output
/.ci/sw_check.sh
10,7 → 10,7
# The directories of the SW source files
srcdir_examples=$homedir/sw/example
srcdir_bootloader=$homedir/sw/bootloader
test_app_dir=$homedir/sw/example/test_exceptions
test_app_dir=$homedir/sw/example/cpu_test
 
# List files
ls -al $srcdir_examples
/docs/figures/neorv32_overview.png Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream
/docs/NEORV32.pdf Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream
/docs/doxygen_makefile_sw
1,51 → 1,448
# Doxyfile 1.8.11
# Doxyfile 1.8.17
 
# This file describes the settings to be used by the documentation system
# doxygen (www.doxygen.org) for a project.
#
# All text after a double hash (##) is considered a comment and is placed in
# front of the TAG it is preceding.
#
# All text after a single hash (#) is considered a comment and will be ignored.
# The format is:
# TAG = value [value, ...]
# For lists, items can also be appended using:
# TAG += value [value, ...]
# Values that contain spaces should be placed between quotes (\" \").
 
#---------------------------------------------------------------------------
# Project related configuration options
#---------------------------------------------------------------------------
 
# This tag specifies the encoding used for all characters in the configuration
# file that follow. The default is UTF-8 which is also the encoding used for all
# text before the first occurrence of this tag. Doxygen uses libiconv (or the
# iconv built into libc) for the transcoding. See
# https://www.gnu.org/software/libiconv/ for the list of possible encodings.
# The default value is: UTF-8.
 
DOXYFILE_ENCODING = UTF-8
 
# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by
# double-quotes, unless you are using Doxywizard) that should identify the
# project for which the documentation is generated. This name is used in the
# title of most generated pages and in a few other places.
# The default value is: My Project.
 
PROJECT_NAME = "The NEORV32 Processor - Software Framework"
 
# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
# could be handy for archiving the generated documentation or if some version
# control system is used.
 
PROJECT_NUMBER = 1.0
 
# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a
# quick idea about the purpose of the project. Keep the description short.
 
PROJECT_BRIEF =
 
# With the PROJECT_LOGO tag one can specify a logo or an icon that is included
# in the documentation. The maximum height of the logo should not exceed 55
# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy
# the logo to the output directory.
 
PROJECT_LOGO =
 
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
# into which the generated documentation will be written. If a relative path is
# entered, it will be relative to the location where doxygen was started. If
# left blank the current directory will be used.
 
OUTPUT_DIRECTORY = build
 
# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub-
# directories (in 2 levels) under the output directory of each output format and
# will distribute the generated files over these directories. Enabling this
# option can be useful when feeding doxygen a huge amount of source files, where
# putting all generated files in the same directory would otherwise causes
# performance problems for the file system.
# The default value is: NO.
 
CREATE_SUBDIRS = NO
 
# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII
# characters to appear in the names of generated files. If set to NO, non-ASCII
# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode
# U+3044.
# The default value is: NO.
 
ALLOW_UNICODE_NAMES = NO
 
# The OUTPUT_LANGUAGE tag is used to specify the language in which all
# documentation generated by doxygen is written. Doxygen will use this
# information to generate all constant output in the proper language.
# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese,
# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States),
# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian,
# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages),
# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian,
# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian,
# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish,
# Ukrainian and Vietnamese.
# The default value is: English.
 
OUTPUT_LANGUAGE = English
 
# The OUTPUT_TEXT_DIRECTION tag is used to specify the direction in which all
# documentation generated by doxygen is written. Doxygen will use this
# information to generate all generated output in the proper direction.
# Possible values are: None, LTR, RTL and Context.
# The default value is: None.
 
OUTPUT_TEXT_DIRECTION = None
 
# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member
# descriptions after the members that are listed in the file and class
# documentation (similar to Javadoc). Set to NO to disable this.
# The default value is: YES.
 
BRIEF_MEMBER_DESC = YES
 
# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief
# description of a member or function before the detailed description
#
# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
# brief descriptions will be completely suppressed.
# The default value is: YES.
 
REPEAT_BRIEF = YES
 
# This tag implements a quasi-intelligent brief description abbreviator that is
# used to form the text in various listings. Each string in this list, if found
# as the leading text of the brief description, will be stripped from the text
# and the result, after processing the whole list, is used as the annotated
# text. Otherwise, the brief description is used as-is. If left blank, the
# following values are used ($name is automatically replaced with the name of
# the entity):The $name class, The $name widget, The $name file, is, provides,
# specifies, contains, represents, a, an and the.
 
ABBREVIATE_BRIEF =
 
# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
# doxygen will generate a detailed section even if there is only a brief
# description.
# The default value is: NO.
 
ALWAYS_DETAILED_SEC = NO
 
# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
# inherited members of a class in the documentation of that class as if those
# members were ordinary class members. Constructors, destructors and assignment
# operators of the base classes will not be shown.
# The default value is: NO.
 
INLINE_INHERITED_MEMB = NO
 
# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path
# before files name in the file list and in the header files. If set to NO the
# shortest path that makes the file name unique will be used
# The default value is: YES.
 
FULL_PATH_NAMES = YES
 
# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path.
# Stripping is only done if one of the specified strings matches the left-hand
# part of the path. The tag can be used to show relative paths in the file list.
# If left blank the directory from which doxygen is run is used as the path to
# strip.
#
# Note that you can specify absolute paths here, but also relative paths, which
# will be relative from the directory where doxygen is started.
# This tag requires that the tag FULL_PATH_NAMES is set to YES.
 
STRIP_FROM_PATH =
 
# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the
# path mentioned in the documentation of a class, which tells the reader which
# header file to include in order to use a class. If left blank only the name of
# the header file containing the class definition is used. Otherwise one should
# specify the list of include paths that are normally passed to the compiler
# using the -I flag.
 
STRIP_FROM_INC_PATH =
 
# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but
# less readable) file names. This can be useful is your file systems doesn't
# support long names like on DOS, Mac, or CD-ROM.
# The default value is: NO.
 
SHORT_NAMES = NO
 
# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the
# first line (until the first dot) of a Javadoc-style comment as the brief
# description. If set to NO, the Javadoc-style will behave just like regular Qt-
# style comments (thus requiring an explicit @brief command for a brief
# description.)
# The default value is: NO.
 
JAVADOC_AUTOBRIEF = NO
 
# If the JAVADOC_BANNER tag is set to YES then doxygen will interpret a line
# such as
# /***************
# as being the beginning of a Javadoc-style comment "banner". If set to NO, the
# Javadoc-style will behave just like regular comments and it will not be
# interpreted by doxygen.
# The default value is: NO.
 
JAVADOC_BANNER = NO
 
# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first
# line (until the first dot) of a Qt-style comment as the brief description. If
# set to NO, the Qt-style will behave just like regular Qt-style comments (thus
# requiring an explicit \brief command for a brief description.)
# The default value is: NO.
 
QT_AUTOBRIEF = NO
 
# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a
# multi-line C++ special comment block (i.e. a block of //! or /// comments) as
# a brief description. This used to be the default behavior. The new default is
# to treat a multi-line C++ comment block as a detailed description. Set this
# tag to YES if you prefer the old behavior instead.
#
# Note that setting this tag to YES also means that rational rose comments are
# not recognized any more.
# The default value is: NO.
 
MULTILINE_CPP_IS_BRIEF = NO
 
# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the
# documentation from any documented member that it re-implements.
# The default value is: YES.
 
INHERIT_DOCS = YES
 
# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new
# page for each member. If set to NO, the documentation of a member will be part
# of the file/class/namespace that contains it.
# The default value is: NO.
 
SEPARATE_MEMBER_PAGES = NO
 
# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen
# uses this value to replace tabs by spaces in code fragments.
# Minimum value: 1, maximum value: 16, default value: 4.
 
TAB_SIZE = 4
 
# This tag can be used to specify a number of aliases that act as commands in
# the documentation. An alias has the form:
# name=value
# For example adding
# "sideeffect=@par Side Effects:\n"
# will allow you to put the command \sideeffect (or @sideeffect) in the
# documentation, which will result in a user-defined paragraph with heading
# "Side Effects:". You can put \n's in the value part of an alias to insert
# newlines (in the resulting output). You can put ^^ in the value part of an
# alias to insert a newline as if a physical newline was in the original file.
# When you need a literal { or } or , in the value part of an alias you have to
# escape them by means of a backslash (\), this can lead to conflicts with the
# commands \{ and \} for these it is advised to use the version @{ and @} or use
# a double escape (\\{ and \\})
 
ALIASES =
 
# This tag can be used to specify a number of word-keyword mappings (TCL only).
# A mapping has the form "name=value". For example adding "class=itcl::class"
# will allow you to use the command class in the itcl::class meaning.
 
TCL_SUBST =
 
# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
# only. Doxygen will then generate output that is more tailored for C. For
# instance, some of the names that are used will be different. The list of all
# members will be omitted, etc.
# The default value is: NO.
 
OPTIMIZE_OUTPUT_FOR_C = YES
 
# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or
# Python sources only. Doxygen will then generate output that is more tailored
# for that language. For instance, namespaces will be presented as packages,
# qualified scopes will look different, etc.
# The default value is: NO.
 
OPTIMIZE_OUTPUT_JAVA = NO
 
# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
# sources. Doxygen will then generate output that is tailored for Fortran.
# The default value is: NO.
 
OPTIMIZE_FOR_FORTRAN = NO
 
# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
# sources. Doxygen will then generate output that is tailored for VHDL.
# The default value is: NO.
 
OPTIMIZE_OUTPUT_VHDL = NO
 
# Set the OPTIMIZE_OUTPUT_SLICE tag to YES if your project consists of Slice
# sources only. Doxygen will then generate output that is more tailored for that
# language. For instance, namespaces will be presented as modules, types will be
# separated into more groups, etc.
# The default value is: NO.
 
OPTIMIZE_OUTPUT_SLICE = NO
 
# Doxygen selects the parser to use depending on the extension of the files it
# parses. With this tag you can assign which parser to use for a given
# extension. Doxygen has a built-in mapping, but you can override or extend it
# using this tag. The format is ext=language, where ext is a file extension, and
# language is one of the parsers supported by doxygen: IDL, Java, JavaScript,
# Csharp (C#), C, C++, D, PHP, md (Markdown), Objective-C, Python, Slice,
# Fortran (fixed format Fortran: FortranFixed, free formatted Fortran:
# FortranFree, unknown formatted Fortran: Fortran. In the later case the parser
# tries to guess whether the code is fixed or free formatted code, this is the
# default for Fortran type files), VHDL, tcl. For instance to make doxygen treat
# .inc files as Fortran files (default is PHP), and .f files as C (default is
# Fortran), use: inc=Fortran f=C.
#
# Note: For files without extension you can use no_extension as a placeholder.
#
# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
# the files are not read by doxygen.
 
EXTENSION_MAPPING =
 
# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments
# according to the Markdown format, which allows for more readable
# documentation. See https://daringfireball.net/projects/markdown/ for details.
# The output of markdown processing is further processed by doxygen, so you can
# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in
# case of backward compatibilities issues.
# The default value is: YES.
 
MARKDOWN_SUPPORT = YES
 
# When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up
# to that level are automatically included in the table of contents, even if
# they do not have an id attribute.
# Note: This feature currently applies only to Markdown headings.
# Minimum value: 0, maximum value: 99, default value: 5.
# This tag requires that the tag MARKDOWN_SUPPORT is set to YES.
 
TOC_INCLUDE_HEADINGS = 5
 
# When enabled doxygen tries to link words that correspond to documented
# classes, or namespaces to their corresponding documentation. Such a link can
# be prevented in individual cases by putting a % sign in front of the word or
# globally by setting AUTOLINK_SUPPORT to NO.
# The default value is: YES.
 
AUTOLINK_SUPPORT = YES
 
# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
# to include (a tag file for) the STL sources as input, then you should set this
# tag to YES in order to let doxygen match functions declarations and
# definitions whose arguments contain STL classes (e.g. func(std::string);
# versus func(std::string) {}). This also make the inheritance and collaboration
# diagrams that involve STL classes more complete and accurate.
# The default value is: NO.
 
BUILTIN_STL_SUPPORT = NO
 
# If you use Microsoft's C++/CLI language, you should set this option to YES to
# enable parsing support.
# The default value is: NO.
 
CPP_CLI_SUPPORT = NO
 
# Set the SIP_SUPPORT tag to YES if your project consists of sip (see:
# https://www.riverbankcomputing.com/software/sip/intro) sources only. Doxygen
# will parse them like normal C++ but will assume all classes use public instead
# of private inheritance when no explicit protection keyword is present.
# The default value is: NO.
 
SIP_SUPPORT = NO
 
# For Microsoft's IDL there are propget and propput attributes to indicate
# getter and setter methods for a property. Setting this option to YES will make
# doxygen to replace the get and set methods by a property in the documentation.
# This will only work if the methods are indeed getting or setting a simple
# type. If this is not the case, or you want to show the methods anyway, you
# should set this option to NO.
# The default value is: YES.
 
IDL_PROPERTY_SUPPORT = YES
 
# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
# tag is set to YES then doxygen will reuse the documentation of the first
# member in the group (if any) for the other members of the group. By default
# all members of a group must be documented explicitly.
# The default value is: NO.
 
DISTRIBUTE_GROUP_DOC = YES
 
# If one adds a struct or class to a group and this option is enabled, then also
# any nested class or struct is added to the same group. By default this option
# is disabled and one has to add nested compounds explicitly via \ingroup.
# The default value is: NO.
 
GROUP_NESTED_COMPOUNDS = NO
 
# Set the SUBGROUPING tag to YES to allow class member groups of the same type
# (for instance a group of public functions) to be put as a subgroup of that
# type (e.g. under the Public Functions section). Set it to NO to prevent
# subgrouping. Alternatively, this can be done per class using the
# \nosubgrouping command.
# The default value is: YES.
 
SUBGROUPING = YES
 
# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions
# are shown inside the group in which they are included (e.g. using \ingroup)
# instead of on a separate page (for HTML and Man pages) or section (for LaTeX
# and RTF).
#
# Note that this feature does not work in combination with
# SEPARATE_MEMBER_PAGES.
# The default value is: NO.
 
INLINE_GROUPED_CLASSES = NO
 
# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions
# with only public data fields or simple typedef fields will be shown inline in
# the documentation of the scope in which they are defined (i.e. file,
# namespace, or group documentation), provided this scope is documented. If set
# to NO, structs, classes, and unions are shown on a separate page (for HTML and
# Man pages) or section (for LaTeX and RTF).
# The default value is: NO.
 
INLINE_SIMPLE_STRUCTS = NO
 
# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or
# enum is documented as struct, union, or enum with the name of the typedef. So
# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
# with name TypeT. When disabled the typedef will appear as a member of a file,
# namespace, or class. And the struct will be named TypeS. This can typically be
# useful for C code in case the coding convention dictates that all compound
# types are typedef'ed and only the typedef is referenced, never the tag name.
# The default value is: NO.
 
TYPEDEF_HIDES_STRUCT = NO
 
# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This
# cache is used to resolve symbols given their name and scope. Since this can be
# an expensive process and often the same symbol appears multiple times in the
# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small
# doxygen will become slower. If the cache is too large, memory is wasted. The
# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range
# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536
# symbols. At the end of a run doxygen will report the cache usage and suggest
# the optimal cache size from a speed point of view.
# Minimum value: 0, maximum value: 9, default value: 0.
 
LOOKUP_CACHE_SIZE = 0
 
#---------------------------------------------------------------------------
52,42 → 449,298
# Build related configuration options
#---------------------------------------------------------------------------
 
# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in
# documentation are documented, even if no documentation was available. Private
# class members and static file members will be hidden unless the
# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES.
# Note: This will also disable the warnings about undocumented members that are
# normally produced when WARNINGS is set to YES.
# The default value is: NO.
 
EXTRACT_ALL = NO
 
# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will
# be included in the documentation.
# The default value is: NO.
 
EXTRACT_PRIVATE = NO
 
# If the EXTRACT_PRIV_VIRTUAL tag is set to YES, documented private virtual
# methods of a class will be included in the documentation.
# The default value is: NO.
 
EXTRACT_PRIV_VIRTUAL = NO
 
# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal
# scope will be included in the documentation.
# The default value is: NO.
 
EXTRACT_PACKAGE = NO
 
# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be
# included in the documentation.
# The default value is: NO.
 
EXTRACT_STATIC = YES
 
# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined
# locally in source files will be included in the documentation. If set to NO,
# only classes defined in header files are included. Does not have any effect
# for Java sources.
# The default value is: YES.
 
EXTRACT_LOCAL_CLASSES = YES
 
# This flag is only useful for Objective-C code. If set to YES, local methods,
# which are defined in the implementation section but not in the interface are
# included in the documentation. If set to NO, only methods in the interface are
# included.
# The default value is: NO.
 
EXTRACT_LOCAL_METHODS = NO
 
# If this flag is set to YES, the members of anonymous namespaces will be
# extracted and appear in the documentation as a namespace called
# 'anonymous_namespace{file}', where file will be replaced with the base name of
# the file that contains the anonymous namespace. By default anonymous namespace
# are hidden.
# The default value is: NO.
 
EXTRACT_ANON_NSPACES = NO
 
# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all
# undocumented members inside documented classes or files. If set to NO these
# members will be included in the various overviews, but no documentation
# section is generated. This option has no effect if EXTRACT_ALL is enabled.
# The default value is: NO.
 
HIDE_UNDOC_MEMBERS = NO
 
# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all
# undocumented classes that are normally visible in the class hierarchy. If set
# to NO, these classes will be included in the various overviews. This option
# has no effect if EXTRACT_ALL is enabled.
# The default value is: NO.
 
HIDE_UNDOC_CLASSES = NO
 
# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
# declarations. If set to NO, these declarations will be included in the
# documentation.
# The default value is: NO.
 
HIDE_FRIEND_COMPOUNDS = NO
 
# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any
# documentation blocks found inside the body of a function. If set to NO, these
# blocks will be appended to the function's detailed documentation block.
# The default value is: NO.
 
HIDE_IN_BODY_DOCS = NO
 
# The INTERNAL_DOCS tag determines if documentation that is typed after a
# \internal command is included. If the tag is set to NO then the documentation
# will be excluded. Set it to YES to include the internal documentation.
# The default value is: NO.
 
INTERNAL_DOCS = NO
 
# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file
# names in lower-case letters. If set to YES, upper-case letters are also
# allowed. This is useful if you have classes or files whose names only differ
# in case and if your file system supports case sensitive file names. Windows
# (including Cygwin) ands Mac users are advised to set this option to NO.
# The default value is: system dependent.
 
CASE_SENSE_NAMES = YES
 
# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with
# their full class and namespace scopes in the documentation. If set to YES, the
# scope will be hidden.
# The default value is: NO.
 
HIDE_SCOPE_NAMES = NO
 
# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will
# append additional text to a page's title, such as Class Reference. If set to
# YES the compound reference will be hidden.
# The default value is: NO.
 
HIDE_COMPOUND_REFERENCE= NO
 
# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of
# the files that are included by a file in the documentation of that file.
# The default value is: YES.
 
SHOW_INCLUDE_FILES = YES
 
# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each
# grouped member an include statement to the documentation, telling the reader
# which file to include in order to use the member.
# The default value is: NO.
 
SHOW_GROUPED_MEMB_INC = NO
 
# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include
# files with double quotes in the documentation rather than with sharp brackets.
# The default value is: NO.
 
FORCE_LOCAL_INCLUDES = NO
 
# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the
# documentation for inline members.
# The default value is: YES.
 
INLINE_INFO = YES
 
# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the
# (detailed) documentation of file and class members alphabetically by member
# name. If set to NO, the members will appear in declaration order.
# The default value is: YES.
 
SORT_MEMBER_DOCS = YES
 
# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief
# descriptions of file, namespace and class members alphabetically by member
# name. If set to NO, the members will appear in declaration order. Note that
# this will also influence the order of the classes in the class list.
# The default value is: NO.
 
SORT_BRIEF_DOCS = NO
 
# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the
# (brief and detailed) documentation of class members so that constructors and
# destructors are listed first. If set to NO the constructors will appear in the
# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS.
# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief
# member documentation.
# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting
# detailed member documentation.
# The default value is: NO.
 
SORT_MEMBERS_CTORS_1ST = NO
 
# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy
# of group names into alphabetical order. If set to NO the group names will
# appear in their defined order.
# The default value is: NO.
 
SORT_GROUP_NAMES = NO
 
# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by
# fully-qualified names, including namespaces. If set to NO, the class list will
# be sorted only by class name, not including the namespace part.
# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
# Note: This option applies only to the class list, not to the alphabetical
# list.
# The default value is: NO.
 
SORT_BY_SCOPE_NAME = NO
 
# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper
# type resolution of all parameters of a function it will reject a match between
# the prototype and the implementation of a member function even if there is
# only one candidate or it is obvious which candidate to choose by doing a
# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still
# accept a match between prototype and implementation in such cases.
# The default value is: NO.
 
STRICT_PROTO_MATCHING = NO
 
# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo
# list. This list is created by putting \todo commands in the documentation.
# The default value is: YES.
 
GENERATE_TODOLIST = YES
 
# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test
# list. This list is created by putting \test commands in the documentation.
# The default value is: YES.
 
GENERATE_TESTLIST = YES
 
# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug
# list. This list is created by putting \bug commands in the documentation.
# The default value is: YES.
 
GENERATE_BUGLIST = YES
 
# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO)
# the deprecated list. This list is created by putting \deprecated commands in
# the documentation.
# The default value is: YES.
 
GENERATE_DEPRECATEDLIST= YES
 
# The ENABLED_SECTIONS tag can be used to enable conditional documentation
# sections, marked by \if <section_label> ... \endif and \cond <section_label>
# ... \endcond blocks.
 
ENABLED_SECTIONS =
 
# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the
# initial value of a variable or macro / define can have for it to appear in the
# documentation. If the initializer consists of more lines than specified here
# it will be hidden. Use a value of 0 to hide initializers completely. The
# appearance of the value of individual variables and macros / defines can be
# controlled using \showinitializer or \hideinitializer command in the
# documentation regardless of this setting.
# Minimum value: 0, maximum value: 10000, default value: 30.
 
MAX_INITIALIZER_LINES = 30
 
# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at
# the bottom of the documentation of classes and structs. If set to YES, the
# list will mention the files that were used to generate the documentation.
# The default value is: YES.
 
SHOW_USED_FILES = YES
 
# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This
# will remove the Files entry from the Quick Index and from the Folder Tree View
# (if specified).
# The default value is: YES.
 
SHOW_FILES = YES
 
# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces
# page. This will remove the Namespaces entry from the Quick Index and from the
# Folder Tree View (if specified).
# The default value is: YES.
 
SHOW_NAMESPACES = YES
 
# The FILE_VERSION_FILTER tag can be used to specify a program or script that
# doxygen should invoke to get the current version for each file (typically from
# the version control system). Doxygen will invoke the program by executing (via
# popen()) the command command input-file, where command is the value of the
# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided
# by doxygen. Whatever the program writes to standard output is used as the file
# version. For an example see the documentation.
 
FILE_VERSION_FILTER =
 
# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
# by doxygen. The layout file controls the global structure of the generated
# output files in an output format independent way. To create the layout file
# that represents doxygen's defaults, run doxygen with the -l option. You can
# optionally specify a file name after the option, if omitted DoxygenLayout.xml
# will be used as the name of the layout file.
#
# Note that if you run doxygen from a directory containing a file called
# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE
# tag is left empty.
 
LAYOUT_FILE =
 
# The CITE_BIB_FILES tag can be used to specify one or more bib files containing
# the reference definitions. This must be a list of .bib files. The .bib
# extension is automatically appended if omitted. This requires the bibtex tool
# to be installed. See also https://en.wikipedia.org/wiki/BibTeX for more info.
# For LaTeX the style of the bibliography can be controlled using
# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the
# search path. See also \cite for info how to create references.
 
CITE_BIB_FILES =
 
#---------------------------------------------------------------------------
94,13 → 747,66
# Configuration options related to warning and progress messages
#---------------------------------------------------------------------------
 
# The QUIET tag can be used to turn on/off the messages that are generated to
# standard output by doxygen. If QUIET is set to YES this implies that the
# messages are off.
# The default value is: NO.
 
QUIET = NO
 
# The WARNINGS tag can be used to turn on/off the warning messages that are
# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES
# this implies that the warnings are on.
#
# Tip: Turn warnings on while writing the documentation.
# The default value is: YES.
 
WARNINGS = YES
 
# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate
# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag
# will automatically be disabled.
# The default value is: YES.
 
WARN_IF_UNDOCUMENTED = YES
 
# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for
# potential errors in the documentation, such as not documenting some parameters
# in a documented function, or documenting parameters that don't exist or using
# markup commands wrongly.
# The default value is: YES.
 
WARN_IF_DOC_ERROR = YES
 
# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that
# are documented, but have no documentation for their parameters or return
# value. If set to NO, doxygen will only warn about wrong or incomplete
# parameter documentation, but not about the absence of documentation. If
# EXTRACT_ALL is set to YES then this flag will automatically be disabled.
# The default value is: NO.
 
WARN_NO_PARAMDOC = NO
 
# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when
# a warning is encountered.
# The default value is: NO.
 
WARN_AS_ERROR = NO
 
# The WARN_FORMAT tag determines the format of the warning messages that doxygen
# can produce. The string should contain the $file, $line, and $text tags, which
# will be replaced by the file and line number from which the warning originated
# and the warning text. Optionally the format may contain $version, which will
# be replaced by the version of the file (if it could be obtained via
# FILE_VERSION_FILTER)
# The default value is: $file:$line: $text.
 
WARN_FORMAT = "$file:$line: $text"
 
# The WARN_LOGFILE tag can be used to specify a file to which warning and error
# messages should be written. If left blank the output is written to standard
# error (stderr).
 
WARN_LOGFILE =
 
#---------------------------------------------------------------------------
107,22 → 813,169
# Configuration options related to the input files
#---------------------------------------------------------------------------
 
INPUT = ../README.md ../sw/lib/source ../sw/lib/include ../sw/bootloader ../sw/example
# The INPUT tag is used to specify the files and/or directories that contain
# documented source files. You may enter file names like myfile.cpp or
# directories like /usr/src/myproject. Separate the files or directories with
# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
# Note: If this tag is empty the current directory is searched.
 
INPUT = ../README.md \
../sw/lib/source \
../sw/lib/include \
../sw/bootloader \
../sw/example
 
# This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
# libiconv (or the iconv built into libc) for the transcoding. See the libiconv
# documentation (see: https://www.gnu.org/software/libiconv/) for the list of
# possible encodings.
# The default value is: UTF-8.
 
INPUT_ENCODING = UTF-8
FILE_PATTERNS = *.c *.h
 
# If the value of the INPUT tag contains directories, you can use the
# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and
# *.h) to filter out the source-files in the directories.
#
# Note that for custom extensions or not directly supported extensions you also
# need to set EXTENSION_MAPPING for the extension otherwise the files are not
# read by doxygen.
#
# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp,
# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h,
# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc,
# *.m, *.markdown, *.md, *.mm, *.dox (to be provided as doxygen C comment),
# *.doc (to be provided as doxygen C comment), *.txt (to be provided as doxygen
# C comment), *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, *.f, *.for, *.tcl, *.vhd,
# *.vhdl, *.ucf, *.qsf and *.ice.
 
FILE_PATTERNS = *.c \
*.h
 
# The RECURSIVE tag can be used to specify whether or not subdirectories should
# be searched for input files as well.
# The default value is: NO.
 
RECURSIVE = YES
 
# The EXCLUDE tag can be used to specify files and/or directories that should be
# excluded from the INPUT source files. This way you can easily exclude a
# subdirectory from a directory tree whose root is specified with the INPUT tag.
#
# Note that relative paths are relative to the directory from which doxygen is
# run.
 
EXCLUDE =
 
# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
# directories that are symbolic links (a Unix file system feature) are excluded
# from the input.
# The default value is: NO.
 
EXCLUDE_SYMLINKS = NO
EXCLUDE_PATTERNS = ~* */example/coremark/*
 
# If the value of the INPUT tag contains directories, you can use the
# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
# certain files from those directories.
#
# Note that the wildcards are matched against the file with absolute path, so to
# exclude all test directories for example use the pattern */test/*
 
EXCLUDE_PATTERNS = ~* \
*/example/coremark/*
 
# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
# (namespaces, classes, functions, etc.) that should be excluded from the
# output. The symbol name can be a fully qualified name, a word, or if the
# wildcard * is used, a substring. Examples: ANamespace, AClass,
# AClass::ANamespace, ANamespace::*Test
#
# Note that the wildcards are matched against the file with absolute path, so to
# exclude all test directories use the pattern */test/*
 
EXCLUDE_SYMBOLS =
 
# The EXAMPLE_PATH tag can be used to specify one or more files or directories
# that contain example code fragments that are included (see the \include
# command).
 
EXAMPLE_PATH =
 
# If the value of the EXAMPLE_PATH tag contains directories, you can use the
# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and
# *.h) to filter out the source-files in the directories. If left blank all
# files are included.
 
EXAMPLE_PATTERNS =
 
# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
# searched for input files to be used with the \include or \dontinclude commands
# irrespective of the value of the RECURSIVE tag.
# The default value is: NO.
 
EXAMPLE_RECURSIVE = NO
 
# The IMAGE_PATH tag can be used to specify one or more files or directories
# that contain images that are to be included in the documentation (see the
# \image command).
 
IMAGE_PATH =
 
# The INPUT_FILTER tag can be used to specify a program that doxygen should
# invoke to filter for each input file. Doxygen will invoke the filter program
# by executing (via popen()) the command:
#
# <filter> <input-file>
#
# where <filter> is the value of the INPUT_FILTER tag, and <input-file> is the
# name of an input file. Doxygen will then use the output that the filter
# program writes to standard output. If FILTER_PATTERNS is specified, this tag
# will be ignored.
#
# Note that the filter must not add or remove lines; it is applied before the
# code is scanned, but not when the output code is generated. If lines are added
# or removed, the anchors will not be placed correctly.
#
# Note that for custom extensions or not directly supported extensions you also
# need to set EXTENSION_MAPPING for the extension otherwise the files are not
# properly processed by doxygen.
 
INPUT_FILTER =
 
# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
# basis. Doxygen will compare the file name with each pattern and apply the
# filter if there is a match. The filters are a list of the form: pattern=filter
# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how
# filters are used. If the FILTER_PATTERNS tag is empty or if none of the
# patterns match the file name, INPUT_FILTER is applied.
#
# Note that for custom extensions or not directly supported extensions you also
# need to set EXTENSION_MAPPING for the extension otherwise the files are not
# properly processed by doxygen.
 
FILTER_PATTERNS =
 
# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
# INPUT_FILTER) will also be used to filter the input files that are used for
# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES).
# The default value is: NO.
 
FILTER_SOURCE_FILES = NO
 
# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and
# it is also possible to disable source filtering for a specific pattern using
# *.ext= (so without naming a filter).
# This tag requires that the tag FILTER_SOURCE_FILES is set to YES.
 
FILTER_SOURCE_PATTERNS =
 
# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that
# is part of the input, its contents will be placed on the main page
# (index.html). This can be useful if you have a project on for instance GitHub
# and want to reuse the introduction page also for the doxygen output.
 
USE_MDFILE_AS_MAINPAGE = ../README.md
 
#---------------------------------------------------------------------------
129,24 → 982,141
# Configuration options related to source browsing
#---------------------------------------------------------------------------
 
# If the SOURCE_BROWSER tag is set to YES then a list of source files will be
# generated. Documented entities will be cross-referenced with these sources.
#
# Note: To get rid of all source code in the generated output, make sure that
# also VERBATIM_HEADERS is set to NO.
# The default value is: NO.
 
SOURCE_BROWSER = NO
 
# Setting the INLINE_SOURCES tag to YES will include the body of functions,
# classes and enums directly into the documentation.
# The default value is: NO.
 
INLINE_SOURCES = NO
 
# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any
# special comment blocks from generated source code fragments. Normal C, C++ and
# Fortran comments will always remain visible.
# The default value is: YES.
 
STRIP_CODE_COMMENTS = YES
 
# If the REFERENCED_BY_RELATION tag is set to YES then for each documented
# entity all documented functions referencing it will be listed.
# The default value is: NO.
 
REFERENCED_BY_RELATION = NO
 
# If the REFERENCES_RELATION tag is set to YES then for each documented function
# all documented entities called/used by that function will be listed.
# The default value is: NO.
 
REFERENCES_RELATION = NO
 
# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set
# to YES then the hyperlinks from functions in REFERENCES_RELATION and
# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will
# link to the documentation.
# The default value is: YES.
 
REFERENCES_LINK_SOURCE = YES
 
# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the
# source code will show a tooltip with additional information such as prototype,
# brief description and links to the definition and documentation. Since this
# will make the HTML file larger and loading of large files a bit slower, you
# can opt to disable this feature.
# The default value is: YES.
# This tag requires that the tag SOURCE_BROWSER is set to YES.
 
SOURCE_TOOLTIPS = YES
 
# If the USE_HTAGS tag is set to YES then the references to source code will
# point to the HTML generated by the htags(1) tool instead of doxygen built-in
# source browser. The htags tool is part of GNU's global source tagging system
# (see https://www.gnu.org/software/global/global.html). You will need version
# 4.8.6 or higher.
#
# To use it do the following:
# - Install the latest version of global
# - Enable SOURCE_BROWSER and USE_HTAGS in the configuration file
# - Make sure the INPUT points to the root of the source tree
# - Run doxygen as normal
#
# Doxygen will invoke htags (and that will in turn invoke gtags), so these
# tools must be available from the command line (i.e. in the search path).
#
# The result: instead of the source browser generated by doxygen, the links to
# source code will now point to the output of htags.
# The default value is: NO.
# This tag requires that the tag SOURCE_BROWSER is set to YES.
 
USE_HTAGS = NO
 
# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a
# verbatim copy of the header file for each class for which an include is
# specified. Set to NO to disable this.
# See also: Section \class.
# The default value is: YES.
 
VERBATIM_HEADERS = YES
 
# If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the
# clang parser (see: http://clang.llvm.org/) for more accurate parsing at the
# cost of reduced performance. This can be particularly helpful with template
# rich C++ code for which doxygen's built-in parser lacks the necessary type
# information.
# Note: The availability of this option depends on whether or not doxygen was
# generated with the -Duse_libclang=ON option for CMake.
# The default value is: NO.
 
CLANG_ASSISTED_PARSING = NO
 
# If clang assisted parsing is enabled you can provide the compiler with command
# line options that you would normally use when invoking the compiler. Note that
# the include paths will already be set by doxygen for the files and directories
# specified with INPUT and INCLUDE_PATH.
# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES.
 
CLANG_OPTIONS =
 
# If clang assisted parsing is enabled you can provide the clang parser with the
# path to the compilation database (see:
# http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html) used when the files
# were built. This is equivalent to specifying the "-p" option to a clang tool,
# such as clang-check. These options will then be passed to the parser.
# Note: The availability of this option depends on whether or not doxygen was
# generated with the -Duse_libclang=ON option for CMake.
 
CLANG_DATABASE_PATH =
 
#---------------------------------------------------------------------------
# Configuration options related to the alphabetical class index
#---------------------------------------------------------------------------
 
# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all
# compounds will be generated. Enable this if the project contains a lot of
# classes, structs, unions or interfaces.
# The default value is: YES.
 
ALPHABETICAL_INDEX = YES
 
# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in
# which the alphabetical index list will be split.
# Minimum value: 1, maximum value: 20, default value: 5.
# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
 
COLS_IN_ALPHA_INDEX = 5
 
# In case all classes in a project start with a common prefix, all classes will
# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag
# can be used to specify a prefix (or a list of prefixes) that should be ignored
# while generating the index headers.
# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
 
IGNORE_PREFIX =
 
#---------------------------------------------------------------------------
153,60 → 1123,561
# Configuration options related to the HTML output
#---------------------------------------------------------------------------
 
# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output
# The default value is: YES.
 
GENERATE_HTML = YES
 
# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a
# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
# it.
# The default directory is: html.
# This tag requires that the tag GENERATE_HTML is set to YES.
 
HTML_OUTPUT = html
 
# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
# generated HTML page (for example: .htm, .php, .asp).
# The default value is: .html.
# This tag requires that the tag GENERATE_HTML is set to YES.
 
HTML_FILE_EXTENSION = .html
 
# The HTML_HEADER tag can be used to specify a user-defined HTML header file for
# each generated HTML page. If the tag is left blank doxygen will generate a
# standard header.
#
# To get valid HTML the header file that includes any scripts and style sheets
# that doxygen needs, which is dependent on the configuration options used (e.g.
# the setting GENERATE_TREEVIEW). It is highly recommended to start with a
# default header using
# doxygen -w html new_header.html new_footer.html new_stylesheet.css
# YourConfigFile
# and then modify the file new_header.html. See also section "Doxygen usage"
# for information on how to generate the default header that doxygen normally
# uses.
# Note: The header is subject to change so you typically have to regenerate the
# default header when upgrading to a newer version of doxygen. For a description
# of the possible markers and block names see the documentation.
# This tag requires that the tag GENERATE_HTML is set to YES.
 
HTML_HEADER =
 
# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each
# generated HTML page. If the tag is left blank doxygen will generate a standard
# footer. See HTML_HEADER for more information on how to generate a default
# footer and what special commands can be used inside the footer. See also
# section "Doxygen usage" for information on how to generate the default footer
# that doxygen normally uses.
# This tag requires that the tag GENERATE_HTML is set to YES.
 
HTML_FOOTER =
 
# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style
# sheet that is used by each HTML page. It can be used to fine-tune the look of
# the HTML output. If left blank doxygen will generate a default style sheet.
# See also section "Doxygen usage" for information on how to generate the style
# sheet that doxygen normally uses.
# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as
# it is more robust and this tag (HTML_STYLESHEET) will in the future become
# obsolete.
# This tag requires that the tag GENERATE_HTML is set to YES.
 
HTML_STYLESHEET =
 
# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined
# cascading style sheets that are included after the standard style sheets
# created by doxygen. Using this option one can overrule certain style aspects.
# This is preferred over using HTML_STYLESHEET since it does not replace the
# standard style sheet and is therefore more robust against future updates.
# Doxygen will copy the style sheet files to the output directory.
# Note: The order of the extra style sheet files is of importance (e.g. the last
# style sheet in the list overrules the setting of the previous ones in the
# list). For an example see the documentation.
# This tag requires that the tag GENERATE_HTML is set to YES.
 
HTML_EXTRA_STYLESHEET =
 
# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
# other source files which should be copied to the HTML output directory. Note
# that these files will be copied to the base HTML output directory. Use the
# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
# files. In the HTML_STYLESHEET file, use the file name only. Also note that the
# files will be copied as-is; there are no commands or markers available.
# This tag requires that the tag GENERATE_HTML is set to YES.
 
HTML_EXTRA_FILES =
 
# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
# will adjust the colors in the style sheet and background images according to
# this color. Hue is specified as an angle on a colorwheel, see
# https://en.wikipedia.org/wiki/Hue for more information. For instance the value
# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300
# purple, and 360 is red again.
# Minimum value: 0, maximum value: 359, default value: 220.
# This tag requires that the tag GENERATE_HTML is set to YES.
 
HTML_COLORSTYLE_HUE = 220
 
# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors
# in the HTML output. For a value of 0 the output will use grayscales only. A
# value of 255 will produce the most vivid colors.
# Minimum value: 0, maximum value: 255, default value: 100.
# This tag requires that the tag GENERATE_HTML is set to YES.
 
HTML_COLORSTYLE_SAT = 100
 
# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the
# luminance component of the colors in the HTML output. Values below 100
# gradually make the output lighter, whereas values above 100 make the output
# darker. The value divided by 100 is the actual gamma applied, so 80 represents
# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not
# change the gamma.
# Minimum value: 40, maximum value: 240, default value: 80.
# This tag requires that the tag GENERATE_HTML is set to YES.
 
HTML_COLORSTYLE_GAMMA = 80
 
# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
# page will contain the date and time when the page was generated. Setting this
# to YES can help to show when doxygen was last run and thus if the
# documentation is up to date.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
 
HTML_TIMESTAMP = NO
 
# If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML
# documentation will contain a main index with vertical navigation menus that
# are dynamically created via JavaScript. If disabled, the navigation index will
# consists of multiple levels of tabs that are statically embedded in every HTML
# page. Disable this option to support browsers that do not have JavaScript,
# like the Qt help browser.
# The default value is: YES.
# This tag requires that the tag GENERATE_HTML is set to YES.
 
HTML_DYNAMIC_MENUS = YES
 
# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
# documentation will contain sections that can be hidden and shown after the
# page has loaded.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
 
HTML_DYNAMIC_SECTIONS = NO
 
# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries
# shown in the various tree structured indices initially; the user can expand
# and collapse entries dynamically later on. Doxygen will expand the tree to
# such a level that at most the specified number of entries are visible (unless
# a fully collapsed tree already exceeds this amount). So setting the number of
# entries 1 will produce a full collapsed tree by default. 0 is a special value
# representing an infinite number of entries and will result in a full expanded
# tree by default.
# Minimum value: 0, maximum value: 9999, default value: 100.
# This tag requires that the tag GENERATE_HTML is set to YES.
 
HTML_INDEX_NUM_ENTRIES = 100
 
# If the GENERATE_DOCSET tag is set to YES, additional index files will be
# generated that can be used as input for Apple's Xcode 3 integrated development
# environment (see: https://developer.apple.com/xcode/), introduced with OSX
# 10.5 (Leopard). To create a documentation set, doxygen will generate a
# Makefile in the HTML output directory. Running make will produce the docset in
# that directory and running make install will install the docset in
# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at
# startup. See https://developer.apple.com/library/archive/featuredarticles/Doxy
# genXcode/_index.html for more information.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
 
GENERATE_DOCSET = NO
 
# This tag determines the name of the docset feed. A documentation feed provides
# an umbrella under which multiple documentation sets from a single provider
# (such as a company or product suite) can be grouped.
# The default value is: Doxygen generated docs.
# This tag requires that the tag GENERATE_DOCSET is set to YES.
 
DOCSET_FEEDNAME = "Doxygen generated docs"
 
# This tag specifies a string that should uniquely identify the documentation
# set bundle. This should be a reverse domain-name style string, e.g.
# com.mycompany.MyDocSet. Doxygen will append .docset to the name.
# The default value is: org.doxygen.Project.
# This tag requires that the tag GENERATE_DOCSET is set to YES.
 
DOCSET_BUNDLE_ID = org.doxygen.Project
 
# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify
# the documentation publisher. This should be a reverse domain-name style
# string, e.g. com.mycompany.MyDocSet.documentation.
# The default value is: org.doxygen.Publisher.
# This tag requires that the tag GENERATE_DOCSET is set to YES.
 
DOCSET_PUBLISHER_ID = org.doxygen.Publisher
 
# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.
# The default value is: Publisher.
# This tag requires that the tag GENERATE_DOCSET is set to YES.
 
DOCSET_PUBLISHER_NAME = Publisher
 
# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
# additional HTML index files: index.hhp, index.hhc, and index.hhk. The
# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop
# (see: https://www.microsoft.com/en-us/download/details.aspx?id=21138) on
# Windows.
#
# The HTML Help Workshop contains a compiler that can convert all HTML output
# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML
# files are now used as the Windows 98 help format, and will replace the old
# Windows help format (.hlp) on all Windows platforms in the future. Compressed
# HTML files also contain an index, a table of contents, and you can search for
# words in the documentation. The HTML workshop also contains a viewer for
# compressed HTML files.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
 
GENERATE_HTMLHELP = NO
 
# The CHM_FILE tag can be used to specify the file name of the resulting .chm
# file. You can add a path in front of the file if the result should not be
# written to the html output directory.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
 
CHM_FILE =
 
# The HHC_LOCATION tag can be used to specify the location (absolute path
# including file name) of the HTML help compiler (hhc.exe). If non-empty,
# doxygen will try to run the HTML help compiler on the generated index.hhp.
# The file has to be specified with full path.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
 
HHC_LOCATION =
 
# The GENERATE_CHI flag controls if a separate .chi index file is generated
# (YES) or that it should be included in the master .chm file (NO).
# The default value is: NO.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
 
GENERATE_CHI = NO
 
# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc)
# and project file content.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
 
CHM_INDEX_ENCODING =
 
# The BINARY_TOC flag controls whether a binary table of contents is generated
# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it
# enables the Previous and Next buttons.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
 
BINARY_TOC = NO
 
# The TOC_EXPAND flag can be set to YES to add extra items for group members to
# the table of contents of the HTML help documentation and to the tree view.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
 
TOC_EXPAND = NO
 
# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that
# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help
# (.qch) of the generated HTML documentation.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
 
GENERATE_QHP = NO
 
# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify
# the file name of the resulting .qch file. The path specified is relative to
# the HTML output folder.
# This tag requires that the tag GENERATE_QHP is set to YES.
 
QCH_FILE =
 
# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
# Project output. For more information please see Qt Help Project / Namespace
# (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace).
# The default value is: org.doxygen.Project.
# This tag requires that the tag GENERATE_QHP is set to YES.
 
QHP_NAMESPACE = org.doxygen.Project
 
# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt
# Help Project output. For more information please see Qt Help Project / Virtual
# Folders (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual-
# folders).
# The default value is: doc.
# This tag requires that the tag GENERATE_QHP is set to YES.
 
QHP_VIRTUAL_FOLDER = doc
 
# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom
# filter to add. For more information please see Qt Help Project / Custom
# Filters (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-
# filters).
# This tag requires that the tag GENERATE_QHP is set to YES.
 
QHP_CUST_FILTER_NAME =
 
# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
# custom filter to add. For more information please see Qt Help Project / Custom
# Filters (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-
# filters).
# This tag requires that the tag GENERATE_QHP is set to YES.
 
QHP_CUST_FILTER_ATTRS =
 
# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
# project's filter section matches. Qt Help Project / Filter Attributes (see:
# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#filter-attributes).
# This tag requires that the tag GENERATE_QHP is set to YES.
 
QHP_SECT_FILTER_ATTRS =
 
# The QHG_LOCATION tag can be used to specify the location of Qt's
# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the
# generated .qhp file.
# This tag requires that the tag GENERATE_QHP is set to YES.
 
QHG_LOCATION =
 
# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be
# generated, together with the HTML files, they form an Eclipse help plugin. To
# install this plugin and make it available under the help contents menu in
# Eclipse, the contents of the directory containing the HTML and XML files needs
# to be copied into the plugins directory of eclipse. The name of the directory
# within the plugins directory should be the same as the ECLIPSE_DOC_ID value.
# After copying Eclipse needs to be restarted before the help appears.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
 
GENERATE_ECLIPSEHELP = NO
 
# A unique identifier for the Eclipse help plugin. When installing the plugin
# the directory name containing the HTML and XML files should also have this
# name. Each documentation set should have its own identifier.
# The default value is: org.doxygen.Project.
# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES.
 
ECLIPSE_DOC_ID = org.doxygen.Project
 
# If you want full control over the layout of the generated HTML pages it might
# be necessary to disable the index and replace it with your own. The
# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top
# of each HTML page. A value of NO enables the index and the value YES disables
# it. Since the tabs in the index contain the same information as the navigation
# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
 
DISABLE_INDEX = NO
 
# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
# structure should be generated to display hierarchical information. If the tag
# value is set to YES, a side panel will be generated containing a tree-like
# index structure (just like the one that is generated for HTML Help). For this
# to work a browser that supports JavaScript, DHTML, CSS and frames is required
# (i.e. any modern browser). Windows users are probably better off using the
# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can
# further fine-tune the look of the index. As an example, the default style
# sheet generated by doxygen has an example that shows how to put an image at
# the root of the tree instead of the PROJECT_NAME. Since the tree basically has
# the same information as the tab index, you could consider setting
# DISABLE_INDEX to YES when enabling this option.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
 
GENERATE_TREEVIEW = NO
 
# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
# doxygen will group on one line in the generated HTML documentation.
#
# Note that a value of 0 will completely suppress the enum values from appearing
# in the overview section.
# Minimum value: 0, maximum value: 20, default value: 4.
# This tag requires that the tag GENERATE_HTML is set to YES.
 
ENUM_VALUES_PER_LINE = 4
 
# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used
# to set the initial width (in pixels) of the frame in which the tree is shown.
# Minimum value: 0, maximum value: 1500, default value: 250.
# This tag requires that the tag GENERATE_HTML is set to YES.
 
TREEVIEW_WIDTH = 250
 
# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to
# external symbols imported via tag files in a separate window.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
 
EXT_LINKS_IN_WINDOW = NO
 
# Use this tag to change the font size of LaTeX formulas included as images in
# the HTML documentation. When you change the font size after a successful
# doxygen run you need to manually remove any form_*.png images from the HTML
# output directory to force them to be regenerated.
# Minimum value: 8, maximum value: 50, default value: 10.
# This tag requires that the tag GENERATE_HTML is set to YES.
 
FORMULA_FONTSIZE = 10
 
# Use the FORMULA_TRANSPARENT tag to determine whether or not the images
# generated for formulas are transparent PNGs. Transparent PNGs are not
# supported properly for IE 6.0, but are supported on all modern browsers.
#
# Note that when changing this option you need to delete any form_*.png files in
# the HTML output directory before the changes have effect.
# The default value is: YES.
# This tag requires that the tag GENERATE_HTML is set to YES.
 
FORMULA_TRANSPARENT = YES
 
# The FORMULA_MACROFILE can contain LaTeX \newcommand and \renewcommand commands
# to create new LaTeX commands to be used in formulas as building blocks. See
# the section "Including formulas" for details.
 
FORMULA_MACROFILE =
 
# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
# https://www.mathjax.org) which uses client side JavaScript for the rendering
# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX
# installed or if you want to formulas look prettier in the HTML output. When
# enabled you may also need to install MathJax separately and configure the path
# to it using the MATHJAX_RELPATH option.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
 
USE_MATHJAX = NO
 
# When MathJax is enabled you can set the default output format to be used for
# the MathJax output. See the MathJax site (see:
# http://docs.mathjax.org/en/latest/output.html) for more details.
# Possible values are: HTML-CSS (which is slower, but has the best
# compatibility), NativeMML (i.e. MathML) and SVG.
# The default value is: HTML-CSS.
# This tag requires that the tag USE_MATHJAX is set to YES.
 
MATHJAX_FORMAT = HTML-CSS
 
# When MathJax is enabled you need to specify the location relative to the HTML
# output directory using the MATHJAX_RELPATH option. The destination directory
# should contain the MathJax.js script. For instance, if the mathjax directory
# is located at the same level as the HTML output directory, then
# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax
# Content Delivery Network so you can quickly see the result without installing
# MathJax. However, it is strongly recommended to install a local copy of
# MathJax from https://www.mathjax.org before deployment.
# The default value is: https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/.
# This tag requires that the tag USE_MATHJAX is set to YES.
 
MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest
 
# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax
# extension names that should be enabled during MathJax rendering. For example
# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols
# This tag requires that the tag USE_MATHJAX is set to YES.
 
MATHJAX_EXTENSIONS =
 
# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces
# of code that will be used on startup of the MathJax code. See the MathJax site
# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an
# example see the documentation.
# This tag requires that the tag USE_MATHJAX is set to YES.
 
MATHJAX_CODEFILE =
 
# When the SEARCHENGINE tag is enabled doxygen will generate a search box for
# the HTML output. The underlying search engine uses javascript and DHTML and
# should work on any modern browser. Note that when using HTML help
# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET)
# there is already a search function so this one should typically be disabled.
# For large projects the javascript based search engine can be slow, then
# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to
# search using the keyboard; to jump to the search box use <access key> + S
# (what the <access key> is depends on the OS and browser, but it is typically
# <CTRL>, <ALT>/<option>, or both). Inside the search box use the <cursor down
# key> to jump into the search results window, the results can be navigated
# using the <cursor keys>. Press <Enter> to select an item or <escape> to cancel
# the search. The filter options can be selected when the cursor is inside the
# search box by pressing <Shift>+<cursor down>. Also here use the <cursor keys>
# to select a filter and <Enter> or <escape> to activate or cancel the filter
# option.
# The default value is: YES.
# This tag requires that the tag GENERATE_HTML is set to YES.
 
SEARCHENGINE = YES
 
# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
# implemented using a web server instead of a web client using JavaScript. There
# are two flavors of web server based searching depending on the EXTERNAL_SEARCH
# setting. When disabled, doxygen will generate a PHP script for searching and
# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing
# and searching needs to be provided by external tools. See the section
# "External Indexing and Searching" for details.
# The default value is: NO.
# This tag requires that the tag SEARCHENGINE is set to YES.
 
SERVER_BASED_SEARCH = NO
 
# When EXTERNAL_SEARCH tag is enabled doxygen will no longer generate the PHP
# script for searching. Instead the search results are written to an XML file
# which needs to be processed by an external indexer. Doxygen will invoke an
# external search engine pointed to by the SEARCHENGINE_URL option to obtain the
# search results.
#
# Doxygen ships with an example indexer (doxyindexer) and search engine
# (doxysearch.cgi) which are based on the open source search engine library
# Xapian (see: https://xapian.org/).
#
# See the section "External Indexing and Searching" for details.
# The default value is: NO.
# This tag requires that the tag SEARCHENGINE is set to YES.
 
EXTERNAL_SEARCH = NO
 
# The SEARCHENGINE_URL should point to a search engine hosted by a web server
# which will return the search results when EXTERNAL_SEARCH is enabled.
#
# Doxygen ships with an example indexer (doxyindexer) and search engine
# (doxysearch.cgi) which are based on the open source search engine library
# Xapian (see: https://xapian.org/). See the section "External Indexing and
# Searching" for details.
# This tag requires that the tag SEARCHENGINE is set to YES.
 
SEARCHENGINE_URL =
 
# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed
# search data is written to a file for indexing by an external tool. With the
# SEARCHDATA_FILE tag the name of this file can be specified.
# The default file is: searchdata.xml.
# This tag requires that the tag SEARCHENGINE is set to YES.
 
SEARCHDATA_FILE = searchdata.xml
 
# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the
# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is
# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple
# projects and redirect the results back to the right project.
# This tag requires that the tag SEARCHENGINE is set to YES.
 
EXTERNAL_SEARCH_ID =
 
# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen
# projects other than the one defined by this configuration file, but that are
# all added to the same external search index. Each project needs to have a
# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id of
# to a relative location where the documentation can be found. The format is:
# EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ...
# This tag requires that the tag SEARCHENGINE is set to YES.
 
EXTRA_SEARCH_MAPPINGS =
 
#---------------------------------------------------------------------------
213,35 → 1684,257
# Configuration options related to the LaTeX output
#---------------------------------------------------------------------------
 
# If the GENERATE_LATEX tag is set to YES, doxygen will generate LaTeX output.
# The default value is: YES.
 
GENERATE_LATEX = NO
 
# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a
# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
# it.
# The default directory is: latex.
# This tag requires that the tag GENERATE_LATEX is set to YES.
 
LATEX_OUTPUT = latex
 
# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
# invoked.
#
# Note that when not enabling USE_PDFLATEX the default is latex when enabling
# USE_PDFLATEX the default is pdflatex and when in the later case latex is
# chosen this is overwritten by pdflatex. For specific output languages the
# default can have been set differently, this depends on the implementation of
# the output language.
# This tag requires that the tag GENERATE_LATEX is set to YES.
 
LATEX_CMD_NAME = latex
 
# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate
# index for LaTeX.
# Note: This tag is used in the Makefile / make.bat.
# See also: LATEX_MAKEINDEX_CMD for the part in the generated output file
# (.tex).
# The default file is: makeindex.
# This tag requires that the tag GENERATE_LATEX is set to YES.
 
MAKEINDEX_CMD_NAME = makeindex
 
# The LATEX_MAKEINDEX_CMD tag can be used to specify the command name to
# generate index for LaTeX. In case there is no backslash (\) as first character
# it will be automatically added in the LaTeX code.
# Note: This tag is used in the generated output file (.tex).
# See also: MAKEINDEX_CMD_NAME for the part in the Makefile / make.bat.
# The default value is: makeindex.
# This tag requires that the tag GENERATE_LATEX is set to YES.
 
LATEX_MAKEINDEX_CMD = makeindex
 
# If the COMPACT_LATEX tag is set to YES, doxygen generates more compact LaTeX
# documents. This may be useful for small projects and may help to save some
# trees in general.
# The default value is: NO.
# This tag requires that the tag GENERATE_LATEX is set to YES.
 
COMPACT_LATEX = NO
 
# The PAPER_TYPE tag can be used to set the paper type that is used by the
# printer.
# Possible values are: a4 (210 x 297 mm), letter (8.5 x 11 inches), legal (8.5 x
# 14 inches) and executive (7.25 x 10.5 inches).
# The default value is: a4.
# This tag requires that the tag GENERATE_LATEX is set to YES.
 
PAPER_TYPE = a4
 
# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names
# that should be included in the LaTeX output. The package can be specified just
# by its name or with the correct syntax as to be used with the LaTeX
# \usepackage command. To get the times font for instance you can specify :
# EXTRA_PACKAGES=times or EXTRA_PACKAGES={times}
# To use the option intlimits with the amsmath package you can specify:
# EXTRA_PACKAGES=[intlimits]{amsmath}
# If left blank no extra packages will be included.
# This tag requires that the tag GENERATE_LATEX is set to YES.
 
EXTRA_PACKAGES =
 
# The LATEX_HEADER tag can be used to specify a personal LaTeX header for the
# generated LaTeX document. The header should contain everything until the first
# chapter. If it is left blank doxygen will generate a standard header. See
# section "Doxygen usage" for information on how to let doxygen write the
# default header to a separate file.
#
# Note: Only use a user-defined header if you know what you are doing! The
# following commands have a special meaning inside the header: $title,
# $datetime, $date, $doxygenversion, $projectname, $projectnumber,
# $projectbrief, $projectlogo. Doxygen will replace $title with the empty
# string, for the replacement values of the other commands the user is referred
# to HTML_HEADER.
# This tag requires that the tag GENERATE_LATEX is set to YES.
 
LATEX_HEADER =
 
# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the
# generated LaTeX document. The footer should contain everything after the last
# chapter. If it is left blank doxygen will generate a standard footer. See
# LATEX_HEADER for more information on how to generate a default footer and what
# special commands can be used inside the footer.
#
# Note: Only use a user-defined footer if you know what you are doing!
# This tag requires that the tag GENERATE_LATEX is set to YES.
 
LATEX_FOOTER =
 
# The LATEX_EXTRA_STYLESHEET tag can be used to specify additional user-defined
# LaTeX style sheets that are included after the standard style sheets created
# by doxygen. Using this option one can overrule certain style aspects. Doxygen
# will copy the style sheet files to the output directory.
# Note: The order of the extra style sheet files is of importance (e.g. the last
# style sheet in the list overrules the setting of the previous ones in the
# list).
# This tag requires that the tag GENERATE_LATEX is set to YES.
 
LATEX_EXTRA_STYLESHEET =
 
# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or
# other source files which should be copied to the LATEX_OUTPUT output
# directory. Note that the files will be copied as-is; there are no commands or
# markers available.
# This tag requires that the tag GENERATE_LATEX is set to YES.
 
LATEX_EXTRA_FILES =
 
# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is
# prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will
# contain links (just like the HTML output) instead of page references. This
# makes the output suitable for online browsing using a PDF viewer.
# The default value is: YES.
# This tag requires that the tag GENERATE_LATEX is set to YES.
 
PDF_HYPERLINKS = YES
 
# If the USE_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate
# the PDF file directly from the LaTeX files. Set this option to YES, to get a
# higher quality PDF documentation.
# The default value is: YES.
# This tag requires that the tag GENERATE_LATEX is set to YES.
 
USE_PDFLATEX = YES
 
# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode
# command to the generated LaTeX files. This will instruct LaTeX to keep running
# if errors occur, instead of asking the user for help. This option is also used
# when generating formulas in HTML.
# The default value is: NO.
# This tag requires that the tag GENERATE_LATEX is set to YES.
 
LATEX_BATCHMODE = NO
 
# If the LATEX_HIDE_INDICES tag is set to YES then doxygen will not include the
# index chapters (such as File Index, Compound Index, etc.) in the output.
# The default value is: NO.
# This tag requires that the tag GENERATE_LATEX is set to YES.
 
LATEX_HIDE_INDICES = NO
 
# If the LATEX_SOURCE_CODE tag is set to YES then doxygen will include source
# code with syntax highlighting in the LaTeX output.
#
# Note that which sources are shown also depends on other settings such as
# SOURCE_BROWSER.
# The default value is: NO.
# This tag requires that the tag GENERATE_LATEX is set to YES.
 
LATEX_SOURCE_CODE = NO
 
# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
# bibliography, e.g. plainnat, or ieeetr. See
# https://en.wikipedia.org/wiki/BibTeX and \cite for more info.
# The default value is: plain.
# This tag requires that the tag GENERATE_LATEX is set to YES.
 
LATEX_BIB_STYLE = plain
 
# If the LATEX_TIMESTAMP tag is set to YES then the footer of each generated
# page will contain the date and time when the page was generated. Setting this
# to NO can help when comparing the output of multiple runs.
# The default value is: NO.
# This tag requires that the tag GENERATE_LATEX is set to YES.
 
LATEX_TIMESTAMP = NO
 
# The LATEX_EMOJI_DIRECTORY tag is used to specify the (relative or absolute)
# path from which the emoji images will be read. If a relative path is entered,
# it will be relative to the LATEX_OUTPUT directory. If left blank the
# LATEX_OUTPUT directory will be used.
# This tag requires that the tag GENERATE_LATEX is set to YES.
 
LATEX_EMOJI_DIRECTORY =
 
#---------------------------------------------------------------------------
# Configuration options related to the RTF output
#---------------------------------------------------------------------------
 
# If the GENERATE_RTF tag is set to YES, doxygen will generate RTF output. The
# RTF output is optimized for Word 97 and may not look too pretty with other RTF
# readers/editors.
# The default value is: NO.
 
GENERATE_RTF = NO
 
# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. If a
# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
# it.
# The default directory is: rtf.
# This tag requires that the tag GENERATE_RTF is set to YES.
 
RTF_OUTPUT = rtf
 
# If the COMPACT_RTF tag is set to YES, doxygen generates more compact RTF
# documents. This may be useful for small projects and may help to save some
# trees in general.
# The default value is: NO.
# This tag requires that the tag GENERATE_RTF is set to YES.
 
COMPACT_RTF = NO
 
# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated will
# contain hyperlink fields. The RTF file will contain links (just like the HTML
# output) instead of page references. This makes the output suitable for online
# browsing using Word or some other Word compatible readers that support those
# fields.
#
# Note: WordPad (write) and others do not support links.
# The default value is: NO.
# This tag requires that the tag GENERATE_RTF is set to YES.
 
RTF_HYPERLINKS = NO
 
# Load stylesheet definitions from file. Syntax is similar to doxygen's
# configuration file, i.e. a series of assignments. You only have to provide
# replacements, missing definitions are set to their default value.
#
# See also section "Doxygen usage" for information on how to generate the
# default style sheet that doxygen normally uses.
# This tag requires that the tag GENERATE_RTF is set to YES.
 
RTF_STYLESHEET_FILE =
 
# Set optional variables used in the generation of an RTF document. Syntax is
# similar to doxygen's configuration file. A template extensions file can be
# generated using doxygen -e rtf extensionFile.
# This tag requires that the tag GENERATE_RTF is set to YES.
 
RTF_EXTENSIONS_FILE =
 
# If the RTF_SOURCE_CODE tag is set to YES then doxygen will include source code
# with syntax highlighting in the RTF output.
#
# Note that which sources are shown also depends on other settings such as
# SOURCE_BROWSER.
# The default value is: NO.
# This tag requires that the tag GENERATE_RTF is set to YES.
 
RTF_SOURCE_CODE = NO
 
#---------------------------------------------------------------------------
248,10 → 1941,44
# Configuration options related to the man page output
#---------------------------------------------------------------------------
 
# If the GENERATE_MAN tag is set to YES, doxygen will generate man pages for
# classes and files.
# The default value is: NO.
 
GENERATE_MAN = NO
 
# The MAN_OUTPUT tag is used to specify where the man pages will be put. If a
# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
# it. A directory man3 will be created inside the directory specified by
# MAN_OUTPUT.
# The default directory is: man.
# This tag requires that the tag GENERATE_MAN is set to YES.
 
MAN_OUTPUT = man
 
# The MAN_EXTENSION tag determines the extension that is added to the generated
# man pages. In case the manual section does not start with a number, the number
# 3 is prepended. The dot (.) at the beginning of the MAN_EXTENSION tag is
# optional.
# The default value is: .3.
# This tag requires that the tag GENERATE_MAN is set to YES.
 
MAN_EXTENSION = .3
 
# The MAN_SUBDIR tag determines the name of the directory created within
# MAN_OUTPUT in which the man pages are placed. If defaults to man followed by
# MAN_EXTENSION with the initial . removed.
# This tag requires that the tag GENERATE_MAN is set to YES.
 
MAN_SUBDIR =
 
# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it
# will generate one additional man file for each entity documented in the real
# man page(s). These additional files only source the real man page, but without
# them the man command would be unable to find the correct page.
# The default value is: NO.
# This tag requires that the tag GENERATE_MAN is set to YES.
 
MAN_LINKS = NO
 
#---------------------------------------------------------------------------
258,16 → 1985,61
# Configuration options related to the XML output
#---------------------------------------------------------------------------
 
# If the GENERATE_XML tag is set to YES, doxygen will generate an XML file that
# captures the structure of the code including all documentation.
# The default value is: NO.
 
GENERATE_XML = NO
 
# The XML_OUTPUT tag is used to specify where the XML pages will be put. If a
# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
# it.
# The default directory is: xml.
# This tag requires that the tag GENERATE_XML is set to YES.
 
XML_OUTPUT = xml
 
# If the XML_PROGRAMLISTING tag is set to YES, doxygen will dump the program
# listings (including syntax highlighting and cross-referencing information) to
# the XML output. Note that enabling this will significantly increase the size
# of the XML output.
# The default value is: YES.
# This tag requires that the tag GENERATE_XML is set to YES.
 
XML_PROGRAMLISTING = YES
 
# If the XML_NS_MEMB_FILE_SCOPE tag is set to YES, doxygen will include
# namespace members in file scope as well, matching the HTML output.
# The default value is: NO.
# This tag requires that the tag GENERATE_XML is set to YES.
 
XML_NS_MEMB_FILE_SCOPE = NO
 
#---------------------------------------------------------------------------
# Configuration options related to the DOCBOOK output
#---------------------------------------------------------------------------
 
# If the GENERATE_DOCBOOK tag is set to YES, doxygen will generate Docbook files
# that can be used to generate PDF.
# The default value is: NO.
 
GENERATE_DOCBOOK = NO
 
# The DOCBOOK_OUTPUT tag is used to specify where the Docbook pages will be put.
# If a relative path is entered the value of OUTPUT_DIRECTORY will be put in
# front of it.
# The default directory is: docbook.
# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
 
DOCBOOK_OUTPUT = docbook
 
# If the DOCBOOK_PROGRAMLISTING tag is set to YES, doxygen will include the
# program listings (including syntax highlighting and cross-referencing
# information) to the DOCBOOK output. Note that enabling this will significantly
# increase the size of the DOCBOOK output.
# The default value is: NO.
# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
 
DOCBOOK_PROGRAMLISTING = NO
 
#---------------------------------------------------------------------------
274,6 → 2046,12
# Configuration options for the AutoGen Definitions output
#---------------------------------------------------------------------------
 
# If the GENERATE_AUTOGEN_DEF tag is set to YES, doxygen will generate an
# AutoGen Definitions (see http://autogen.sourceforge.net/) file that captures
# the structure of the code including all documentation. Note that this feature
# is still experimental and incomplete at the moment.
# The default value is: NO.
 
GENERATE_AUTOGEN_DEF = NO
 
#---------------------------------------------------------------------------
280,9 → 2058,38
# Configuration options related to the Perl module output
#---------------------------------------------------------------------------
 
# If the GENERATE_PERLMOD tag is set to YES, doxygen will generate a Perl module
# file that captures the structure of the code including all documentation.
#
# Note that this feature is still experimental and incomplete at the moment.
# The default value is: NO.
 
GENERATE_PERLMOD = NO
 
# If the PERLMOD_LATEX tag is set to YES, doxygen will generate the necessary
# Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI
# output from the Perl module output.
# The default value is: NO.
# This tag requires that the tag GENERATE_PERLMOD is set to YES.
 
PERLMOD_LATEX = NO
 
# If the PERLMOD_PRETTY tag is set to YES, the Perl module output will be nicely
# formatted so it can be parsed by a human reader. This is useful if you want to
# understand what is going on. On the other hand, if this tag is set to NO, the
# size of the Perl module output will be much smaller and Perl will parse it
# just the same.
# The default value is: YES.
# This tag requires that the tag GENERATE_PERLMOD is set to YES.
 
PERLMOD_PRETTY = YES
 
# The names of the make variables in the generated doxyrules.make file are
# prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. This is useful
# so different doxyrules.make files included by the same Makefile don't
# overwrite each other's variables.
# This tag requires that the tag GENERATE_PERLMOD is set to YES.
 
PERLMOD_MAKEVAR_PREFIX =
 
#---------------------------------------------------------------------------
289,14 → 2096,78
# Configuration options related to the preprocessor
#---------------------------------------------------------------------------
 
# If the ENABLE_PREPROCESSING tag is set to YES, doxygen will evaluate all
# C-preprocessor directives found in the sources and include files.
# The default value is: YES.
 
ENABLE_PREPROCESSING = YES
 
# If the MACRO_EXPANSION tag is set to YES, doxygen will expand all macro names
# in the source code. If set to NO, only conditional compilation will be
# performed. Macro expansion can be done in a controlled way by setting
# EXPAND_ONLY_PREDEF to YES.
# The default value is: NO.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
 
MACRO_EXPANSION = YES
 
# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then
# the macro expansion is limited to the macros specified with the PREDEFINED and
# EXPAND_AS_DEFINED tags.
# The default value is: NO.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
 
EXPAND_ONLY_PREDEF = YES
 
# If the SEARCH_INCLUDES tag is set to YES, the include files in the
# INCLUDE_PATH will be searched if a #include is found.
# The default value is: YES.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
 
SEARCH_INCLUDES = YES
 
# The INCLUDE_PATH tag can be used to specify one or more directories that
# contain include files that are not input files but should be processed by the
# preprocessor.
# This tag requires that the tag SEARCH_INCLUDES is set to YES.
 
INCLUDE_PATH =
 
# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
# patterns (like *.h and *.hpp) to filter out the header-files in the
# directories. If left blank, the patterns specified with FILE_PATTERNS will be
# used.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
 
INCLUDE_FILE_PATTERNS =
 
# The PREDEFINED tag can be used to specify one or more macro names that are
# defined before the preprocessor is started (similar to the -D option of e.g.
# gcc). The argument of the tag is a list of macros of the form: name or
# name=definition (no spaces). If the definition and the "=" are omitted, "=1"
# is assumed. To prevent a macro definition from being undefined via #undef or
# recursively expanded use the := operator instead of the = operator.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
 
PREDEFINED = __attribute__((x))=
 
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
# tag can be used to specify a list of macro names that should be expanded. The
# macro definition that is found in the sources will be used. Use the PREDEFINED
# tag if you want to use a different macro definition that overrules the
# definition found in the source code.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
 
EXPAND_AS_DEFINED =
 
# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
# remove all references to function-like macros that are alone on a line, have
# an all uppercase name, and do not end with a semicolon. Such function macros
# are typically used for boiler-plate code, and will confuse the parser if not
# removed.
# The default value is: YES.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
 
SKIP_FUNCTION_MACROS = YES
 
#---------------------------------------------------------------------------
303,49 → 2174,356
# Configuration options related to external references
#---------------------------------------------------------------------------
 
# The TAGFILES tag can be used to specify one or more tag files. For each tag
# file the location of the external documentation should be added. The format of
# a tag file without this location is as follows:
# TAGFILES = file1 file2 ...
# Adding location for the tag files is done as follows:
# TAGFILES = file1=loc1 "file2 = loc2" ...
# where loc1 and loc2 can be relative or absolute paths or URLs. See the
# section "Linking to external documentation" for more information about the use
# of tag files.
# Note: Each tag file must have a unique name (where the name does NOT include
# the path). If a tag file is not located in the directory in which doxygen is
# run, you must also specify the path to the tagfile here.
 
TAGFILES =
 
# When a file name is specified after GENERATE_TAGFILE, doxygen will create a
# tag file that is based on the input files it reads. See section "Linking to
# external documentation" for more information about the usage of tag files.
 
GENERATE_TAGFILE =
 
# If the ALLEXTERNALS tag is set to YES, all external class will be listed in
# the class index. If set to NO, only the inherited external classes will be
# listed.
# The default value is: NO.
 
ALLEXTERNALS = NO
 
# If the EXTERNAL_GROUPS tag is set to YES, all external groups will be listed
# in the modules index. If set to NO, only the current project's groups will be
# listed.
# The default value is: YES.
 
EXTERNAL_GROUPS = YES
 
# If the EXTERNAL_PAGES tag is set to YES, all external pages will be listed in
# the related pages index. If set to NO, only the current project's pages will
# be listed.
# The default value is: YES.
 
EXTERNAL_PAGES = YES
PERL_PATH = /usr/bin/perl
 
#---------------------------------------------------------------------------
# Configuration options related to the dot tool
#---------------------------------------------------------------------------
 
# If the CLASS_DIAGRAMS tag is set to YES, doxygen will generate a class diagram
# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to
# NO turns the diagrams off. Note that this option also works with HAVE_DOT
# disabled, but it is recommended to install and use dot, since it yields more
# powerful graphs.
# The default value is: YES.
 
CLASS_DIAGRAMS = NO
MSCGEN_PATH =
 
# You can include diagrams made with dia in doxygen documentation. Doxygen will
# then run dia to produce the diagram and insert it in the documentation. The
# DIA_PATH tag allows you to specify the directory where the dia binary resides.
# If left empty dia is assumed to be found in the default search path.
 
DIA_PATH =
 
# If set to YES the inheritance and collaboration graphs will hide inheritance
# and usage relations if the target is undocumented or is not a class.
# The default value is: YES.
 
HIDE_UNDOC_RELATIONS = YES
 
# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
# available from the path. This tool is part of Graphviz (see:
# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent
# Bell Labs. The other options in this section have no effect if this option is
# set to NO
# The default value is: YES.
 
HAVE_DOT = NO
 
# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed
# to run in parallel. When set to 0 doxygen will base this on the number of
# processors available in the system. You can set it explicitly to a value
# larger than 0 to get control over the balance between CPU load and processing
# speed.
# Minimum value: 0, maximum value: 32, default value: 0.
# This tag requires that the tag HAVE_DOT is set to YES.
 
DOT_NUM_THREADS = 0
 
# When you want a differently looking font in the dot files that doxygen
# generates you can specify the font name using DOT_FONTNAME. You need to make
# sure dot is able to find the font, which can be done by putting it in a
# standard location or by setting the DOTFONTPATH environment variable or by
# setting DOT_FONTPATH to the directory containing the font.
# The default value is: Helvetica.
# This tag requires that the tag HAVE_DOT is set to YES.
 
DOT_FONTNAME = Helvetica
 
# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of
# dot graphs.
# Minimum value: 4, maximum value: 24, default value: 10.
# This tag requires that the tag HAVE_DOT is set to YES.
 
DOT_FONTSIZE = 10
 
# By default doxygen will tell dot to use the default font as specified with
# DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set
# the path where dot can find it using this tag.
# This tag requires that the tag HAVE_DOT is set to YES.
 
DOT_FONTPATH =
 
# If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for
# each documented class showing the direct and indirect inheritance relations.
# Setting this tag to YES will force the CLASS_DIAGRAMS tag to NO.
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
 
CLASS_GRAPH = YES
 
# If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a
# graph for each documented class showing the direct and indirect implementation
# dependencies (inheritance, containment, and class references variables) of the
# class with other documented classes.
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
 
COLLABORATION_GRAPH = YES
 
# If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for
# groups, showing the direct groups dependencies.
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
 
GROUP_GRAPHS = YES
 
# If the UML_LOOK tag is set to YES, doxygen will generate inheritance and
# collaboration diagrams in a style similar to the OMG's Unified Modeling
# Language.
# The default value is: NO.
# This tag requires that the tag HAVE_DOT is set to YES.
 
UML_LOOK = NO
 
# If the UML_LOOK tag is enabled, the fields and methods are shown inside the
# class node. If there are many fields or methods and many nodes the graph may
# become too big to be useful. The UML_LIMIT_NUM_FIELDS threshold limits the
# number of items for each type to make the size more manageable. Set this to 0
# for no limit. Note that the threshold may be exceeded by 50% before the limit
# is enforced. So when you set the threshold to 10, up to 15 fields may appear,
# but if the number exceeds 15, the total amount of fields shown is limited to
# 10.
# Minimum value: 0, maximum value: 100, default value: 10.
# This tag requires that the tag HAVE_DOT is set to YES.
 
UML_LIMIT_NUM_FIELDS = 10
 
# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and
# collaboration graphs will show the relations between templates and their
# instances.
# The default value is: NO.
# This tag requires that the tag HAVE_DOT is set to YES.
 
TEMPLATE_RELATIONS = NO
 
# If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to
# YES then doxygen will generate a graph for each documented file showing the
# direct and indirect include dependencies of the file with other documented
# files.
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
 
INCLUDE_GRAPH = YES
 
# If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are
# set to YES then doxygen will generate a graph for each documented file showing
# the direct and indirect include dependencies of the file with other documented
# files.
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
 
INCLUDED_BY_GRAPH = YES
 
# If the CALL_GRAPH tag is set to YES then doxygen will generate a call
# dependency graph for every global function or class method.
#
# Note that enabling this option will significantly increase the time of a run.
# So in most cases it will be better to enable call graphs for selected
# functions only using the \callgraph command. Disabling a call graph can be
# accomplished by means of the command \hidecallgraph.
# The default value is: NO.
# This tag requires that the tag HAVE_DOT is set to YES.
 
CALL_GRAPH = NO
 
# If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller
# dependency graph for every global function or class method.
#
# Note that enabling this option will significantly increase the time of a run.
# So in most cases it will be better to enable caller graphs for selected
# functions only using the \callergraph command. Disabling a caller graph can be
# accomplished by means of the command \hidecallergraph.
# The default value is: NO.
# This tag requires that the tag HAVE_DOT is set to YES.
 
CALLER_GRAPH = NO
 
# If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical
# hierarchy of all classes instead of a textual one.
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
 
GRAPHICAL_HIERARCHY = YES
 
# If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the
# dependencies a directory has on other directories in a graphical way. The
# dependency relations are determined by the #include relations between the
# files in the directories.
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
 
DIRECTORY_GRAPH = YES
 
# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
# generated by dot. For an explanation of the image formats see the section
# output formats in the documentation of the dot tool (Graphviz (see:
# http://www.graphviz.org/)).
# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order
# to make the SVG files visible in IE 9+ (other browsers do not have this
# requirement).
# Possible values are: png, png:cairo, png:cairo:cairo, png:cairo:gd, png:gd,
# png:gd:gd, jpg, jpg:cairo, jpg:cairo:gd, jpg:gd, jpg:gd:gd, gif, gif:cairo,
# gif:cairo:gd, gif:gd, gif:gd:gd, svg, png:gd, png:gd:gd, png:cairo,
# png:cairo:gd, png:cairo:cairo, png:cairo:gdiplus, png:gdiplus and
# png:gdiplus:gdiplus.
# The default value is: png.
# This tag requires that the tag HAVE_DOT is set to YES.
 
DOT_IMAGE_FORMAT = png
 
# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
# enable generation of interactive SVG images that allow zooming and panning.
#
# Note that this requires a modern browser other than Internet Explorer. Tested
# and working are Firefox, Chrome, Safari, and Opera.
# Note: For IE 9+ you need to set HTML_FILE_EXTENSION to xhtml in order to make
# the SVG files visible. Older versions of IE do not have SVG support.
# The default value is: NO.
# This tag requires that the tag HAVE_DOT is set to YES.
 
INTERACTIVE_SVG = NO
 
# The DOT_PATH tag can be used to specify the path where the dot tool can be
# found. If left blank, it is assumed the dot tool can be found in the path.
# This tag requires that the tag HAVE_DOT is set to YES.
 
DOT_PATH =
 
# The DOTFILE_DIRS tag can be used to specify one or more directories that
# contain dot files that are included in the documentation (see the \dotfile
# command).
# This tag requires that the tag HAVE_DOT is set to YES.
 
DOTFILE_DIRS =
 
# The MSCFILE_DIRS tag can be used to specify one or more directories that
# contain msc files that are included in the documentation (see the \mscfile
# command).
 
MSCFILE_DIRS =
 
# The DIAFILE_DIRS tag can be used to specify one or more directories that
# contain dia files that are included in the documentation (see the \diafile
# command).
 
DIAFILE_DIRS =
 
# When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the
# path where java can find the plantuml.jar file. If left blank, it is assumed
# PlantUML is not used or called during a preprocessing step. Doxygen will
# generate a warning when it encounters a \startuml command in this case and
# will not generate output for the diagram.
 
PLANTUML_JAR_PATH =
 
# When using plantuml, the PLANTUML_CFG_FILE tag can be used to specify a
# configuration file for plantuml.
 
PLANTUML_CFG_FILE =
 
# When using plantuml, the specified paths are searched for files specified by
# the !include statement in a plantuml block.
 
PLANTUML_INCLUDE_PATH =
 
# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes
# that will be shown in the graph. If the number of nodes in a graph becomes
# larger than this value, doxygen will truncate the graph, which is visualized
# by representing a node as a red box. Note that doxygen if the number of direct
# children of the root node in a graph is already larger than
# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note that
# the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
# Minimum value: 0, maximum value: 10000, default value: 50.
# This tag requires that the tag HAVE_DOT is set to YES.
 
DOT_GRAPH_MAX_NODES = 50
 
# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the graphs
# generated by dot. A depth value of 3 means that only nodes reachable from the
# root by following a path via at most 3 edges will be shown. Nodes that lay
# further from the root node will be omitted. Note that setting this option to 1
# or 2 may greatly reduce the computation time needed for large code bases. Also
# note that the size of a graph can be further restricted by
# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
# Minimum value: 0, maximum value: 1000, default value: 0.
# This tag requires that the tag HAVE_DOT is set to YES.
 
MAX_DOT_GRAPH_DEPTH = 0
 
# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
# background. This is disabled by default, because dot on Windows does not seem
# to support this out of the box.
#
# Warning: Depending on the platform used, enabling this option may lead to
# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
# read).
# The default value is: NO.
# This tag requires that the tag HAVE_DOT is set to YES.
 
DOT_TRANSPARENT = NO
 
# Set the DOT_MULTI_TARGETS tag to YES to allow dot to generate multiple output
# files in one run (i.e. multiple -o and -T options on the command line). This
# makes dot run faster, but since only newer versions of dot (>1.8.10) support
# this, this feature is disabled by default.
# The default value is: NO.
# This tag requires that the tag HAVE_DOT is set to YES.
 
DOT_MULTI_TARGETS = NO
 
# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page
# explaining the meaning of the various boxes and arrows in the dot generated
# graphs.
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
 
GENERATE_LEGEND = YES
 
# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate dot
# files that are used to generate the various graphs.
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
 
DOT_CLEANUP = YES
/rtl/core/neorv32_bootloader_image.vhd
51,13 → 51,13
00000040 => x"01612823",
00000041 => x"01712623",
00000042 => x"01812423",
00000043 => x"4e9000ef",
00000044 => x"4ad000ef",
00000045 => x"415000ef",
00000046 => x"285000ef",
00000047 => x"4c5000ef",
00000048 => x"26d000ef",
00000049 => x"fc101473",
00000043 => x"4fd000ef",
00000044 => x"4c1000ef",
00000045 => x"429000ef",
00000046 => x"299000ef",
00000047 => x"4d9000ef",
00000048 => x"281000ef",
00000049 => x"fc102473",
00000050 => x"026267b7",
00000051 => x"9ff78793",
00000052 => x"00000713",
67,954 → 67,961
00000056 => x"00200513",
00000057 => x"0087f463",
00000058 => x"00400513",
00000059 => x"391000ef",
00000059 => x"3a5000ef",
00000060 => x"00005537",
00000061 => x"00000613",
00000062 => x"00000593",
00000063 => x"b0050513",
00000064 => x"279000ef",
00000065 => x"251000ef",
00000064 => x"28d000ef",
00000065 => x"265000ef",
00000066 => x"00245793",
00000067 => x"00a78533",
00000068 => x"00f537b3",
00000069 => x"00b785b3",
00000070 => x"249000ef",
00000070 => x"25d000ef",
00000071 => x"ffff07b7",
00000072 => x"41478793",
00000072 => x"42878793",
00000073 => x"30579073",
00000074 => x"08000793",
00000075 => x"30479073",
00000076 => x"441000ef",
00000076 => x"455000ef",
00000077 => x"00100513",
00000078 => x"41d000ef",
00000078 => x"431000ef",
00000079 => x"00000793",
00000080 => x"34079073",
00000081 => x"ffff1537",
00000082 => x"ed850513",
00000083 => x"2d9000ef",
00000084 => x"3bc000ef",
00000082 => x"eec50513",
00000083 => x"2ed000ef",
00000084 => x"3d0000ef",
00000085 => x"ffff1537",
00000086 => x"f1050513",
00000087 => x"2c9000ef",
00000088 => x"fc101573",
00000089 => x"240000ef",
00000086 => x"f2450513",
00000087 => x"2dd000ef",
00000088 => x"fc102573",
00000089 => x"254000ef",
00000090 => x"ffff1537",
00000091 => x"f1850513",
00000092 => x"2b5000ef",
00000093 => x"30101573",
00000094 => x"22c000ef",
00000091 => x"f2c50513",
00000092 => x"2c9000ef",
00000093 => x"f1402573",
00000094 => x"240000ef",
00000095 => x"ffff1537",
00000096 => x"f2450513",
00000097 => x"2a1000ef",
00000098 => x"fc001573",
00000099 => x"218000ef",
00000096 => x"f3850513",
00000097 => x"2b5000ef",
00000098 => x"30102573",
00000099 => x"22c000ef",
00000100 => x"ffff1537",
00000101 => x"f2c50513",
00000102 => x"28d000ef",
00000103 => x"fc601573",
00000104 => x"ffff14b7",
00000105 => x"200000ef",
00000106 => x"f3448513",
00000107 => x"279000ef",
00000108 => x"fc401573",
00000109 => x"1f0000ef",
00000110 => x"ffff1537",
00000111 => x"f4050513",
00000112 => x"265000ef",
00000113 => x"fc701573",
00000114 => x"1dc000ef",
00000115 => x"f3448513",
00000116 => x"255000ef",
00000117 => x"fc501573",
00000118 => x"1cc000ef",
00000119 => x"ffff1537",
00000120 => x"f4850513",
00000121 => x"241000ef",
00000122 => x"00341413",
00000123 => x"00000493",
00000124 => x"ffff1937",
00000125 => x"fa402783",
00000126 => x"0607d063",
00000127 => x"ffff1537",
00000128 => x"f7850513",
00000129 => x"221000ef",
00000130 => x"ffff1937",
00000131 => x"0f4000ef",
00000132 => x"ffff19b7",
00000133 => x"07200a13",
00000134 => x"06800a93",
00000135 => x"07500b13",
00000136 => x"07300b93",
00000137 => x"ffff14b7",
00000138 => x"ffff1c37",
00000139 => x"f8490513",
00000140 => x"1f5000ef",
00000141 => x"1e1000ef",
00000142 => x"00050413",
00000143 => x"1c9000ef",
00000144 => x"f7498513",
00000145 => x"1e1000ef",
00000146 => x"09440263",
00000147 => x"03541863",
00000148 => x"0b0000ef",
00000149 => x"fd9ff06f",
00000150 => x"0fd000ef",
00000151 => x"00b49463",
00000152 => x"f8856ae3",
00000153 => x"00100513",
00000154 => x"508000ef",
00000155 => x"f7490513",
00000156 => x"1b5000ef",
00000157 => x"098000ef",
00000158 => x"f7dff06f",
00000159 => x"00000513",
00000160 => x"01640e63",
00000161 => x"01741663",
00000162 => x"72c000ef",
00000163 => x"fa1ff06f",
00000164 => x"06c00793",
00000165 => x"00f41863",
00000166 => x"00100513",
00000167 => x"4d4000ef",
00000168 => x"f8dff06f",
00000169 => x"06500793",
00000170 => x"00f41663",
00000171 => x"060000ef",
00000172 => x"f7dff06f",
00000173 => x"03f00793",
00000174 => x"f8cc0513",
00000175 => x"00f40463",
00000176 => x"fa048513",
00000177 => x"161000ef",
00000178 => x"f65ff06f",
00000179 => x"02c12083",
00000180 => x"02812403",
00000181 => x"02412483",
00000182 => x"02012903",
00000183 => x"01c12983",
00000184 => x"01812a03",
00000185 => x"01412a83",
00000186 => x"01012b03",
00000187 => x"00c12b83",
00000188 => x"00812c03",
00000189 => x"00000513",
00000190 => x"03010113",
00000191 => x"00008067",
00000192 => x"ffff1537",
00000193 => x"da850513",
00000194 => x"11d0006f",
00000195 => x"340017f3",
00000196 => x"00079863",
00000101 => x"f4050513",
00000102 => x"2a1000ef",
00000103 => x"fc002573",
00000104 => x"218000ef",
00000105 => x"ffff1537",
00000106 => x"f4850513",
00000107 => x"28d000ef",
00000108 => x"fc602573",
00000109 => x"ffff14b7",
00000110 => x"200000ef",
00000111 => x"f5048513",
00000112 => x"279000ef",
00000113 => x"fc402573",
00000114 => x"1f0000ef",
00000115 => x"ffff1537",
00000116 => x"f5c50513",
00000117 => x"265000ef",
00000118 => x"fc702573",
00000119 => x"1dc000ef",
00000120 => x"f5048513",
00000121 => x"255000ef",
00000122 => x"fc502573",
00000123 => x"1cc000ef",
00000124 => x"ffff1537",
00000125 => x"f6450513",
00000126 => x"241000ef",
00000127 => x"00341413",
00000128 => x"00000493",
00000129 => x"ffff1937",
00000130 => x"fa402783",
00000131 => x"0607d063",
00000132 => x"ffff1537",
00000133 => x"f9450513",
00000134 => x"221000ef",
00000135 => x"ffff1937",
00000136 => x"0f4000ef",
00000137 => x"ffff19b7",
00000138 => x"07200a13",
00000139 => x"06800a93",
00000140 => x"07500b13",
00000141 => x"07300b93",
00000142 => x"ffff14b7",
00000143 => x"ffff1c37",
00000144 => x"fa090513",
00000145 => x"1f5000ef",
00000146 => x"1e1000ef",
00000147 => x"00050413",
00000148 => x"1c9000ef",
00000149 => x"f9098513",
00000150 => x"1e1000ef",
00000151 => x"09440263",
00000152 => x"03541863",
00000153 => x"0b0000ef",
00000154 => x"fd9ff06f",
00000155 => x"0fd000ef",
00000156 => x"00b49463",
00000157 => x"f8856ae3",
00000158 => x"00100513",
00000159 => x"508000ef",
00000160 => x"f9090513",
00000161 => x"1b5000ef",
00000162 => x"098000ef",
00000163 => x"f7dff06f",
00000164 => x"00000513",
00000165 => x"01640e63",
00000166 => x"01741663",
00000167 => x"72c000ef",
00000168 => x"fa1ff06f",
00000169 => x"06c00793",
00000170 => x"00f41863",
00000171 => x"00100513",
00000172 => x"4d4000ef",
00000173 => x"f8dff06f",
00000174 => x"06500793",
00000175 => x"00f41663",
00000176 => x"060000ef",
00000177 => x"f7dff06f",
00000178 => x"03f00793",
00000179 => x"fa8c0513",
00000180 => x"00f40463",
00000181 => x"fbc48513",
00000182 => x"161000ef",
00000183 => x"f65ff06f",
00000184 => x"02c12083",
00000185 => x"02812403",
00000186 => x"02412483",
00000187 => x"02012903",
00000188 => x"01c12983",
00000189 => x"01812a03",
00000190 => x"01412a83",
00000191 => x"01012b03",
00000192 => x"00c12b83",
00000193 => x"00812c03",
00000194 => x"00000513",
00000195 => x"03010113",
00000196 => x"00008067",
00000197 => x"ffff1537",
00000198 => x"e0c50513",
00000199 => x"1090006f",
00000200 => x"ff010113",
00000201 => x"00112623",
00000202 => x"251000ef",
00000203 => x"00000793",
00000204 => x"30479073",
00000205 => x"ffff1537",
00000206 => x"e2850513",
00000207 => x"0e9000ef",
00000208 => x"fa002783",
00000209 => x"fe07cee3",
00000210 => x"fc4017f3",
00000211 => x"00078067",
00000212 => x"ff9ff06f",
00000213 => x"ff010113",
00000214 => x"00812423",
00000215 => x"00050413",
00000216 => x"ffff1537",
00000217 => x"e3850513",
00000218 => x"00112623",
00000219 => x"0b9000ef",
00000220 => x"00500793",
00000221 => x"0287e063",
00000222 => x"03040513",
00000223 => x"0ff57513",
00000224 => x"085000ef",
00000225 => x"1f5000ef",
00000226 => x"00100513",
00000227 => x"1c9000ef",
00000228 => x"0000006f",
00000229 => x"ffff1537",
00000230 => x"e4050513",
00000231 => x"089000ef",
00000232 => x"fe5ff06f",
00000233 => x"fe010113",
00000234 => x"01212823",
00000235 => x"00050913",
00000236 => x"ffff1537",
00000237 => x"00912a23",
00000238 => x"e4850513",
00000239 => x"ffff14b7",
00000240 => x"00812c23",
00000241 => x"01312623",
00000242 => x"00112e23",
00000243 => x"01c00413",
00000244 => x"055000ef",
00000245 => x"fac48493",
00000246 => x"ffc00993",
00000247 => x"008957b3",
00000248 => x"00f7f793",
00000249 => x"00f487b3",
00000250 => x"0007c503",
00000251 => x"ffc40413",
00000252 => x"015000ef",
00000253 => x"ff3414e3",
00000254 => x"01c12083",
00000255 => x"01812403",
00000256 => x"01412483",
00000257 => x"01012903",
00000258 => x"00c12983",
00000259 => x"02010113",
00000260 => x"00008067",
00000261 => x"fb010113",
00000262 => x"04112623",
00000263 => x"04512423",
00000264 => x"04612223",
00000265 => x"04712023",
00000266 => x"02812e23",
00000267 => x"02a12c23",
00000268 => x"02b12a23",
00000269 => x"02c12823",
00000270 => x"02d12623",
00000271 => x"02e12423",
00000272 => x"02f12223",
00000273 => x"03012023",
00000274 => x"01112e23",
00000275 => x"01c12c23",
00000276 => x"01d12a23",
00000277 => x"01e12823",
00000278 => x"01f12623",
00000279 => x"34201473",
00000280 => x"800007b7",
00000281 => x"00778793",
00000282 => x"02f40a63",
00000283 => x"ffff1537",
00000284 => x"e4c50513",
00000285 => x"7b0000ef",
00000286 => x"00040513",
00000287 => x"f29ff0ef",
00000198 => x"dbc50513",
00000199 => x"11d0006f",
00000200 => x"340027f3",
00000201 => x"00079863",
00000202 => x"ffff1537",
00000203 => x"e2050513",
00000204 => x"1090006f",
00000205 => x"ff010113",
00000206 => x"00112623",
00000207 => x"251000ef",
00000208 => x"00000793",
00000209 => x"30479073",
00000210 => x"ffff1537",
00000211 => x"e3c50513",
00000212 => x"0e9000ef",
00000213 => x"fa002783",
00000214 => x"fe07cee3",
00000215 => x"fc4027f3",
00000216 => x"00078067",
00000217 => x"ff9ff06f",
00000218 => x"ff010113",
00000219 => x"00812423",
00000220 => x"00050413",
00000221 => x"ffff1537",
00000222 => x"e4c50513",
00000223 => x"00112623",
00000224 => x"0b9000ef",
00000225 => x"00500793",
00000226 => x"0287e063",
00000227 => x"03040513",
00000228 => x"0ff57513",
00000229 => x"085000ef",
00000230 => x"1f5000ef",
00000231 => x"00100513",
00000232 => x"1c9000ef",
00000233 => x"0000006f",
00000234 => x"ffff1537",
00000235 => x"e5450513",
00000236 => x"089000ef",
00000237 => x"fe5ff06f",
00000238 => x"fe010113",
00000239 => x"01212823",
00000240 => x"00050913",
00000241 => x"ffff1537",
00000242 => x"00912a23",
00000243 => x"e5c50513",
00000244 => x"ffff14b7",
00000245 => x"00812c23",
00000246 => x"01312623",
00000247 => x"00112e23",
00000248 => x"01c00413",
00000249 => x"055000ef",
00000250 => x"fc848493",
00000251 => x"ffc00993",
00000252 => x"008957b3",
00000253 => x"00f7f793",
00000254 => x"00f487b3",
00000255 => x"0007c503",
00000256 => x"ffc40413",
00000257 => x"015000ef",
00000258 => x"ff3414e3",
00000259 => x"01c12083",
00000260 => x"01812403",
00000261 => x"01412483",
00000262 => x"01012903",
00000263 => x"00c12983",
00000264 => x"02010113",
00000265 => x"00008067",
00000266 => x"fb010113",
00000267 => x"04112623",
00000268 => x"04512423",
00000269 => x"04612223",
00000270 => x"04712023",
00000271 => x"02812e23",
00000272 => x"02a12c23",
00000273 => x"02b12a23",
00000274 => x"02c12823",
00000275 => x"02d12623",
00000276 => x"02e12423",
00000277 => x"02f12223",
00000278 => x"03012023",
00000279 => x"01112e23",
00000280 => x"01c12c23",
00000281 => x"01d12a23",
00000282 => x"01e12823",
00000283 => x"01f12623",
00000284 => x"34202473",
00000285 => x"800007b7",
00000286 => x"00778793",
00000287 => x"02f40a63",
00000288 => x"ffff1537",
00000289 => x"e5c50513",
00000290 => x"79c000ef",
00000291 => x"34101573",
00000292 => x"f15ff0ef",
00000293 => x"00500513",
00000294 => x"ebdff0ef",
00000295 => x"00000513",
00000296 => x"095000ef",
00000297 => x"6b0000ef",
00000298 => x"fc1017f3",
00000299 => x"0027d793",
00000300 => x"00a78533",
00000301 => x"00f537b3",
00000302 => x"00b785b3",
00000303 => x"6a4000ef",
00000304 => x"03c12403",
00000305 => x"04c12083",
00000306 => x"04812283",
00000307 => x"04412303",
00000308 => x"04012383",
00000309 => x"03812503",
00000310 => x"03412583",
00000311 => x"03012603",
00000312 => x"02c12683",
00000313 => x"02812703",
00000314 => x"02412783",
00000315 => x"02012803",
00000316 => x"01c12883",
00000317 => x"01812e03",
00000318 => x"01412e83",
00000319 => x"01012f03",
00000320 => x"00c12f83",
00000321 => x"05010113",
00000322 => x"30200073",
00000323 => x"fe010113",
00000324 => x"00112e23",
00000325 => x"00812c23",
00000326 => x"00912a23",
00000327 => x"01212823",
00000328 => x"01312623",
00000329 => x"01412423",
00000330 => x"01512223",
00000331 => x"f1301973",
00000332 => x"00000a93",
00000333 => x"00900993",
00000334 => x"00300a13",
00000335 => x"00400493",
00000336 => x"41500433",
00000337 => x"00341413",
00000338 => x"01840413",
00000339 => x"00895433",
00000340 => x"0ff47413",
00000341 => x"00000513",
00000342 => x"0489ec63",
00000343 => x"00050863",
00000344 => x"03050513",
00000345 => x"0ff57513",
00000346 => x"69c000ef",
00000347 => x"03040513",
00000348 => x"0ff57513",
00000349 => x"690000ef",
00000350 => x"014a8663",
00000351 => x"02e00513",
00000352 => x"684000ef",
00000353 => x"001a8a93",
00000354 => x"fa9a9ce3",
00000355 => x"01c12083",
00000356 => x"01812403",
00000357 => x"01412483",
00000358 => x"01012903",
00000359 => x"00c12983",
00000360 => x"00812a03",
00000361 => x"00412a83",
00000362 => x"02010113",
00000363 => x"00008067",
00000364 => x"ff640413",
00000365 => x"00150513",
00000366 => x"0ff47413",
00000367 => x"0ff57513",
00000368 => x"f99ff06f",
00000369 => x"ff010113",
00000370 => x"00000513",
00000371 => x"00112623",
00000372 => x"00812423",
00000373 => x"708000ef",
00000374 => x"00500513",
00000375 => x"744000ef",
00000376 => x"00000513",
00000377 => x"73c000ef",
00000378 => x"00050413",
00000379 => x"00000513",
00000380 => x"70c000ef",
00000381 => x"00c12083",
00000382 => x"0ff47513",
00000383 => x"00812403",
00000384 => x"01010113",
00000385 => x"00008067",
00000386 => x"ff010113",
00000387 => x"00000513",
00000388 => x"00112623",
00000389 => x"00812423",
00000390 => x"6c4000ef",
00000391 => x"09e00513",
00000392 => x"700000ef",
00000393 => x"00000513",
00000394 => x"6f8000ef",
00000395 => x"00050413",
00000396 => x"00000513",
00000397 => x"6c8000ef",
00000398 => x"00c12083",
00000399 => x"0ff47513",
00000400 => x"00812403",
00000401 => x"01010113",
00000402 => x"00008067",
00000403 => x"ff010113",
00000404 => x"00000513",
00000405 => x"00112623",
00000406 => x"684000ef",
00000407 => x"00600513",
00000408 => x"6c0000ef",
00000409 => x"00c12083",
00000410 => x"00000513",
00000411 => x"01010113",
00000412 => x"68c0006f",
00000413 => x"ff010113",
00000414 => x"00812423",
00000415 => x"00050413",
00000416 => x"01055513",
00000417 => x"0ff57513",
00000418 => x"00112623",
00000419 => x"694000ef",
00000420 => x"00845513",
00000421 => x"0ff57513",
00000422 => x"688000ef",
00000423 => x"0ff47513",
00000424 => x"00812403",
00000425 => x"00c12083",
00000426 => x"01010113",
00000427 => x"6740006f",
00000428 => x"ff010113",
00000429 => x"00812423",
00000430 => x"00050413",
00000431 => x"00000513",
00000432 => x"00112623",
00000433 => x"618000ef",
00000434 => x"00300513",
00000435 => x"654000ef",
00000436 => x"00040513",
00000437 => x"fa1ff0ef",
00000438 => x"00000513",
00000439 => x"644000ef",
00000440 => x"00050413",
00000441 => x"00000513",
00000442 => x"614000ef",
00000443 => x"00c12083",
00000444 => x"0ff47513",
00000445 => x"00812403",
00000446 => x"01010113",
00000447 => x"00008067",
00000448 => x"fd010113",
00000449 => x"02812423",
00000450 => x"02912223",
00000451 => x"03212023",
00000452 => x"01312e23",
00000453 => x"02112623",
00000454 => x"00050493",
00000455 => x"00300413",
00000456 => x"00358913",
00000457 => x"fff00993",
00000458 => x"02049e63",
00000459 => x"4e8000ef",
00000460 => x"00c10793",
00000461 => x"008787b3",
00000462 => x"00a78023",
00000463 => x"fff40413",
00000464 => x"ff3414e3",
00000465 => x"02c12083",
00000466 => x"02812403",
00000467 => x"00c12503",
00000468 => x"02412483",
00000469 => x"02012903",
00000470 => x"01c12983",
00000471 => x"03010113",
00000472 => x"00008067",
00000473 => x"40890533",
00000474 => x"f49ff0ef",
00000475 => x"fc5ff06f",
00000476 => x"fd010113",
00000477 => x"02112623",
00000478 => x"02812423",
00000479 => x"02912223",
00000480 => x"03212023",
00000481 => x"01312e23",
00000482 => x"01412c23",
00000483 => x"01512a23",
00000484 => x"01612823",
00000485 => x"01712623",
00000486 => x"fc001473",
00000487 => x"00847413",
00000488 => x"00040663",
00000489 => x"00400513",
00000490 => x"badff0ef",
00000491 => x"00050493",
00000492 => x"02051863",
00000493 => x"ffff1537",
00000494 => x"e6450513",
00000495 => x"468000ef",
00000496 => x"000405b7",
00000497 => x"00048513",
00000498 => x"f39ff0ef",
00000499 => x"4788d7b7",
00000500 => x"afe78793",
00000501 => x"02f50463",
00000502 => x"00000513",
00000503 => x"fcdff06f",
00000504 => x"ffff1537",
00000505 => x"e8450513",
00000506 => x"43c000ef",
00000507 => x"e1dff0ef",
00000508 => x"fc0518e3",
00000509 => x"00300513",
00000510 => x"fb1ff06f",
00000511 => x"00040a37",
00000512 => x"004a0593",
00000513 => x"00048513",
00000514 => x"ef9ff0ef",
00000515 => x"00050913",
00000516 => x"008a0593",
00000517 => x"00048513",
00000518 => x"ee9ff0ef",
00000519 => x"00050a93",
00000520 => x"fc6017f3",
00000521 => x"00100513",
00000522 => x"f927e0e3",
00000523 => x"fc401bf3",
00000524 => x"00000993",
00000525 => x"ffc97b13",
00000526 => x"00ca0a13",
00000527 => x"014985b3",
00000528 => x"053b1663",
00000529 => x"01540433",
00000530 => x"00200513",
00000531 => x"f4041ee3",
00000532 => x"ffff1537",
00000533 => x"e9050513",
00000534 => x"3cc000ef",
00000535 => x"34091073",
00000536 => x"02c12083",
00000537 => x"02812403",
00000538 => x"02412483",
00000539 => x"02012903",
00000540 => x"01c12983",
00000541 => x"01812a03",
00000542 => x"01412a83",
00000543 => x"01012b03",
00000544 => x"00c12b83",
00000545 => x"03010113",
00000546 => x"00008067",
00000547 => x"00048513",
00000548 => x"e71ff0ef",
00000549 => x"017987b3",
00000550 => x"00a40433",
00000551 => x"00a7a023",
00000552 => x"00498993",
00000553 => x"f99ff06f",
00000554 => x"ff010113",
00000555 => x"00112623",
00000556 => x"00812423",
00000557 => x"00912223",
00000558 => x"00058413",
00000559 => x"00050493",
00000560 => x"d8dff0ef",
00000561 => x"00000513",
00000562 => x"414000ef",
00000563 => x"00200513",
00000564 => x"450000ef",
00000565 => x"00048513",
00000566 => x"d9dff0ef",
00000567 => x"00040513",
00000568 => x"440000ef",
00000569 => x"00000513",
00000570 => x"414000ef",
00000571 => x"cd9ff0ef",
00000572 => x"00157513",
00000573 => x"fe051ce3",
00000574 => x"00c12083",
00000575 => x"00812403",
00000576 => x"00412483",
00000577 => x"01010113",
00000578 => x"00008067",
00000579 => x"fe010113",
00000580 => x"00812c23",
00000581 => x"00912a23",
00000582 => x"01212823",
00000583 => x"00112e23",
00000584 => x"00b12623",
00000585 => x"00300413",
00000586 => x"00350493",
00000587 => x"fff00913",
00000588 => x"00c10793",
00000589 => x"008787b3",
00000590 => x"0007c583",
00000591 => x"40848533",
00000592 => x"fff40413",
00000593 => x"f65ff0ef",
00000594 => x"ff2414e3",
00000595 => x"01c12083",
00000596 => x"01812403",
00000597 => x"01412483",
00000598 => x"01012903",
00000599 => x"02010113",
00000600 => x"00008067",
00000601 => x"ff010113",
00000602 => x"00112623",
00000603 => x"00812423",
00000604 => x"00050413",
00000605 => x"cd9ff0ef",
00000606 => x"00000513",
00000607 => x"360000ef",
00000608 => x"0d800513",
00000609 => x"39c000ef",
00000610 => x"00040513",
00000611 => x"ce9ff0ef",
00000612 => x"00000513",
00000613 => x"368000ef",
00000614 => x"c2dff0ef",
00000615 => x"00157513",
00000616 => x"fe051ce3",
00000617 => x"00c12083",
00000618 => x"00812403",
00000619 => x"01010113",
00000620 => x"00008067",
00000621 => x"fe010113",
00000622 => x"00112e23",
00000623 => x"00812c23",
00000624 => x"00912a23",
00000625 => x"01212823",
00000626 => x"01312623",
00000627 => x"01412423",
00000628 => x"01512223",
00000629 => x"34001473",
00000630 => x"02041863",
00000631 => x"ffff1537",
00000632 => x"e0c50513",
00000633 => x"01812403",
00000634 => x"01c12083",
00000635 => x"01412483",
00000636 => x"01012903",
00000637 => x"00c12983",
00000638 => x"00812a03",
00000639 => x"00412a83",
00000640 => x"02010113",
00000641 => x"2200006f",
00000642 => x"ffff1537",
00000643 => x"e9450513",
00000644 => x"214000ef",
00000645 => x"00040513",
00000646 => x"98dff0ef",
00000289 => x"e6050513",
00000290 => x"7b0000ef",
00000291 => x"00040513",
00000292 => x"f29ff0ef",
00000293 => x"ffff1537",
00000294 => x"e7050513",
00000295 => x"79c000ef",
00000296 => x"34102573",
00000297 => x"f15ff0ef",
00000298 => x"00500513",
00000299 => x"ebdff0ef",
00000300 => x"00000513",
00000301 => x"095000ef",
00000302 => x"6b0000ef",
00000303 => x"fc1027f3",
00000304 => x"0027d793",
00000305 => x"00a78533",
00000306 => x"00f537b3",
00000307 => x"00b785b3",
00000308 => x"6a4000ef",
00000309 => x"03c12403",
00000310 => x"04c12083",
00000311 => x"04812283",
00000312 => x"04412303",
00000313 => x"04012383",
00000314 => x"03812503",
00000315 => x"03412583",
00000316 => x"03012603",
00000317 => x"02c12683",
00000318 => x"02812703",
00000319 => x"02412783",
00000320 => x"02012803",
00000321 => x"01c12883",
00000322 => x"01812e03",
00000323 => x"01412e83",
00000324 => x"01012f03",
00000325 => x"00c12f83",
00000326 => x"05010113",
00000327 => x"30200073",
00000328 => x"fe010113",
00000329 => x"00112e23",
00000330 => x"00812c23",
00000331 => x"00912a23",
00000332 => x"01212823",
00000333 => x"01312623",
00000334 => x"01412423",
00000335 => x"01512223",
00000336 => x"f1302973",
00000337 => x"00000a93",
00000338 => x"00900993",
00000339 => x"00300a13",
00000340 => x"00400493",
00000341 => x"41500433",
00000342 => x"00341413",
00000343 => x"01840413",
00000344 => x"00895433",
00000345 => x"0ff47413",
00000346 => x"00000513",
00000347 => x"0489ec63",
00000348 => x"00050863",
00000349 => x"03050513",
00000350 => x"0ff57513",
00000351 => x"69c000ef",
00000352 => x"03040513",
00000353 => x"0ff57513",
00000354 => x"690000ef",
00000355 => x"014a8663",
00000356 => x"02e00513",
00000357 => x"684000ef",
00000358 => x"001a8a93",
00000359 => x"fa9a9ce3",
00000360 => x"01c12083",
00000361 => x"01812403",
00000362 => x"01412483",
00000363 => x"01012903",
00000364 => x"00c12983",
00000365 => x"00812a03",
00000366 => x"00412a83",
00000367 => x"02010113",
00000368 => x"00008067",
00000369 => x"ff640413",
00000370 => x"00150513",
00000371 => x"0ff47413",
00000372 => x"0ff57513",
00000373 => x"f99ff06f",
00000374 => x"ff010113",
00000375 => x"00000513",
00000376 => x"00112623",
00000377 => x"00812423",
00000378 => x"708000ef",
00000379 => x"00500513",
00000380 => x"744000ef",
00000381 => x"00000513",
00000382 => x"73c000ef",
00000383 => x"00050413",
00000384 => x"00000513",
00000385 => x"70c000ef",
00000386 => x"00c12083",
00000387 => x"0ff47513",
00000388 => x"00812403",
00000389 => x"01010113",
00000390 => x"00008067",
00000391 => x"ff010113",
00000392 => x"00000513",
00000393 => x"00112623",
00000394 => x"00812423",
00000395 => x"6c4000ef",
00000396 => x"09e00513",
00000397 => x"700000ef",
00000398 => x"00000513",
00000399 => x"6f8000ef",
00000400 => x"00050413",
00000401 => x"00000513",
00000402 => x"6c8000ef",
00000403 => x"00c12083",
00000404 => x"0ff47513",
00000405 => x"00812403",
00000406 => x"01010113",
00000407 => x"00008067",
00000408 => x"ff010113",
00000409 => x"00000513",
00000410 => x"00112623",
00000411 => x"684000ef",
00000412 => x"00600513",
00000413 => x"6c0000ef",
00000414 => x"00c12083",
00000415 => x"00000513",
00000416 => x"01010113",
00000417 => x"68c0006f",
00000418 => x"ff010113",
00000419 => x"00812423",
00000420 => x"00050413",
00000421 => x"01055513",
00000422 => x"0ff57513",
00000423 => x"00112623",
00000424 => x"694000ef",
00000425 => x"00845513",
00000426 => x"0ff57513",
00000427 => x"688000ef",
00000428 => x"0ff47513",
00000429 => x"00812403",
00000430 => x"00c12083",
00000431 => x"01010113",
00000432 => x"6740006f",
00000433 => x"ff010113",
00000434 => x"00812423",
00000435 => x"00050413",
00000436 => x"00000513",
00000437 => x"00112623",
00000438 => x"618000ef",
00000439 => x"00300513",
00000440 => x"654000ef",
00000441 => x"00040513",
00000442 => x"fa1ff0ef",
00000443 => x"00000513",
00000444 => x"644000ef",
00000445 => x"00050413",
00000446 => x"00000513",
00000447 => x"614000ef",
00000448 => x"00c12083",
00000449 => x"0ff47513",
00000450 => x"00812403",
00000451 => x"01010113",
00000452 => x"00008067",
00000453 => x"fd010113",
00000454 => x"02812423",
00000455 => x"02912223",
00000456 => x"03212023",
00000457 => x"01312e23",
00000458 => x"02112623",
00000459 => x"00050493",
00000460 => x"00300413",
00000461 => x"00358913",
00000462 => x"fff00993",
00000463 => x"02049e63",
00000464 => x"4e8000ef",
00000465 => x"00c10793",
00000466 => x"008787b3",
00000467 => x"00a78023",
00000468 => x"fff40413",
00000469 => x"ff3414e3",
00000470 => x"02c12083",
00000471 => x"02812403",
00000472 => x"00c12503",
00000473 => x"02412483",
00000474 => x"02012903",
00000475 => x"01c12983",
00000476 => x"03010113",
00000477 => x"00008067",
00000478 => x"40890533",
00000479 => x"f49ff0ef",
00000480 => x"fc5ff06f",
00000481 => x"fd010113",
00000482 => x"02112623",
00000483 => x"02812423",
00000484 => x"02912223",
00000485 => x"03212023",
00000486 => x"01312e23",
00000487 => x"01412c23",
00000488 => x"01512a23",
00000489 => x"01612823",
00000490 => x"01712623",
00000491 => x"fc002473",
00000492 => x"00847413",
00000493 => x"00040663",
00000494 => x"00400513",
00000495 => x"badff0ef",
00000496 => x"00050493",
00000497 => x"02051863",
00000498 => x"ffff1537",
00000499 => x"e7850513",
00000500 => x"468000ef",
00000501 => x"000405b7",
00000502 => x"00048513",
00000503 => x"f39ff0ef",
00000504 => x"4788d7b7",
00000505 => x"afe78793",
00000506 => x"02f50463",
00000507 => x"00000513",
00000508 => x"fcdff06f",
00000509 => x"ffff1537",
00000510 => x"e9850513",
00000511 => x"43c000ef",
00000512 => x"e1dff0ef",
00000513 => x"fc0518e3",
00000514 => x"00300513",
00000515 => x"fb1ff06f",
00000516 => x"00040a37",
00000517 => x"004a0593",
00000518 => x"00048513",
00000519 => x"ef9ff0ef",
00000520 => x"00050913",
00000521 => x"008a0593",
00000522 => x"00048513",
00000523 => x"ee9ff0ef",
00000524 => x"00050a93",
00000525 => x"fc6027f3",
00000526 => x"00100513",
00000527 => x"f927e0e3",
00000528 => x"fc402bf3",
00000529 => x"00000993",
00000530 => x"ffc97b13",
00000531 => x"00ca0a13",
00000532 => x"014985b3",
00000533 => x"053b1663",
00000534 => x"01540433",
00000535 => x"00200513",
00000536 => x"f4041ee3",
00000537 => x"ffff1537",
00000538 => x"ea450513",
00000539 => x"3cc000ef",
00000540 => x"34091073",
00000541 => x"02c12083",
00000542 => x"02812403",
00000543 => x"02412483",
00000544 => x"02012903",
00000545 => x"01c12983",
00000546 => x"01812a03",
00000547 => x"01412a83",
00000548 => x"01012b03",
00000549 => x"00c12b83",
00000550 => x"03010113",
00000551 => x"00008067",
00000552 => x"00048513",
00000553 => x"e71ff0ef",
00000554 => x"017987b3",
00000555 => x"00a40433",
00000556 => x"00a7a023",
00000557 => x"00498993",
00000558 => x"f99ff06f",
00000559 => x"ff010113",
00000560 => x"00112623",
00000561 => x"00812423",
00000562 => x"00912223",
00000563 => x"00058413",
00000564 => x"00050493",
00000565 => x"d8dff0ef",
00000566 => x"00000513",
00000567 => x"414000ef",
00000568 => x"00200513",
00000569 => x"450000ef",
00000570 => x"00048513",
00000571 => x"d9dff0ef",
00000572 => x"00040513",
00000573 => x"440000ef",
00000574 => x"00000513",
00000575 => x"414000ef",
00000576 => x"cd9ff0ef",
00000577 => x"00157513",
00000578 => x"fe051ce3",
00000579 => x"00c12083",
00000580 => x"00812403",
00000581 => x"00412483",
00000582 => x"01010113",
00000583 => x"00008067",
00000584 => x"fe010113",
00000585 => x"00812c23",
00000586 => x"00912a23",
00000587 => x"01212823",
00000588 => x"00112e23",
00000589 => x"00b12623",
00000590 => x"00300413",
00000591 => x"00350493",
00000592 => x"fff00913",
00000593 => x"00c10793",
00000594 => x"008787b3",
00000595 => x"0007c583",
00000596 => x"40848533",
00000597 => x"fff40413",
00000598 => x"f65ff0ef",
00000599 => x"ff2414e3",
00000600 => x"01c12083",
00000601 => x"01812403",
00000602 => x"01412483",
00000603 => x"01012903",
00000604 => x"02010113",
00000605 => x"00008067",
00000606 => x"ff010113",
00000607 => x"00112623",
00000608 => x"00812423",
00000609 => x"00050413",
00000610 => x"cd9ff0ef",
00000611 => x"00000513",
00000612 => x"360000ef",
00000613 => x"0d800513",
00000614 => x"39c000ef",
00000615 => x"00040513",
00000616 => x"ce9ff0ef",
00000617 => x"00000513",
00000618 => x"368000ef",
00000619 => x"c2dff0ef",
00000620 => x"00157513",
00000621 => x"fe051ce3",
00000622 => x"00c12083",
00000623 => x"00812403",
00000624 => x"01010113",
00000625 => x"00008067",
00000626 => x"fe010113",
00000627 => x"00112e23",
00000628 => x"00812c23",
00000629 => x"00912a23",
00000630 => x"01212823",
00000631 => x"01312623",
00000632 => x"01412423",
00000633 => x"01512223",
00000634 => x"34002473",
00000635 => x"02041863",
00000636 => x"ffff1537",
00000637 => x"e2050513",
00000638 => x"01812403",
00000639 => x"01c12083",
00000640 => x"01412483",
00000641 => x"01012903",
00000642 => x"00c12983",
00000643 => x"00812a03",
00000644 => x"00412a83",
00000645 => x"02010113",
00000646 => x"2200006f",
00000647 => x"ffff1537",
00000648 => x"ea050513",
00000649 => x"200000ef",
00000650 => x"00040537",
00000651 => x"979ff0ef",
00000648 => x"ea850513",
00000649 => x"214000ef",
00000650 => x"00040513",
00000651 => x"98dff0ef",
00000652 => x"ffff1537",
00000653 => x"ebc50513",
00000654 => x"1ec000ef",
00000655 => x"1d8000ef",
00000656 => x"00050493",
00000657 => x"1c0000ef",
00000658 => x"07900793",
00000659 => x"0af49e63",
00000660 => x"bb9ff0ef",
00000661 => x"00051663",
00000662 => x"00300513",
00000663 => x"8f9ff0ef",
00000664 => x"ffff1537",
00000665 => x"ec850513",
00000666 => x"01045493",
00000667 => x"1b8000ef",
00000668 => x"00148493",
00000669 => x"00040937",
00000670 => x"fff00993",
00000671 => x"00010a37",
00000672 => x"fff48493",
00000673 => x"07349063",
00000674 => x"4788d5b7",
00000675 => x"afe58593",
00000676 => x"00040537",
00000677 => x"e79ff0ef",
00000678 => x"00040537",
00000679 => x"00040593",
00000680 => x"00450513",
00000681 => x"e69ff0ef",
00000682 => x"fc401a73",
00000683 => x"000409b7",
00000684 => x"ffc47413",
00000685 => x"00000493",
00000686 => x"00000913",
00000687 => x"00c98a93",
00000688 => x"01548533",
00000689 => x"014487b3",
00000690 => x"02849663",
00000691 => x"00898513",
00000692 => x"412005b3",
00000693 => x"e39ff0ef",
00000694 => x"ffff1537",
00000695 => x"e9050513",
00000696 => x"f05ff06f",
00000697 => x"00090513",
00000698 => x"e7dff0ef",
00000699 => x"01490933",
00000700 => x"f91ff06f",
00000701 => x"0007a583",
00000702 => x"00448493",
00000703 => x"00b90933",
00000704 => x"e0dff0ef",
00000705 => x"fbdff06f",
00000706 => x"01c12083",
00000707 => x"01812403",
00000708 => x"01412483",
00000709 => x"01012903",
00000710 => x"00c12983",
00000711 => x"00812a03",
00000712 => x"00412a83",
00000713 => x"02010113",
00000714 => x"00008067",
00000715 => x"000047b7",
00000716 => x"70078793",
00000717 => x"f8f02623",
00000718 => x"00008067",
00000719 => x"fc000713",
00000720 => x"00072783",
00000721 => x"00179793",
00000722 => x"0017d793",
00000723 => x"00f72023",
00000724 => x"00008067",
00000725 => x"f9002503",
00000726 => x"f9402583",
00000727 => x"00008067",
00000728 => x"f9800693",
00000729 => x"fff00613",
00000730 => x"00c6a023",
00000731 => x"00a6a023",
00000732 => x"00b6a223",
00000733 => x"00008067",
00000734 => x"fa002023",
00000735 => x"fc1016f3",
00000736 => x"00000713",
00000737 => x"00151513",
00000738 => x"04a6f263",
00000739 => x"000016b7",
00000740 => x"00000793",
00000741 => x"ffe68693",
00000742 => x"04e6e463",
00000743 => x"00167613",
00000744 => x"0015f593",
00000745 => x"01879793",
00000746 => x"01e61613",
00000747 => x"00c7e7b3",
00000748 => x"01d59593",
00000749 => x"00b7e7b3",
00000750 => x"00e7e7b3",
00000751 => x"10000737",
00000752 => x"00e7e7b3",
00000753 => x"faf02023",
00000754 => x"00008067",
00000755 => x"00170793",
00000756 => x"01079713",
00000757 => x"40a686b3",
00000758 => x"01075713",
00000759 => x"fadff06f",
00000760 => x"ffe78513",
00000761 => x"0fd57513",
00000762 => x"00051a63",
00000763 => x"00375713",
00000764 => x"00178793",
00000765 => x"0ff7f793",
00000766 => x"fa1ff06f",
00000767 => x"00175713",
00000768 => x"ff1ff06f",
00000769 => x"fa002783",
00000770 => x"fe07cee3",
00000771 => x"faa02223",
00000772 => x"00008067",
00000773 => x"fa402503",
00000774 => x"fe055ee3",
00000775 => x"0ff57513",
00000776 => x"00008067",
00000777 => x"ff010113",
00000778 => x"00812423",
00000779 => x"01212023",
00000780 => x"00112623",
00000781 => x"00912223",
00000782 => x"00050413",
00000783 => x"00a00913",
00000784 => x"00044483",
00000785 => x"00140413",
00000786 => x"00049e63",
00000787 => x"00c12083",
00000788 => x"00812403",
00000789 => x"00412483",
00000790 => x"00012903",
00000791 => x"01010113",
00000792 => x"00008067",
00000793 => x"01249663",
00000794 => x"00d00513",
00000795 => x"f99ff0ef",
00000796 => x"00048513",
00000797 => x"f91ff0ef",
00000798 => x"fc9ff06f",
00000799 => x"00757513",
00000800 => x"00177793",
00000801 => x"01079793",
00000802 => x"0036f693",
00000803 => x"00a51513",
00000804 => x"00f56533",
00000805 => x"00167613",
00000806 => x"00e69793",
00000807 => x"0015f593",
00000808 => x"00f567b3",
00000809 => x"00d61613",
00000810 => x"00c7e7b3",
00000811 => x"00959593",
00000812 => x"fa800813",
00000813 => x"00b7e7b3",
00000814 => x"00082023",
00000815 => x"1007e793",
00000816 => x"00f82023",
00000817 => x"00008067",
00000818 => x"fa800713",
00000819 => x"00072783",
00000820 => x"eff7f793",
00000821 => x"00f72023",
00000653 => x"eb450513",
00000654 => x"200000ef",
00000655 => x"00040537",
00000656 => x"979ff0ef",
00000657 => x"ffff1537",
00000658 => x"ed050513",
00000659 => x"1ec000ef",
00000660 => x"1d8000ef",
00000661 => x"00050493",
00000662 => x"1c0000ef",
00000663 => x"07900793",
00000664 => x"0af49e63",
00000665 => x"bb9ff0ef",
00000666 => x"00051663",
00000667 => x"00300513",
00000668 => x"8f9ff0ef",
00000669 => x"ffff1537",
00000670 => x"edc50513",
00000671 => x"01045493",
00000672 => x"1b8000ef",
00000673 => x"00148493",
00000674 => x"00040937",
00000675 => x"fff00993",
00000676 => x"00010a37",
00000677 => x"fff48493",
00000678 => x"07349063",
00000679 => x"4788d5b7",
00000680 => x"afe58593",
00000681 => x"00040537",
00000682 => x"e79ff0ef",
00000683 => x"00040537",
00000684 => x"00040593",
00000685 => x"00450513",
00000686 => x"e69ff0ef",
00000687 => x"fc402a73",
00000688 => x"000409b7",
00000689 => x"ffc47413",
00000690 => x"00000493",
00000691 => x"00000913",
00000692 => x"00c98a93",
00000693 => x"01548533",
00000694 => x"014487b3",
00000695 => x"02849663",
00000696 => x"00898513",
00000697 => x"412005b3",
00000698 => x"e39ff0ef",
00000699 => x"ffff1537",
00000700 => x"ea450513",
00000701 => x"f05ff06f",
00000702 => x"00090513",
00000703 => x"e7dff0ef",
00000704 => x"01490933",
00000705 => x"f91ff06f",
00000706 => x"0007a583",
00000707 => x"00448493",
00000708 => x"00b90933",
00000709 => x"e0dff0ef",
00000710 => x"fbdff06f",
00000711 => x"01c12083",
00000712 => x"01812403",
00000713 => x"01412483",
00000714 => x"01012903",
00000715 => x"00c12983",
00000716 => x"00812a03",
00000717 => x"00412a83",
00000718 => x"02010113",
00000719 => x"00008067",
00000720 => x"000047b7",
00000721 => x"70078793",
00000722 => x"f8f02623",
00000723 => x"00008067",
00000724 => x"fc000713",
00000725 => x"00072783",
00000726 => x"00179793",
00000727 => x"0017d793",
00000728 => x"00f72023",
00000729 => x"00008067",
00000730 => x"f9002503",
00000731 => x"f9402583",
00000732 => x"00008067",
00000733 => x"f9800693",
00000734 => x"fff00613",
00000735 => x"00c6a023",
00000736 => x"00a6a023",
00000737 => x"00b6a223",
00000738 => x"00008067",
00000739 => x"fa002023",
00000740 => x"fc1026f3",
00000741 => x"00000713",
00000742 => x"00151513",
00000743 => x"04a6f263",
00000744 => x"000016b7",
00000745 => x"00000793",
00000746 => x"ffe68693",
00000747 => x"04e6e463",
00000748 => x"00167613",
00000749 => x"0015f593",
00000750 => x"01879793",
00000751 => x"01e61613",
00000752 => x"00c7e7b3",
00000753 => x"01d59593",
00000754 => x"00b7e7b3",
00000755 => x"00e7e7b3",
00000756 => x"10000737",
00000757 => x"00e7e7b3",
00000758 => x"faf02023",
00000759 => x"00008067",
00000760 => x"00170793",
00000761 => x"01079713",
00000762 => x"40a686b3",
00000763 => x"01075713",
00000764 => x"fadff06f",
00000765 => x"ffe78513",
00000766 => x"0fd57513",
00000767 => x"00051a63",
00000768 => x"00375713",
00000769 => x"00178793",
00000770 => x"0ff7f793",
00000771 => x"fa1ff06f",
00000772 => x"00175713",
00000773 => x"ff1ff06f",
00000774 => x"fa002783",
00000775 => x"fe07cee3",
00000776 => x"faa02223",
00000777 => x"00008067",
00000778 => x"fa402503",
00000779 => x"fe055ee3",
00000780 => x"0ff57513",
00000781 => x"00008067",
00000782 => x"ff010113",
00000783 => x"00812423",
00000784 => x"01212023",
00000785 => x"00112623",
00000786 => x"00912223",
00000787 => x"00050413",
00000788 => x"00a00913",
00000789 => x"00044483",
00000790 => x"00140413",
00000791 => x"00049e63",
00000792 => x"00c12083",
00000793 => x"00812403",
00000794 => x"00412483",
00000795 => x"00012903",
00000796 => x"01010113",
00000797 => x"00008067",
00000798 => x"01249663",
00000799 => x"00d00513",
00000800 => x"f99ff0ef",
00000801 => x"00048513",
00000802 => x"f91ff0ef",
00000803 => x"fc9ff06f",
00000804 => x"00757513",
00000805 => x"00177793",
00000806 => x"01079793",
00000807 => x"0036f693",
00000808 => x"00a51513",
00000809 => x"00f56533",
00000810 => x"00167613",
00000811 => x"00e69793",
00000812 => x"0015f593",
00000813 => x"00f567b3",
00000814 => x"00d61613",
00000815 => x"00c7e7b3",
00000816 => x"00959593",
00000817 => x"fa800813",
00000818 => x"00b7e7b3",
00000819 => x"00082023",
00000820 => x"1007e793",
00000821 => x"00f82023",
00000822 => x"00008067",
00000823 => x"fa800713",
00000824 => x"00072683",
00000825 => x"00757793",
00000826 => x"00100513",
00000827 => x"00f51533",
00000828 => x"00d56533",
00000829 => x"00a72023",
00000830 => x"00008067",
00000831 => x"fa800713",
00000832 => x"00072683",
00000833 => x"00757513",
00000834 => x"00100793",
00000835 => x"00a797b3",
00000836 => x"fff7c793",
00000837 => x"00d7f7b3",
00000838 => x"00f72023",
00000839 => x"00008067",
00000840 => x"faa02623",
00000841 => x"fa802783",
00000842 => x"fe07cee3",
00000843 => x"fac02503",
00000824 => x"00072783",
00000825 => x"eff7f793",
00000826 => x"00f72023",
00000827 => x"00008067",
00000828 => x"fa800713",
00000829 => x"00072683",
00000830 => x"00757793",
00000831 => x"00100513",
00000832 => x"00f51533",
00000833 => x"00d56533",
00000834 => x"00a72023",
00000835 => x"00008067",
00000836 => x"fa800713",
00000837 => x"00072683",
00000838 => x"00757513",
00000839 => x"00100793",
00000840 => x"00a797b3",
00000841 => x"fff7c793",
00000842 => x"00d7f7b3",
00000843 => x"00f72023",
00000844 => x"00008067",
00000845 => x"f8400713",
00000846 => x"00072683",
00000847 => x"00f57793",
00000848 => x"00100513",
00000849 => x"00f51533",
00000850 => x"00d54533",
00000851 => x"00a72023",
00000852 => x"00008067",
00000853 => x"f8a02223",
00000854 => x"00008067",
00000855 => x"fb800713",
00000856 => x"00072783",
00000857 => x"ffe7f793",
00000858 => x"00f72023",
00000845 => x"faa02623",
00000846 => x"fa802783",
00000847 => x"fe07cee3",
00000848 => x"fac02503",
00000849 => x"00008067",
00000850 => x"f8400713",
00000851 => x"00072683",
00000852 => x"00f57793",
00000853 => x"00100513",
00000854 => x"00f51533",
00000855 => x"00d54533",
00000856 => x"00a72023",
00000857 => x"00008067",
00000858 => x"f8a02223",
00000859 => x"00008067",
00000860 => x"30046073",
00000861 => x"00008067",
00000862 => x"30047073",
00000863 => x"00008067",
00000864 => x"fb000713",
00000865 => x"00072783",
00000866 => x"ff77f793",
00000867 => x"00f72023",
00000860 => x"fb800713",
00000861 => x"00072783",
00000862 => x"ffe7f793",
00000863 => x"00f72023",
00000864 => x"00008067",
00000865 => x"30046073",
00000866 => x"00008067",
00000867 => x"30047073",
00000868 => x"00008067",
00000869 => x"f8800713",
00000869 => x"fb000713",
00000870 => x"00072783",
00000871 => x"fef7f793",
00000871 => x"ff77f793",
00000872 => x"00f72023",
00000873 => x"00008067",
00000874 => x"69617641",
00000875 => x"6c62616c",
00000876 => x"4d432065",
00000877 => x"0a3a7344",
00000878 => x"203a6820",
00000879 => x"706c6548",
00000880 => x"3a72200a",
00000881 => x"73655220",
00000882 => x"74726174",
00000883 => x"3a75200a",
00000884 => x"6c705520",
00000885 => x"0a64616f",
00000886 => x"203a7320",
00000887 => x"726f7453",
00000888 => x"6f742065",
00000889 => x"616c6620",
00000890 => x"200a6873",
00000891 => x"4c203a6c",
00000892 => x"2064616f",
00000893 => x"6d6f7266",
00000874 => x"f8800713",
00000875 => x"00072783",
00000876 => x"fef7f793",
00000877 => x"00f72023",
00000878 => x"00008067",
00000879 => x"69617641",
00000880 => x"6c62616c",
00000881 => x"4d432065",
00000882 => x"0a3a7344",
00000883 => x"203a6820",
00000884 => x"706c6548",
00000885 => x"3a72200a",
00000886 => x"73655220",
00000887 => x"74726174",
00000888 => x"3a75200a",
00000889 => x"6c705520",
00000890 => x"0a64616f",
00000891 => x"203a7320",
00000892 => x"726f7453",
00000893 => x"6f742065",
00000894 => x"616c6620",
00000895 => x"200a6873",
00000896 => x"45203a65",
00000897 => x"75636578",
00000898 => x"00006574",
00000899 => x"65206f4e",
00000900 => x"75636578",
00000901 => x"6c626174",
00000902 => x"76612065",
00000903 => x"616c6961",
00000904 => x"2e656c62",
00000905 => x"00000000",
00000906 => x"746f6f42",
00000907 => x"2e676e69",
00000908 => x"0a0a2e2e",
00000909 => x"00000000",
00000910 => x"52450a07",
00000911 => x"00005f52",
00000912 => x"6e6b6e75",
00000913 => x"006e776f",
00000914 => x"00007830",
00000915 => x"58450a0a",
00000916 => x"54504543",
00000917 => x"3a4e4f49",
00000918 => x"00000020",
00000919 => x"30204020",
00000920 => x"00000078",
00000921 => x"69617741",
00000922 => x"676e6974",
00000923 => x"6f656e20",
00000924 => x"32337672",
00000925 => x"6578655f",
00000926 => x"6e69622e",
00000927 => x"202e2e2e",
00000928 => x"00000000",
00000929 => x"64616f4c",
00000930 => x"2e676e69",
00000931 => x"00202e2e",
00000932 => x"00004b4f",
00000933 => x"74697257",
00000934 => x"78302065",
00000935 => x"00000000",
00000936 => x"74796220",
00000937 => x"74207365",
00000938 => x"5053206f",
00000939 => x"6c662049",
00000940 => x"20687361",
00000941 => x"78302040",
00000942 => x"00000000",
00000943 => x"7928203f",
00000944 => x"20296e2f",
00000945 => x"00000000",
00000946 => x"616c460a",
00000947 => x"6e696873",
00000948 => x"2e2e2e67",
00000949 => x"00000020",
00000950 => x"0a0a0a0a",
00000951 => x"4e203c3c",
00000952 => x"56524f45",
00000953 => x"42203233",
00000954 => x"6c746f6f",
00000955 => x"6564616f",
00000956 => x"3e3e2072",
00000957 => x"4c420a0a",
00000958 => x"203a5644",
00000959 => x"206e754a",
00000960 => x"32203732",
00000961 => x"0a303230",
00000962 => x"3a565748",
00000963 => x"00002020",
00000964 => x"4b4c430a",
00000965 => x"0020203a",
00000966 => x"0a7a4820",
00000967 => x"4153494d",
00000968 => x"0000203a",
00000969 => x"4e4f430a",
00000970 => x"00203a46",
00000971 => x"454d490a",
00000972 => x"00203a4d",
00000973 => x"74796220",
00000974 => x"40207365",
00000975 => x"00000020",
00000976 => x"454d440a",
00000977 => x"00203a4d",
00000978 => x"75410a0a",
00000979 => x"6f626f74",
00000980 => x"6920746f",
00000981 => x"3828206e",
00000982 => x"202e7329",
00000983 => x"73657250",
00000984 => x"656b2073",
00000985 => x"6f742079",
00000986 => x"6f626120",
00000987 => x"0a2e7472",
00000988 => x"00000000",
00000989 => x"0000000a",
00000990 => x"726f6241",
00000991 => x"2e646574",
00000992 => x"00000a0a",
00000993 => x"444d430a",
00000994 => x"00203e3a",
00000995 => x"53207962",
00000996 => x"68706574",
00000997 => x"4e206e61",
00000998 => x"69746c6f",
00000999 => x"0000676e",
00001000 => x"61766e49",
00001001 => x"2064696c",
00001002 => x"00444d43",
00001003 => x"33323130",
00001004 => x"37363534",
00001005 => x"42413938",
00001006 => x"46454443",
00000896 => x"4c203a6c",
00000897 => x"2064616f",
00000898 => x"6d6f7266",
00000899 => x"616c6620",
00000900 => x"200a6873",
00000901 => x"45203a65",
00000902 => x"75636578",
00000903 => x"00006574",
00000904 => x"65206f4e",
00000905 => x"75636578",
00000906 => x"6c626174",
00000907 => x"76612065",
00000908 => x"616c6961",
00000909 => x"2e656c62",
00000910 => x"00000000",
00000911 => x"746f6f42",
00000912 => x"2e676e69",
00000913 => x"0a0a2e2e",
00000914 => x"00000000",
00000915 => x"52450a07",
00000916 => x"00005f52",
00000917 => x"6e6b6e75",
00000918 => x"006e776f",
00000919 => x"00007830",
00000920 => x"58450a0a",
00000921 => x"54504543",
00000922 => x"3a4e4f49",
00000923 => x"00000020",
00000924 => x"30204020",
00000925 => x"00000078",
00000926 => x"69617741",
00000927 => x"676e6974",
00000928 => x"6f656e20",
00000929 => x"32337672",
00000930 => x"6578655f",
00000931 => x"6e69622e",
00000932 => x"202e2e2e",
00000933 => x"00000000",
00000934 => x"64616f4c",
00000935 => x"2e676e69",
00000936 => x"00202e2e",
00000937 => x"00004b4f",
00000938 => x"74697257",
00000939 => x"78302065",
00000940 => x"00000000",
00000941 => x"74796220",
00000942 => x"74207365",
00000943 => x"5053206f",
00000944 => x"6c662049",
00000945 => x"20687361",
00000946 => x"78302040",
00000947 => x"00000000",
00000948 => x"7928203f",
00000949 => x"20296e2f",
00000950 => x"00000000",
00000951 => x"616c460a",
00000952 => x"6e696873",
00000953 => x"2e2e2e67",
00000954 => x"00000020",
00000955 => x"0a0a0a0a",
00000956 => x"4e203c3c",
00000957 => x"56524f45",
00000958 => x"42203233",
00000959 => x"6c746f6f",
00000960 => x"6564616f",
00000961 => x"3e3e2072",
00000962 => x"4c420a0a",
00000963 => x"203a5644",
00000964 => x"206c754a",
00000965 => x"32203520",
00000966 => x"0a303230",
00000967 => x"3a565748",
00000968 => x"00002020",
00000969 => x"4b4c430a",
00000970 => x"0020203a",
00000971 => x"0a7a4820",
00000972 => x"4449484d",
00000973 => x"0000203a",
00000974 => x"53494d0a",
00000975 => x"00203a41",
00000976 => x"4e4f430a",
00000977 => x"00203a46",
00000978 => x"454d490a",
00000979 => x"00203a4d",
00000980 => x"74796220",
00000981 => x"40207365",
00000982 => x"00000020",
00000983 => x"454d440a",
00000984 => x"00203a4d",
00000985 => x"75410a0a",
00000986 => x"6f626f74",
00000987 => x"6920746f",
00000988 => x"3828206e",
00000989 => x"202e7329",
00000990 => x"73657250",
00000991 => x"656b2073",
00000992 => x"6f742079",
00000993 => x"6f626120",
00000994 => x"0a2e7472",
00000995 => x"00000000",
00000996 => x"0000000a",
00000997 => x"726f6241",
00000998 => x"2e646574",
00000999 => x"00000a0a",
00001000 => x"444d430a",
00001001 => x"00203e3a",
00001002 => x"53207962",
00001003 => x"68706574",
00001004 => x"4e206e61",
00001005 => x"69746c6f",
00001006 => x"0000676e",
00001007 => x"61766e49",
00001008 => x"2064696c",
00001009 => x"00444d43",
00001010 => x"33323130",
00001011 => x"37363534",
00001012 => x"42413938",
00001013 => x"46454443",
others => x"00000000"
);
 
/rtl/core/neorv32_cpu.vhd
53,6 → 53,7
CLOCK_FREQUENCY : natural := 0; -- clock frequency of clk_i in Hz
HART_ID : std_ulogic_vector(31 downto 0) := x"00000000"; -- custom hardware thread ID
BOOTLOADER_USE : boolean := true; -- implement processor-internal bootloader?
CSR_COUNTERS_USE : boolean := true; -- implement RISC-V perf. counters ([m]instret[h], [m]cycle[h], time[h])?
-- RISC-V CPU Extensions --
CPU_EXTENSION_RISCV_C : boolean := false; -- implement compressed extension?
CPU_EXTENSION_RISCV_E : boolean := false; -- implement embedded RF extension?
109,8 → 110,6
signal ctrl : std_ulogic_vector(ctrl_width_c-1 downto 0); -- main control bus
signal alu_cmp : std_ulogic_vector(1 downto 0); -- alu comparator result
signal imm : std_ulogic_vector(data_width_c-1 downto 0); -- immediate
signal pc : std_ulogic_vector(data_width_c-1 downto 0); -- current program counter
signal pc_delayed : std_ulogic_vector(data_width_c-1 downto 0); -- delayed program counter
signal instr : std_ulogic_vector(data_width_c-1 downto 0); -- new instruction
signal rs1, rs2 : std_ulogic_vector(data_width_c-1 downto 0); -- source registers
signal alu_res : std_ulogic_vector(data_width_c-1 downto 0); -- alu result
127,6 → 126,10
signal be_load : std_ulogic; -- bus error on load data access
signal be_store : std_ulogic; -- bus error on store data access
signal bus_exc_ack : std_ulogic; -- bus exception error acknowledge
signal bus_busy : std_ulogic; -- bus unit is busy
signal fetch_pc : std_ulogic_vector(data_width_c-1 downto 0); -- pc for instruction fetch
signal curr_pc : std_ulogic_vector(data_width_c-1 downto 0); -- current pc (for current executed instruction)
signal next_pc : std_ulogic_vector(data_width_c-1 downto 0); -- next pc (for current executed instruction)
 
-- co-processor interface --
signal cp0_data, cp1_data : std_ulogic_vector(data_width_c-1 downto 0);
139,9 → 142,10
neorv32_cpu_control_inst: neorv32_cpu_control
generic map (
-- General --
CLOCK_FREQUENCY => CLOCK_FREQUENCY, -- clock frequency of clk_i in Hz
HART_ID => HART_ID, -- custom hardware thread ID
BOOTLOADER_USE => BOOTLOADER_USE, -- implement processor-internal bootloader?
CLOCK_FREQUENCY => CLOCK_FREQUENCY, -- clock frequency of clk_i in Hz
HART_ID => HART_ID, -- custom hardware thread ID
BOOTLOADER_USE => BOOTLOADER_USE, -- implement processor-internal bootloader?
CSR_COUNTERS_USE => CSR_COUNTERS_USE, -- implement RISC-V perf. counters ([m]instret[h], [m]cycle[h], time[h])?
-- RISC-V CPU Extensions --
CPU_EXTENSION_RISCV_C => CPU_EXTENSION_RISCV_C, -- implement compressed extension?
CPU_EXTENSION_RISCV_E => CPU_EXTENSION_RISCV_E, -- implement embedded RF extension?
186,8 → 190,9
alu_add_i => alu_add, -- ALU.add result
-- data output --
imm_o => imm, -- immediate
pc_o => pc, -- current PC
alu_pc_o => pc_delayed, -- delayed PC for ALU
fetch_pc_o => fetch_pc, -- PC for instruction fetch
curr_pc_o => curr_pc, -- current PC (corresponding to current instruction)
next_pc_o => next_pc, -- next PC (corresponding to current instruction)
-- csr interface --
csr_wdata_i => alu_res, -- CSR write data
csr_rdata_o => csr_rdata, -- CSR read data
202,7 → 207,8
be_instr_i => be_instr, -- bus error on instruction access
be_load_i => be_load, -- bus error on load data access
be_store_i => be_store, -- bus error on store data access
bus_exc_ack_o => bus_exc_ack -- bus exception error acknowledge
bus_exc_ack_o => bus_exc_ack, -- bus exception error acknowledge
bus_busy_i => bus_busy -- bus unit is busy
);
 
 
220,7 → 226,7
mem_i => rdata, -- memory read data
alu_i => alu_res, -- ALU result
csr_i => csr_rdata, -- CSR read data
pc_i => pc, -- current pc
pc_i => next_pc, -- next pc
-- data output --
rs1_o => rs1, -- operand 1
rs2_o => rs2 -- operand 2
230,10 → 236,6
-- ALU ------------------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
neorv32_cpu_alu_inst: neorv32_cpu_alu
generic map (
CPU_EXTENSION_RISCV_C => CPU_EXTENSION_RISCV_C, -- implement compressed extension?
CPU_EXTENSION_RISCV_M => CPU_EXTENSION_RISCV_M -- implement mul/div extension?
)
port map (
-- global control --
clk_i => clk_i, -- global clock, rising edge
242,8 → 244,7
-- data input --
rs1_i => rs1, -- rf source 1
rs2_i => rs2, -- rf source 2
pc_i => pc, -- current PC
pc2_i => pc_delayed, -- delayed PC
pc2_i => curr_pc, -- delayed PC
imm_i => imm, -- immediate
csr_i => csr_rdata, -- csr read data
-- data output --
296,8 → 297,7
-- -------------------------------------------------------------------------------------------
neorv32_cpu_bus_inst: neorv32_cpu_bus
generic map (
CPU_EXTENSION_RISCV_C => CPU_EXTENSION_RISCV_C, -- implement compressed extension?
MEM_EXT_TIMEOUT => MEM_EXT_TIMEOUT -- cycles after which a valid bus access will timeout
MEM_EXT_TIMEOUT => MEM_EXT_TIMEOUT -- cycles after which a valid bus access will timeout
)
port map (
-- global control --
306,7 → 306,7
ctrl_i => ctrl, -- main control bus
-- data input --
wdata_i => rs2, -- write data
pc_i => pc, -- current PC
pc_i => fetch_pc, -- current PC for instruction fetch
alu_i => alu_res, -- ALU result
-- data output --
instr_o => instr, -- instruction
320,6 → 320,7
be_load_o => be_load, -- bus error on load data access
be_store_o => be_store, -- bus error on store data access
bus_wait_o => bus_wait, -- wait for bus operation to finish
bus_busy_o => bus_busy, -- bus unit is busy
exc_ack_i => bus_exc_ack, -- exception controller ACK
-- bus system --
bus_addr_o => bus_addr_o, -- bus access address
/rtl/core/neorv32_cpu_alu.vhd
42,10 → 42,6
use neorv32.neorv32_package.all;
 
entity neorv32_cpu_alu is
generic (
CPU_EXTENSION_RISCV_C : boolean := false; -- implement compressed extension?
CPU_EXTENSION_RISCV_M : boolean := false -- implement mul/div extension?
);
port (
-- global control --
clk_i : in std_ulogic; -- global clock, rising edge
54,7 → 50,6
-- data input --
rs1_i : in std_ulogic_vector(data_width_c-1 downto 0); -- rf source 1
rs2_i : in std_ulogic_vector(data_width_c-1 downto 0); -- rf source 2
pc_i : in std_ulogic_vector(data_width_c-1 downto 0); -- current PC
pc2_i : in std_ulogic_vector(data_width_c-1 downto 0); -- delayed PC
imm_i : in std_ulogic_vector(data_width_c-1 downto 0); -- immediate
csr_i : in std_ulogic_vector(data_width_c-1 downto 0); -- csr read data
75,7 → 70,7
architecture neorv32_cpu_cpu_rtl of neorv32_cpu_alu is
 
-- operands --
signal opa, opb, opc, pc_inc : std_ulogic_vector(data_width_c-1 downto 0);
signal opa, opb, opc : std_ulogic_vector(data_width_c-1 downto 0);
 
-- results --
signal add_res : std_ulogic_vector(data_width_c-1 downto 0);
109,22 → 104,28
 
-- Operand Mux ----------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
input_op_mux: process(ctrl_i, csr_i, pc2_i, pc_i, rs1_i, rs2_i, imm_i, pc_inc)
input_op_mux: process(ctrl_i, csr_i, pc2_i, rs1_i, rs2_i, imm_i)
begin
-- opa (first ALU input operand) --
case ctrl_i(ctrl_alu_opa_mux_msb_c downto ctrl_alu_opa_mux_lsb_c) is
when "00" => opa <= rs1_i;
when "01" => opa <= pc2_i;
when "10" => opa <= csr_i;
when others => opa <= pc_i;
end case;
if (ctrl_i(ctrl_alu_opa_mux_msb_c) = '0') then
if (ctrl_i(ctrl_alu_opa_mux_lsb_c) = '0') then
opa <= rs1_i;
else
opa <= pc2_i;
end if;
else
opa <= csr_i;
end if;
-- opb (second ALU input operand) --
case ctrl_i(ctrl_alu_opb_mux_msb_c downto ctrl_alu_opb_mux_lsb_c) is
when "00" => opb <= rs2_i;
when "01" => opb <= imm_i;
when "10" => opb <= rs1_i;
when others => opb <= pc_inc;
end case;
if (ctrl_i(ctrl_alu_opb_mux_msb_c) = '0') then
if (ctrl_i(ctrl_alu_opb_mux_lsb_c) = '0') then
opb <= rs2_i;
else
opb <= imm_i;
end if;
else
opb <= rs1_i;
end if;
-- opc (second operand for comparison (and SUB)) --
if (ctrl_i(ctrl_alu_opc_mux_c) = '0') then
opc <= imm_i;
133,10 → 134,7
end if;
end process input_op_mux;
 
-- PC increment --
pc_inc <= x"00000002" when (CPU_EXTENSION_RISCV_C = true) else x"00000004";
 
 
-- Comparator Unit ------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- less than (x < y) --
202,7 → 200,7
cp_rb_ff0 <= '0';
cp_rb_ff1 <= '0';
elsif rising_edge(clk_i) then
if (CPU_EXTENSION_RISCV_M = true) then
if (ctrl_i(ctrl_sys_m_ext_en_c) = '1') then
cp_cmd_ff <= ctrl_i(ctrl_cp_use_c);
cp_rb_ff0 <= '0';
cp_rb_ff1 <= cp_rb_ff0;
/rtl/core/neorv32_cpu_bus.vhd
43,8 → 43,7
 
entity neorv32_cpu_bus is
generic (
CPU_EXTENSION_RISCV_C : boolean := false; -- implement compressed extension?
MEM_EXT_TIMEOUT : natural := 15 -- cycles after which a valid bus access will timeout
MEM_EXT_TIMEOUT : natural := 15 -- cycles after which a valid bus access will timeout
);
port (
-- global control --
67,6 → 66,7
be_load_o : out std_ulogic; -- bus error on load data access
be_store_o : out std_ulogic; -- bus error on store data access
bus_wait_o : out std_ulogic; -- wait for bus operation to finish
bus_busy_o : out std_ulogic; -- bus unit is busy
exc_ack_i : in std_ulogic; -- exception controller ACK
-- bus system --
bus_addr_o : out std_ulogic_vector(data_width_c-1 downto 0); -- bus access address
113,7 → 113,7
end process mem_adr_reg;
 
-- address output --
bus_addr_o <= pc_i when (ctrl_i(ctrl_bus_if_c) = '1') else mar; -- is instruction fetch?
bus_addr_o <= pc_i when ((bus_if_req or ctrl_i(ctrl_bus_if_c)) = '1') else mar; -- is instruction fetch?
mar_o <= mar;
 
-- write request output --
120,7 → 120,7
bus_we_o <= ctrl_i(ctrl_bus_wr_c) and (not misaligned_data);
 
-- read request output (also used for instruction fetch) --
bus_re_o <= (ctrl_i(ctrl_bus_rd_c) and (not misaligned_data)) or (ctrl_i(ctrl_bus_if_c) and (not misaligned_instr));
bus_re_o <= (ctrl_i(ctrl_bus_rd_c) and (not misaligned_data)) or ((bus_if_req or ctrl_i(ctrl_bus_if_c)) and (not misaligned_instr));
 
 
-- Write Data -----------------------------------------------------------------------------
263,6 → 263,7
ma_store_o <= bus_wr_req and align_err;
 
-- wait for bus --
bus_busy_o <= bus_busy;
bus_wait_o <= bus_busy and (not bus_ack_i); -- FIXME: 'async' ack
 
 
290,11 → 291,9
begin
-- check instruction access --
misaligned_instr <= '0'; -- default
if (CPU_EXTENSION_RISCV_C = true) then -- 16-bit instruction access only
if (pc_i(0) /= '0') then
misaligned_instr <= '1';
end if;
else -- 32-bit instruction access only
if (ctrl_i(ctrl_sys_c_ext_en_c) = '1') then -- 16-bit and 32-bit instruction accesses
misaligned_instr <= '0';
else -- 32-bit instruction accesses only
if (pc_i(1 downto 0) /= "00") then
misaligned_instr <= '1';
end if;
/rtl/core/neorv32_cpu_control.vhd
1,8 → 1,9
-- #################################################################################################
-- # << NEORV32 - CPU Control >> #
-- # ********************************************************************************************* #
-- # FSM to control CPU operations. This unit also includes the control and status registers (CSR) #
-- # and the interrupt and exception controller. #
-- # CPU operation is split into a fetch engine (responsible for fetching an decompressing instr- #
-- # uctions), an execute engine (responsible for actually executing the instructions), an inter- #
-- # rupt and exception handling controller and the RISC-V status and control registers (CSRs). #
-- # ********************************************************************************************* #
-- # BSD 3-Clause License #
-- # #
48,6 → 49,7
CLOCK_FREQUENCY : natural := 0; -- clock frequency of clk_i in Hz
HART_ID : std_ulogic_vector(31 downto 0) := x"00000000"; -- custom hardware thread ID
BOOTLOADER_USE : boolean := true; -- implement processor-internal bootloader?
CSR_COUNTERS_USE : boolean := true; -- implement RISC-V perf. counters ([m]instret[h], [m]cycle[h], time[h])?
-- RISC-V CPU Extensions --
CPU_EXTENSION_RISCV_C : boolean := false; -- implement compressed extension?
CPU_EXTENSION_RISCV_E : boolean := false; -- implement embedded RF extension?
92,8 → 94,9
alu_add_i : in std_ulogic_vector(data_width_c-1 downto 0); -- ALU.add result
-- data output --
imm_o : out std_ulogic_vector(data_width_c-1 downto 0); -- immediate
pc_o : out std_ulogic_vector(data_width_c-1 downto 0); -- current PC
alu_pc_o : out std_ulogic_vector(data_width_c-1 downto 0); -- delayed PC for ALU
fetch_pc_o : out std_ulogic_vector(data_width_c-1 downto 0); -- PC for instruction fetch
curr_pc_o : out std_ulogic_vector(data_width_c-1 downto 0); -- current PC (corresponding to current instruction)
next_pc_o : out std_ulogic_vector(data_width_c-1 downto 0); -- next PC (corresponding to current instruction)
-- csr data interface --
csr_wdata_i : in std_ulogic_vector(data_width_c-1 downto 0); -- CSR write data
csr_rdata_o : out std_ulogic_vector(data_width_c-1 downto 0); -- CSR read data
108,90 → 111,151
be_instr_i : in std_ulogic; -- bus error on instruction access
be_load_i : in std_ulogic; -- bus error on load data access
be_store_i : in std_ulogic; -- bus error on store data access
bus_exc_ack_o : out std_ulogic -- bus exception error acknowledge
bus_exc_ack_o : out std_ulogic; -- bus exception error acknowledge
bus_busy_i : in std_ulogic -- bus unit is busy
);
end neorv32_cpu_control;
 
architecture neorv32_cpu_control_rtl of neorv32_cpu_control is
 
-- state machine --
type state_t is (IFETCH_0, IFETCH_1, IFETCH_2, IFETCH_3, IFETCH_4, IFETCH_5, IFETCH_6, EXECUTE,
ALU_WAIT, STORE_0, LOAD_0, LOADSTORE_0, LOADSTORE_1, CSR_ACCESS, SLEEP);
signal state, state_nxt : state_t;
signal ctrl_nxt, ctrl : std_ulogic_vector(ctrl_width_c-1 downto 0);
signal hw_control : std_ulogic_vector(data_width_c-1 downto 0);
-- instruction fetch enginge --
type fetch_engine_state_t is (IFETCH_RESET, IFETCH_0, IFETCH_1, IFETCH_2, IFETCH_3);
type fetch_engine_t is record
state : fetch_engine_state_t;
state_nxt : fetch_engine_state_t;
i_buf : std_ulogic_vector(33 downto 0);
i_buf_nxt : std_ulogic_vector(33 downto 0);
i_buf2 : std_ulogic_vector(33 downto 0);
i_buf2_nxt : std_ulogic_vector(33 downto 0);
ci_reg : std_ulogic_vector(17 downto 0);
ci_reg_nxt : std_ulogic_vector(17 downto 0);
i_buf_state : std_ulogic_vector(01 downto 0);
i_buf_state_nxt : std_ulogic_vector(01 downto 0);
pc_real : std_ulogic_vector(data_width_c-1 downto 0);
pc_real_add : std_ulogic_vector(data_width_c-1 downto 0);
pc_fetch : std_ulogic_vector(data_width_c-1 downto 0);
pc_fetch_add : std_ulogic_vector(data_width_c-1 downto 0);
ci_return : std_ulogic;
ci_return_nxt : std_ulogic;
reset : std_ulogic;
bus_err_ack : std_ulogic;
end record;
signal fetch_engine : fetch_engine_t;
 
-- pre-decoder --
signal ci_instr32 : std_ulogic_vector(31 downto 0);
signal ci_valid : std_ulogic;
signal ci_illegal : std_ulogic;
 
-- instruction register --
signal i_reg, i_reg_nxt : std_ulogic_vector(31 downto 0);
signal i_buf, i_buf_nxt : std_ulogic_vector(15 downto 0);
signal ci_reg, ci_reg_nxt : std_ulogic_vector(15 downto 0);
signal iavail, iavail_nxt : std_ulogic;
signal is_ci, is_ci_nxt : std_ulogic; -- current instruction is COMPRESSED instruction flag
-- instrucion prefetch buffer (IPB) --
type ipb_t is record
wdata : std_ulogic_vector(34 downto 0);
rdata : std_ulogic_vector(34 downto 0);
waddr : std_ulogic_vector(31 downto 0);
raddr : std_ulogic_vector(31 downto 0);
status : std_ulogic;
free : std_ulogic;
avail : std_ulogic;
we : std_ulogic;
re : std_ulogic;
clear : std_ulogic;
end record;
signal ipb : ipb_t;
 
-- immediates --
signal imm_reg : std_ulogic_vector(data_width_c-1 downto 0);
-- instruction execution engine --
type execute_engine_state_t is (IDLE, DISPATCH, TRAP, EXECUTE, ALU_WAIT, BRANCH, STORE, LOAD, LOADSTORE_0, LOADSTORE_1, CSR_ACCESS);
type execute_engine_t is record
state : execute_engine_state_t;
state_nxt : execute_engine_state_t;
state_prev : execute_engine_state_t;
i_reg : std_ulogic_vector(31 downto 0);
i_reg_nxt : std_ulogic_vector(31 downto 0);
is_ci : std_ulogic; -- current instruction is de-compressed instruction
is_ci_nxt : std_ulogic;
is_jump : std_ulogic; -- current instruction is jump instruction
is_jump_nxt : std_ulogic;
branch_taken : std_ulogic; -- branch condition fullfilled
pc : std_ulogic_vector(data_width_c-1 downto 0); -- actual PC, corresponding to current executed instruction
pc_nxt : std_ulogic_vector(data_width_c-1 downto 0);
next_pc : std_ulogic_vector(data_width_c-1 downto 0); -- next PC, corresponding to next instruction to be executed
last_pc : std_ulogic_vector(data_width_c-1 downto 0); -- PC of last executed instruction
end record;
signal execute_engine : execute_engine_t;
 
-- branch system --
signal is_branch : std_ulogic;
signal is_branch_nxt : std_ulogic;
signal branch_taken : std_ulogic;
-- trap controller --
type trap_ctrl_t is record
exc_buf : std_ulogic_vector(exception_width_c-1 downto 0);
exc_fire : std_ulogic; -- set if there is a valid source in the exception buffer
irq_buf : std_ulogic_vector(interrupt_width_c-1 downto 0);
irq_fire : std_ulogic; -- set if there is a valid source in the interrupt buffer
exc_ack : std_ulogic; -- acknowledge all exceptions
irq_ack : std_ulogic_vector(interrupt_width_c-1 downto 0); -- acknowledge specific interrupt
irq_ack_nxt : std_ulogic_vector(interrupt_width_c-1 downto 0);
cause : std_ulogic_vector(data_width_c-1 downto 0); -- trap ID (for "mcause")
cause_nxt : std_ulogic_vector(data_width_c-1 downto 0);
instr : std_ulogic_vector(31 downto 0); -- faulting instruction
exc_src : std_ulogic_vector(exception_width_c-1 downto 0);
--
env_start : std_ulogic; -- start trap handler env
env_start_ack : std_ulogic; -- start of trap handler acknowledged
env_end : std_ulogic; -- end trap handler env
--
instr_be : std_ulogic; -- instruction fetch bus error
instr_ma : std_ulogic; -- instruction fetch misaligned address
instr_il : std_ulogic; -- illegal instruction
env_call : std_ulogic;
break_point : std_ulogic;
end record;
signal trap_ctrl : trap_ctrl_t;
-- CPU control signals --
signal ctrl_nxt, ctrl : std_ulogic_vector(ctrl_width_c-1 downto 0);
 
-- program counter --
signal pc_reg : std_ulogic_vector(data_width_c-1 downto 0); -- actual PC
signal pc_backup_reg : std_ulogic_vector(data_width_c-1 downto 0); -- delayed PC (for ALU operations)
signal pc_backup2_reg : std_ulogic_vector(data_width_c-1 downto 0); -- delayed delayed PC (for exception handling)
signal mepc : std_ulogic_vector(data_width_c-1 downto 0); -- exception PC
-- fast bus access --
signal bus_fast_ir : std_ulogic;
signal bus_fast_rd : std_ulogic;
signal bus_fast_wr : std_ulogic;
 
-- irq controller --
signal exc_buf : std_ulogic_vector(exception_width_c-1 downto 0);
signal exc_ack : std_ulogic;
signal exc_src : std_ulogic_vector(exception_width_c-1 downto 0);
signal exc_fire : std_ulogic;
signal irq_buf : std_ulogic_vector(interrupt_width_c-1 downto 0);
signal irq_ack : std_ulogic_vector(interrupt_width_c-1 downto 0);
signal irq_ack_nxt : std_ulogic_vector(interrupt_width_c-1 downto 0);
signal irq_fire : std_ulogic;
signal exc_cpu_start : std_ulogic; -- starting exception env
signal exc_cpu_ack : std_ulogic; -- starting of exception env acknowledge
signal exc_cpu_end : std_ulogic; -- exiting eception env
signal exc_cause : std_ulogic_vector(data_width_c-1 downto 0);
signal exc_cause_nxt : std_ulogic_vector(data_width_c-1 downto 0);
-- RISC-V control and status registers (CSRs) --
type csr_t is record
we : std_ulogic; -- write enable
we_nxt : std_ulogic;
re : std_ulogic; -- read enable
re_nxt : std_ulogic;
mstatus_mie : std_ulogic; -- mstatus.MIE: global IRQ enable (R/W)
mstatus_mpie : std_ulogic; -- mstatus.MPIE: previous global IRQ enable (R/-)
mip_msip : std_ulogic; -- mip.MSIP: machine software interrupt pending (R/W)
mie_msie : std_ulogic; -- mie.MSIE: machine software interrupt enable (R/W)
mie_meie : std_ulogic; -- mie.MEIE: machine external interrupt enable (R/W)
mie_mtie : std_ulogic; -- mie.MEIE: machine timer interrupt enable (R/W)
mepc : std_ulogic_vector(data_width_c-1 downto 0); -- mepc: machine exception pc (R/W)
mcause : std_ulogic_vector(data_width_c-1 downto 0); -- mcause: machine trap cause (R/-)
mtvec : std_ulogic_vector(data_width_c-1 downto 0); -- mtvec: machine trap-handler base address (R/W)
mtval : std_ulogic_vector(data_width_c-1 downto 0); -- mtval: machine bad address or isntruction (R/-)
mscratch : std_ulogic_vector(data_width_c-1 downto 0); -- mscratch: scratch register (R/W)
mtinst : std_ulogic_vector(data_width_c-1 downto 0); -- mtinst: machine trap instruction (transformed) (R/-)
cycle : std_ulogic_vector(32 downto 0); -- cycle, mtime (R/-), plus carry bit
instret : std_ulogic_vector(32 downto 0); -- instret (R/-), plus carry bit
cycleh : std_ulogic_vector(31 downto 0); -- cycleh, mtimeh (R/-)
instreth : std_ulogic_vector(31 downto 0); -- instreth (R/-)
misa_c_en : std_ulogic; -- misa: C extension enable bit (R/W)
misa_m_en : std_ulogic; -- misa: M extension enable bit (R/W)
end record;
signal csr : csr_t;
 
-- RISC-V CSRs --
signal mstatus_mie : std_ulogic; -- mstatus.MIE: global IRQ enable (R/W)
signal mstatus_mpie : std_ulogic; -- mstatus.MPIE: previous global IRQ enable (R/-)
signal mip_msip : std_ulogic; -- mip.MSIP: machine software interrupt pending (R/W)
signal mie_msie : std_ulogic; -- mie.MSIE: machine software interrupt enable (R/W)
signal mie_meie : std_ulogic; -- mie.MEIE: machine external interrupt enable (R/W)
signal mie_mtie : std_ulogic; -- mie.MEIE: machine timer interrupt enable (R/W)
signal mtvec : std_ulogic_vector(data_width_c-1 downto 0); -- mtvec: machine trap-handler base address (R/W)
signal mtval : std_ulogic_vector(data_width_c-1 downto 0); -- mtval: machine bad address or isntruction (R/-)
signal mscratch : std_ulogic_vector(data_width_c-1 downto 0); -- mscratch: scratch register (R/W)
signal mtinst : std_ulogic_vector(data_width_c-1 downto 0); -- mtinst: machine trap instruction (transformed) (R/-)
signal cycle_lo : std_ulogic_vector(32 downto 0); -- cycle, mtime (R/-)
signal instret_lo : std_ulogic_vector(32 downto 0); -- instret (R/-)
signal cycle_hi : std_ulogic_vector(15 downto 0); -- cycleh, mtimeh (R/-) - only 16-bit wide
signal instret_hi : std_ulogic_vector(15 downto 0); -- instreth (R/-) - only 16-bit wide
signal cycle_lo_msb : std_ulogic;
signal instret_lo_msb : std_ulogic;
signal cycle_msb : std_ulogic;
signal instret_msb : std_ulogic;
 
-- illegal instruction check ..
-- illegal instruction check --
signal illegal_instruction : std_ulogic;
signal illegal_register : std_ulogic; -- only for E-extension
signal illegal_compressed : std_ulogic; -- only fir C-extension
 
-- synchronous exceptions trigger --
signal illegal_instr_exc : std_ulogic;
signal env_call : std_ulogic;
signal break_point : std_ulogic;
 
begin
 
-- ****************************************************************************************************************************
-- Instruction Fetch
-- ****************************************************************************************************************************
 
-- Compressed Instructions Recoding -------------------------------------------------------
-- -------------------------------------------------------------------------------------------
neorv32_cpu_decompressor_inst_true:
199,9 → 263,8
neorv32_cpu_decompressor_inst: neorv32_cpu_decompressor
port map (
-- instruction input --
ci_instr16_i => ci_reg, -- compressed instruction input
ci_instr16_i => fetch_engine.ci_reg(15 downto 0), -- compressed instruction input
-- instruction output --
ci_valid_o => ci_valid, -- is a compressed instruction
ci_illegal_o => ci_illegal, -- is an illegal compressed instruction
ci_instr32_o => ci_instr32 -- 32-bit decompressed instruction
);
209,290 → 272,460
 
neorv32_cpu_decompressor_inst_false:
if (CPU_EXTENSION_RISCV_C = false) generate
ci_instr32 <= instr_i;
ci_valid <= '0';
ci_instr32 <= (others => '0');
ci_illegal <= '0';
end generate;
 
 
-- Fetch Engine FSM Sync ------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- for registers that require a specific reset state --
fetch_engine_fsm_sync_rst: process(rstn_i, clk_i)
begin
if (rstn_i = '0') then
fetch_engine.state <= IFETCH_RESET;
elsif rising_edge(clk_i) then
if (fetch_engine.reset = '1') then
fetch_engine.state <= IFETCH_RESET;
else
fetch_engine.state <= fetch_engine.state_nxt;
end if;
end if;
end process fetch_engine_fsm_sync_rst;
 
 
-- for registers that DO NOT require a specific reset state --
fetch_engine_fsm_sync: process(clk_i)
begin
if rising_edge(clk_i) then
if (fetch_engine.state = IFETCH_RESET) then
fetch_engine.pc_fetch <= execute_engine.pc(data_width_c-1 downto 1) & '0'; -- initialize with "real" application PC
fetch_engine.pc_real <= execute_engine.pc(data_width_c-1 downto 1) & '0'; -- initialize with "real" application PC
else
fetch_engine.pc_real <= std_ulogic_vector(unsigned(fetch_engine.pc_real(data_width_c-1 downto 1) & '0') + unsigned(fetch_engine.pc_real_add(data_width_c-1 downto 1) & '0'));
fetch_engine.pc_fetch <= std_ulogic_vector(unsigned(fetch_engine.pc_fetch(data_width_c-1 downto 1) & '0') + unsigned(fetch_engine.pc_fetch_add(data_width_c-1 downto 1) & '0'));
end if;
--
fetch_engine.i_buf <= fetch_engine.i_buf_nxt;
fetch_engine.i_buf2 <= fetch_engine.i_buf2_nxt;
fetch_engine.i_buf_state <= fetch_engine.i_buf_state_nxt;
--
fetch_engine.ci_reg <= fetch_engine.ci_reg_nxt;
fetch_engine.ci_return <= fetch_engine.ci_return_nxt;
end if;
end process fetch_engine_fsm_sync;
 
 
-- Fetch Engine FSM Comb ------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
fetch_engine_fsm_comb: process(fetch_engine, execute_engine, csr, ipb, instr_i, bus_wait_i, bus_busy_i, ci_instr32, be_instr_i, ma_instr_i)
begin
-- arbiter defaults --
fetch_engine.state_nxt <= fetch_engine.state;
fetch_engine.pc_fetch_add <= (others => '0');
fetch_engine.pc_real_add <= (others => '0');
bus_fast_ir <= '0';
fetch_engine.i_buf_nxt <= fetch_engine.i_buf;
fetch_engine.i_buf2_nxt <= fetch_engine.i_buf2;
fetch_engine.i_buf_state_nxt <= fetch_engine.i_buf_state;
fetch_engine.ci_reg_nxt <= fetch_engine.ci_reg;
fetch_engine.ci_return_nxt <= fetch_engine.ci_return;
fetch_engine.bus_err_ack <= '0';
 
-- instruction prefetch buffer interface --
ipb.we <= '0';
ipb.clear <= '0';
ipb.wdata <= fetch_engine.i_buf2(33 downto 32) & '0' & fetch_engine.i_buf2(31 downto 0);
ipb.waddr <= fetch_engine.pc_real(data_width_c-1 downto 1) & '0';
 
-- state machine --
case fetch_engine.state is
 
when IFETCH_RESET => -- reset engine, prefetch buffer, get PC
-- ------------------------------------------------------------
fetch_engine.i_buf_state_nxt <= (others => '0');
fetch_engine.ci_return_nxt <= '0';
ipb.clear <= '1'; -- clear instruction prefetch buffer
fetch_engine.bus_err_ack <= '1'; -- ack bus errors, the execute engine has to take care of them
fetch_engine.state_nxt <= IFETCH_0;
 
when IFETCH_0 => -- output current PC to bus system, request 32-bit word
-- ------------------------------------------------------------
if (bus_busy_i = '0') and (execute_engine.state /= LOAD) and (execute_engine.state /= STORE) and
(execute_engine.state /= LOADSTORE_0) and (execute_engine.state /= LOADSTORE_1) then -- wait if execute engine is using bus unit
bus_fast_ir <= '1'; -- fast instruction fetch request (output PC to bus.address)
fetch_engine.state_nxt <= IFETCH_1;
end if;
 
when IFETCH_1 => -- store data from memory to buffer(s)
-- ------------------------------------------------------------
fetch_engine.i_buf_nxt <= be_instr_i & ma_instr_i & instr_i(31 downto 0); -- store data word and exception info
if (bus_wait_i = '0') then -- wait for bus response
fetch_engine.i_buf2_nxt <= fetch_engine.i_buf;
fetch_engine.i_buf_state_nxt(1) <= fetch_engine.i_buf_state(0);
fetch_engine.state_nxt <= IFETCH_2;
end if;
fetch_engine.i_buf_state_nxt(0) <= '1';
if (be_instr_i = '1') or (ma_instr_i = '1') then -- any fetch exception?
fetch_engine.bus_err_ack <= '1'; -- ack bus errors, the execute engine has to take care of them
end if;
 
when IFETCH_2 => -- construct instruction and issue
-- ------------------------------------------------------------
if (fetch_engine.i_buf_state(1) = '1') then
if (fetch_engine.pc_fetch(1) = '0') or (CPU_EXTENSION_RISCV_C = false) or (csr.misa_c_en = '0') then -- 32-bit aligned
fetch_engine.ci_reg_nxt <= fetch_engine.i_buf2(33 downto 32) & fetch_engine.i_buf2(15 downto 00);
ipb.wdata <= fetch_engine.i_buf2(33 downto 32) & '0' & fetch_engine.i_buf2(31 downto 0);
if (fetch_engine.i_buf2(01 downto 00) = "11") or (CPU_EXTENSION_RISCV_C = false) or (csr.misa_c_en = '0') then -- uncompressed
if (ipb.free = '1') then -- free entry in buffer?
ipb.we <= '1';
fetch_engine.pc_real_add <= std_ulogic_vector(to_unsigned(4, data_width_c));
fetch_engine.pc_fetch_add <= std_ulogic_vector(to_unsigned(4, data_width_c));
fetch_engine.state_nxt <= IFETCH_0;
end if;
else -- compressed
fetch_engine.pc_fetch_add <= std_ulogic_vector(to_unsigned(2, data_width_c));
fetch_engine.ci_return_nxt <= '1'; -- come back here after issueing
fetch_engine.state_nxt <= IFETCH_3;
end if;
else -- 16-bit aligned
fetch_engine.ci_reg_nxt <= fetch_engine.i_buf2(33 downto 32) & fetch_engine.i_buf2(31 downto 16);
ipb.wdata <= fetch_engine.i_buf(33 downto 32) & '0' & fetch_engine.i_buf(15 downto 00) & fetch_engine.i_buf2(31 downto 16);
if (fetch_engine.i_buf2(17 downto 16) = "11") then -- uncompressed
if (ipb.free = '1') then -- free entry in buffer?
ipb.we <= '1';
fetch_engine.pc_real_add <= std_ulogic_vector(to_unsigned(4, data_width_c));
fetch_engine.pc_fetch_add <= std_ulogic_vector(to_unsigned(4, data_width_c));
fetch_engine.state_nxt <= IFETCH_0;
end if;
else -- compressed
fetch_engine.pc_fetch_add <= std_ulogic_vector(to_unsigned(2, data_width_c));
fetch_engine.ci_return_nxt <= '0'; -- start next fetch after issueing
fetch_engine.state_nxt <= IFETCH_3;
end if;
end if;
else
fetch_engine.pc_fetch_add <= std_ulogic_vector(to_unsigned(4, data_width_c));
fetch_engine.state_nxt <= IFETCH_0;
end if;
 
when IFETCH_3 => -- additional cycle for issueing decompressed instructions
-- ------------------------------------------------------------
if (ipb.free = '1') then -- free entry in buffer?
ipb.we <= '1';
ipb.wdata <= fetch_engine.ci_reg(17 downto 16) & '1' & ci_instr32;
fetch_engine.pc_real_add <= std_ulogic_vector(to_unsigned(2, data_width_c));
if (fetch_engine.ci_return = '0') then
fetch_engine.state_nxt <= IFETCH_0;
else
fetch_engine.state_nxt <= IFETCH_2;
end if;
end if;
 
when others => -- undefined
-- ------------------------------------------------------------
fetch_engine.state_nxt <= IFETCH_RESET;
 
end case;
end process fetch_engine_fsm_comb;
 
 
-- ****************************************************************************************************************************
-- Instruction Prefetch Buffer
-- ****************************************************************************************************************************
 
 
-- Instruction Prefetch Buffer Stage ------------------------------------------------------
-- -------------------------------------------------------------------------------------------
instr_prefetch_buffer: process(rstn_i, clk_i)
begin
if (rstn_i = '0') then
ipb.status <= '0';
ipb.rdata <= (others => '0');
ipb.raddr <= (others => '0');
elsif rising_edge(clk_i) then
if (ipb.clear = '1') then
ipb.status <= '0';
elsif (ipb.we = '1') then
ipb.status <= '1';
elsif (ipb.re = '1') then
ipb.status <= '0';
end if;
if (ipb.we = '1') then
ipb.rdata <= ipb.wdata;
ipb.raddr <= ipb.waddr;
end if;
end if;
end process instr_prefetch_buffer;
 
-- status --
ipb.free <= not ipb.status;
ipb.avail <= ipb.status;
 
 
-- ****************************************************************************************************************************
-- Instruction Execution
-- ****************************************************************************************************************************
 
 
-- Immediate Generator --------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
imm_gen: process(clk_i)
begin
if rising_edge(clk_i) then
-- default: I-immediate --
imm_reg(31 downto 11) <= (others => i_reg(31)); -- sign extension
imm_reg(10 downto 05) <= i_reg(30 downto 25);
imm_reg(04 downto 01) <= i_reg(24 downto 21);
imm_reg(00) <= i_reg(20);
case i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c) is
case execute_engine.i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c) is
when opcode_store_c => -- S-immediate
imm_reg(31 downto 11) <= (others => i_reg(31)); -- sign extension
imm_reg(10 downto 05) <= i_reg(30 downto 25);
imm_reg(04 downto 01) <= i_reg(11 downto 08);
imm_reg(00) <= i_reg(07);
imm_o(31 downto 11) <= (others => execute_engine.i_reg(31)); -- sign extension
imm_o(10 downto 05) <= execute_engine.i_reg(30 downto 25);
imm_o(04 downto 01) <= execute_engine.i_reg(11 downto 08);
imm_o(00) <= execute_engine.i_reg(07);
when opcode_branch_c => -- B-immediate
imm_reg(31 downto 12) <= (others => i_reg(31)); -- sign extension
imm_reg(11) <= i_reg(07);
imm_reg(10 downto 05) <= i_reg(30 downto 25);
imm_reg(04 downto 01) <= i_reg(11 downto 08);
imm_reg(00) <= '0';
imm_o(31 downto 12) <= (others => execute_engine.i_reg(31)); -- sign extension
imm_o(11) <= execute_engine.i_reg(07);
imm_o(10 downto 05) <= execute_engine.i_reg(30 downto 25);
imm_o(04 downto 01) <= execute_engine.i_reg(11 downto 08);
imm_o(00) <= '0';
when opcode_lui_c | opcode_auipc_c => -- U-immediate
imm_reg(31 downto 20) <= i_reg(31 downto 20);
imm_reg(19 downto 12) <= i_reg(19 downto 12);
imm_reg(11 downto 00) <= (others => '0');
imm_o(31 downto 20) <= execute_engine.i_reg(31 downto 20);
imm_o(19 downto 12) <= execute_engine.i_reg(19 downto 12);
imm_o(11 downto 00) <= (others => '0');
when opcode_jal_c => -- J-immediate
imm_reg(31 downto 20) <= (others => i_reg(31)); -- sign extension
imm_reg(19 downto 12) <= i_reg(19 downto 12);
imm_reg(11) <= i_reg(20);
imm_reg(10 downto 05) <= i_reg(30 downto 25);
imm_reg(04 downto 01) <= i_reg(24 downto 21);
imm_reg(00) <= '0';
imm_o(31 downto 20) <= (others => execute_engine.i_reg(31)); -- sign extension
imm_o(19 downto 12) <= execute_engine.i_reg(19 downto 12);
imm_o(11) <= execute_engine.i_reg(20);
imm_o(10 downto 05) <= execute_engine.i_reg(30 downto 25);
imm_o(04 downto 01) <= execute_engine.i_reg(24 downto 21);
imm_o(00) <= '0';
when opcode_syscsr_c => -- CSR-immediate
imm_reg(31 downto 05) <= (others => '0');
imm_reg(04 downto 00) <= i_reg(19 downto 15);
imm_o(31 downto 05) <= (others => '0');
imm_o(04 downto 00) <= execute_engine.i_reg(19 downto 15);
when others => -- I-immediate
imm_reg(31 downto 11) <= (others => i_reg(31)); -- sign extension
imm_reg(10 downto 05) <= i_reg(30 downto 25);
imm_reg(04 downto 01) <= i_reg(24 downto 21);
imm_reg(00) <= i_reg(20);
imm_o(31 downto 11) <= (others => execute_engine.i_reg(31)); -- sign extension
imm_o(10 downto 05) <= execute_engine.i_reg(30 downto 25);
imm_o(04 downto 01) <= execute_engine.i_reg(24 downto 21);
imm_o(00) <= execute_engine.i_reg(20);
end case;
end if;
end process imm_gen;
 
-- output --
imm_o <= imm_reg;
 
 
-- Branch Condition Check -----------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
branch_check: process(i_reg, cmp_i)
branch_check: process(execute_engine.i_reg, cmp_i)
begin
case i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) is
case execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) is
when funct3_beq_c => -- branch if equal
branch_taken <= cmp_i(alu_cmp_equal_c);
execute_engine.branch_taken <= cmp_i(alu_cmp_equal_c);
when funct3_bne_c => -- branch if not equal
branch_taken <= not cmp_i(alu_cmp_equal_c);
execute_engine.branch_taken <= not cmp_i(alu_cmp_equal_c);
when funct3_blt_c | funct3_bltu_c => -- branch if less (signed/unsigned)
branch_taken <= cmp_i(alu_cmp_less_c);
execute_engine.branch_taken <= cmp_i(alu_cmp_less_c);
when funct3_bge_c | funct3_bgeu_c => -- branch if greater or equal (signed/unsigned)
branch_taken <= not cmp_i(alu_cmp_less_c);
execute_engine.branch_taken <= not cmp_i(alu_cmp_less_c);
when others => -- undefined
branch_taken <= '0';
execute_engine.branch_taken <= '0';
end case;
end process branch_check;
 
 
-- Arbiter State Machine Sync -------------------------------------------------------------
-- Execute Engine FSM Sync ----------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
arbiter_sync_rst: process(rstn_i, clk_i)
-- for registers that require a specific reset state --
execute_engine_fsm_sync_rst: process(rstn_i, clk_i)
begin
if (rstn_i = '0') then
-- these registers REQUIRE a specific reset state
state <= IFETCH_0;
if (BOOTLOADER_USE = true) then -- boot from bootloader ROM
execute_engine.pc <= boot_base_c(data_width_c-1 downto 1) & '0';
execute_engine.last_pc <= boot_base_c(data_width_c-1 downto 1) & '0';
else -- boot from IMEM
execute_engine.pc <= MEM_ISPACE_BASE(data_width_c-1 downto 1) & '0';
execute_engine.last_pc <= MEM_ISPACE_BASE(data_width_c-1 downto 1) & '0';
end if;
execute_engine.state <= IDLE;
execute_engine.state_prev <= IDLE;
elsif rising_edge(clk_i) then
state <= state_nxt;
execute_engine.pc <= execute_engine.pc_nxt(data_width_c-1 downto 1) & '0';
if (execute_engine.state = EXECUTE) then
execute_engine.last_pc <= execute_engine.pc(data_width_c-1 downto 1) & '0';
end if;
execute_engine.state <= execute_engine.state_nxt;
execute_engine.state_prev <= execute_engine.state;
end if;
end process arbiter_sync_rst;
end process execute_engine_fsm_sync_rst;
 
arbiter_sync: process(clk_i)
 
-- for registers that DO NOT require a specific reset state --
execute_engine_fsm_sync: process(clk_i)
begin
if rising_edge(clk_i) then
-- these registers do not need a specific reset state
ctrl <= ctrl_nxt;
i_reg <= i_reg_nxt;
i_buf <= i_buf_nxt;
ci_reg <= ci_reg_nxt;
iavail <= iavail_nxt;
is_ci <= is_ci_nxt;
is_branch <= is_branch_nxt;
execute_engine.i_reg <= execute_engine.i_reg_nxt;
execute_engine.is_ci <= execute_engine.is_ci_nxt;
execute_engine.is_jump <= execute_engine.is_jump_nxt;
-- control signals --
ctrl <= ctrl_nxt;
end if;
end process arbiter_sync;
end process execute_engine_fsm_sync;
 
-- control bus output --
ctrl_outpu: process(ctrl, i_reg)
 
-- PC output --
execute_engine.next_pc <= std_ulogic_vector(unsigned(execute_engine.pc(data_width_c-1 downto 1) & '0') + 2) when (execute_engine.is_ci = '1') else
std_ulogic_vector(unsigned(execute_engine.pc(data_width_c-1 downto 1) & '0') + 4);
fetch_pc_o <= fetch_engine.pc_fetch(data_width_c-1 downto 1) & '0';
curr_pc_o <= execute_engine.pc(data_width_c-1 downto 1) & '0';
next_pc_o <= execute_engine.next_pc(data_width_c-1 downto 1) & '0';
 
 
-- CPU Control Bus Output -----------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
ctrl_output: process(ctrl, execute_engine, csr, bus_fast_ir, bus_fast_rd, bus_fast_wr)
begin
ctrl_o <= ctrl;
-- direct output of register addresses --
ctrl_o(ctrl_rf_rd_adr4_c downto ctrl_rf_rd_adr0_c) <= i_reg(instr_rd_msb_c downto instr_rd_lsb_c);
ctrl_o(ctrl_rf_rs1_adr4_c downto ctrl_rf_rs1_adr0_c) <= i_reg(instr_rs1_msb_c downto instr_rs1_lsb_c);
ctrl_o(ctrl_rf_rs2_adr4_c downto ctrl_rf_rs2_adr0_c) <= i_reg(instr_rs2_msb_c downto instr_rs2_lsb_c);
end process ctrl_outpu;
ctrl_o(ctrl_rf_rd_adr4_c downto ctrl_rf_rd_adr0_c) <= execute_engine.i_reg(instr_rd_msb_c downto instr_rd_lsb_c);
ctrl_o(ctrl_rf_rs1_adr4_c downto ctrl_rf_rs1_adr0_c) <= execute_engine.i_reg(instr_rs1_msb_c downto instr_rs1_lsb_c);
ctrl_o(ctrl_rf_rs2_adr4_c downto ctrl_rf_rs2_adr0_c) <= execute_engine.i_reg(instr_rs2_msb_c downto instr_rs2_lsb_c);
-- bus access requests --
ctrl_o(ctrl_bus_if_c) <= ctrl(ctrl_bus_if_c) or bus_fast_ir;
ctrl_o(ctrl_bus_rd_c) <= ctrl(ctrl_bus_rd_c) or bus_fast_rd;
ctrl_o(ctrl_bus_wr_c) <= ctrl(ctrl_bus_wr_c) or bus_fast_wr;
-- cpu extension control --
ctrl_o(ctrl_sys_c_ext_en_c) <= csr.misa_c_en; -- C extension enabled
ctrl_o(ctrl_sys_m_ext_en_c) <= csr.misa_m_en; -- M extension enabled
end process ctrl_output;
 
 
-- Arbiter State Machine Comb -----------------------------------------------
-- -----------------------------------------------------------------------------
arbiter_comb: process(state, ctrl, i_reg, alu_wait_i, bus_wait_i, exc_cpu_start, ma_load_i, be_load_i, ma_store_i, be_store_i,
ci_reg, i_buf, instr_i, is_ci, iavail, pc_backup_reg, ci_valid, ci_instr32)
-- Execute Engine FSM Comb ----------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
execute_engine_fsm_comb: process(execute_engine, fetch_engine, ipb, trap_ctrl, csr, ctrl,
alu_add_i, alu_wait_i, bus_wait_i, ma_load_i, be_load_i, ma_store_i, be_store_i)
variable alu_immediate_v : std_ulogic;
variable alu_operation_v : std_ulogic_vector(2 downto 0);
variable rd_is_r0_v : std_ulogic;
variable rs1_is_r0_v : std_ulogic;
begin
-- arbiter defaults --
state_nxt <= state;
is_branch_nxt <= '0';
exc_cpu_ack <= '0';
exc_cpu_end <= '0';
execute_engine.state_nxt <= execute_engine.state;
execute_engine.i_reg_nxt <= execute_engine.i_reg;
execute_engine.is_jump_nxt <= '0';
execute_engine.is_ci_nxt <= execute_engine.is_ci;
execute_engine.pc_nxt <= execute_engine.pc(data_width_c-1 downto 1) & '0';
 
i_reg_nxt <= i_reg;
i_buf_nxt <= i_buf;
ci_reg_nxt <= ci_reg;
iavail_nxt <= iavail;
is_ci_nxt <= is_ci;
-- instruction dispatch --
fetch_engine.reset <= '0';
ipb.re <= '0';
 
-- trap environment control --
trap_ctrl.env_start_ack <= '0';
trap_ctrl.env_end <= '0';
 
-- bus access (fast) --
bus_fast_rd <= '0';
bus_fast_wr <= '0';
 
-- exception trigger --
env_call <= '0';
break_point <= '0';
trap_ctrl.instr_be <= '0';
trap_ctrl.instr_ma <= '0';
trap_ctrl.env_call <= '0';
trap_ctrl.break_point <= '0';
 
-- CSR access --
csr.we_nxt <= '0';
csr.re_nxt <= '0';
 
-- control defaults --
ctrl_nxt <= (others => '0'); -- all off at first
ctrl_nxt(ctrl_bus_unsigned_c) <= i_reg(instr_funct3_msb_c); -- unsigned LOAD (LBU, LHU)
if (i_reg(instr_opcode_lsb_c+4) = '1') then -- ALU ops
ctrl_nxt(ctrl_alu_unsigned_c) <= i_reg(instr_funct3_lsb_c+0); -- unsigned ALU operation (SLTIU, SLTU)
ctrl_nxt(ctrl_bus_unsigned_c) <= execute_engine.i_reg(instr_funct3_msb_c); -- unsigned LOAD (LBU, LHU)
if (execute_engine.i_reg(instr_opcode_lsb_c+4) = '1') then -- ALU ops
ctrl_nxt(ctrl_alu_unsigned_c) <= execute_engine.i_reg(instr_funct3_lsb_c+0); -- unsigned ALU operation (SLTIU, SLTU)
else -- branches
ctrl_nxt(ctrl_alu_unsigned_c) <= i_reg(instr_funct3_lsb_c+1); -- unsigned branches (BLTU, BGEU)
ctrl_nxt(ctrl_alu_unsigned_c) <= execute_engine.i_reg(instr_funct3_lsb_c+1); -- unsigned branches (BLTU, BGEU)
end if;
ctrl_nxt(ctrl_alu_shift_dir_c) <= i_reg(instr_funct3_msb_c); -- shift direction
ctrl_nxt(ctrl_alu_shift_ar_c) <= i_reg(30); -- arithmetic shift
ctrl_nxt(ctrl_bus_size_lsb_c) <= i_reg(instr_funct3_lsb_c+0); -- transfer size lsb (00=byte, 01=half-word)
ctrl_nxt(ctrl_bus_size_msb_c) <= i_reg(instr_funct3_lsb_c+1); -- transfer size msb (10=word, 11=?)
ctrl_nxt(ctrl_alu_shift_dir_c) <= execute_engine.i_reg(instr_funct3_msb_c); -- shift direction
ctrl_nxt(ctrl_alu_shift_ar_c) <= execute_engine.i_reg(30); -- arithmetic shift
ctrl_nxt(ctrl_bus_size_lsb_c) <= execute_engine.i_reg(instr_funct3_lsb_c+0); -- transfer size lsb (00=byte, 01=half-word)
ctrl_nxt(ctrl_bus_size_msb_c) <= execute_engine.i_reg(instr_funct3_lsb_c+1); -- transfer size msb (10=word, 11=?)
ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_add_c; -- actual ALU operation = add
ctrl_nxt(ctrl_cp_cmd2_c downto ctrl_cp_cmd0_c) <= i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c); -- CP operation
ctrl_nxt(ctrl_cp_cmd2_c downto ctrl_cp_cmd0_c) <= execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c); -- CP operation
ctrl_nxt(ctrl_cp_id_msb_c downto ctrl_cp_id_lsb_c) <= cp_sel_muldiv_c; -- only CP0 implemented yet
 
-- is immediate operation? --
alu_immediate_v := '0';
if (i_reg(instr_opcode_msb_c-1) = '0') then
if (execute_engine.i_reg(instr_opcode_msb_c-1) = '0') then
alu_immediate_v := '1';
end if;
 
-- hardware branch operation control --
hw_control(31 downto 24) <= ('0' & funct3_bne_c) & ('1' & funct3_bne_c);
hw_control(23 downto 16) <= funct3_xor_c & funct3_slt_c & "00";
hw_control(15 downto 08) <= funct3_beq_c & funct3_bne_c & "11";
hw_control(07 downto 00) <= funct3_beq_c & funct3_bne_c & "00";
 
-- alu operation --
case i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) is
-- alu operation re-coding --
case execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) is
when funct3_subadd_c => -- SUB / ADD(I)
if (alu_immediate_v = '0') and (i_reg(instr_funct7_msb_c-1) = '1') then -- not immediate and funct7 = SUB
if (alu_immediate_v = '0') and (execute_engine.i_reg(instr_funct7_msb_c-1) = '1') then -- not immediate and funct7 = SUB
alu_operation_v := alu_cmd_sub_c;
else
alu_operation_v := alu_cmd_add_c;
end if;
when funct3_sll_c => alu_operation_v := alu_cmd_shift_c; -- SLL(I)
when funct3_slt_c => alu_operation_v := alu_cmd_slt_c; -- SLT(I)
when funct3_sltu_c => alu_operation_v := alu_cmd_slt_c; -- SLTU(I)
when funct3_xor_c => alu_operation_v := alu_cmd_xor_c; -- XOR(I)
when funct3_slt_c => alu_operation_v := alu_cmd_slt_c; -- SLT(I)
when funct3_sltu_c => alu_operation_v := alu_cmd_slt_c; -- SLTU(I)
when funct3_xor_c => alu_operation_v := alu_cmd_xor_c; -- XOR(I)
when funct3_sr_c => alu_operation_v := alu_cmd_shift_c; -- SRL(I) / SRA(I)
when funct3_or_c => alu_operation_v := alu_cmd_or_c; -- OR(I)
when funct3_and_c => alu_operation_v := alu_cmd_and_c; -- AND(I)
when funct3_or_c => alu_operation_v := alu_cmd_or_c; -- OR(I)
when funct3_and_c => alu_operation_v := alu_cmd_and_c; -- AND(I)
when others => alu_operation_v := (others => '0'); -- undefined
end case;
 
-- is rd = r0? --
rd_is_r0_v := '0';
if (execute_engine.i_reg(instr_rd_msb_c downto instr_rd_lsb_c) = "00000") then
rd_is_r0_v := '1';
end if;
 
-- is rs1 = r0? --
rs1_is_r0_v := '0';
if (i_reg(instr_rs1_msb_c downto instr_rs1_lsb_c) = "00000") then
if (execute_engine.i_reg(instr_rs1_msb_c downto instr_rs1_lsb_c) = "00000") then
rs1_is_r0_v := '1';
end if;
 
-- state machine --
case execute_engine.state is
 
-- state machine: instruction fetch and execution --
case state is
 
when IFETCH_0 => -- output current PC to bus system
when IDLE => -- Delay cycle (used to wait for side effects to kick in)
-- ------------------------------------------------------------
ctrl_nxt(ctrl_bus_if_c) <= '1'; -- instruction fetch request (output PC to bus address)
iavail_nxt <= '0'; -- absolutely no instruction available yet
state_nxt <= IFETCH_1;
execute_engine.state_nxt <= DISPATCH;
 
when IFETCH_1 => -- memory latency, update PC
-- ------------------------------------------------------------
ctrl_nxt(ctrl_alu_opa_mux_msb_c downto ctrl_alu_opa_mux_lsb_c) <= "11"; -- opa = current PC
ctrl_nxt(ctrl_alu_opb_mux_msb_c downto ctrl_alu_opb_mux_lsb_c) <= "11"; -- opb = PC_increment
ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_add_c; -- actual ALU operation = ADD
ctrl_nxt(ctrl_csr_pc_we_c) <= '1'; -- update PC
state_nxt <= IFETCH_2;
when DISPATCH => -- Get new command from instruction prefetch buffer (IPB)
-- ------------------------------------------------------------
if (ipb.avail = '1') then -- instruction available?
ipb.re <= '1';
trap_ctrl.instr_ma <= ipb.rdata(33);
trap_ctrl.instr_be <= ipb.rdata(34);
if (trap_ctrl.env_start = '1') or (ipb.rdata(33) = '1') or (ipb.rdata(34) = '1') then -- exception/interrupt?
execute_engine.state_nxt <= TRAP;
else
execute_engine.is_ci_nxt <= ipb.rdata(32); -- flag to indicate this is a compressed instruction beeing executed
execute_engine.i_reg_nxt <= ipb.rdata(31 downto 0);
execute_engine.pc_nxt <= ipb.raddr(data_width_c-1 downto 1) & '0'; -- the PC according to the current instruction
execute_engine.state_nxt <= EXECUTE;
end if;
end if;
 
when IFETCH_2 => -- update instruction buffers
when TRAP => -- Start trap environment (also used as sleep state)
-- ------------------------------------------------------------
if (exc_cpu_start = '1') then -- exception detected!
exc_cpu_ack <= '1';
state_nxt <= IFETCH_0; -- start new instruction fetch
else -- normal operation
-- instruction register update --
if (CPU_EXTENSION_RISCV_C = true) then -- compressed AND uncompressed instructions possible
if (pc_backup_reg(1) = '0') then
i_buf_nxt <= instr_i(31 downto 16);
ci_reg_nxt <= instr_i(15 downto 00);
else
i_buf_nxt <= instr_i(15 downto 00);
ci_reg_nxt <= instr_i(31 downto 16);
end if;
else -- only uncompressed instructions
i_reg_nxt <= instr_i(31 downto 0);
end if;
-- next state --
if (bus_wait_i = '0') then -- wait for bus response
if (CPU_EXTENSION_RISCV_C = true) then -- compressed AND uncompressed instructions possible
state_nxt <= IFETCH_3;
else -- only uncompressed instructions
state_nxt <= EXECUTE;
end if;
end if;
if (trap_ctrl.env_start = '1') then
trap_ctrl.env_start_ack <= '1';
execute_engine.pc_nxt <= csr.mtvec(data_width_c-1 downto 1) & '0';
fetch_engine.reset <= '1';
execute_engine.state_nxt <= IDLE;
end if;
 
 
when IFETCH_3 => -- check for exception, start instruction execution (only available for C-extension)
when EXECUTE => -- Decode and execute instruction
-- ------------------------------------------------------------
ctrl_nxt(ctrl_alu_opa_mux_msb_c downto ctrl_alu_opa_mux_lsb_c) <= "11"; -- opa = current PC
ctrl_nxt(ctrl_alu_opb_mux_msb_c downto ctrl_alu_opb_mux_lsb_c) <= "11"; -- opb = PC_increment
ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_add_c; -- actual ALU operation = ADD
--
if (exc_cpu_start = '1') then -- exception detected!
exc_cpu_ack <= '1';
state_nxt <= IFETCH_0; -- start new instruction fetch
else -- normal operation
if (ci_valid = '1') then -- directly execute decoded compressed instruction
i_reg_nxt <= ci_instr32;
state_nxt <= EXECUTE;
elsif (pc_backup_reg(1) = '0') or (iavail = '1') then -- 32-bit aligned uncompressed instruction
i_reg_nxt <= i_buf & ci_reg;
state_nxt <= EXECUTE;
ctrl_nxt(ctrl_csr_pc_we_c) <= not pc_backup_reg(1); -- update PC again when on 32b-aligned address
else
i_reg_nxt <= i_buf & ci_reg;
state_nxt <= IFETCH_4;
end if;
end if;
case execute_engine.i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c) is
 
when IFETCH_4 => -- get missing instruction parts: output current PC to bus system (only available for C-extension)
-- ------------------------------------------------------------
ctrl_nxt(ctrl_bus_if_c) <= '1'; -- instruction fetch request (output PC to bus address)
state_nxt <= IFETCH_5;
 
when IFETCH_5 => -- memory latency, update PC (only available for C-extension)
-- ------------------------------------------------------------
ctrl_nxt(ctrl_alu_opa_mux_msb_c downto ctrl_alu_opa_mux_lsb_c) <= "11"; -- opa = current PC
ctrl_nxt(ctrl_alu_opb_mux_msb_c downto ctrl_alu_opb_mux_lsb_c) <= "11"; -- opb = PC_increment
ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_add_c; -- actual ALU operation = ADD
ctrl_nxt(ctrl_csr_pc_we_c) <= '1'; -- update PC
state_nxt <= IFETCH_6;
 
when IFETCH_6 => -- update missing instruction buffer parts (only available for C-extension)
-- ------------------------------------------------------------
if (bus_wait_i = '0') then -- wait for bus response
i_buf_nxt <= instr_i(15 downto 00);
iavail_nxt <= '1';
state_nxt <= IFETCH_3;
end if;
 
 
when EXECUTE => -- decode and execute instruction
-- ------------------------------------------------------------
is_ci_nxt <= ci_valid; -- flag to indicate this is a compressed instruction beeing executed (ci_valid is zero if not C-ext is not implemented)
case i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c) is
 
when opcode_alu_c | opcode_alui_c => -- ALU operation
-- ------------------------------------------------------------
ctrl_nxt(ctrl_alu_opa_mux_lsb_c) <= '0'; -- use RS1 as ALU.OPA
500,31 → 733,31
ctrl_nxt(ctrl_alu_opc_mux_c) <= not alu_immediate_v;
ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_operation_v; -- actual ALU operation
ctrl_nxt(ctrl_rf_in_mux_msb_c downto ctrl_rf_in_mux_lsb_c) <= "00"; -- RF input = ALU result
if (CPU_EXTENSION_RISCV_M = true) and (i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c) = opcode_alu_c) and
(i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0000001") then -- MULDIV?
if (CPU_EXTENSION_RISCV_M = true) and (execute_engine.i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c) = opcode_alu_c) and
(execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0000001") then -- MULDIV?
ctrl_nxt(ctrl_cp_use_c) <= '1'; -- use CP
ctrl_nxt(ctrl_cp_id_msb_c downto ctrl_cp_id_lsb_c) <= cp_sel_muldiv_c; -- muldiv CP
state_nxt <= ALU_WAIT;
execute_engine.state_nxt <= ALU_WAIT;
elsif (alu_operation_v = alu_cmd_shift_c) then -- multi-cycle shift operation?
state_nxt <= ALU_WAIT;
execute_engine.state_nxt <= ALU_WAIT;
else
ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write-back
state_nxt <= IFETCH_0;
execute_engine.state_nxt <= DISPATCH;
end if;
 
when opcode_lui_c | opcode_auipc_c => -- load upper immediate (add to PC)
-- ------------------------------------------------------------
ctrl_nxt(ctrl_rf_clear_rs1_c) <= '1'; -- force RS1 = r0
if (i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c) = opcode_auipc_c) then -- AUIPC
if (execute_engine.i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c) = opcode_auipc_c) then -- AUIPC
ctrl_nxt(ctrl_alu_opa_mux_lsb_c) <= '1'; -- use PC as ALU.OPA
else -- LUI
ctrl_nxt(ctrl_alu_opa_mux_lsb_c) <= '0'; -- use RS1 as ALU.OPA
end if;
ctrl_nxt(ctrl_alu_opb_mux_lsb_c) <= '1'; -- use IMM as ALU.OPB
ctrl_nxt(ctrl_alu_opb_mux_lsb_c) <= '1'; -- use IMM as ALU.OPB
ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_add_c; -- actual ALU operation
ctrl_nxt(ctrl_rf_in_mux_msb_c downto ctrl_rf_in_mux_lsb_c) <= "00"; -- RF input = ALU result
ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write-back
state_nxt <= IFETCH_0;
execute_engine.state_nxt <= DISPATCH;
 
when opcode_load_c | opcode_store_c => -- load/store
-- ------------------------------------------------------------
531,12 → 764,14
ctrl_nxt(ctrl_alu_opa_mux_lsb_c) <= '0'; -- use RS1 as ALU.OPA
ctrl_nxt(ctrl_alu_opb_mux_lsb_c) <= '1'; -- use IMM as ALU.OPB
ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_add_c; -- actual ALU operation
ctrl_nxt(ctrl_bus_mar_we_c) <= '1'; -- write to MAR
ctrl_nxt(ctrl_bus_mdo_we_c) <= '1'; -- write to MDO (only relevant for stores)
if (i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c) = opcode_load_c) then -- LOAD
state_nxt <= LOAD_0;
else -- STORE
state_nxt <= STORE_0;
ctrl_nxt(ctrl_bus_mar_we_c) <= '1'; -- write to MAR
ctrl_nxt(ctrl_bus_mdo_we_c) <= '1'; -- write to MDO (only relevant for stores)
if (fetch_engine.state /= IFETCH_0) then
if (execute_engine.i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c) = opcode_load_c) then -- LOAD
execute_engine.state_nxt <= LOAD;
else -- STORE
execute_engine.state_nxt <= STORE;
end if;
end if;
 
when opcode_branch_c => -- branch instruction
543,14 → 778,13
-- ------------------------------------------------------------
ctrl_nxt(ctrl_alu_opa_mux_lsb_c) <= '1'; -- use PC as ALU.OPA
ctrl_nxt(ctrl_alu_opb_mux_lsb_c) <= '1'; -- use IMM as ALU.OPB
ctrl_nxt(ctrl_alu_opc_mux_c) <= '1'; -- use RS2 as ALU.OPC
is_branch_nxt <= '1';
state_nxt <= IFETCH_0;
ctrl_nxt(ctrl_alu_opc_mux_c) <= '1'; -- use RS2 as ALU.OPC
execute_engine.state_nxt <= BRANCH;
 
when opcode_jal_c | opcode_jalr_c => -- jump and link (with register)
-- ------------------------------------------------------------
-- compute target address --
if (i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c) = opcode_jal_c) then -- JAL
if (execute_engine.i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c) = opcode_jal_c) then -- JAL
ctrl_nxt(ctrl_alu_opa_mux_lsb_c) <= '1'; -- use PC as ALU.OPA
else -- JALR
ctrl_nxt(ctrl_alu_opa_mux_lsb_c) <= '0'; -- use RS1 as ALU.OPA
559,70 → 793,49
-- save return address --
ctrl_nxt(ctrl_rf_in_mux_msb_c downto ctrl_rf_in_mux_lsb_c) <= "10"; -- RF input = current PC
ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write-back
-- update PC --
ctrl_nxt(ctrl_csr_pc_we_c) <= '1'; -- update PC
state_nxt <= IFETCH_0;
--
execute_engine.is_jump_nxt <= '1'; -- this is a jump operation
execute_engine.state_nxt <= BRANCH;
 
when opcode_syscsr_c => -- system/csr access
-- ------------------------------------------------------------
ctrl_nxt(ctrl_csr_re_c) <= '1'; -- ALWAYS READ CSR!!! (OLD: valid CSR read if rd is not r0)
if (i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_env_c) then -- system
case i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) is
when x"000" => env_call <= '1'; state_nxt <= IFETCH_0; -- ECALL
when x"001" => break_point <= '1'; state_nxt <= IFETCH_0; -- EBREAK
when x"302" => exc_cpu_end <= '1'; state_nxt <= IFETCH_0; -- MRET
when x"105" => state_nxt <= SLEEP; -- WFI
when others => NULL; -- undefined
if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrw_c) or
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrwi_c) then
csr.re_nxt <= not rd_is_r0_v; -- only read CSR if not writing to zero_reg
else
csr.re_nxt <= '1'; -- always read CSR
end if;
--
if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_env_c) then -- system
case execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) is
when x"000" => -- ECALL
trap_ctrl.env_call <= '1';
execute_engine.state_nxt <= IDLE;
when x"001" => -- EBREAK
trap_ctrl.break_point <= '1';
execute_engine.state_nxt <= IDLE;
when x"302" => -- MRET
trap_ctrl.env_end <= '1';
execute_engine.pc_nxt <= csr.mepc(data_width_c-1 downto 1) & '0';
fetch_engine.reset <= '1';
execute_engine.state_nxt <= IDLE;
when x"105" => -- WFI
execute_engine.state_nxt <= TRAP;
when others => -- undefined
NULL;
end case;
elsif (CPU_EXTENSION_RISCV_Zicsr = true) then -- CSR access
state_nxt <= CSR_ACCESS;
execute_engine.state_nxt <= CSR_ACCESS;
else
state_nxt <= IFETCH_0;
execute_engine.state_nxt <= DISPATCH;
end if;
 
when others => -- undefined
-- ------------------------------------------------------------
state_nxt <= IFETCH_0;
execute_engine.state_nxt <= DISPATCH;
 
end case;
 
when ALU_WAIT => -- wait for multi-cycle ALU operation to finish
-- ------------------------------------------------------------
ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_operation_v; -- actual ALU operation
ctrl_nxt(ctrl_rf_in_mux_msb_c downto ctrl_rf_in_mux_lsb_c) <= "00"; -- RF input = ALU result
ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write-back (write back all the time)
if (alu_wait_i = '0') then
state_nxt <= IFETCH_0;
end if;
 
when LOAD_0 => -- trigger memory read request
-- ------------------------------------------------------------
ctrl_nxt(ctrl_bus_rd_c) <= '1'; -- read request
state_nxt <= LOADSTORE_0;
 
when STORE_0 => -- trigger memory write request
-- ------------------------------------------------------------
ctrl_nxt(ctrl_bus_wr_c) <= '1'; -- write request
state_nxt <= LOADSTORE_0;
 
when LOADSTORE_0 => -- memory latency
-- ------------------------------------------------------------
ctrl_nxt(ctrl_bus_mdi_we_c) <= '1'; -- write input data to MDI (only relevant for LOAD)
state_nxt <= LOADSTORE_1;
 
when LOADSTORE_1 => -- wait for bus transaction to finish
-- ------------------------------------------------------------
ctrl_nxt(ctrl_bus_mdi_we_c) <= '1'; -- keep writing input data to MDI (only relevant for LOAD)
ctrl_nxt(ctrl_rf_in_mux_msb_c downto ctrl_rf_in_mux_lsb_c) <= "01"; -- RF input = memory input (only relevant for LOAD)
if (ma_load_i = '1') or (be_load_i = '1') or (ma_store_i = '1') or (be_store_i = '1') then -- abort if exception
state_nxt <= IFETCH_0;
elsif (bus_wait_i = '0') then -- wait here for bus to finish transaction
if (i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c) = opcode_load_c) then -- LOAD?
ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write-back
end if;
state_nxt <= IFETCH_0;
end if;
 
when CSR_ACCESS => -- write CSR data to RF, write ALU.res to CSR
-- ------------------------------------------------------------
ctrl_nxt(ctrl_alu_opa_mux_msb_c) <= '0'; -- default
629,34 → 842,39
ctrl_nxt(ctrl_alu_opa_mux_lsb_c) <= '0'; -- default
ctrl_nxt(ctrl_alu_opb_mux_msb_c) <= '0'; -- default
ctrl_nxt(ctrl_alu_opb_mux_lsb_c) <= '0'; -- default
ctrl_nxt(ctrl_csr_we_c) <= not rs1_is_r0_v; -- valid CSR write if rs1 is not r0 (or not imm5 = 0)
case i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) is
when funct3_csrrw_c => -- CSSRW
case execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) is
when funct3_csrrw_c => -- CSRRW
ctrl_nxt(ctrl_alu_opa_mux_lsb_c) <= '0'; -- OPA = rs1
ctrl_nxt(ctrl_alu_opb_mux_lsb_c) <= '0'; -- OPB = rs2
ctrl_nxt(ctrl_rf_clear_rs2_c) <= '1'; -- rs2 = 0
ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_add_c; -- actual ALU operation = ADD
when funct3_csrrs_c => -- CSSRS
csr.we_nxt <= '1'; -- always write CSR
when funct3_csrrs_c => -- CSRRS
ctrl_nxt(ctrl_alu_opa_mux_msb_c) <= '1'; -- OPA = csr
ctrl_nxt(ctrl_alu_opb_mux_msb_c) <= '1'; -- OPB = crs1
ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_or_c; -- actual ALU operation = OR
when funct3_csrrc_c => -- CSSRC
csr.we_nxt <= not rs1_is_r0_v; -- write CSR if rs1 is not zero_reg
when funct3_csrrc_c => -- CSRRC
ctrl_nxt(ctrl_alu_opa_mux_msb_c) <= '1'; -- OPA = csr
ctrl_nxt(ctrl_alu_opb_mux_msb_c) <= '1'; -- OPB = rs1
ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_bitc_c; -- actual ALU operation = bit clear
when funct3_csrrwi_c => -- CSSRWI
csr.we_nxt <= not rs1_is_r0_v; -- write CSR if rs1 is not zero_reg
when funct3_csrrwi_c => -- CSRRWI
ctrl_nxt(ctrl_alu_opa_mux_lsb_c) <= '0'; -- OPA = rs1
ctrl_nxt(ctrl_rf_clear_rs1_c) <= '1'; -- rs1 = 0
ctrl_nxt(ctrl_alu_opb_mux_lsb_c) <= '1'; -- OPB = immediate
ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_add_c; -- actual ALU operation = ADD
when funct3_csrrsi_c => -- CSSRSI
csr.we_nxt <= '1'; -- always write CSR
when funct3_csrrsi_c => -- CSRRSI
ctrl_nxt(ctrl_alu_opa_mux_msb_c) <= '1'; -- OPA = csr
ctrl_nxt(ctrl_alu_opb_mux_lsb_c) <= '1'; -- OPB = immediate
ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_or_c; -- actual ALU operation = OR
when funct3_csrrci_c => -- CSSRCI
csr.we_nxt <= not rs1_is_r0_v; -- write CSR if UIMM5 is not zero (bits from rs1 filed)
when funct3_csrrci_c => -- CSRRCI
ctrl_nxt(ctrl_alu_opa_mux_msb_c) <= '1'; -- OPA = csr
ctrl_nxt(ctrl_alu_opb_mux_lsb_c) <= '1'; -- OPB = immediate
ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_bitc_c; -- actual ALU operation = bit clear
csr.we_nxt <= not rs1_is_r0_v; -- write CSR if UIMM5 is not zero (bits from rs1 filed)
when others => -- undefined
NULL;
end case;
663,28 → 881,66
-- RF write back --
ctrl_nxt(ctrl_rf_in_mux_msb_c downto ctrl_rf_in_mux_lsb_c) <= "11"; -- RF input = CSR output register
ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write-back
state_nxt <= IFETCH_0;
execute_engine.state_nxt <= DISPATCH;
 
when SLEEP => -- stall and wait for interrupt (WFI)
when ALU_WAIT => -- wait for multi-cycle ALU operation to finish
-- ------------------------------------------------------------
if (exc_cpu_start = '1') then -- exception detected!
exc_cpu_ack <= '1';
state_nxt <= IFETCH_0; -- start new instruction fetch
ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_operation_v; -- actual ALU operation
ctrl_nxt(ctrl_rf_in_mux_msb_c downto ctrl_rf_in_mux_lsb_c) <= "00"; -- RF input = ALU result
ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write-back (write back all the time)
if (alu_wait_i = '0') then
execute_engine.state_nxt <= DISPATCH;
end if;
 
when BRANCH => -- update PC for taken branches and jumps
-- ------------------------------------------------------------
if (execute_engine.is_jump = '1') or (execute_engine.branch_taken = '1') then
execute_engine.pc_nxt <= alu_add_i(data_width_c-1 downto 1) & '0';
fetch_engine.reset <= '1';
end if;
execute_engine.state_nxt <= IDLE;
 
when LOAD => -- trigger memory read request
-- ------------------------------------------------------------
ctrl_nxt(ctrl_bus_rd_c) <= '1';--bus_fast_rd <= '1'; -- fast read request
execute_engine.state_nxt <= LOADSTORE_0;
 
when STORE => -- trigger memory write request
-- ------------------------------------------------------------
ctrl_nxt(ctrl_bus_wr_c) <= '1';--bus_fast_wr <= '1'; -- fast write request
execute_engine.state_nxt <= LOADSTORE_0;
 
when LOADSTORE_0 => -- memory latency
-- ------------------------------------------------------------
ctrl_nxt(ctrl_bus_mdi_we_c) <= '1'; -- write input data to MDI (only relevant for LOAD)
execute_engine.state_nxt <= LOADSTORE_1;
 
when LOADSTORE_1 => -- wait for bus transaction to finish
-- ------------------------------------------------------------
ctrl_nxt(ctrl_bus_mdi_we_c) <= '1'; -- keep writing input data to MDI (only relevant for LOAD)
ctrl_nxt(ctrl_rf_in_mux_msb_c downto ctrl_rf_in_mux_lsb_c) <= "01"; -- RF input = memory input (only relevant for LOAD)
if (ma_load_i = '1') or (be_load_i = '1') or (ma_store_i = '1') or (be_store_i = '1') then -- abort if exception
execute_engine.state_nxt <= IDLE;
elsif (bus_wait_i = '0') then -- wait here for bus to finish transaction
if (execute_engine.i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c) = opcode_load_c) then -- LOAD?
ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write-back
end if;
execute_engine.state_nxt <= DISPATCH;
end if;
 
when others => -- undefined
-- ------------------------------------------------------------
state_nxt <= IFETCH_0;
execute_engine.state_nxt <= IDLE;
 
end case;
end process arbiter_comb;
end process execute_engine_fsm_comb;
 
 
-- Illegal Instruction Check --------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
illegal_instruction_check: process(i_reg, state, ctrl_nxt, ci_valid, ci_illegal)
illegal_instruction_check: process(execute_engine, csr, ctrl_nxt, ci_illegal)
begin
if (state = EXECUTE) then
if (execute_engine.state = EXECUTE) then
-- defaults --
illegal_instruction <= '0';
illegal_register <= '0';
691,14 → 947,14
illegal_compressed <= '0';
 
-- check if using reg >= 16 for E-CPUs --
if (CPU_EXTENSION_RISCV_E = true) then
illegal_register <= ctrl_nxt(ctrl_rf_rd_adr4_c) or ctrl_nxt(ctrl_rf_rs2_adr4_c) or ctrl_nxt(ctrl_rf_rs1_adr4_c);
else
illegal_register <= '0';
end if;
--if (CPU_EXTENSION_RISCV_E = true) then
-- illegal_register <= ctrl_nxt(ctrl_rf_rd_adr4_c) or ctrl_nxt(ctrl_rf_rs2_adr4_c) or ctrl_nxt(ctrl_rf_rs1_adr4_c);
--else
-- illegal_register <= '0';
--end if;
 
-- check instructions --
case i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c) is
case execute_engine.i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c) is
 
-- OPCODE check sufficient: LUI, UIPC, JAL --
when opcode_lui_c | opcode_auipc_c | opcode_jal_c =>
705,11 → 961,11
illegal_instruction <= '0';
 
when opcode_alui_c => -- check ALUI funct7
if ((i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sll_c) and
(i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) /= "0000000")) or -- shift logical left
((i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sr_c) and
((i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) /= "0000000") and
(i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) /= "0100000"))) then -- shift right
if ((execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sll_c) and
(execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) /= "0000000")) or -- shift logical left
((execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sr_c) and
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) /= "0000000") and
(execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) /= "0100000"))) then -- shift right
illegal_instruction <= '1';
else
illegal_instruction <= '0';
716,11 → 972,11
end if;
when opcode_load_c => -- check LOAD funct3
if (i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_lb_c) or
(i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_lh_c) or
(i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_lw_c) or
(i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_lbu_c) or
(i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_lhu_c) then
if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_lb_c) or
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_lh_c) or
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_lw_c) or
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_lbu_c) or
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_lhu_c) then
illegal_instruction <= '0';
else
illegal_instruction <= '1';
727,9 → 983,9
end if;
when opcode_store_c => -- check STORE funct3
if (i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sb_c) or
(i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sh_c) or
(i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sw_c) then
if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sb_c) or
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sh_c) or
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sw_c) then
illegal_instruction <= '0';
else
illegal_instruction <= '1';
736,12 → 992,12
end if;
 
when opcode_branch_c => -- check BRANCH funct3
if (i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_beq_c) or
(i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_bne_c) or
(i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_blt_c) or
(i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_bge_c) or
(i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_bltu_c) or
(i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_bgeu_c) then
if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_beq_c) or
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_bne_c) or
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_blt_c) or
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_bge_c) or
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_bltu_c) or
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_bgeu_c) then
illegal_instruction <= '0';
else
illegal_instruction <= '1';
748,7 → 1004,7
end if;
 
when opcode_jalr_c => -- check JALR funct3
if (i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "000") then
if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "000") then
illegal_instruction <= '0';
else
illegal_instruction <= '1';
755,14 → 1011,14
end if;
 
when opcode_alu_c => -- check ALU funct3 & funct7
if (i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0000001") then -- MULDIV
if (CPU_EXTENSION_RISCV_M = false) then
if (execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0000001") then -- MULDIV
if (CPU_EXTENSION_RISCV_M = false) or (csr.misa_m_en = '0') then -- not implemented or disabled
illegal_instruction <= '1';
end if;
elsif ((i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_subadd_c) or
(i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sr_c)) and -- ADD/SUB or SRA/SRL check
((i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) /= "0000000") and
(i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) /= "0100000")) then -- ADD/SUB or SRA/SRL select
elsif ((execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_subadd_c) or
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sr_c)) and -- ADD/SUB or SRA/SRL check
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) /= "0000000") and
(execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) /= "0100000")) then -- ADD/SUB or SRA/SRL select
illegal_instruction <= '1';
else
illegal_instruction <= '0';
770,46 → 1026,45
 
when opcode_syscsr_c => -- check system instructions --
-- CSR access --
if (i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrw_c) or
(i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrs_c) or
(i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrc_c) or
(i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrwi_c) or
(i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrsi_c) or
(i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrci_c) then
if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrw_c) or
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrs_c) or
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrc_c) or
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrwi_c) or
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrsi_c) or
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrci_c) then
-- valid CSR? --
if (i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"300") or -- mstatus
(i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"301") or -- misa
(i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"304") or -- mie
(i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"305") or -- mtvev
(i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"340") or -- mscratch
(i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"341") or -- mepc
(i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"342") or -- mcause
(i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"343") or -- mtval
(i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"344") or -- mip
(i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"34a") or -- mtinst
if (execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"300") or -- mstatus
(execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"301") or -- misa
(execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"304") or -- mie
(execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"305") or -- mtvev
(execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"340") or -- mscratch
(execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"341") or -- mepc
(execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"342") or -- mcause
(execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"343") or -- mtval
(execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"344") or -- mip
(execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"34a") or -- mtinst
--
((i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"c00") and (CPU_EXTENSION_RISCV_E = false)) or -- cycle
((i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"c01") and (CPU_EXTENSION_RISCV_E = false)) or -- time
((i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"c02") and (CPU_EXTENSION_RISCV_E = false)) or -- instret
((i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"c80") and (CPU_EXTENSION_RISCV_E = false)) or -- cycleh
((i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"c81") and (CPU_EXTENSION_RISCV_E = false)) or -- timeh
((i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"c82") and (CPU_EXTENSION_RISCV_E = false)) or -- instreth
((execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"c00") and (CPU_EXTENSION_RISCV_E = false) and (CSR_COUNTERS_USE = true)) or -- cycle
((execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"c01") and (CPU_EXTENSION_RISCV_E = false) and (CSR_COUNTERS_USE = true)) or -- time
((execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"c02") and (CPU_EXTENSION_RISCV_E = false) and (CSR_COUNTERS_USE = true)) or -- instret
((execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"c80") and (CPU_EXTENSION_RISCV_E = false) and (CSR_COUNTERS_USE = true)) or -- cycleh
((execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"c81") and (CPU_EXTENSION_RISCV_E = false) and (CSR_COUNTERS_USE = true)) or -- timeh
((execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"c82") and (CPU_EXTENSION_RISCV_E = false) and (CSR_COUNTERS_USE = true)) or -- instreth
--
((i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"b00") and (CPU_EXTENSION_RISCV_E = false)) or -- mcycle
((i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"b02") and (CPU_EXTENSION_RISCV_E = false)) or -- minstret
((i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"b80") and (CPU_EXTENSION_RISCV_E = false)) or -- mcycleh
((i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"b82") and (CPU_EXTENSION_RISCV_E = false)) or -- minstreth
((execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"b00") and (CPU_EXTENSION_RISCV_E = false) and (CSR_COUNTERS_USE = true)) or -- mcycle
((execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"b02") and (CPU_EXTENSION_RISCV_E = false) and (CSR_COUNTERS_USE = true)) or -- minstret
((execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"b80") and (CPU_EXTENSION_RISCV_E = false) and (CSR_COUNTERS_USE = true)) or -- mcycleh
((execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"b82") and (CPU_EXTENSION_RISCV_E = false) and (CSR_COUNTERS_USE = true)) or -- minstreth
--
(i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"f13") or -- mimpid
(i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"f14") or -- mhartid
(i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"fff") or -- mhwctrl
(execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"f13") or -- mimpid
(execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"f14") or -- mhartid
--
(i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"fc0") or -- mfeatures
(i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"fc1") or -- mclock
(i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"fc4") or -- mispacebase
(i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"fc5") or -- mispacesize
(i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"fc6") or -- mdspacebase
(i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"fc7") then -- mdspacesize
(execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"fc0") or -- mfeatures
(execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"fc1") or -- mclock
(execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"fc4") or -- mispacebase
(execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"fc5") or -- mispacesize
(execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"fc6") or -- mdspacebase
(execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"fc7") then -- mdspacesize
illegal_instruction <= '0';
else
illegal_instruction <= '1';
816,12 → 1071,12
end if;
 
-- ecall, ebreak, mret, wfi --
elsif (i_reg(instr_rd_msb_c downto instr_rd_lsb_c) = "00000") and
(i_reg(instr_rs1_msb_c downto instr_rs1_lsb_c) = "00000") then
if (i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = "000000000000") or -- ECALL
(i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = "000000000001") or -- EBREAK
(i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = "001100000010") or -- MRET
(i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = "000100000101") then -- WFI
elsif (execute_engine.i_reg(instr_rd_msb_c downto instr_rd_lsb_c) = "00000") and
(execute_engine.i_reg(instr_rs1_msb_c downto instr_rs1_lsb_c) = "00000") then
if (execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = "000000000000") or -- ECALL
(execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = "000000000001") or -- EBREAK
(execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = "001100000010") or -- MRET
(execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = "000100000101") then -- WFI
illegal_instruction <= '0';
else
illegal_instruction <= '1';
831,10 → 1086,10
end if;
 
when others => -- compressed instruction or undefined instruction
if (i_reg(1 downto 0) = "11") then -- undefined/unimplemented opcode
if (execute_engine.i_reg(1 downto 0) = "11") then -- undefined/unimplemented opcode
illegal_instruction <= '1';
else -- compressed instruction
illegal_compressed <= ci_valid and ci_illegal;
else -- compressed instruction: illegal or disabled / not implemented
illegal_compressed <= ci_illegal or (not csr.misa_c_en);
end if;
 
end case;
846,142 → 1101,106
end process illegal_instruction_check;
 
-- any illegal condition? --
illegal_instr_exc <= illegal_instruction or illegal_register or illegal_compressed;
trap_ctrl.instr_il <= illegal_instruction or illegal_register or illegal_compressed;
 
 
-- Program Counter ------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
program_counter: process(rstn_i, clk_i)
begin
if (rstn_i = '0') then
if (BOOTLOADER_USE = true) then -- boot from bootloader ROM
pc_reg <= boot_base_c;
pc_backup_reg <= boot_base_c;
pc_backup2_reg <= boot_base_c;
else -- boot from IMEM
pc_reg <= MEM_ISPACE_BASE;
pc_backup_reg <= MEM_ISPACE_BASE;
pc_backup2_reg <= MEM_ISPACE_BASE;
end if;
elsif rising_edge(clk_i) then
-- actual PC --
if (exc_cpu_ack = '1') then -- exception start?
pc_reg <= mtvec;
elsif (exc_cpu_end = '1') then -- return from exception
pc_reg <= mepc;
elsif (ctrl(ctrl_csr_pc_we_c) = '1') or ((is_branch and branch_taken) = '1') then -- manual update or taken branch
pc_reg <= alu_add_i;
end if;
-- delayed PC --
if (state = IFETCH_1) then
pc_backup_reg <= pc_reg; -- PC for ALU address computations
end if;
if (state = EXECUTE) then
pc_backup2_reg <= pc_backup_reg; -- PC backup for exceptions
end if;
end if;
end process program_counter;
-- ****************************************************************************************************************************
-- Exception and Interrupt Control
-- ****************************************************************************************************************************
 
-- output --
pc_o <= pc_reg;
alu_pc_o <= pc_backup_reg;
 
 
-- Exception Controller -------------------------------------------------------------------
-- Trap Controller ------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
exception_controller: process(rstn_i, clk_i)
trap_controller: process(rstn_i, clk_i)
begin
if (rstn_i = '0') then
exc_buf <= (others => '0');
irq_buf <= (others => '0');
exc_ack <= '0';
irq_ack <= (others => '0');
exc_src <= (others => '0');
exc_cpu_start <= '0';
exc_cause <= (others => '0');
mtinst <= (others => '0');
trap_ctrl.exc_buf <= (others => '0');
trap_ctrl.irq_buf <= (others => '0');
trap_ctrl.exc_ack <= '0';
trap_ctrl.irq_ack <= (others => '0');
trap_ctrl.cause <= (others => '0');
trap_ctrl.instr <= (others => '0');
trap_ctrl.exc_src <= (others => '0');
trap_ctrl.env_start <= '0';
elsif rising_edge(clk_i) then
if (CPU_EXTENSION_RISCV_Zicsr = true) then
-- exception buffer: misaligned load/store/instruction address
exc_buf(exception_lalign_c) <= (exc_buf(exception_lalign_c) or ma_load_i) and (not exc_ack);
exc_buf(exception_salign_c) <= (exc_buf(exception_salign_c) or ma_store_i) and (not exc_ack);
exc_buf(exception_ialign_c) <= (exc_buf(exception_ialign_c) or ma_instr_i) and (not exc_ack);
trap_ctrl.exc_buf(exception_lalign_c) <= (trap_ctrl.exc_buf(exception_lalign_c) or ma_load_i) and (not trap_ctrl.exc_ack);
trap_ctrl.exc_buf(exception_salign_c) <= (trap_ctrl.exc_buf(exception_salign_c) or ma_store_i) and (not trap_ctrl.exc_ack);
trap_ctrl.exc_buf(exception_ialign_c) <= (trap_ctrl.exc_buf(exception_ialign_c) or trap_ctrl.instr_ma) and (not trap_ctrl.exc_ack);
-- exception buffer: load/store/instruction bus access error
exc_buf(exception_laccess_c) <= (exc_buf(exception_laccess_c) or be_load_i) and (not exc_ack);
exc_buf(exception_saccess_c) <= (exc_buf(exception_saccess_c) or be_store_i) and (not exc_ack);
exc_buf(exception_iaccess_c) <= (exc_buf(exception_iaccess_c) or be_instr_i) and (not exc_ack);
trap_ctrl.exc_buf(exception_laccess_c) <= (trap_ctrl.exc_buf(exception_laccess_c) or be_load_i) and (not trap_ctrl.exc_ack);
trap_ctrl.exc_buf(exception_saccess_c) <= (trap_ctrl.exc_buf(exception_saccess_c) or be_store_i) and (not trap_ctrl.exc_ack);
trap_ctrl.exc_buf(exception_iaccess_c) <= (trap_ctrl.exc_buf(exception_iaccess_c) or trap_ctrl.instr_be) and (not trap_ctrl.exc_ack);
-- exception buffer: illegal instruction / env call / break point
exc_buf(exception_iillegal_c) <= (exc_buf(exception_iillegal_c) or illegal_instr_exc) and (not exc_ack);
exc_buf(exception_m_envcall_c) <= (exc_buf(exception_m_envcall_c) or env_call) and (not exc_ack);
exc_buf(exception_break_c) <= (exc_buf(exception_break_c) or break_point) and (not exc_ack);
trap_ctrl.exc_buf(exception_m_envcall_c) <= (trap_ctrl.exc_buf(exception_m_envcall_c) or trap_ctrl.env_call) and (not trap_ctrl.exc_ack);
trap_ctrl.exc_buf(exception_break_c) <= (trap_ctrl.exc_buf(exception_break_c) or trap_ctrl.break_point) and (not trap_ctrl.exc_ack);
trap_ctrl.exc_buf(exception_iillegal_c) <= (trap_ctrl.exc_buf(exception_iillegal_c) or trap_ctrl.instr_il) and (not trap_ctrl.exc_ack);
-- interrupt buffer: machine software/external/timer interrupt
irq_buf(interrupt_msw_irq_c) <= mie_msie and (irq_buf(interrupt_msw_irq_c) or mip_msip) and (not irq_ack(interrupt_msw_irq_c));
irq_buf(interrupt_mext_irq_c) <= mie_meie and (irq_buf(interrupt_mext_irq_c) or clic_irq_i) and (not irq_ack(interrupt_mext_irq_c));
irq_buf(interrupt_mtime_irq_c) <= mie_mtie and (irq_buf(interrupt_mtime_irq_c) or mtime_irq_i) and (not irq_ack(interrupt_mtime_irq_c));
trap_ctrl.irq_buf(interrupt_msw_irq_c) <= csr.mie_msie and (trap_ctrl.irq_buf(interrupt_msw_irq_c) or csr.mip_msip) and (not trap_ctrl.irq_ack(interrupt_msw_irq_c));
trap_ctrl.irq_buf(interrupt_mext_irq_c) <= csr.mie_meie and (trap_ctrl.irq_buf(interrupt_mext_irq_c) or clic_irq_i) and (not trap_ctrl.irq_ack(interrupt_mext_irq_c));
trap_ctrl.irq_buf(interrupt_mtime_irq_c) <= csr.mie_mtie and (trap_ctrl.irq_buf(interrupt_mtime_irq_c) or mtime_irq_i) and (not trap_ctrl.irq_ack(interrupt_mtime_irq_c));
 
-- exception control --
if (exc_cpu_start = '0') then --
-- exception/interrupt triggered, waiting for IRQ in EXECUTE (make sure at least 1 instr. is executed even for a continous IRQ)
if (exc_fire = '1') or ((irq_fire = '1') and ((state = EXECUTE) or (state = SLEEP))) then
exc_cause <= exc_cause_nxt; -- capture source for program
mtinst <= i_reg; -- MTINST NOT FOULLY IMPLEMENTED YET! FIXME
mtinst(1) <= not is_ci; -- bit is set for uncompressed instruction
exc_src <= exc_buf; -- capture source for hardware
exc_ack <= '1'; -- clear execption
irq_ack <= irq_ack_nxt; -- capture and clear with interrupt ACK mask
exc_cpu_start <= '1';
-- trap control --
if (trap_ctrl.env_start = '0') then -- no started trap handler
if (trap_ctrl.exc_fire = '1') or ((trap_ctrl.irq_fire = '1') and
((execute_engine.state = EXECUTE) or (execute_engine.state = TRAP))) then -- exception/IRQ detected!
trap_ctrl.cause <= trap_ctrl.cause_nxt; -- capture source ID for program
trap_ctrl.instr <= execute_engine.i_reg; -- FIXME mtinst transformation not fully implemented yet!
trap_ctrl.instr(1) <= not execute_engine.is_ci; -- bit is set for uncompressed instruction
trap_ctrl.exc_src <= trap_ctrl.exc_buf; -- capture exception source for hardware
trap_ctrl.exc_ack <= '1'; -- clear execption
trap_ctrl.irq_ack <= trap_ctrl.irq_ack_nxt; -- capture and clear with interrupt ACK mask
trap_ctrl.env_start <= '1'; -- now we want to start the trap handler
end if;
else -- waiting for exception handler to get started
if (exc_cpu_ack = '1') then -- handler started?
exc_ack <= '0';
irq_ack <= (others => '0');
exc_cpu_start <= '0';
else -- trap waiting to get started
if (trap_ctrl.env_start_ack = '1') then -- start of trap handler acknowledged by execution engine
trap_ctrl.exc_ack <= '0';
trap_ctrl.irq_ack <= (others => '0');
trap_ctrl.env_start <= '0';
end if;
end if;
else -- (CPU_EXTENSION_RISCV_Zicsr = false)
exc_buf <= (others => '0');
irq_buf <= (others => '0');
exc_ack <= '0';
irq_ack <= (others => '0');
exc_src <= (others => '0');
exc_cpu_start <= '0';
exc_cause <= (others => '0');
mtinst <= (others => '0');
end if;
end if;
end process exception_controller;
end process trap_controller;
 
-- any exception/interrupt? --
exc_fire <= or_all_f(exc_buf); -- classic exceptions (faults/traps) cannot be masked
irq_fire <= or_all_f(irq_buf) and mstatus_mie; -- classic interrupts can be enabled/disabled
trap_ctrl.exc_fire <= or_all_f(trap_ctrl.exc_buf); -- classic exceptions (faults/traps) cannot be masked
trap_ctrl.irq_fire <= or_all_f(trap_ctrl.irq_buf) and csr.mstatus_mie; -- classic interrupts can be enabled/disabled
 
-- exception acknowledge for bus unit --
bus_exc_ack_o <= exc_cpu_ack;
bus_exc_ack_o <= trap_ctrl.env_start_ack or fetch_engine.bus_err_ack;
 
-- exception priority encoder --
exc_priority: process(exc_buf, irq_buf)
-- exception/interrupt/status ID visible for program --
csr.mcause <= trap_ctrl.cause;
csr.mtinst <= trap_ctrl.instr;
 
 
-- Trap Priority Detector -----------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
trap_priority: process(trap_ctrl)
begin
-- defaults --
exc_cause_nxt <= (others => '0');
irq_ack_nxt <= (others => '0');
trap_ctrl.cause_nxt <= (others => '0');
trap_ctrl.irq_ack_nxt <= (others => '0');
 
-- interrupt: 1.11 machine external interrupt --
if (irq_buf(interrupt_mext_irq_c) = '1') then
exc_cause_nxt(exc_cause_nxt'left) <= '1';
exc_cause_nxt(3 downto 0) <= "1011";
irq_ack_nxt(interrupt_mext_irq_c) <= '1';
if (trap_ctrl.irq_buf(interrupt_mext_irq_c) = '1') then
trap_ctrl.cause_nxt(data_width_c-1) <= '1';
trap_ctrl.cause_nxt(3 downto 0) <= "1011";
trap_ctrl.irq_ack_nxt(interrupt_mext_irq_c) <= '1';
 
-- interrupt: 1.7 machine timer interrupt --
elsif (irq_buf(interrupt_mtime_irq_c) = '1') then
exc_cause_nxt(exc_cause_nxt'left) <= '1';
exc_cause_nxt(3 downto 0) <= "0111";
irq_ack_nxt(interrupt_mtime_irq_c) <= '1';
elsif (trap_ctrl.irq_buf(interrupt_mtime_irq_c) = '1') then
trap_ctrl.cause_nxt(data_width_c-1) <= '1';
trap_ctrl.cause_nxt(3 downto 0) <= "0111";
trap_ctrl.irq_ack_nxt(interrupt_mtime_irq_c) <= '1';
 
-- interrupt: 1.3 machine SW interrupt --
elsif (irq_buf(interrupt_msw_irq_c) = '1') then
exc_cause_nxt(exc_cause_nxt'left) <= '1';
exc_cause_nxt(3 downto 0) <= "0011";
irq_ack_nxt(interrupt_msw_irq_c) <= '1';
elsif (trap_ctrl.irq_buf(interrupt_msw_irq_c) = '1') then
trap_ctrl.cause_nxt(data_width_c-1) <= '1';
trap_ctrl.cause_nxt(3 downto 0) <= "0011";
trap_ctrl.irq_ack_nxt(interrupt_msw_irq_c) <= '1';
 
 
-- the following traps are caused by synchronous exceptions
988,150 → 1207,161
-- here we do not need an acknowledge mask since only one exception can trigger at the same time
 
-- trap/fault: 0.0 instruction address misaligned --
elsif (exc_buf(exception_ialign_c) = '1') then
exc_cause_nxt(exc_cause_nxt'left) <= '0';
exc_cause_nxt(3 downto 0) <= "0000";
elsif (trap_ctrl.exc_buf(exception_ialign_c) = '1') then
trap_ctrl.cause_nxt(data_width_c-1) <= '0';
trap_ctrl.cause_nxt(3 downto 0) <= "0000";
 
-- trap/fault: 0.1 instruction access fault --
elsif (exc_buf(exception_iaccess_c) = '1') then
exc_cause_nxt(exc_cause_nxt'left) <= '0';
exc_cause_nxt(3 downto 0) <= "0001";
elsif (trap_ctrl.exc_buf(exception_iaccess_c) = '1') then
trap_ctrl.cause_nxt(data_width_c-1) <= '0';
trap_ctrl.cause_nxt(3 downto 0) <= "0001";
 
-- trap/fault: 0.2 illegal instruction --
elsif (exc_buf(exception_iillegal_c) = '1') then
exc_cause_nxt(exc_cause_nxt'left) <= '0';
exc_cause_nxt(3 downto 0) <= "0010";
elsif (trap_ctrl.exc_buf(exception_iillegal_c) = '1') then
trap_ctrl.cause_nxt(data_width_c-1) <= '0';
trap_ctrl.cause_nxt(3 downto 0) <= "0010";
 
 
-- trap/fault: 0.11 environment call from M-mode --
elsif (exc_buf(exception_m_envcall_c) = '1') then
exc_cause_nxt(exc_cause_nxt'left) <= '0';
exc_cause_nxt(3 downto 0) <= "1011";
elsif (trap_ctrl.exc_buf(exception_m_envcall_c) = '1') then
trap_ctrl.cause_nxt(data_width_c-1) <= '0';
trap_ctrl.cause_nxt(3 downto 0) <= "1011";
 
-- trap/fault: 0.3 breakpoint --
elsif (exc_buf(exception_break_c) = '1') then
exc_cause_nxt(exc_cause_nxt'left) <= '0';
exc_cause_nxt(3 downto 0) <= "0011";
elsif (trap_ctrl.exc_buf(exception_break_c) = '1') then
trap_ctrl.cause_nxt(data_width_c-1) <= '0';
trap_ctrl.cause_nxt(3 downto 0) <= "0011";
 
 
-- trap/fault: 0.6 store address misaligned -
elsif (exc_buf(exception_salign_c) = '1') then
exc_cause_nxt(exc_cause_nxt'left) <= '0';
exc_cause_nxt(3 downto 0) <= "0110";
elsif (trap_ctrl.exc_buf(exception_salign_c) = '1') then
trap_ctrl.cause_nxt(data_width_c-1) <= '0';
trap_ctrl.cause_nxt(3 downto 0) <= "0110";
 
-- trap/fault: 0.4 load address misaligned --
elsif (exc_buf(exception_lalign_c) = '1') then
exc_cause_nxt(exc_cause_nxt'left) <= '0';
exc_cause_nxt(3 downto 0) <= "0100";
elsif (trap_ctrl.exc_buf(exception_lalign_c) = '1') then
trap_ctrl.cause_nxt(data_width_c-1) <= '0';
trap_ctrl.cause_nxt(3 downto 0) <= "0100";
 
-- trap/fault: 0.7 store access fault --
elsif (exc_buf(exception_saccess_c) = '1') then
exc_cause_nxt(exc_cause_nxt'left) <= '0';
exc_cause_nxt(3 downto 0) <= "0111";
elsif (trap_ctrl.exc_buf(exception_saccess_c) = '1') then
trap_ctrl.cause_nxt(data_width_c-1) <= '0';
trap_ctrl.cause_nxt(3 downto 0) <= "0111";
 
-- trap/fault: 0.5 load access fault --
elsif (exc_buf(exception_laccess_c) = '1') then
exc_cause_nxt(exc_cause_nxt'left) <= '0';
exc_cause_nxt(3 downto 0) <= "0101";
elsif (trap_ctrl.exc_buf(exception_laccess_c) = '1') then
trap_ctrl.cause_nxt(data_width_c-1) <= '0';
trap_ctrl.cause_nxt(3 downto 0) <= "0101";
 
-- undefined / not implemented --
else
exc_cause_nxt <= (others => '0');
irq_ack_nxt <= (others => '0');
trap_ctrl.cause_nxt <= (others => '0');
trap_ctrl.irq_ack_nxt <= (others => '0');
end if;
end process exc_priority;
end process trap_priority;
 
-- ****************************************************************************************************************************
-- Control and Status Registers (CSRs)
-- ****************************************************************************************************************************
 
-- CSR CPU Access -------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
csr_cpu_acc: process(clk_i)
begin
if rising_edge(clk_i) then
csr.we <= csr.we_nxt;
csr.re <= csr.re_nxt;
end if;
end process csr_cpu_acc;
 
 
-- Control and Status Registers Write Access ----------------------------------------------
-- -------------------------------------------------------------------------------------------
csr_write_access: process(rstn_i, clk_i)
begin
if (rstn_i = '0') then
mstatus_mie <= '0';
mstatus_mpie <= '0';
mie_msie <= '0';
mie_meie <= '0';
mie_mtie <= '0';
mtvec <= (others => '0');
mtval <= (others => '0');
mepc <= (others => '0');
mip_msip <= '0';
csr.mstatus_mie <= '0';
csr.mstatus_mpie <= '0';
csr.mie_msie <= '0';
csr.mie_meie <= '0';
csr.mie_mtie <= '0';
csr.mtvec <= (others => '0');
csr.mtval <= (others => '0');
csr.mepc <= (others => '0');
csr.mip_msip <= '0';
csr.misa_c_en <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_C); -- C CPU extension
csr.misa_m_en <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_M); -- M CPU extension
elsif rising_edge(clk_i) then
if (CPU_EXTENSION_RISCV_Zicsr = true) then
mip_msip <= '0';
csr.mip_msip <= '0';
 
-- register that can be modified by user --
if (ctrl(ctrl_csr_we_c) = '1') then -- manual update
if (csr.we = '1') then -- manual update
 
-- machine trap setup --
if (i_reg(31 downto 24) = x"30") then
if (i_reg(23 downto 20) = x"0") then -- R/W: mstatus - machine status register
mstatus_mie <= csr_wdata_i(03);
mstatus_mpie <= csr_wdata_i(07);
if (execute_engine.i_reg(31 downto 24) = x"30") then
if (execute_engine.i_reg(23 downto 20) = x"0") then -- R/W: mstatus - machine status register
csr.mstatus_mie <= csr_wdata_i(03);
csr.mstatus_mpie <= csr_wdata_i(07);
end if;
if (i_reg(23 downto 20) = x"4") then -- R/W: mie - machine interrupt-enable register
mie_msie <= csr_wdata_i(03); -- SW IRQ enable
mie_mtie <= csr_wdata_i(07); -- TIMER IRQ enable
mie_meie <= csr_wdata_i(11); -- EXT IRQ enable
if (execute_engine.i_reg(23 downto 20) = x"1") then -- R/W: misa - machine instruction set extensions
csr.misa_c_en <= csr_wdata_i(02); -- C extension enable/disable
csr.misa_m_en <= csr_wdata_i(12); -- M extension enable/disable
end if;
if (i_reg(23 downto 20) = x"5") then -- R/W: mtvec - machine trap-handler base address (for ALL exceptions)
mtvec <= csr_wdata_i;
if (execute_engine.i_reg(23 downto 20) = x"4") then -- R/W: mie - machine interrupt-enable register
csr.mie_msie <= csr_wdata_i(03); -- SW IRQ enable
csr.mie_mtie <= csr_wdata_i(07); -- TIMER IRQ enable
csr.mie_meie <= csr_wdata_i(11); -- EXT IRQ enable
end if;
if (execute_engine.i_reg(23 downto 20) = x"5") then -- R/W: mtvec - machine trap-handler base address (for ALL exceptions)
csr.mtvec <= csr_wdata_i;
end if;
end if;
 
-- machine trap handling --
if (i_reg(31 downto 24) = x"34") then
if (i_reg(23 downto 20) = x"0") then -- R/W: mscratch - machine scratch register
mscratch <= csr_wdata_i;
if (execute_engine.i_reg(31 downto 24) = x"34") then
if (execute_engine.i_reg(23 downto 20) = x"0") then -- R/W: mscratch - machine scratch register
csr.mscratch <= csr_wdata_i;
end if;
if (i_reg(23 downto 20) = x"1") then-- R/W: mepc - machine exception program counter
mepc <= csr_wdata_i;
if (execute_engine.i_reg(23 downto 20) = x"1") then-- R/W: mepc - machine exception program counter
csr.mepc <= csr_wdata_i;
end if;
if (i_reg(23 downto 20) = x"4") then -- R/W: mip - machine interrupt pending
mip_msip <= csr_wdata_i(03); -- manual SW IRQ trigger
if (execute_engine.i_reg(23 downto 20) = x"4") then -- R/W: mip - machine interrupt pending
csr.mip_msip <= csr_wdata_i(03); -- manual SW IRQ trigger
end if;
end if;
 
else -- automatic update by hardware
-- machine exception PC & exception value register --
if (exc_cpu_ack = '1') then -- exception start?
if (exc_cause(exc_cause_nxt'left) = '1') then -- for INTERRUPTs: mepc = address of next (unclompeted) instruction
mepc <= pc_reg;
mtval <= (others => '0'); -- not specified
else -- for EXCEPTIONs: mepc = address of next (unclompeted) instruction
mepc <= pc_backup2_reg;
if ((exc_src(exception_iaccess_c) or exc_src(exception_ialign_c)) = '1') then -- instruction access error OR misaligned instruction
mtval <= pc_backup_reg;
elsif (exc_src(exception_iillegal_c) = '1') then -- illegal instruction
mtval <= i_reg;
elsif ((exc_src(exception_lalign_c) or exc_src(exception_salign_c) or
exc_src(exception_laccess_c) or exc_src(exception_saccess_c)) = '1') then -- load/store misaligned / access error
mtval <= mar_i;
if (trap_ctrl.env_start_ack = '1') then -- trap handler started?
if (csr.mcause(data_width_c-1) = '1') then -- for INTERRUPTS only (mtval not defined for interrupts)
csr.mepc <= execute_engine.pc(data_width_c-1 downto 1) & '0'; -- this is the CURRENT pc = interrupted instruction
csr.mtval <= (others => '0');
else -- for EXCEPTIONs
csr.mepc <= execute_engine.last_pc(data_width_c-1 downto 1) & '0'; -- this is the LAST pc = last executed instruction
if ((trap_ctrl.exc_src(exception_iaccess_c) or trap_ctrl.exc_src(exception_ialign_c)) = '1') then -- instruction access error OR misaligned instruction
csr.mtval <= execute_engine.pc(data_width_c-1 downto 1) & '0';
elsif (trap_ctrl.exc_src(exception_iillegal_c) = '1') then -- illegal instruction
csr.mtval <= execute_engine.i_reg;
else -- everything else
--elsif ((trap_ctrl.exc_src(exception_lalign_c) or trap_ctrl.exc_src(exception_salign_c) or
-- trap_ctrl.exc_src(exception_laccess_c) or trap_ctrl.exc_src(exception_saccess_c)) = '1') then -- load/store misaligned / access error
csr.mtval <= mar_i;
end if;
end if;
end if;
 
-- context switch in mstatus --
if (exc_cpu_ack = '1') then -- actually entering trap
mstatus_mie <= '0';
if (mstatus_mpie = '0') then -- FIXME: prevent loosing the prev MIE state after several traps
mstatus_mpie <= mstatus_mie;
if (trap_ctrl.env_start_ack = '1') then -- actually entering trap
csr.mstatus_mie <= '0';
if (csr.mstatus_mpie = '0') then -- FIXME: prevent loosing the prev MIE state after several traps
csr.mstatus_mpie <= csr.mstatus_mie;
end if;
elsif (exc_cpu_end = '1') then -- return from exception
mstatus_mie <= mstatus_mpie;
elsif (trap_ctrl.env_end = '1') then -- return from exception
csr.mstatus_mie <= csr.mstatus_mpie;
end if;
end if;
 
else -- CPU_EXTENSION_RISCV_Zicsr = false
mstatus_mie <= '0';
mstatus_mpie <= '0';
mie_msie <= '0';
mie_meie <= '0';
mie_mtie <= '0';
mtvec <= (others => '0');
mtval <= (others => '0');
mepc <= (others => '0');
mip_msip <= '0';
end if;
end if;
end process csr_write_access;
1144,67 → 1374,66
if rising_edge(clk_i) then
csr_rdata_o <= (others => '0'); -- default
if (CPU_EXTENSION_RISCV_Zicsr = true) then -- implement CSR access at all?
if (ctrl(ctrl_csr_re_c) = '1') then
case i_reg(31 downto 20) is
if (csr.re = '1') then
case execute_engine.i_reg(31 downto 20) is
-- machine trap setup --
when x"300" => -- R/W: mstatus - machine status register
csr_rdata_o(03) <= mstatus_mie; -- MIE
csr_rdata_o(07) <= mstatus_mpie; -- MPIE
csr_rdata_o(03) <= csr.mstatus_mie; -- MIE
csr_rdata_o(07) <= csr.mstatus_mpie; -- MPIE
csr_rdata_o(11) <= '1'; -- MPP low
csr_rdata_o(12) <= '1'; -- MPP high
when x"301" => -- R/-: misa - ISA and extensions
csr_rdata_o(02) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_C); -- C CPU extension
when x"301" => -- R/W: misa - ISA and extensions
csr_rdata_o(02) <= csr.misa_c_en; -- C CPU extension
csr_rdata_o(04) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_E); -- E CPU extension
csr_rdata_o(08) <= not bool_to_ulogic_f(CPU_EXTENSION_RISCV_E); -- I CPU extension (if not E)
csr_rdata_o(12) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_M); -- M CPU extension
csr_rdata_o(12) <= csr.misa_m_en; -- M CPU extension
csr_rdata_o(23) <= '1'; -- X CPU extension: non-standard extensions
csr_rdata_o(25) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zicsr); -- Z CPU extension
csr_rdata_o(30) <= '1'; -- 32-bit architecture (MXL lo)
csr_rdata_o(31) <= '0'; -- 32-bit architecture (MXL hi)
when x"304" => -- R/W: mie - machine interrupt-enable register
csr_rdata_o(03) <= mie_msie; -- software IRQ enable
csr_rdata_o(07) <= mie_mtie; -- timer IRQ enable
csr_rdata_o(11) <= mie_meie; -- external IRQ enable
csr_rdata_o(03) <= csr.mie_msie; -- software IRQ enable
csr_rdata_o(07) <= csr.mie_mtie; -- timer IRQ enable
csr_rdata_o(11) <= csr.mie_meie; -- external IRQ enable
when x"305" => -- R/W: mtvec - machine trap-handler base address (for ALL exceptions)
csr_rdata_o <= mtvec;
csr_rdata_o <= csr.mtvec;
-- machine trap handling --
when x"340" => -- R/W: mscratch - machine scratch register
csr_rdata_o <= mscratch;
csr_rdata_o <= csr.mscratch;
when x"341" => -- R/W: mepc - machine exception program counter
csr_rdata_o <= mepc;
csr_rdata_o <= csr.mepc;
when x"342" => -- R/-: mcause - machine trap cause
csr_rdata_o <= exc_cause;
csr_rdata_o <= csr.mcause;
when x"343" => -- R/-: mtval - machine bad address or instruction
csr_rdata_o <= mtval;
csr_rdata_o <= csr.mtval;
when x"344" => -- R/W: mip - machine interrupt pending
csr_rdata_o(03) <= irq_buf(interrupt_msw_irq_c);
csr_rdata_o(07) <= irq_buf(interrupt_mtime_irq_c);
csr_rdata_o(11) <= irq_buf(interrupt_mext_irq_c);
csr_rdata_o(03) <= trap_ctrl.irq_buf(interrupt_msw_irq_c);
csr_rdata_o(07) <= trap_ctrl.irq_buf(interrupt_mtime_irq_c);
csr_rdata_o(11) <= trap_ctrl.irq_buf(interrupt_mext_irq_c);
when x"34a" => -- R/-: mtinst - machine trap instruction (transformed)
csr_rdata_o <= mtinst;
csr_rdata_o <= csr.mtinst;
-- counter and timers --
when x"c00" | x"c01" | x"b00" => -- R/-: cycle/time/mcycle: Cycle counter LOW / Timer LOW
csr_rdata_o <= cycle_lo(31 downto 0);
csr_rdata_o <= csr.cycle(31 downto 0);
when x"c02" | x"b02" => -- R/-: instret/minstret: Instructions-retired counter LOW
csr_rdata_o <= instret_lo(31 downto 0);
csr_rdata_o <= csr.instret(31 downto 0);
when x"c80" | x"c81" | x"b80" => -- R/-: cycleh/timeh/mcycleh: Cycle counter HIGH / Timer HIGH
csr_rdata_o(15 downto 0) <= cycle_hi; -- counter is only 16-bit wide!
csr_rdata_o <= csr.cycleh;
when x"c82" | x"b82" => -- R/-: instreth/minstreth: Instructions-retired counter HIGH
csr_rdata_o(15 downto 0) <= instret_hi; -- counter is only 16-bit wide!
csr_rdata_o <= csr.instreth;
-- machine information registers --
when x"f13" => -- R/-: mimpid - implementation ID / version
csr_rdata_o <= hw_version_c;
when x"f14" => -- R/-: mhartid - hardware thread ID
csr_rdata_o <= HART_ID;
when x"fff" => -- R/-: mhwctrl - hardware controller
csr_rdata_o <= hw_control;
-- CUSTOM read-only machine CSRs --
when x"fc0" => -- R/-: mfeatures - implemented processor devices/features
csr_rdata_o(00) <= bool_to_ulogic_f(BOOTLOADER_USE); -- implement processor-internal bootloader?
csr_rdata_o(01) <= bool_to_ulogic_f(MEM_EXT_USE); -- implement external memory bus interface?
csr_rdata_o(02) <= bool_to_ulogic_f(MEM_INT_IMEM_USE); -- implement processor-internal instruction memory
csr_rdata_o(03) <= bool_to_ulogic_f(MEM_INT_IMEM_ROM); -- implement processor-internal instruction memory as ROM
csr_rdata_o(04) <= bool_to_ulogic_f(MEM_INT_DMEM_USE); -- implement processor-internal data memory
csr_rdata_o(02) <= bool_to_ulogic_f(MEM_INT_IMEM_USE); -- implement processor-internal instruction memory?
csr_rdata_o(03) <= bool_to_ulogic_f(MEM_INT_IMEM_ROM); -- implement processor-internal instruction memory as ROM?
csr_rdata_o(04) <= bool_to_ulogic_f(MEM_INT_DMEM_USE); -- implement processor-internal data memory?
csr_rdata_o(05) <= bool_to_ulogic_f(CSR_COUNTERS_USE); -- implement RISC-V (performance) counter?
--
csr_rdata_o(16) <= bool_to_ulogic_f(IO_GPIO_USE); -- implement general purpose input/output port unit (GPIO)?
csr_rdata_o(17) <= bool_to_ulogic_f(IO_MTIME_USE); -- implement machine system timer (MTIME)?
1236,41 → 1465,34
end process csr_read_access;
 
 
-- Optional RISC-V CSRs: Counters ---------------------------------------------------------
-- RISC-V Counter CSRs --------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
csr_counters: process(rstn_i, clk_i)
begin
if rising_edge(clk_i) then
if (rstn_i = '0') then
cycle_lo <= (others => '0');
instret_lo <= (others => '0');
cycle_hi <= (others => '0');
instret_hi <= (others => '0');
cycle_lo_msb <= '0';
instret_lo_msb <= '0';
elsif (CPU_EXTENSION_RISCV_E = false) then
if (rstn_i = '0') then
csr.cycle <= (others => '0');
csr.instret <= (others => '0');
csr.cycleh <= (others => '0');
csr.instreth <= (others => '0');
cycle_msb <= '0';
instret_msb <= '0';
elsif rising_edge(clk_i) then
if (CPU_EXTENSION_RISCV_E = false) and (CSR_COUNTERS_USE = true) then
-- low word overflow buffers --
cycle_lo_msb <= cycle_lo(cycle_lo'left);
instret_lo_msb <= instret_lo(instret_lo'left);
cycle_msb <= csr.cycle(csr.cycle'left);
instret_msb <= csr.instret(csr.instret'left);
-- low word counters --
cycle_lo <= std_ulogic_vector(unsigned(cycle_lo) + 1);
if (state = EXECUTE) then
instret_lo <= std_ulogic_vector(unsigned(instret_lo) + 1);
csr.cycle <= std_ulogic_vector(unsigned(csr.cycle) + 1);
if (execute_engine.state_prev /= EXECUTE) and (execute_engine.state = EXECUTE) then
csr.instret <= std_ulogic_vector(unsigned(csr.instret) + 1);
end if;
-- high word counters --
if ((cycle_lo_msb xor cycle_lo(cycle_lo'left)) = '1') then
cycle_hi <= std_ulogic_vector(unsigned(cycle_hi) + 1);
if ((cycle_msb xor csr.cycle(csr.cycle'left)) = '1') then
csr.cycleh <= std_ulogic_vector(unsigned(csr.cycleh) + 1);
end if;
if ((instret_lo_msb xor instret_lo(instret_lo'left)) = '1') then
instret_hi <= std_ulogic_vector(unsigned(instret_hi) + 1);
if ((instret_msb xor csr.instret(csr.instret'left)) = '1') then
csr.instreth <= std_ulogic_vector(unsigned(csr.instreth) + 1);
end if;
else -- counters are not available in embedded mode
cycle_lo <= (others => '0');
instret_lo <= (others => '0');
cycle_hi <= (others => '0');
instret_hi <= (others => '0');
cycle_lo_msb <= '0';
instret_lo_msb <= '0';
end if;
end if;
end process csr_counters;
/rtl/core/neorv32_cpu_cp_muldiv.vhd
2,8 → 2,8
-- # << NEORV32 - CPU Co-Processor: MULDIV unit >> #
-- # ********************************************************************************************* #
-- # Multiplier and Divider unit. Implements the RISC-V RV32-M CPU extension. #
-- # Multiplier core (signed/unsigned) uses serial algorithm. -> 32+8 cycles latency #
-- # Divider core (unsigned) uses serial algorithm. -> 32+8 cycles latency #
-- # Multiplier core (signed/unsigned) uses serial algorithm. -> 32+4 cycles latency #
-- # Divider core (unsigned) uses serial algorithm. -> 32+6 cycles latency #
-- # ********************************************************************************************* #
-- # BSD 3-Clause License #
-- # #
60,6 → 60,9
 
architecture neorv32_cpu_cp_muldiv_rtl of neorv32_cpu_cp_muldiv is
 
-- constants --
constant all_zero_c : std_ulogic_vector(data_width_c-1 downto 0) := (others => '0');
 
-- controller --
type state_t is (IDLE, DECODE, INIT_OPX, INIT_OPY, PROCESSING, FINALIZE, COMPLETED);
signal state : state_t;
70,6 → 73,7
signal opx, opy : std_ulogic_vector(data_width_c-1 downto 0); -- input operands
signal opx_is_signed : std_ulogic;
signal opy_is_signed : std_ulogic;
signal opy_is_zero : std_ulogic;
signal div_res_corr : std_ulogic;
 
-- divider core --
101,6 → 105,7
start <= '0';
valid_o <= '0';
div_res_corr <= '0';
opy_is_zero <= '0';
elsif rising_edge(clk_i) then
-- defaults --
start <= '0';
118,11 → 123,19
 
when DECODE =>
cnt <= "11111";
if (cp_op = cp_op_div_c) or (cp_op = cp_op_rem_c) then -- result sign compensation for div?
if (cp_op = cp_op_div_c) then -- result sign compensation for div?
div_res_corr <= opx(opx'left) xor opy(opy'left);
elsif (cp_op = cp_op_rem_c) then -- result sign compensation for rem?
div_res_corr <= opx(opx'left);
else
div_res_corr <= '0';
end if;
-- if (cp_op = cp_op_div_c) and (opy = all_zero_c) then -- *divide* by 0?
if (opy = all_zero_c) then -- *divide* by 0?
opy_is_zero <= '1';
else
opy_is_zero <= '0';
end if;
if (operation = '1') then -- division
state <= INIT_OPX;
else -- multiplication
175,7 → 188,7
begin
if rising_edge(clk_i) then
if (start = '1') then -- start new multiplication
mul_product(63 downto 32) <= (others => (opy(opy'left) and opy_is_signed)); -- sign extension
mul_product(63 downto 32) <= (others => '0');
mul_product(31 downto 00) <= opy;
elsif ((state = PROCESSING) or (state = FINALIZE)) and (operation = '0') then
mul_product(63 downto 31) <= mul_do_add(32 downto 0);
189,9 → 202,9
begin
if (mul_product(0) = '1') then
if (mul_sign_cycle = '1') then -- for signed operation only: take care of negative weighted MSB
mul_do_add <= std_ulogic_vector(unsigned(mul_p_sext & mul_product(63 downto 32)) - unsigned((opx(opy'left) and opx_is_signed) & opx));
mul_do_add <= std_ulogic_vector(unsigned(mul_p_sext & mul_product(63 downto 32)) - unsigned((opx(opx'left) and opx_is_signed) & opx));
else
mul_do_add <= std_ulogic_vector(unsigned(mul_p_sext & mul_product(63 downto 32)) + unsigned((opx(opy'left) and opx_is_signed) & opx));
mul_do_add <= std_ulogic_vector(unsigned(mul_p_sext & mul_product(63 downto 32)) + unsigned((opx(opx'left) and opx_is_signed) & opx));
end if;
else
mul_do_add <= mul_p_sext & mul_product(63 downto 32);
232,7 → 245,7
div_sign_comp <= std_ulogic_vector(0 - unsigned(div_sign_comp_in));
 
-- result sign correction --
div_res <= div_sign_comp when (div_res_corr = '1') else div_sign_comp_in;
div_res <= div_sign_comp when (div_res_corr = '1') and (opy_is_zero = '0') else div_sign_comp_in;
 
 
-- Data Output ----------------------------------------------------------------------------
240,6 → 253,7
operation_result: process(clk_i)
begin
if rising_edge(clk_i) then
res_o <= (others => '0'); -- default
case cp_op is
when cp_op_mul_c =>
res_o <= mul_product(31 downto 00);
250,7 → 264,11
when cp_op_divu_c =>
res_o <= quotient;
when cp_op_rem_c =>
res_o <= div_res;
if (opy_is_zero = '0') then
res_o <= div_res;
else
res_o <= opx;
end if;
when cp_op_remu_c =>
res_o <= remainder;
when others => -- undefined
/rtl/core/neorv32_cpu_decompressor.vhd
44,7 → 44,6
-- instruction input --
ci_instr16_i : in std_ulogic_vector(15 downto 0); -- compressed instruction input
-- instruction output --
ci_valid_o : out std_ulogic; -- is a compressed instruction
ci_illegal_o : out std_ulogic; -- is an illegal compressed instruction
ci_instr32_o : out std_ulogic_vector(31 downto 0) -- 32-bit decompressed instruction
);
147,7 → 146,7
ci_instr32_o(24) <= ci_instr16_i(11);
ci_instr32_o(25) <= ci_instr16_i(12);
ci_instr32_o(26) <= ci_instr16_i(5);
ci_instr32_o(31 downto 26) <= (others => '0');
ci_instr32_o(31 downto 27) <= (others => '0');
ci_instr32_o(instr_funct3_msb_c downto instr_funct3_lsb_c) <= funct3_lw_c;
ci_instr32_o(instr_rs1_msb_c downto instr_rs1_lsb_c) <= "01" & ci_instr16_i(ci_rs1_3_msb_c downto ci_rs1_3_lsb_c); -- x8 - x15
ci_instr32_o(instr_rd_msb_c downto instr_rd_lsb_c) <= "01" & ci_instr16_i(ci_rd_3_msb_c downto ci_rd_3_lsb_c); -- x8 - x15
432,8 → 431,5
end case;
end process decompressor;
 
-- is compressed instruction at all? --
ci_valid_o <= '0' when (ci_instr16_i(ci_opcode_msb_c downto ci_opcode_lsb_c) = "11") else '1';
 
 
end neorv32_cpu_decompressor_rtl;
/rtl/core/neorv32_devnull.vhd
3,6 → 3,7
-- # ********************************************************************************************* #
-- # In simulation: This unit will output the lowest 8 bit of the written data as ASCII chars #
-- # to the simulator console and to a text file ("neorv32.devnull.out"). #
-- # The complete data 32-bit data word is dumped to "neorv32.devnull.data.out". #
-- # In real hardware: This unit implements a "/dev/null" device. #
-- # ********************************************************************************************* #
-- # BSD 3-Clause License #
61,7 → 62,8
architecture neorv32_devnull_rtl of neorv32_devnull is
 
-- configuration --
constant sim_output_en_c : boolean := true; -- output lowest byte as char to simulator when enabled
constant sim_text_output_en_c : boolean := true; -- output lowest byte as char to simulator and file when enabled
constant sim_data_output_en_c : boolean := true; -- dump 32-word to file when enabled
 
-- IO space: module base address --
constant hi_abb_c : natural := index_size_f(io_size_c)-1; -- high address boundary bit
80,26 → 82,36
-- Read/Write Access ----------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
rw_access: process(clk_i)
file file_devnull_out : text open write_mode is "neorv32.devnull.out";
file file_devnull_text_out : text open write_mode is "neorv32.devnull.out";
file file_devnull_data_out : text open write_mode is "neorv32.devnull.data.out";
variable i : integer;
variable la, lb : line; -- we need to variables here since "writeline" seems to flush the source variable
variable la, lb, lc : line; -- we need several variables here since "writeline" seems to flush the source variable
begin
if rising_edge(clk_i) then
ack_o <= acc_en and (wren_i or rden_i);
if ((acc_en and wren_i and ben_i(0)) = '1') and (sim_output_en_c = true) then
-- print lowest byte as ASCII to console --
i := to_integer(unsigned(data_i(7 downto 0)));
if (i >= 128) then -- out of range?
i := 0;
if (acc_en = '1') and (wren_i = '1') then
if (sim_text_output_en_c = true) and (ben_i(0) = '1') then
-- print lowest byte as ASCII to console --
i := to_integer(unsigned(data_i(7 downto 0)));
if (i >= 128) then -- out of range?
i := 0;
end if;
if (i /= 10) and (i /= 13) then -- skip line breaks - they are issued via "writeline"
write(la, character'val(i));
write(lb, character'val(i));
end if;
if (i = 10) then -- line break: write to screen and file
writeline(output, la);
writeline(file_devnull_text_out, lb);
end if;
end if;
if (i /= 10) and (i /= 13) then -- skip line breaks - they are issued via "writeline"
write(la, character'val(i));
write(lb, character'val(i));
if (sim_data_output_en_c = true) then
-- dump raw data
for x in 7 downto 0 loop
write(lc, to_hexchar_f(data_i(3+x*4 downto 0+x*4))); -- write in hex form
end loop; -- x
writeline(file_devnull_data_out, lc);
end if;
if (i = 10) then -- line break: write to screen and file
writeline(output, la);
writeline(file_devnull_out, lb);
end if;
end if;
end if;
end process rw_access;
/rtl/core/neorv32_mtime.vhd
108,6 → 108,7
else
-- mtime low --
mtime_lo <= std_ulogic_vector(unsigned(mtime_lo) + 1);
mtime_lo_msb_ff <= mtime_lo(mtime_lo'left);
-- mtime high --
if ((mtime_lo_msb_ff xor mtime_lo(mtime_lo'left)) = '1') then -- mtime_lo carry?
mtime_hi <= std_ulogic_vector(unsigned(mtime_hi) + 1);
/rtl/core/neorv32_package.vhd
41,7 → 41,7
-- Architecture Constants -----------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
constant data_width_c : natural := 32; -- data width - FIXED!
constant hw_version_c : std_ulogic_vector(31 downto 0) := x"00000206"; -- no touchy!
constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01000000"; -- no touchy!
 
-- Internal Functions ---------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
53,6 → 53,7
function and_all_f( a : std_ulogic_vector) return std_ulogic;
function xor_all_f( a : std_ulogic_vector) return std_ulogic;
function xnor_all_f(a : std_ulogic_vector) return std_ulogic;
function to_hexchar_f(input : std_ulogic_vector(3 downto 0)) return character;
 
-- Processor-internal Address Space Layout ------------------------------------------------
-- -------------------------------------------------------------------------------------------
160,9 → 161,9
constant ctrl_alu_cmd1_c : natural := 21; -- ALU command bit 1
constant ctrl_alu_cmd2_c : natural := 22; -- ALU command bit 2
constant ctrl_alu_opa_mux_lsb_c : natural := 23; -- operand A select lsb (00=rs1, 01=PC)
constant ctrl_alu_opa_mux_msb_c : natural := 24; -- operand A select msb (10=CSR, 11=CSR)
constant ctrl_alu_opb_mux_lsb_c : natural := 25; -- operand B select lsb (00=rs2, 01=PC)
constant ctrl_alu_opb_mux_msb_c : natural := 26; -- operand B select msb (10=rs1, 11=PC_increment(2/4))
constant ctrl_alu_opa_mux_msb_c : natural := 24; -- operand A select msb (10=CSR, 11=?)
constant ctrl_alu_opb_mux_lsb_c : natural := 25; -- operand B select lsb (00=rs2, 01=IMM)
constant ctrl_alu_opb_mux_msb_c : natural := 26; -- operand B select msb (10=rs1, 11=?)
constant ctrl_alu_opc_mux_c : natural := 27; -- operand C select (0=IMM, 1=rs2)
constant ctrl_alu_unsigned_c : natural := 28; -- is unsigned ALU operation
constant ctrl_alu_shift_dir_c : natural := 29; -- shift direction (0=left, 1=right)
177,24 → 178,23
constant ctrl_bus_mdo_we_c : natural := 37; -- memory data out register write enable
constant ctrl_bus_mdi_we_c : natural := 38; -- memory data in register write enable
constant ctrl_bus_unsigned_c : natural := 39; -- is unsigned load
-- csr/system --
constant ctrl_csr_pc_we_c : natural := 40; -- PC write enable
constant ctrl_csr_re_c : natural := 41; -- valid CSR read
constant ctrl_csr_we_c : natural := 42; -- valid CSR write
-- co-processor --
constant ctrl_cp_use_c : natural := 43; -- is cp operation
constant ctrl_cp_id_lsb_c : natural := 44; -- cp select lsb
constant ctrl_cp_id_msb_c : natural := 45; -- cp select msb
constant ctrl_cp_cmd0_c : natural := 46; -- cp command bit 0
constant ctrl_cp_cmd1_c : natural := 47; -- cp command bit 1
constant ctrl_cp_cmd2_c : natural := 48; -- cp command bit 2
constant ctrl_cp_use_c : natural := 40; -- is cp operation
constant ctrl_cp_id_lsb_c : natural := 41; -- cp select lsb
constant ctrl_cp_id_msb_c : natural := 42; -- cp select msb
constant ctrl_cp_cmd0_c : natural := 43; -- cp command bit 0
constant ctrl_cp_cmd1_c : natural := 44; -- cp command bit 1
constant ctrl_cp_cmd2_c : natural := 45; -- cp command bit 2
-- system --
constant ctrl_sys_c_ext_en_c : natural := 46; -- CPU C extension enabled
constant ctrl_sys_m_ext_en_c : natural := 47; -- CPU M extension enabled
-- control bus size --
constant ctrl_width_c : natural := 49; -- control bus size
constant ctrl_width_c : natural := 48; -- control bus size
 
-- ALU Comparator Bus ---------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
constant alu_cmp_equal_c : natural := 0;
constant alu_cmp_less_c : natural := 1; -- for signed and unsigned
constant alu_cmp_less_c : natural := 1; -- for signed and unsigned comparisons
 
-- RISC-V Opcode Layout -------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
279,14 → 279,14
-- cp ids --
constant cp_sel_muldiv_c : std_ulogic_vector(1 downto 0) := "00"; -- MULDIV CP
-- muldiv cp --
constant cp_op_mul_c : std_ulogic_vector(2 downto 0) := "000"; -- mul
constant cp_op_mulh_c : std_ulogic_vector(2 downto 0) := "001"; -- mulh
constant cp_op_mulhsu_c : std_ulogic_vector(2 downto 0) := "010"; -- mulhsu
constant cp_op_mulhu_c : std_ulogic_vector(2 downto 0) := "011"; -- mulhu
constant cp_op_div_c : std_ulogic_vector(2 downto 0) := "100"; -- div
constant cp_op_divu_c : std_ulogic_vector(2 downto 0) := "101"; -- divu
constant cp_op_rem_c : std_ulogic_vector(2 downto 0) := "110"; -- rem
constant cp_op_remu_c : std_ulogic_vector(2 downto 0) := "111"; -- remu
constant cp_op_mul_c : std_ulogic_vector(2 downto 0) := "000"; -- mul
constant cp_op_mulh_c : std_ulogic_vector(2 downto 0) := "001"; -- mulh
constant cp_op_mulhsu_c : std_ulogic_vector(2 downto 0) := "010"; -- mulhsu
constant cp_op_mulhu_c : std_ulogic_vector(2 downto 0) := "011"; -- mulhu
constant cp_op_div_c : std_ulogic_vector(2 downto 0) := "100"; -- div
constant cp_op_divu_c : std_ulogic_vector(2 downto 0) := "101"; -- divu
constant cp_op_rem_c : std_ulogic_vector(2 downto 0) := "110"; -- rem
constant cp_op_remu_c : std_ulogic_vector(2 downto 0) := "111"; -- remu
 
-- ALU Function Codes ---------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
337,6 → 337,7
CLOCK_FREQUENCY : natural := 0; -- clock frequency of clk_i in Hz
HART_ID : std_ulogic_vector(31 downto 0) := x"00000000"; -- custom hardware thread ID
BOOTLOADER_USE : boolean := true; -- implement processor-internal bootloader?
CSR_COUNTERS_USE : boolean := true; -- implement RISC-V perf. counters ([m]instret[h], [m]cycle[h], time[h])?
-- RISC-V CPU Extensions --
CPU_EXTENSION_RISCV_C : boolean := false; -- implement compressed extension?
CPU_EXTENSION_RISCV_E : boolean := false; -- implement embedded RF extension?
390,9 → 391,9
uart_txd_o : out std_ulogic; -- UART send data
uart_rxd_i : in std_ulogic := '0'; -- UART receive data
-- SPI --
spi_sclk_o : out std_ulogic; -- serial clock line
spi_mosi_o : out std_ulogic; -- serial data line out
spi_miso_i : in std_ulogic := '0'; -- serial data line in
spi_sck_o : out std_ulogic; -- SPI serial clock
spi_sdo_o : out std_ulogic; -- controller data out, peripheral data in
spi_sdi_i : in std_ulogic; -- controller data in, peripheral data out
spi_csn_o : out std_ulogic_vector(07 downto 0); -- SPI CS
-- TWI --
twi_sda_io : inout std_logic := 'H'; -- twi serial data line
413,6 → 414,7
CLOCK_FREQUENCY : natural := 0; -- clock frequency of clk_i in Hz
HART_ID : std_ulogic_vector(31 downto 0) := x"00000000"; -- custom hardware thread ID
BOOTLOADER_USE : boolean := true; -- implement processor-internal bootloader?
CSR_COUNTERS_USE : boolean := true; -- implement RISC-V perf. counters ([m]instret[h], [m]cycle[h], time[h])?
-- RISC-V CPU Extensions --
CPU_EXTENSION_RISCV_C : boolean := false; -- implement compressed extension?
CPU_EXTENSION_RISCV_E : boolean := false; -- implement embedded RF extension?
471,6 → 473,7
CLOCK_FREQUENCY : natural := 0; -- clock frequency of clk_i in Hz
HART_ID : std_ulogic_vector(31 downto 0) := x"00000000"; -- custom hardware thread ID
BOOTLOADER_USE : boolean := true; -- implement processor-internal bootloader?
CSR_COUNTERS_USE : boolean := true; -- implement RISC-V perf. counters ([m]instret[h], [m]cycle[h], time[h])?
-- RISC-V CPU Extensions --
CPU_EXTENSION_RISCV_C : boolean := false; -- implement compressed extension?
CPU_EXTENSION_RISCV_E : boolean := false; -- implement embedded RF extension?
515,8 → 518,9
alu_add_i : in std_ulogic_vector(data_width_c-1 downto 0); -- ALU.add result
-- data output --
imm_o : out std_ulogic_vector(data_width_c-1 downto 0); -- immediate
pc_o : out std_ulogic_vector(data_width_c-1 downto 0); -- current PC
alu_pc_o : out std_ulogic_vector(data_width_c-1 downto 0); -- delayed PC for ALU
fetch_pc_o : out std_ulogic_vector(data_width_c-1 downto 0); -- PC for instruction fetch
curr_pc_o : out std_ulogic_vector(data_width_c-1 downto 0); -- current PC (corresponding to current instruction)
next_pc_o : out std_ulogic_vector(data_width_c-1 downto 0); -- next PC (corresponding to current instruction)
-- csr interface --
csr_wdata_i : in std_ulogic_vector(data_width_c-1 downto 0); -- CSR write data
csr_rdata_o : out std_ulogic_vector(data_width_c-1 downto 0); -- CSR read data
531,7 → 535,8
be_instr_i : in std_ulogic; -- bus error on instruction access
be_load_i : in std_ulogic; -- bus error on load data access
be_store_i : in std_ulogic; -- bus error on store data access
bus_exc_ack_o : out std_ulogic -- bus exception error acknowledge
bus_exc_ack_o : out std_ulogic; -- bus exception error acknowledge
bus_busy_i : in std_ulogic -- bus unit is busy
);
end component;
 
559,10 → 564,6
-- Component: CPU ALU ---------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
component neorv32_cpu_alu
generic (
CPU_EXTENSION_RISCV_C : boolean := false; -- implement compressed extension?
CPU_EXTENSION_RISCV_M : boolean := false -- implement mul/div extension?
);
port (
-- global control --
clk_i : in std_ulogic; -- global clock, rising edge
571,7 → 572,6
-- data input --
rs1_i : in std_ulogic_vector(data_width_c-1 downto 0); -- rf source 1
rs2_i : in std_ulogic_vector(data_width_c-1 downto 0); -- rf source 2
pc_i : in std_ulogic_vector(data_width_c-1 downto 0); -- current PC
pc2_i : in std_ulogic_vector(data_width_c-1 downto 0); -- delayed PC
imm_i : in std_ulogic_vector(data_width_c-1 downto 0); -- immediate
csr_i : in std_ulogic_vector(data_width_c-1 downto 0); -- csr read data
610,8 → 610,7
-- -------------------------------------------------------------------------------------------
component neorv32_cpu_bus
generic (
CPU_EXTENSION_RISCV_C : boolean := false; -- implement compressed extension?
MEM_EXT_TIMEOUT : natural := 15 -- cycles after which a valid bus access will timeout
MEM_EXT_TIMEOUT : natural := 15 -- cycles after which a valid bus access will timeout
);
port (
-- global control --
634,6 → 633,7
be_load_o : out std_ulogic; -- bus error on load data access
be_store_o : out std_ulogic; -- bus error on store data
bus_wait_o : out std_ulogic; -- wait for bus operation to finish
bus_busy_o : out std_ulogic; -- bus unit is busy
exc_ack_i : in std_ulogic; -- exception controller ACK
-- bus system --
bus_addr_o : out std_ulogic_vector(data_width_c-1 downto 0); -- bus access address
654,7 → 654,6
-- instruction input --
ci_instr16_i : in std_ulogic_vector(15 downto 0); -- compressed instruction input
-- instruction output --
ci_valid_o : out std_ulogic; -- is a compressed instruction
ci_illegal_o : out std_ulogic; -- is an illegal compressed instruction
ci_instr32_o : out std_ulogic_vector(31 downto 0) -- 32-bit decompressed instruction
);
838,9 → 837,9
clkgen_en_o : out std_ulogic; -- enable clock generator
clkgen_i : in std_ulogic_vector(07 downto 0);
-- com lines --
spi_sclk_o : out std_ulogic; -- SPI serial clock
spi_mosi_o : out std_ulogic; -- SPI master out, slave in
spi_miso_i : in std_ulogic; -- SPI master in, slave out
spi_sck_o : out std_ulogic; -- SPI serial clock
spi_sdo_o : out std_ulogic; -- controller data out, peripheral data in
spi_sdi_i : in std_ulogic; -- controller data in, peripheral data out
spi_csn_o : out std_ulogic_vector(07 downto 0); -- SPI CS
-- interrupt --
spi_irq_o : out std_ulogic -- transmission done interrupt
1063,4 → 1062,31
return tmp_v;
end function xnor_all_f;
 
-- Function: Convert to hex char ----------------------------------------------------------
-- -------------------------------------------------------------------------------------------
function to_hexchar_f(input : std_ulogic_vector(3 downto 0)) return character is
variable output_v : character;
begin
case input is
when x"0" => output_v := '0';
when x"1" => output_v := '1';
when x"2" => output_v := '2';
when x"3" => output_v := '3';
when x"4" => output_v := '4';
when x"5" => output_v := '5';
when x"6" => output_v := '6';
when x"7" => output_v := '7';
when x"8" => output_v := '8';
when x"9" => output_v := '9';
when x"a" => output_v := 'a';
when x"b" => output_v := 'b';
when x"c" => output_v := 'c';
when x"d" => output_v := 'd';
when x"e" => output_v := 'e';
when x"f" => output_v := 'f';
when others => output_v := '?';
end case;
return output_v;
end function to_hexchar_f;
 
end neorv32_package;
/rtl/core/neorv32_spi.vhd
1,5 → 1,5
-- #################################################################################################
-- # << NEORV32 - Serial Peripheral Interface Master (SPI) >> #
-- # << NEORV32 - Serial Peripheral Interface Controller (SPI) >> #
-- # ********************************************************************************************* #
-- # Frame format: 8/16/24/32-bit RTX, MSB or LSB first, 2 clock modes, 8 clock speeds, #
-- # 8 dedicated CS lines (low-active). Interrupt: SPI_transfer_done #
57,9 → 57,9
clkgen_en_o : out std_ulogic; -- enable clock generator
clkgen_i : in std_ulogic_vector(07 downto 0);
-- com lines --
spi_sclk_o : out std_ulogic; -- SPI serial clock
spi_mosi_o : out std_ulogic; -- SPI master out, slave in
spi_miso_i : in std_ulogic; -- SPI master in, slave out
spi_sck_o : out std_ulogic; -- SPI serial clock
spi_sdo_o : out std_ulogic; -- controller data out, peripheral data in
spi_sdi_i : in std_ulogic; -- controller data in, peripheral data out
spi_csn_o : out std_ulogic_vector(07 downto 0); -- SPI CS
-- interrupt --
spi_irq_o : out std_ulogic -- transmission done interrupt
116,8 → 116,8
signal spi_rtx_sreg : std_ulogic_vector(31 downto 0);
signal spi_rx_data : std_ulogic_vector(31 downto 0);
signal spi_bitcnt : std_ulogic_vector(05 downto 0);
signal spi_miso_ff0 : std_ulogic;
signal spi_miso_ff1 : std_ulogic;
signal spi_sdi_ff0 : std_ulogic;
signal spi_sdi_ff1 : std_ulogic;
 
begin
 
217,9 → 217,9
spi_rtx_unit: process(clk_i)
begin
if rising_edge(clk_i) then
-- input (MISO) synchronizer --
spi_miso_ff0 <= spi_miso_i;
spi_miso_ff1 <= spi_miso_ff0;
-- input (sdi) synchronizer --
spi_sdi_ff0 <= spi_sdi_i;
spi_sdi_ff1 <= spi_sdi_ff0;
 
-- serial engine --
spi_irq_o <= '0';
231,8 → 231,8
when others => spi_bitcnt <= "100000"; -- 32-bit mode
end case;
spi_state1 <= '0';
spi_mosi_o <= '0';
spi_sclk_o <= '0';
spi_sdo_o <= '0';
spi_sck_o <= '0';
if (ctrl(ctrl_spi_en_c) = '0') then -- disabled
spi_busy <= '0';
elsif (spi_start = '1') then -- start new transmission
249,19 → 249,19
else -- transmission in progress
if (spi_state1 = '0') then -- first half of transmission
 
spi_sclk_o <= ctrl(ctrl_spi_cpha_c);
spi_sck_o <= ctrl(ctrl_spi_cpha_c);
if (ctrl(ctrl_spi_dir_c) = '0') then
spi_mosi_o <= spi_rtx_sreg(31); -- MSB first
spi_sdo_o <= spi_rtx_sreg(31); -- MSB first
else
spi_mosi_o <= spi_rtx_sreg(0); -- LSB first
spi_sdo_o <= spi_rtx_sreg(0); -- LSB first
end if;
if (spi_clk = '1') then
spi_state1 <= '1';
if (ctrl(ctrl_spi_cpha_c) = '0') then
if (ctrl(ctrl_spi_dir_c) = '0') then
spi_rtx_sreg <= spi_rtx_sreg(30 downto 0) & spi_miso_ff1; -- MSB first
spi_rtx_sreg <= spi_rtx_sreg(30 downto 0) & spi_sdi_ff1; -- MSB first
else
spi_rtx_sreg <= spi_miso_ff1 & spi_rtx_sreg(31 downto 1); -- LSB first
spi_rtx_sreg <= spi_sdi_ff1 & spi_rtx_sreg(31 downto 1); -- LSB first
end if;
end if;
spi_bitcnt <= std_ulogic_vector(unsigned(spi_bitcnt) - 1);
268,14 → 268,14
end if;
else -- second half of transmission
 
spi_sclk_o <= not ctrl(ctrl_spi_cpha_c);
spi_sck_o <= not ctrl(ctrl_spi_cpha_c);
if (spi_clk = '1') then
spi_state1 <= '0';
if (ctrl(ctrl_spi_cpha_c) = '1') then
if (ctrl(ctrl_spi_dir_c) = '0') then
spi_rtx_sreg <= spi_rtx_sreg(30 downto 0) & spi_miso_ff1; -- MSB first
spi_rtx_sreg <= spi_rtx_sreg(30 downto 0) & spi_sdi_ff1; -- MSB first
else
spi_rtx_sreg <= spi_miso_ff1 & spi_rtx_sreg(31 downto 1); -- LSB first
spi_rtx_sreg <= spi_sdi_ff1 & spi_rtx_sreg(31 downto 1); -- LSB first
end if;
end if;
if (spi_bitcnt = "000000") then
/rtl/core/neorv32_top.vhd
50,6 → 50,7
CLOCK_FREQUENCY : natural := 0; -- clock frequency of clk_i in Hz
HART_ID : std_ulogic_vector(31 downto 0) := x"00000000"; -- custom hardware thread ID
BOOTLOADER_USE : boolean := true; -- implement processor-internal bootloader?
CSR_COUNTERS_USE : boolean := true; -- implement RISC-V perf. counters ([m]instret[h], [m]cycle[h], time[h])?
-- RISC-V CPU Extensions --
CPU_EXTENSION_RISCV_C : boolean := false; -- implement compressed extension?
CPU_EXTENSION_RISCV_E : boolean := false; -- implement embedded RF extension?
103,9 → 104,9
uart_txd_o : out std_ulogic; -- UART send data
uart_rxd_i : in std_ulogic := '0'; -- UART receive data
-- SPI (available if IO_SPI_USE = true) --
spi_sclk_o : out std_ulogic; -- serial clock line
spi_mosi_o : out std_ulogic; -- serial data line out
spi_miso_i : in std_ulogic := '0'; -- serial data line in
spi_sck_o : out std_ulogic; -- SPI serial clock
spi_sdo_o : out std_ulogic; -- controller data out, peripheral data in
spi_sdi_i : in std_ulogic; -- controller data in, peripheral data out
spi_csn_o : out std_ulogic_vector(07 downto 0); -- SPI CS
-- TWI (available if IO_TWI_USE = true) --
twi_sda_io : inout std_logic := 'H'; -- twi serial data line
315,6 → 316,7
CLOCK_FREQUENCY => CLOCK_FREQUENCY, -- clock frequency of clk_i in Hz
HART_ID => HART_ID, -- custom hardware thread ID
BOOTLOADER_USE => BOOTLOADER_USE, -- implement processor-internal bootloader?
CSR_COUNTERS_USE => CSR_COUNTERS_USE, -- implement RISC-V perf. counters ([m]instret[h], [m]cycle[h], time[h])?
-- RISC-V CPU Extensions --
CPU_EXTENSION_RISCV_C => CPU_EXTENSION_RISCV_C, -- implement compressed extension?
CPU_EXTENSION_RISCV_E => CPU_EXTENSION_RISCV_E, -- implement embedded RF extension?
719,9 → 721,9
clkgen_en_o => spi_cg_en, -- enable clock generator
clkgen_i => clk_gen,
-- com lines --
spi_sclk_o => spi_sclk_o, -- SPI serial clock
spi_mosi_o => spi_mosi_o, -- SPI master out, slave in
spi_miso_i => spi_miso_i, -- SPI master in, slave out
spi_sck_o => spi_sck_o, -- SPI serial clock
spi_sdo_o => spi_sdo_o, -- controller data out, peripheral data in
spi_sdi_i => spi_sdi_i, -- controller data in, peripheral data out
spi_csn_o => spi_csn_o, -- SPI CS
-- interrupt --
spi_irq_o => spi_irq -- transmission done interrupt
732,8 → 734,8
if (IO_SPI_USE = false) generate
spi_rdata <= (others => '0');
spi_ack <= '0';
spi_sclk_o <= '0';
spi_mosi_o <= '0';
spi_sck_o <= '0';
spi_sdo_o <= '0';
spi_csn_o <= (others => '1'); -- CSn lines are low-active
spi_cg_en <= '0';
spi_irq <= '0';
/rtl/core/neorv32_twi.vhd
1,9 → 1,9
-- #################################################################################################
-- # << NEORV32 - Two-Wire Interface Master (TWI) >> #
-- # << NEORV32 - Two-Wire Interface Controller (TWI) >> #
-- # ********************************************************************************************* #
-- # Supports START and STOP conditions, 8 bit data + ACK/NACK transfers and clock stretching. #
-- # Supports ACKs by the master. No multi-master support and no slave mode support yet! #
-- # Interrupt: TWI_transfer_done #
-- # Supports ACKs by the constroller. No multi-controller support and no peripheral mode support #
-- # yet. Interrupt: TWI_transfer_done #
-- # ********************************************************************************************* #
-- # BSD 3-Clause License #
-- # #
79,7 → 79,7
constant ctrl_twi_prsc0_c : natural := 4; -- r/w: CLK prsc bit 0
constant ctrl_twi_prsc1_c : natural := 5; -- r/w: CLK prsc bit 1
constant ctrl_twi_prsc2_c : natural := 6; -- r/w: CLK prsc bit 2
constant ctrl_twi_mack_c : natural := 7; -- r/w: generate ACK by master for transmission
constant ctrl_twi_mack_c : natural := 7; -- r/w: generate ACK by controller for transmission
--
constant ctrl_twi_ack_c : natural := 30; -- r/-: Set if ACK received
constant ctrl_twi_busy_c : natural := 31; -- r/-: Set if TWI unit is busy
201,7 → 201,7
-- TWI bus signals are set/sampled using 4 clock phases
case arbiter is
 
when "100" => -- IDLE: waiting for requests, bus might be still claimed by this master if no STOP condition was generated
when "100" => -- IDLE: waiting for requests, bus might be still claimed by this controller if no STOP condition was generated
twi_bitcnt <= (others => '0');
if (wr_en = '1') then
if (addr = twi_ctrl_addr_c) then
211,8 → 211,8
arbiter(1 downto 0) <= "10";
end if;
elsif (addr = twi_rtx_addr_c) then -- start a data transmission
-- one bit extra for ack, issued by master if ctrl_twi_mack_c is set,
-- sampled from slave if ctrl_twi_mack_c is cleared
-- one bit extra for ack, issued by controller if ctrl_twi_mack_c is set,
-- sampled from peripheral if ctrl_twi_mack_c is cleared
if (ben_i(0) = '1') then
twi_rtx_sreg <= data_i(7 downto 0) & (not ctrl(ctrl_twi_mack_c));
arbiter(1 downto 0) <= "11";
279,10 → 279,10
-- -------------------------------------------------------------------------------------------
clock_stretching: process(arbiter, twi_scl_o, twi_scl_i_ff1)
begin
-- clock stretching by the slave can happen at "any time"
-- clock stretching by the peripheral can happen at "any time"
if (arbiter(2) = '1') and -- module enabled
(twi_scl_o = '1') and -- master wants to pull scl high
(twi_scl_i_ff1 = '0') then -- but scl is pulled low by slave
(twi_scl_o = '1') and -- controller wants to pull scl high
(twi_scl_i_ff1 = '0') then -- but scl is pulled low by peripheral
twi_clk_halt <= '1';
else
twi_clk_halt <= '0';
/rtl/top_templates/neorv32_test_setup.vhd
72,6 → 72,7
CLOCK_FREQUENCY => 100000000, -- clock frequency of clk_i in Hz
HART_ID => x"00000000", -- custom hardware thread ID
BOOTLOADER_USE => true, -- implement processor-internal bootloader?
CSR_COUNTERS_USE => true, -- implement RISC-V perf. counters ([m]instret[h], [m]cycle[h], time[h])?
-- RISC-V CPU Extensions --
CPU_EXTENSION_RISCV_C => false, -- implement compressed extension?
CPU_EXTENSION_RISCV_E => false, -- implement embedded RF extension?
125,9 → 126,9
uart_txd_o => uart_txd_o, -- UART send data
uart_rxd_i => uart_rxd_i, -- UART receive data
-- SPI --
spi_sclk_o => open, -- serial clock line
spi_mosi_o => open, -- serial data line out
spi_miso_i => '0', -- serial data line in
spi_sck_o => open, -- SPI serial clock
spi_sdo_o => open, -- controller data out, peripheral data in
spi_sdi_i => '0', -- controller data in, peripheral data out
spi_csn_o => open, -- SPI CS
-- TWI --
twi_sda_io => open, -- twi serial data line
/sim/ghdl/ghdl_sim.sh
3,6 → 3,9
# Abort if any command returns != 0
set -e
 
# Simulation config
SIM_CONFIG=--stop-time=5ms
 
# Project home folder
homedir="$( cd "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )"
homedir=$homedir/../..
11,6 → 14,9
srcdir_core=$homedir/rtl/core
srcdir_sim=$homedir/sim
 
# Simulation time define by user?
if [ -z ${1} ]; then echo "Using default simulation config: $SIM_CONFIG"; else SIM_CONFIG=$1; echo "Using user simulation config: $SIM_CONFIG"; fi
 
# Show GHDL version
ghdl -v
 
21,7 → 27,7
 
# Just a hint
echo ""
echo "Compile application with USER_FLAGS+=-DDEVNULL_UART_OVERRIDE to have faster UART/console output."
echo "Tip: Compile application with USER_FLAGS+=-DDEVNULL_UART_OVERRIDE to have faster UART/console output."
echo ""
 
# Analyse sources; libs and images at first!
59,7 → 65,9
chmod 777 neorv32.testbench_uart.out
touch neorv32.devnull.out
chmod 777 neorv32.devnull.out
touch neorv32.devnull.data.out
chmod 777 neorv32.devnull.data.out
 
# Run simulation
ghdl -e --work=neorv32 neorv32_tb
ghdl -r --work=neorv32 neorv32_tb --stop-time=4ms --ieee-asserts=disable --assert-level=error
ghdl -r --work=neorv32 neorv32_tb --ieee-asserts=disable --assert-level=error $SIM_CONFIG
/sim/vivado/neorv32_tb_behav.wcfg
0,0 → 1,791
<?xml version="1.0" encoding="UTF-8"?>
<wave_config>
<wave_state>
</wave_state>
<db_ref_list>
<db_ref path="neorv32_tb_behav.wdb" id="1">
<top_modules>
<top_module name="neorv32_application_image" />
<top_module name="neorv32_package" />
<top_module name="neorv32_tb" />
</top_modules>
</db_ref>
</db_ref_list>
<zoom_setting>
<ZoomStartTime time="1950430583fs"></ZoomStartTime>
<ZoomEndTime time="1950447384fs"></ZoomEndTime>
<Cursor1Time time="1950490183fs"></Cursor1Time>
</zoom_setting>
<column_width_setting>
<NameColumnWidth column_width="178"></NameColumnWidth>
<ValueColumnWidth column_width="131"></ValueColumnWidth>
</column_width_setting>
<WVObjectSize size="156" />
<wvobject type="divider" fp_name="divider273">
<obj_property name="label">CPU: Control.FETCH</obj_property>
<obj_property name="DisplayName">label</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/clk_i" type="logic">
<obj_property name="ElementShortName">clk_i</obj_property>
<obj_property name="ObjectShortName">clk_i</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/rstn_i" type="logic">
<obj_property name="ElementShortName">rstn_i</obj_property>
<obj_property name="ObjectShortName">rstn_i</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/bus_wait_i" type="logic">
<obj_property name="ElementShortName">bus_wait_i</obj_property>
<obj_property name="ObjectShortName">bus_wait_i</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/bus_fast_ir" type="logic">
<obj_property name="ElementShortName">bus_fast_ir</obj_property>
<obj_property name="ObjectShortName">bus_fast_ir</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/ma_instr_i" type="logic">
<obj_property name="ElementShortName">ma_instr_i</obj_property>
<obj_property name="ObjectShortName">ma_instr_i</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/be_instr_i" type="logic">
<obj_property name="ElementShortName">be_instr_i</obj_property>
<obj_property name="ObjectShortName">be_instr_i</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/instr_i" type="array">
<obj_property name="ElementShortName">instr_i[31:0]</obj_property>
<obj_property name="ObjectShortName">instr_i[31:0]</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/ci_instr32" type="array">
<obj_property name="ElementShortName">ci_instr32[31:0]</obj_property>
<obj_property name="ObjectShortName">ci_instr32[31:0]</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/ci_illegal" type="logic">
<obj_property name="ElementShortName">ci_illegal</obj_property>
<obj_property name="ObjectShortName">ci_illegal</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/fetch_engine" type="array">
<obj_property name="ElementShortName">fetch_engine</obj_property>
<obj_property name="ObjectShortName">fetch_engine</obj_property>
<obj_property name="isExpanded"></obj_property>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/fetch_engine.state" type="other">
<obj_property name="ElementShortName">.state</obj_property>
<obj_property name="ObjectShortName">.state</obj_property>
<obj_property name="CustomSignalColor">#FFD700</obj_property>
<obj_property name="UseCustomSignalColor">true</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/fetch_engine.state_nxt" type="other">
<obj_property name="ElementShortName">.state_nxt</obj_property>
<obj_property name="ObjectShortName">.state_nxt</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/fetch_engine.i_buf" type="array">
<obj_property name="ElementShortName">.i_buf[33:0]</obj_property>
<obj_property name="ObjectShortName">.i_buf[33:0]</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/fetch_engine.i_buf_nxt" type="array">
<obj_property name="ElementShortName">.i_buf_nxt[33:0]</obj_property>
<obj_property name="ObjectShortName">.i_buf_nxt[33:0]</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/fetch_engine.i_buf2" type="array">
<obj_property name="ElementShortName">.i_buf2[33:0]</obj_property>
<obj_property name="ObjectShortName">.i_buf2[33:0]</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/fetch_engine.i_buf2_nxt" type="array">
<obj_property name="ElementShortName">.i_buf2_nxt[33:0]</obj_property>
<obj_property name="ObjectShortName">.i_buf2_nxt[33:0]</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/fetch_engine.ci_reg" type="array">
<obj_property name="ElementShortName">.ci_reg[17:0]</obj_property>
<obj_property name="ObjectShortName">.ci_reg[17:0]</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/fetch_engine.ci_reg_nxt" type="array">
<obj_property name="ElementShortName">.ci_reg_nxt[17:0]</obj_property>
<obj_property name="ObjectShortName">.ci_reg_nxt[17:0]</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/fetch_engine.i_buf_state" type="array">
<obj_property name="ElementShortName">.i_buf_state[1:0]</obj_property>
<obj_property name="ObjectShortName">.i_buf_state[1:0]</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/fetch_engine.i_buf_state_nxt" type="array">
<obj_property name="ElementShortName">.i_buf_state_nxt[1:0]</obj_property>
<obj_property name="ObjectShortName">.i_buf_state_nxt[1:0]</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/fetch_engine.pc_real" type="array">
<obj_property name="ElementShortName">.pc_real[31:0]</obj_property>
<obj_property name="ObjectShortName">.pc_real[31:0]</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/fetch_engine.pc_real_add" type="array">
<obj_property name="ElementShortName">.pc_real_add[31:0]</obj_property>
<obj_property name="ObjectShortName">.pc_real_add[31:0]</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/fetch_engine.pc_fetch" type="array">
<obj_property name="ElementShortName">.pc_fetch[31:0]</obj_property>
<obj_property name="ObjectShortName">.pc_fetch[31:0]</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/fetch_engine.pc_fetch_add" type="array">
<obj_property name="ElementShortName">.pc_fetch_add[31:0]</obj_property>
<obj_property name="ObjectShortName">.pc_fetch_add[31:0]</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/fetch_engine.ci_return" type="logic">
<obj_property name="ElementShortName">.ci_return</obj_property>
<obj_property name="ObjectShortName">.ci_return</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/fetch_engine.ci_return_nxt" type="logic">
<obj_property name="ElementShortName">.ci_return_nxt</obj_property>
<obj_property name="ObjectShortName">.ci_return_nxt</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/fetch_engine.reset" type="logic">
<obj_property name="ElementShortName">.reset</obj_property>
<obj_property name="ObjectShortName">.reset</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/fetch_engine.bus_err_ack" type="logic">
<obj_property name="ElementShortName">.bus_err_ack</obj_property>
<obj_property name="ObjectShortName">.bus_err_ack</obj_property>
</wvobject>
</wvobject>
<wvobject type="divider" fp_name="divider273">
<obj_property name="label">CPU: Control.IPB</obj_property>
<obj_property name="DisplayName">label</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/ipb" type="array">
<obj_property name="ElementShortName">ipb</obj_property>
<obj_property name="ObjectShortName">ipb</obj_property>
</wvobject>
<wvobject type="divider" fp_name="divider273">
<obj_property name="label">CPU: Control.EXE</obj_property>
<obj_property name="DisplayName">label</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/alu_wait_i" type="logic">
<obj_property name="ElementShortName">alu_wait_i</obj_property>
<obj_property name="ObjectShortName">alu_wait_i</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/bus_wait_i" type="logic">
<obj_property name="ElementShortName">bus_wait_i</obj_property>
<obj_property name="ObjectShortName">bus_wait_i</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/instr_i" type="array">
<obj_property name="ElementShortName">instr_i[31:0]</obj_property>
<obj_property name="ObjectShortName">instr_i[31:0]</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/cmp_i" type="array">
<obj_property name="ElementShortName">cmp_i[1:0]</obj_property>
<obj_property name="ObjectShortName">cmp_i[1:0]</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/alu_add_i" type="array">
<obj_property name="ElementShortName">alu_add_i[31:0]</obj_property>
<obj_property name="ObjectShortName">alu_add_i[31:0]</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/imm_o" type="array">
<obj_property name="ElementShortName">imm_o[31:0]</obj_property>
<obj_property name="ObjectShortName">imm_o[31:0]</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/csr_wdata_i" type="array">
<obj_property name="ElementShortName">csr_wdata_i[31:0]</obj_property>
<obj_property name="ObjectShortName">csr_wdata_i[31:0]</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/csr_rdata_o" type="array">
<obj_property name="ElementShortName">csr_rdata_o[31:0]</obj_property>
<obj_property name="ObjectShortName">csr_rdata_o[31:0]</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/clic_irq_i" type="logic">
<obj_property name="ElementShortName">clic_irq_i</obj_property>
<obj_property name="ObjectShortName">clic_irq_i</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/mtime_irq_i" type="logic">
<obj_property name="ElementShortName">mtime_irq_i</obj_property>
<obj_property name="ObjectShortName">mtime_irq_i</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/mar_i" type="array">
<obj_property name="ElementShortName">mar_i[31:0]</obj_property>
<obj_property name="ObjectShortName">mar_i[31:0]</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/ma_load_i" type="logic">
<obj_property name="ElementShortName">ma_load_i</obj_property>
<obj_property name="ObjectShortName">ma_load_i</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/ma_store_i" type="logic">
<obj_property name="ElementShortName">ma_store_i</obj_property>
<obj_property name="ObjectShortName">ma_store_i</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/be_load_i" type="logic">
<obj_property name="ElementShortName">be_load_i</obj_property>
<obj_property name="ObjectShortName">be_load_i</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/be_store_i" type="logic">
<obj_property name="ElementShortName">be_store_i</obj_property>
<obj_property name="ObjectShortName">be_store_i</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/bus_exc_ack_o" type="logic">
<obj_property name="ElementShortName">bus_exc_ack_o</obj_property>
<obj_property name="ObjectShortName">bus_exc_ack_o</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/ctrl" type="array">
<obj_property name="ElementShortName">ctrl[47:0]</obj_property>
<obj_property name="ObjectShortName">ctrl[47:0]</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/ctrl_o" type="array">
<obj_property name="ElementShortName">ctrl_o[47:0]</obj_property>
<obj_property name="ObjectShortName">ctrl_o[47:0]</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/bus_fast_rd" type="logic">
<obj_property name="ElementShortName">bus_fast_rd</obj_property>
<obj_property name="ObjectShortName">bus_fast_rd</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/bus_fast_wr" type="logic">
<obj_property name="ElementShortName">bus_fast_wr</obj_property>
<obj_property name="ObjectShortName">bus_fast_wr</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/ci_instr32" type="array">
<obj_property name="ElementShortName">ci_instr32[31:0]</obj_property>
<obj_property name="ObjectShortName">ci_instr32[31:0]</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/ci_illegal" type="logic">
<obj_property name="ElementShortName">ci_illegal</obj_property>
<obj_property name="ObjectShortName">ci_illegal</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/fetch_pc_o" type="array">
<obj_property name="ElementShortName">fetch_pc_o[31:0]</obj_property>
<obj_property name="ObjectShortName">fetch_pc_o[31:0]</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/curr_pc_o" type="array">
<obj_property name="ElementShortName">curr_pc_o[31:0]</obj_property>
<obj_property name="ObjectShortName">curr_pc_o[31:0]</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/next_pc_o" type="array">
<obj_property name="ElementShortName">next_pc_o[31:0]</obj_property>
<obj_property name="ObjectShortName">next_pc_o[31:0]</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/illegal_instruction" type="logic">
<obj_property name="ElementShortName">illegal_instruction</obj_property>
<obj_property name="ObjectShortName">illegal_instruction</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/illegal_register" type="logic">
<obj_property name="ElementShortName">illegal_register</obj_property>
<obj_property name="ObjectShortName">illegal_register</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/illegal_compressed" type="logic">
<obj_property name="ElementShortName">illegal_compressed</obj_property>
<obj_property name="ObjectShortName">illegal_compressed</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/execute_engine" type="array">
<obj_property name="ElementShortName">execute_engine</obj_property>
<obj_property name="ObjectShortName">execute_engine</obj_property>
<obj_property name="isExpanded"></obj_property>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/execute_engine.state" type="other">
<obj_property name="ElementShortName">.state</obj_property>
<obj_property name="ObjectShortName">.state</obj_property>
<obj_property name="CustomSignalColor">#FFD700</obj_property>
<obj_property name="UseCustomSignalColor">true</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/execute_engine.state_nxt" type="other">
<obj_property name="ElementShortName">.state_nxt</obj_property>
<obj_property name="ObjectShortName">.state_nxt</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/execute_engine.state_prev" type="other">
<obj_property name="ElementShortName">.state_prev</obj_property>
<obj_property name="ObjectShortName">.state_prev</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/execute_engine.i_reg" type="array">
<obj_property name="ElementShortName">.i_reg[31:0]</obj_property>
<obj_property name="ObjectShortName">.i_reg[31:0]</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/execute_engine.i_reg_nxt" type="array">
<obj_property name="ElementShortName">.i_reg_nxt[31:0]</obj_property>
<obj_property name="ObjectShortName">.i_reg_nxt[31:0]</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/execute_engine.is_ci" type="logic">
<obj_property name="ElementShortName">.is_ci</obj_property>
<obj_property name="ObjectShortName">.is_ci</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/execute_engine.is_ci_nxt" type="logic">
<obj_property name="ElementShortName">.is_ci_nxt</obj_property>
<obj_property name="ObjectShortName">.is_ci_nxt</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/execute_engine.is_jump" type="logic">
<obj_property name="ElementShortName">.is_jump</obj_property>
<obj_property name="ObjectShortName">.is_jump</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/execute_engine.is_jump_nxt" type="logic">
<obj_property name="ElementShortName">.is_jump_nxt</obj_property>
<obj_property name="ObjectShortName">.is_jump_nxt</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/execute_engine.branch_taken" type="logic">
<obj_property name="ElementShortName">.branch_taken</obj_property>
<obj_property name="ObjectShortName">.branch_taken</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/execute_engine.pc" type="array">
<obj_property name="ElementShortName">.pc[31:0]</obj_property>
<obj_property name="ObjectShortName">.pc[31:0]</obj_property>
<obj_property name="CustomSignalColor">#FFFFFF</obj_property>
<obj_property name="UseCustomSignalColor">true</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/execute_engine.pc_nxt" type="array">
<obj_property name="ElementShortName">.pc_nxt[31:0]</obj_property>
<obj_property name="ObjectShortName">.pc_nxt[31:0]</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/execute_engine.next_pc" type="array">
<obj_property name="ElementShortName">.next_pc[31:0]</obj_property>
<obj_property name="ObjectShortName">.next_pc[31:0]</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/execute_engine.last_pc" type="array">
<obj_property name="ElementShortName">.last_pc[31:0]</obj_property>
<obj_property name="ObjectShortName">.last_pc[31:0]</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/execute_engine.pc_we" type="logic">
<obj_property name="ElementShortName">.pc_we</obj_property>
<obj_property name="ObjectShortName">.pc_we</obj_property>
</wvobject>
</wvobject>
<wvobject type="divider" fp_name="divider139">
<obj_property name="label">CPU: Control.TRAP</obj_property>
<obj_property name="DisplayName">label</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/trap_ctrl" type="array">
<obj_property name="ElementShortName">trap_ctrl</obj_property>
<obj_property name="ObjectShortName">trap_ctrl</obj_property>
<obj_property name="isExpanded"></obj_property>
</wvobject>
<wvobject type="divider" fp_name="divider139">
<obj_property name="label">CPU: Control.CSR</obj_property>
<obj_property name="DisplayName">label</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/csr" type="array">
<obj_property name="ElementShortName">csr</obj_property>
<obj_property name="ObjectShortName">csr</obj_property>
<obj_property name="isExpanded"></obj_property>
</wvobject>
<wvobject type="divider" fp_name="divider139">
<obj_property name="label">CPU: RegFile</obj_property>
<obj_property name="DisplayName">label</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_regfile_inst/reg_file" type="array">
<obj_property name="ElementShortName">reg_file[31:0][31:0]</obj_property>
<obj_property name="ObjectShortName">reg_file[31:0][31:0]</obj_property>
</wvobject>
<wvobject type="divider" fp_name="divider367">
<obj_property name="label">CPU: ALU</obj_property>
<obj_property name="DisplayName">label</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_alu_inst/clk_i" type="logic">
<obj_property name="ElementShortName">clk_i</obj_property>
<obj_property name="ObjectShortName">clk_i</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_alu_inst/rstn_i" type="logic">
<obj_property name="ElementShortName">rstn_i</obj_property>
<obj_property name="ObjectShortName">rstn_i</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_alu_inst/ctrl_i" type="array">
<obj_property name="ElementShortName">ctrl_i[47:0]</obj_property>
<obj_property name="ObjectShortName">ctrl_i[47:0]</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_alu_inst/rs1_i" type="array">
<obj_property name="ElementShortName">rs1_i[31:0]</obj_property>
<obj_property name="ObjectShortName">rs1_i[31:0]</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_alu_inst/rs2_i" type="array">
<obj_property name="ElementShortName">rs2_i[31:0]</obj_property>
<obj_property name="ObjectShortName">rs2_i[31:0]</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_alu_inst/pc2_i" type="array">
<obj_property name="ElementShortName">pc2_i[31:0]</obj_property>
<obj_property name="ObjectShortName">pc2_i[31:0]</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_alu_inst/imm_i" type="array">
<obj_property name="ElementShortName">imm_i[31:0]</obj_property>
<obj_property name="ObjectShortName">imm_i[31:0]</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_alu_inst/csr_i" type="array">
<obj_property name="ElementShortName">csr_i[31:0]</obj_property>
<obj_property name="ObjectShortName">csr_i[31:0]</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_alu_inst/cmp_o" type="array">
<obj_property name="ElementShortName">cmp_o[1:0]</obj_property>
<obj_property name="ObjectShortName">cmp_o[1:0]</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_alu_inst/add_o" type="array">
<obj_property name="ElementShortName">add_o[31:0]</obj_property>
<obj_property name="ObjectShortName">add_o[31:0]</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_alu_inst/res_o" type="array">
<obj_property name="ElementShortName">res_o[31:0]</obj_property>
<obj_property name="ObjectShortName">res_o[31:0]</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_alu_inst/cp0_data_i" type="array">
<obj_property name="ElementShortName">cp0_data_i[31:0]</obj_property>
<obj_property name="ObjectShortName">cp0_data_i[31:0]</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_alu_inst/cp0_valid_i" type="logic">
<obj_property name="ElementShortName">cp0_valid_i</obj_property>
<obj_property name="ObjectShortName">cp0_valid_i</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_alu_inst/cp1_data_i" type="array">
<obj_property name="ElementShortName">cp1_data_i[31:0]</obj_property>
<obj_property name="ObjectShortName">cp1_data_i[31:0]</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_alu_inst/cp1_valid_i" type="logic">
<obj_property name="ElementShortName">cp1_valid_i</obj_property>
<obj_property name="ObjectShortName">cp1_valid_i</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_alu_inst/wait_o" type="logic">
<obj_property name="ElementShortName">wait_o</obj_property>
<obj_property name="ObjectShortName">wait_o</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_alu_inst/opa" type="array">
<obj_property name="ElementShortName">opa[31:0]</obj_property>
<obj_property name="ObjectShortName">opa[31:0]</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_alu_inst/opb" type="array">
<obj_property name="ElementShortName">opb[31:0]</obj_property>
<obj_property name="ObjectShortName">opb[31:0]</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_alu_inst/opc" type="array">
<obj_property name="ElementShortName">opc[31:0]</obj_property>
<obj_property name="ObjectShortName">opc[31:0]</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_alu_inst/add_res" type="array">
<obj_property name="ElementShortName">add_res[31:0]</obj_property>
<obj_property name="ObjectShortName">add_res[31:0]</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_alu_inst/alu_res" type="array">
<obj_property name="ElementShortName">alu_res[31:0]</obj_property>
<obj_property name="ObjectShortName">alu_res[31:0]</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_alu_inst/cmp_opx" type="array">
<obj_property name="ElementShortName">cmp_opx[32:0]</obj_property>
<obj_property name="ObjectShortName">cmp_opx[32:0]</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_alu_inst/cmp_opy" type="array">
<obj_property name="ElementShortName">cmp_opy[32:0]</obj_property>
<obj_property name="ObjectShortName">cmp_opy[32:0]</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_alu_inst/cmp_sub" type="array">
<obj_property name="ElementShortName">cmp_sub[32:0]</obj_property>
<obj_property name="ObjectShortName">cmp_sub[32:0]</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_alu_inst/sub_res" type="array">
<obj_property name="ElementShortName">sub_res[31:0]</obj_property>
<obj_property name="ObjectShortName">sub_res[31:0]</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_alu_inst/cmp_equal" type="logic">
<obj_property name="ElementShortName">cmp_equal</obj_property>
<obj_property name="ObjectShortName">cmp_equal</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_alu_inst/cmp_less" type="logic">
<obj_property name="ElementShortName">cmp_less</obj_property>
<obj_property name="ObjectShortName">cmp_less</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_alu_inst/shift_cmd" type="logic">
<obj_property name="ElementShortName">shift_cmd</obj_property>
<obj_property name="ObjectShortName">shift_cmd</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_alu_inst/shift_cmd_ff" type="logic">
<obj_property name="ElementShortName">shift_cmd_ff</obj_property>
<obj_property name="ObjectShortName">shift_cmd_ff</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_alu_inst/shift_start" type="logic">
<obj_property name="ElementShortName">shift_start</obj_property>
<obj_property name="ObjectShortName">shift_start</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_alu_inst/shift_run" type="logic">
<obj_property name="ElementShortName">shift_run</obj_property>
<obj_property name="ObjectShortName">shift_run</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_alu_inst/shift_cnt" type="array">
<obj_property name="ElementShortName">shift_cnt[4:0]</obj_property>
<obj_property name="ObjectShortName">shift_cnt[4:0]</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_alu_inst/shift_sreg" type="array">
<obj_property name="ElementShortName">shift_sreg[31:0]</obj_property>
<obj_property name="ObjectShortName">shift_sreg[31:0]</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_alu_inst/cp_cmd_ff" type="logic">
<obj_property name="ElementShortName">cp_cmd_ff</obj_property>
<obj_property name="ObjectShortName">cp_cmd_ff</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_alu_inst/cp_run" type="logic">
<obj_property name="ElementShortName">cp_run</obj_property>
<obj_property name="ObjectShortName">cp_run</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_alu_inst/cp_start" type="logic">
<obj_property name="ElementShortName">cp_start</obj_property>
<obj_property name="ObjectShortName">cp_start</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_alu_inst/cp_busy" type="logic">
<obj_property name="ElementShortName">cp_busy</obj_property>
<obj_property name="ObjectShortName">cp_busy</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_alu_inst/cp_rb_ff0" type="logic">
<obj_property name="ElementShortName">cp_rb_ff0</obj_property>
<obj_property name="ObjectShortName">cp_rb_ff0</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_alu_inst/cp_rb_ff1" type="logic">
<obj_property name="ElementShortName">cp_rb_ff1</obj_property>
<obj_property name="ObjectShortName">cp_rb_ff1</obj_property>
</wvobject>
<wvobject type="divider" fp_name="divider367">
<obj_property name="label">CPU: BUS_UNIT</obj_property>
<obj_property name="DisplayName">label</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/rstn_i" type="logic">
<obj_property name="ElementShortName">rstn_i</obj_property>
<obj_property name="ObjectShortName">rstn_i</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/clk_i" type="logic">
<obj_property name="ElementShortName">clk_i</obj_property>
<obj_property name="ObjectShortName">clk_i</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/ctrl_i" type="array">
<obj_property name="ElementShortName">ctrl_i[47:0]</obj_property>
<obj_property name="ObjectShortName">ctrl_i[47:0]</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/wdata_i" type="array">
<obj_property name="ElementShortName">wdata_i[31:0]</obj_property>
<obj_property name="ObjectShortName">wdata_i[31:0]</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/pc_i" type="array">
<obj_property name="ElementShortName">pc_i[31:0]</obj_property>
<obj_property name="ObjectShortName">pc_i[31:0]</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/alu_i" type="array">
<obj_property name="ElementShortName">alu_i[31:0]</obj_property>
<obj_property name="ObjectShortName">alu_i[31:0]</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/instr_o" type="array">
<obj_property name="ElementShortName">instr_o[31:0]</obj_property>
<obj_property name="ObjectShortName">instr_o[31:0]</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/rdata_o" type="array">
<obj_property name="ElementShortName">rdata_o[31:0]</obj_property>
<obj_property name="ObjectShortName">rdata_o[31:0]</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/mar_o" type="array">
<obj_property name="ElementShortName">mar_o[31:0]</obj_property>
<obj_property name="ObjectShortName">mar_o[31:0]</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/ma_instr_o" type="logic">
<obj_property name="ElementShortName">ma_instr_o</obj_property>
<obj_property name="ObjectShortName">ma_instr_o</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/ma_load_o" type="logic">
<obj_property name="ElementShortName">ma_load_o</obj_property>
<obj_property name="ObjectShortName">ma_load_o</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/ma_store_o" type="logic">
<obj_property name="ElementShortName">ma_store_o</obj_property>
<obj_property name="ObjectShortName">ma_store_o</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/be_instr_o" type="logic">
<obj_property name="ElementShortName">be_instr_o</obj_property>
<obj_property name="ObjectShortName">be_instr_o</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/be_load_o" type="logic">
<obj_property name="ElementShortName">be_load_o</obj_property>
<obj_property name="ObjectShortName">be_load_o</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/be_store_o" type="logic">
<obj_property name="ElementShortName">be_store_o</obj_property>
<obj_property name="ObjectShortName">be_store_o</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/bus_wait_o" type="logic">
<obj_property name="ElementShortName">bus_wait_o</obj_property>
<obj_property name="ObjectShortName">bus_wait_o</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/exc_ack_i" type="logic">
<obj_property name="ElementShortName">exc_ack_i</obj_property>
<obj_property name="ObjectShortName">exc_ack_i</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/bus_addr_o" type="array">
<obj_property name="ElementShortName">bus_addr_o[31:0]</obj_property>
<obj_property name="ObjectShortName">bus_addr_o[31:0]</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/bus_rdata_i" type="array">
<obj_property name="ElementShortName">bus_rdata_i[31:0]</obj_property>
<obj_property name="ObjectShortName">bus_rdata_i[31:0]</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/bus_wdata_o" type="array">
<obj_property name="ElementShortName">bus_wdata_o[31:0]</obj_property>
<obj_property name="ObjectShortName">bus_wdata_o[31:0]</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/bus_ben_o" type="array">
<obj_property name="ElementShortName">bus_ben_o[3:0]</obj_property>
<obj_property name="ObjectShortName">bus_ben_o[3:0]</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/bus_we_o" type="logic">
<obj_property name="ElementShortName">bus_we_o</obj_property>
<obj_property name="ObjectShortName">bus_we_o</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/bus_re_o" type="logic">
<obj_property name="ElementShortName">bus_re_o</obj_property>
<obj_property name="ObjectShortName">bus_re_o</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/bus_ack_i" type="logic">
<obj_property name="ElementShortName">bus_ack_i</obj_property>
<obj_property name="ObjectShortName">bus_ack_i</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/bus_err_i" type="logic">
<obj_property name="ElementShortName">bus_err_i</obj_property>
<obj_property name="ObjectShortName">bus_err_i</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/mar" type="array">
<obj_property name="ElementShortName">mar[31:0]</obj_property>
<obj_property name="ObjectShortName">mar[31:0]</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/mdo" type="array">
<obj_property name="ElementShortName">mdo[31:0]</obj_property>
<obj_property name="ObjectShortName">mdo[31:0]</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/mdi" type="array">
<obj_property name="ElementShortName">mdi[31:0]</obj_property>
<obj_property name="ObjectShortName">mdi[31:0]</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/bus_busy" type="logic">
<obj_property name="ElementShortName">bus_busy</obj_property>
<obj_property name="ObjectShortName">bus_busy</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/bus_if_req" type="logic">
<obj_property name="ElementShortName">bus_if_req</obj_property>
<obj_property name="ObjectShortName">bus_if_req</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/bus_rd_req" type="logic">
<obj_property name="ElementShortName">bus_rd_req</obj_property>
<obj_property name="ObjectShortName">bus_rd_req</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/bus_wr_req" type="logic">
<obj_property name="ElementShortName">bus_wr_req</obj_property>
<obj_property name="ObjectShortName">bus_wr_req</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/access_err" type="logic">
<obj_property name="ElementShortName">access_err</obj_property>
<obj_property name="ObjectShortName">access_err</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/align_err" type="logic">
<obj_property name="ElementShortName">align_err</obj_property>
<obj_property name="ObjectShortName">align_err</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/bus_timeout" type="array">
<obj_property name="ElementShortName">bus_timeout[3:0]</obj_property>
<obj_property name="ObjectShortName">bus_timeout[3:0]</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/misaligned_data" type="logic">
<obj_property name="ElementShortName">misaligned_data</obj_property>
<obj_property name="ObjectShortName">misaligned_data</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/misaligned_instr" type="logic">
<obj_property name="ElementShortName">misaligned_instr</obj_property>
<obj_property name="ObjectShortName">misaligned_instr</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/MEM_EXT_TIMEOUT" type="other">
<obj_property name="ElementShortName">MEM_EXT_TIMEOUT</obj_property>
<obj_property name="ObjectShortName">MEM_EXT_TIMEOUT</obj_property>
</wvobject>
<wvobject type="divider" fp_name="divider298">
<obj_property name="label">CPU: MULDIC CP</obj_property>
<obj_property name="DisplayName">label</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_cp_muldiv_inst_true/neorv32_cpu_cp_muldiv_inst/clk_i" type="logic">
<obj_property name="ElementShortName">clk_i</obj_property>
<obj_property name="ObjectShortName">clk_i</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_cp_muldiv_inst_true/neorv32_cpu_cp_muldiv_inst/rstn_i" type="logic">
<obj_property name="ElementShortName">rstn_i</obj_property>
<obj_property name="ObjectShortName">rstn_i</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_cp_muldiv_inst_true/neorv32_cpu_cp_muldiv_inst/ctrl_i" type="array">
<obj_property name="ElementShortName">ctrl_i[47:0]</obj_property>
<obj_property name="ObjectShortName">ctrl_i[47:0]</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_cp_muldiv_inst_true/neorv32_cpu_cp_muldiv_inst/rs1_i" type="array">
<obj_property name="ElementShortName">rs1_i[31:0]</obj_property>
<obj_property name="ObjectShortName">rs1_i[31:0]</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_cp_muldiv_inst_true/neorv32_cpu_cp_muldiv_inst/rs2_i" type="array">
<obj_property name="ElementShortName">rs2_i[31:0]</obj_property>
<obj_property name="ObjectShortName">rs2_i[31:0]</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_cp_muldiv_inst_true/neorv32_cpu_cp_muldiv_inst/res_o" type="array">
<obj_property name="ElementShortName">res_o[31:0]</obj_property>
<obj_property name="ObjectShortName">res_o[31:0]</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_cp_muldiv_inst_true/neorv32_cpu_cp_muldiv_inst/valid_o" type="logic">
<obj_property name="ElementShortName">valid_o</obj_property>
<obj_property name="ObjectShortName">valid_o</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_cp_muldiv_inst_true/neorv32_cpu_cp_muldiv_inst/state" type="other">
<obj_property name="ElementShortName">state</obj_property>
<obj_property name="ObjectShortName">state</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_cp_muldiv_inst_true/neorv32_cpu_cp_muldiv_inst/cnt" type="array">
<obj_property name="ElementShortName">cnt[4:0]</obj_property>
<obj_property name="ObjectShortName">cnt[4:0]</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_cp_muldiv_inst_true/neorv32_cpu_cp_muldiv_inst/cp_op" type="array">
<obj_property name="ElementShortName">cp_op[2:0]</obj_property>
<obj_property name="ObjectShortName">cp_op[2:0]</obj_property>
<obj_property name="Radix">BINARYRADIX</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_cp_muldiv_inst_true/neorv32_cpu_cp_muldiv_inst/start" type="logic">
<obj_property name="ElementShortName">start</obj_property>
<obj_property name="ObjectShortName">start</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_cp_muldiv_inst_true/neorv32_cpu_cp_muldiv_inst/operation" type="logic">
<obj_property name="ElementShortName">operation</obj_property>
<obj_property name="ObjectShortName">operation</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_cp_muldiv_inst_true/neorv32_cpu_cp_muldiv_inst/opx" type="array">
<obj_property name="ElementShortName">opx[31:0]</obj_property>
<obj_property name="ObjectShortName">opx[31:0]</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_cp_muldiv_inst_true/neorv32_cpu_cp_muldiv_inst/opy" type="array">
<obj_property name="ElementShortName">opy[31:0]</obj_property>
<obj_property name="ObjectShortName">opy[31:0]</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_cp_muldiv_inst_true/neorv32_cpu_cp_muldiv_inst/opx_is_signed" type="logic">
<obj_property name="ElementShortName">opx_is_signed</obj_property>
<obj_property name="ObjectShortName">opx_is_signed</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_cp_muldiv_inst_true/neorv32_cpu_cp_muldiv_inst/opy_is_signed" type="logic">
<obj_property name="ElementShortName">opy_is_signed</obj_property>
<obj_property name="ObjectShortName">opy_is_signed</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_cp_muldiv_inst_true/neorv32_cpu_cp_muldiv_inst/div_res_corr" type="logic">
<obj_property name="ElementShortName">div_res_corr</obj_property>
<obj_property name="ObjectShortName">div_res_corr</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_cp_muldiv_inst_true/neorv32_cpu_cp_muldiv_inst/remainder" type="array">
<obj_property name="ElementShortName">remainder[31:0]</obj_property>
<obj_property name="ObjectShortName">remainder[31:0]</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_cp_muldiv_inst_true/neorv32_cpu_cp_muldiv_inst/quotient" type="array">
<obj_property name="ElementShortName">quotient[31:0]</obj_property>
<obj_property name="ObjectShortName">quotient[31:0]</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_cp_muldiv_inst_true/neorv32_cpu_cp_muldiv_inst/div_sub" type="array">
<obj_property name="ElementShortName">div_sub[32:0]</obj_property>
<obj_property name="ObjectShortName">div_sub[32:0]</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_cp_muldiv_inst_true/neorv32_cpu_cp_muldiv_inst/div_sign_comp_in" type="array">
<obj_property name="ElementShortName">div_sign_comp_in[31:0]</obj_property>
<obj_property name="ObjectShortName">div_sign_comp_in[31:0]</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_cp_muldiv_inst_true/neorv32_cpu_cp_muldiv_inst/div_sign_comp" type="array">
<obj_property name="ElementShortName">div_sign_comp[31:0]</obj_property>
<obj_property name="ObjectShortName">div_sign_comp[31:0]</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_cp_muldiv_inst_true/neorv32_cpu_cp_muldiv_inst/div_res" type="array">
<obj_property name="ElementShortName">div_res[31:0]</obj_property>
<obj_property name="ObjectShortName">div_res[31:0]</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_cp_muldiv_inst_true/neorv32_cpu_cp_muldiv_inst/mul_product" type="array">
<obj_property name="ElementShortName">mul_product[63:0]</obj_property>
<obj_property name="ObjectShortName">mul_product[63:0]</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_cp_muldiv_inst_true/neorv32_cpu_cp_muldiv_inst/mul_do_add" type="array">
<obj_property name="ElementShortName">mul_do_add[32:0]</obj_property>
<obj_property name="ObjectShortName">mul_do_add[32:0]</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_cp_muldiv_inst_true/neorv32_cpu_cp_muldiv_inst/mul_sign_cycle" type="logic">
<obj_property name="ElementShortName">mul_sign_cycle</obj_property>
<obj_property name="ObjectShortName">mul_sign_cycle</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_cp_muldiv_inst_true/neorv32_cpu_cp_muldiv_inst/mul_p_sext" type="logic">
<obj_property name="ElementShortName">mul_p_sext</obj_property>
<obj_property name="ObjectShortName">mul_p_sext</obj_property>
</wvobject>
</wave_config>
/sim/neorv32_tb.vhd
126,8 → 126,9
generic map (
-- General --
CLOCK_FREQUENCY => f_clock_nat_c, -- clock frequency of clk_i in Hz
HART_ID => x"ABCD1234", -- custom hardware thread ID
HART_ID => x"00000000", -- custom hardware thread ID
BOOTLOADER_USE => false, -- implement processor-internal bootloader?
CSR_COUNTERS_USE => true, -- implement RISC-V perf. counters ([m]instret[h], [m]cycle[h], time[h])?
-- RISC-V CPU Extensions --
CPU_EXTENSION_RISCV_C => true, -- implement compressed extension?
CPU_EXTENSION_RISCV_E => false, -- implement embedded RF extension?
181,9 → 182,9
uart_txd_o => uart_txd, -- UART send data
uart_rxd_i => uart_txd, -- UART receive data
-- SPI --
spi_sclk_o => open, -- serial clock line
spi_mosi_o => spi_data, -- serial data line out
spi_miso_i => spi_data, -- serial data line in
spi_sck_o => open, -- SPI serial clock
spi_sdo_o => spi_data, -- controller data out, peripheral data in
spi_sdi_i => spi_data, -- controller data in, peripheral data out
spi_csn_o => open, -- SPI CS
-- TWI --
twi_sda_io => twi_sda, -- twi serial data line
/sw/bootloader/bootloader.c
218,7 → 218,9
print_proc_version();
neorv32_uart_print("\nCLK: ");
print_hex_word(neorv32_cpu_csr_read(CSR_MCLOCK));
neorv32_uart_print(" Hz\nMISA: ");
neorv32_uart_print(" Hz\nMHID: ");
print_hex_word(neorv32_cpu_csr_read(CSR_MHARTID));
neorv32_uart_print("\nMISA: ");
print_hex_word(neorv32_cpu_csr_read(CSR_MISA));
neorv32_uart_print("\nCONF: ");
print_hex_word(neorv32_cpu_csr_read(CSR_MFEATURES));
/sw/common/crt0.S
1,7 → 1,7
/* ################################################################################################# */
/* # << NEORV32 - crt0.S - Application Start-Up Code >> # */
/* # << NEORV32 - crt0.S - Application Start-Up Code & Minimal Runtime Environment >> # */
/* # ********************************************************************************************* # */
/* # The start-up code provides a minimal runtime environment that catches all exceptions/ # */
/* # The start-up code provides a minimal runtime environment that catches all exceptions and # */
/* # interrupts and delegates them to the handler functions (installed by user via dedicated # */
/* # install function from the neorv32 runtime environment library). # */
/* # ********************************************************************************************* # */
117,8 → 117,8
// Setup stack pointer
// *********************************************************
__crt0_stack_pointer_init:
csrrw x11, CSR_MDSPACEBASE, zero // data memory space base address
csrrw x12, CSR_MDSPACESIZE, zero // data memory space size
csrr x11, CSR_MDSPACEBASE // data memory space base address
csrr x12, CSR_MDSPACESIZE // data memory space size
add sp, x11, x12
addi sp, sp, -4 // stack pointer = last entry
addi fp, sp, 0 // frame pointer = stack pointer
139,9 → 139,9
// *********************************************************
__crt0_neorv32_rte_init:
la x11, __crt0_neorv32_rte
csrrw zero, mtvec, x11 // set address of first-level exception handler
csrw mtvec, x11 // set address of first-level exception handler
 
csrrw x11, CSR_MDSPACEBASE, zero // data memory space base address
csrr x11, CSR_MDSPACEBASE // data memory space base address
la x12, __crt0_neorv32_rte_dummy_hanlder
li x13, 2*16 // number of entries (16xEXC, 16xIRQ)
 
278,14 → 278,14
// --------------------------------------------
// get cause and prepare jump into vector table
// --------------------------------------------
csrrw t0, mcause, zero // get cause code
csrr t0, mcause // get cause code
 
andi t1, t0, 0x0f // isolate cause ID
slli t1, t1, 2 // make address offset
csrrw ra, CSR_MDSPACEBASE, zero // data memory space base address
csrr ra, CSR_MDSPACEBASE // data memory space base address
add t1, t1, ra // get vetor table entry address (EXC vectors)
 
csrrw ra, mepc, zero // get return address
csrr ra, mepc // get return address
 
blt t0, zero, __crt0_neorv32_rte_is_irq // branch if this is an INTERRUPT
 
296,11 → 296,11
__crt0_neorv32_rte_is_exc:
 
// is faulting instruction compressed?
csrrw t0, mtinst, zero
andi t0, t0, 2 // get compression flag (bit #1): 0=compressed, 2=uncompressed
csrr t0, mtinst
andi t0, t0, 2 // get compression flag (bit #1): 0=compressed, 1=uncompressed
 
addi ra, ra, +2 // only this for compressed instr
add ra, ra, t0 // add another 2 (0+4) for uncompressed instr
addi ra, ra, +2 // only this for compressed instructions
add ra, ra, t0 // add another 2 (making +4) for uncompressed instructions
j __crt0_neorv32_rte_execute
 
 
320,7 → 320,6
// push ra
addi sp, sp, -4
sw ra, 0(sp)
csrrw zero, mscratch, ra
 
jalr ra, t0 // call second-level handler
 
328,7 → 327,7
lw ra, 0(sp)
addi sp, sp, +4
 
csrrw zero, mepc, ra
csrw mepc, ra
 
 
// --------------------------------------------
/sw/example/blink_led/makefile
82,16 → 82,14
 
 
# -----------------------------------------------------------------------------
# Add NEORV32 sources to input SRCs
# NEORV32 core sources
# -----------------------------------------------------------------------------
APP_SRC += $(wildcard $(NEORV32_SRC_PATH)/*.c)
CORE_SRC = $(wildcard $(NEORV32_SRC_PATH)/*.c)
 
 
# -----------------------------------------------------------------------------
# Make defaults
# -----------------------------------------------------------------------------
.SUFFIXES:
.PHONY: all
.DEFAULT_GOAL := help
 
 
106,7 → 104,8
all: $(APP_ASM) $(APP_EXE) neorv32_application_image.vhd
 
# define all object files
OBJ = $(APP_SRC:.c=.o)
OBJ = $(APP_SRC:.c=.o)
OBJ += $(CORE_SRC:.c=.o)
 
 
# -----------------------------------------------------------------------------
259,13 → 258,18
# -----------------------------------------------------------------------------
info:
@echo "---------------- Info: Project ----------------"
@echo "Project: $(shell basename $(CURDIR))"
@echo "Project source files: $(APP_SRC)"
@echo "Project include folders: $(NEORV32_INC_PATH) $(APP_INC)"
@echo "Project object files: $(OBJ)"
@echo "Project folder: $(shell basename $(CURDIR))"
@echo "Source files: $(APP_SRC)"
@echo "Include folder(s): $(APP_INC)"
@echo "---------------- Info: NEORV32 ----------------"
@echo "NEORV32 home folder (NEORV32_HOME): $(NEORV32_HOME)"
@echo "IMAGE_GEN: $(IMAGE_GEN)"
@echo "Core source files:"
@echo "$(CORE_SRC)"
@echo "Core include folder:"
@echo "$(NEORV32_INC_PATH)"
@echo "Project object files:"
@echo "$(OBJ)"
@echo "---------------- Info: RISC-V CPU ----------------"
@echo "MARCH: $(MARCH)"
@echo "MABI: $(MABI)"
/sw/example/coremark/makefile
82,16 → 82,14
 
 
# -----------------------------------------------------------------------------
# Add NEORV32 sources to input SRCs
# NEORV32 core sources
# -----------------------------------------------------------------------------
APP_SRC += $(wildcard $(NEORV32_SRC_PATH)/*.c)
CORE_SRC = $(wildcard $(NEORV32_SRC_PATH)/*.c)
 
 
# -----------------------------------------------------------------------------
# Make defaults
# -----------------------------------------------------------------------------
.SUFFIXES:
.PHONY: all
.DEFAULT_GOAL := help
 
 
106,7 → 104,8
all: $(APP_ASM) $(APP_EXE) neorv32_application_image.vhd
 
# define all object files
OBJ = $(APP_SRC:.c=.o)
OBJ = $(APP_SRC:.c=.o)
OBJ += $(CORE_SRC:.c=.o)
 
 
# -----------------------------------------------------------------------------
259,13 → 258,18
# -----------------------------------------------------------------------------
info:
@echo "---------------- Info: Project ----------------"
@echo "Project: $(shell basename $(CURDIR))"
@echo "Project source files: $(APP_SRC)"
@echo "Project include folders: $(NEORV32_INC_PATH) $(APP_INC)"
@echo "Project object files: $(OBJ)"
@echo "Project folder: $(shell basename $(CURDIR))"
@echo "Source files: $(APP_SRC)"
@echo "Include folder(s): $(APP_INC)"
@echo "---------------- Info: NEORV32 ----------------"
@echo "NEORV32 home folder (NEORV32_HOME): $(NEORV32_HOME)"
@echo "IMAGE_GEN: $(IMAGE_GEN)"
@echo "Core source files:"
@echo "$(CORE_SRC)"
@echo "Core include folder:"
@echo "$(NEORV32_INC_PATH)"
@echo "Project object files:"
@echo "$(OBJ)"
@echo "---------------- Info: RISC-V CPU ----------------"
@echo "MARCH: $(MARCH)"
@echo "MABI: $(MABI)"
/sw/example/cpu_test/main.c
0,0 → 1,586
// #################################################################################################
// # << NEORV32 - CPU Test Program >> #
// # ********************************************************************************************* #
// # BSD 3-Clause License #
// # #
// # Copyright (c) 2020, Stephan Nolting. All rights reserved. #
// # #
// # Redistribution and use in source and binary forms, with or without modification, are #
// # permitted provided that the following conditions are met: #
// # #
// # 1. Redistributions of source code must retain the above copyright notice, this list of #
// # conditions and the following disclaimer. #
// # #
// # 2. Redistributions in binary form must reproduce the above copyright notice, this list of #
// # conditions and the following disclaimer in the documentation and/or other materials #
// # provided with the distribution. #
// # #
// # 3. Neither the name of the copyright holder nor the names of its contributors may be used to #
// # endorse or promote products derived from this software without specific prior written #
// # permission. #
// # #
// # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS #
// # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF #
// # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE #
// # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, #
// # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE #
// # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED #
// # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING #
// # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED #
// # OF THE POSSIBILITY OF SUCH DAMAGE. #
// # ********************************************************************************************* #
// # The NEORV32 Processor - https://github.com/stnolting/neorv32 (c) Stephan Nolting #
// #################################################################################################
 
 
/**********************************************************************//**
* @file cpu_test/main.c
* @author Stephan Nolting
* @brief Simple CPU interrupts and exceptions test program.
**************************************************************************/
 
#include <neorv32.h>
 
 
/**********************************************************************//**
* @name User configuration
**************************************************************************/
/**@{*/
/** UART BAUD rate */
#define BAUD_RATE 19200
//** Set 1 for detailed exception debug information */
#define DETAILED_EXCEPTION_DEBUG 0
//** Reachable unaligned address */
#define ADDR_UNALIGNED 0x00000002
//** Unreachable aligned address */
#define ADDR_UNREACHABLE 0xFFFFFF00
/**@}*/
 
 
/**********************************************************************//**
* @name Exception handler acknowledges
**************************************************************************/
/**@{*/
/** Exception handler answers / identifiers */
enum EXC_HANDLER_ANSWERS {
ANSWER_I_MISALIGN = 0x12345678, /**< Answer for misaligned instruction address excetion */
ANSWER_I_ACCESS = 0xAABB1133, /**< Answer for instruction access fault excetion */
ANSWER_I_ILLEGAL = 0x0199203B, /**< Answer for illegal instruction excetion */
ANSWER_BREAKPOINT = 0x12322330, /**< Answer for breakpoint excetion */
ANSWER_L_MISALIGN = 0xBABCCCCC, /**< Answer for misaligned load address excetion */
ANSWER_L_ACCESS = 0xDEF728AA, /**< Answer for load access fault excetion */
ANSWER_S_MISALIGN = 0xFF0927DD, /**< Answer for misaligned store address excetion */
ANSWER_S_ACCESS = 0x20091777, /**< Answer for store access fault excetion */
ANSWER_ENVCALL = 0x55662244, /**< Answer for environment call excetion */
ANSWER_MSI = 0xCDECDEA9, /**< Answer for machine software interrupt */
ANSWER_MTI = 0x0012FA53, /**< Answer for machine timer interrupt */
ANSWER_CLIC = 0xEEF33088 /**< Answer for machine external interrupt */
};
/** Gloabl volatile variable to store exception handler answer */
volatile uint32_t exception_handler_answer;
/**@}*/
 
 
// Prototypes
void exc_handler_i_misalign(void);
void exc_handler_i_access(void);
void exc_handler_i_illegal(void);
void exc_handler_breakpoint(void);
void exc_handler_l_misalign(void);
void exc_handler_l_access(void);
void exc_handler_s_misalign(void);
void exc_handler_s_access(void);
void exc_handler_envcall(void);
void exc_handler_msi(void);
void exc_handler_mti(void);
void irq_handler_clic_ch0();
 
 
/**********************************************************************//**
* Unreachable memory-mapped register that should be always available
**************************************************************************/
#define MMR_UNREACHABLE (*(IO_REG32 (ADDR_UNREACHABLE)))
 
 
/**********************************************************************//**
* This program uses mostly synthetic case to trigger all implemented exceptions.
* Each exception is captured and evaluated for correct detection.
*
* @note This program requires the UART, MTIME and CLIC to be synthesized.
*
* @return Irrelevant.
**************************************************************************/
int main() {
 
register uint32_t tmp_a;
volatile uint32_t dummy_dst __attribute__((unused));
 
int cnt_fail = 0;
int cnt_ok = 0;
int cnt_test = 0;
 
// check if UART unit is implemented at all
if (neorv32_uart_available() == 0) {
return 0;
}
 
// check if CLIC unit is implemented at all
if (neorv32_clic_available() == 0) {
return 0;
}
 
// check if MTIME unit is implemented at all
if (neorv32_mtime_available() == 0) {
return 0;
}
 
 
// init UART at default baud rate, no rx interrupt, no tx interrupt
neorv32_uart_setup(BAUD_RATE, 0, 0);
 
 
// set CMP of machine system timer MTIME to max to prevent an IRQ
uint64_t mtime_cmp_max = 0xFFFFFFFFFFFFFFFFL;
neorv32_mtime_set_timecmp(mtime_cmp_max);
 
// intro
neorv32_uart_printf("\n\n------ CPU TEST ------\n\n");
 
// show full HW config report
neorv32_rte_print_hw_config();
 
// intro2
neorv32_uart_printf("\n\nNEORV32 exceptions and interrupts test program\n\n");
 
// install exception handler functions
int install_err = 0;
install_err += neorv32_rte_exception_install(EXCID_I_MISALIGNED, exc_handler_i_misalign);
install_err += neorv32_rte_exception_install(EXCID_I_ACCESS, exc_handler_i_access);
install_err += neorv32_rte_exception_install(EXCID_I_ILLEGAL, exc_handler_i_illegal);
install_err += neorv32_rte_exception_install(EXCID_BREAKPOINT, exc_handler_breakpoint);
install_err += neorv32_rte_exception_install(EXCID_L_MISALIGNED, exc_handler_l_misalign);
install_err += neorv32_rte_exception_install(EXCID_L_ACCESS, exc_handler_l_access);
install_err += neorv32_rte_exception_install(EXCID_S_MISALIGNED, exc_handler_s_misalign);
install_err += neorv32_rte_exception_install(EXCID_S_ACCESS, exc_handler_s_access);
install_err += neorv32_rte_exception_install(EXCID_MENV_CALL, exc_handler_envcall);
install_err += neorv32_rte_exception_install(EXCID_MSI, exc_handler_msi);
install_err += neorv32_rte_exception_install(EXCID_MTI, exc_handler_mti);
//install_err += neorv32_rte_exception_install(EXCID_MEI, -); done by neorv32_clic_handler_install
 
if (install_err) {
neorv32_uart_printf("install error!\n");
return 0;
}
 
 
// install interrupt handler for clic WDT channel
install_err += neorv32_clic_handler_install(CLIC_CH_WDT, irq_handler_clic_ch0);
 
if (install_err) {
neorv32_uart_printf("CLIC install error!\n");
return 0;
}
 
 
#if (DETAILED_EXCEPTION_DEBUG==1)
// enable debug mode for uninitialized exception/interrupt vectors
// and overwrite previous exception handler installations
// -> any exception/interrupt will show a message from the neorv32 runtime environment
neorv32_rte_enable_debug_mode();
#endif
 
 
// enable global interrupts
neorv32_cpu_eint();
 
exception_handler_answer = 0;
 
 
// ----------------------------------------------------------
// Unaligned instruction address
// ----------------------------------------------------------
neorv32_uart_printf("EXC I_ALIGN: ");
cnt_test++;
 
// skip if C-mode is not implemented
if ((neorv32_cpu_csr_read(CSR_MISA) | (1<<CPU_MISA_C_EXT)) == 0) {
 
// call unaligned address
((void (*)(void))ADDR_UNALIGNED)();
 
#if (DETAILED_EXCEPTION_DEBUG==0)
if (exception_handler_answer == ANSWER_I_MISALIGN) {
neorv32_uart_printf("ok\n");
cnt_ok++;
}
else {
neorv32_uart_printf("fail\n");
cnt_fail++;
}
exception_handler_answer = 0;
#endif
}
else {
neorv32_uart_printf("skipped (no EXC I_ALIGN possible in C-mode)\n");
}
 
 
// ----------------------------------------------------------
// Instruction access fault
// ----------------------------------------------------------
neorv32_uart_printf("EXC I_ACC: ");
cnt_test++;
 
// call unreachable aligned address
((void (*)(void))ADDR_UNREACHABLE)();
 
#if (DETAILED_EXCEPTION_DEBUG==0)
if (exception_handler_answer == ANSWER_I_ACCESS) {
neorv32_uart_printf("ok\n");
cnt_ok++;
}
else {
neorv32_uart_printf("fail\n");
cnt_fail++;
}
exception_handler_answer = 0;
#endif
 
 
// ----------------------------------------------------------
// Illegal instruction
// ----------------------------------------------------------
neorv32_uart_printf("EXC I_ILLEG: ");
cnt_test++;
 
// create test program in RAM
static const uint32_t dummy_sub_program[2] = {
0xDEAD007F, // undefined 32-bit opcode -> illegal instruction exception
0x00008067 // ret (32-bit)
};
 
tmp_a = (uint32_t)&dummy_sub_program; // call the dummy sub program
asm volatile ( "jalr ra, %0 " : "=r" (tmp_a) : "r" (tmp_a));
 
#if (DETAILED_EXCEPTION_DEBUG==0)
if (exception_handler_answer == ANSWER_I_ILLEGAL) {
neorv32_uart_printf("ok\n");
cnt_ok++;
}
else {
neorv32_uart_printf("fail\n");
cnt_fail++;
}
exception_handler_answer = 0;
#endif
 
 
// ----------------------------------------------------------
// Breakpoint instruction
// ----------------------------------------------------------
neorv32_uart_printf("EXC BREAK: ");
cnt_test++;
 
asm volatile("EBREAK");
 
#if (DETAILED_EXCEPTION_DEBUG==0)
if (exception_handler_answer == ANSWER_BREAKPOINT) {
neorv32_uart_printf("ok\n");
cnt_ok++;
}
else {
neorv32_uart_printf("fail\n");
cnt_fail++;
}
exception_handler_answer = 0;
#endif
 
 
// ----------------------------------------------------------
// Unaligned load address
// ----------------------------------------------------------
neorv32_uart_printf("EXC L_ALIGN: ");
cnt_test++;
 
// load from unaligned address
asm volatile ("lw zero, %[input_i](zero)" : : [input_i] "i" (ADDR_UNALIGNED));
 
#if (DETAILED_EXCEPTION_DEBUG==0)
if (exception_handler_answer == ANSWER_L_MISALIGN) {
neorv32_uart_printf("ok\n");
cnt_ok++;
}
else {
neorv32_uart_printf("fail\n");
cnt_fail++;
}
exception_handler_answer = 0;
#endif
 
 
// ----------------------------------------------------------
// Load access fault
// ----------------------------------------------------------
neorv32_uart_printf("EXC L_ACC: ");
cnt_test++;
 
// load from unreachable aligned address
dummy_dst = MMR_UNREACHABLE;
 
#if (DETAILED_EXCEPTION_DEBUG==0)
if (exception_handler_answer == ANSWER_L_ACCESS) {
neorv32_uart_printf("ok\n");
cnt_ok++;
}
else {
neorv32_uart_printf("fail\n");
cnt_fail++;
}
exception_handler_answer = 0;
#endif
 
 
// ----------------------------------------------------------
// Unaligned store address
// ----------------------------------------------------------
neorv32_uart_printf("EXC S_ALIGN: ");
cnt_test++;
 
// store to unaligned address
asm volatile ("sw zero, %[input_i](zero)" : : [input_i] "i" (ADDR_UNALIGNED));
 
#if (DETAILED_EXCEPTION_DEBUG==0)
if (exception_handler_answer == ANSWER_S_MISALIGN) {
neorv32_uart_printf("ok\n");
cnt_ok++;
}
else {
neorv32_uart_printf("fail\n");
cnt_fail++;
}
exception_handler_answer = 0;
#endif
 
 
// ----------------------------------------------------------
// Store access fault
// ----------------------------------------------------------
neorv32_uart_printf("EXC S_ACC: ");
cnt_test++;
 
// store to unreachable aligned address
MMR_UNREACHABLE = 0;
 
#if (DETAILED_EXCEPTION_DEBUG==0)
if (exception_handler_answer == ANSWER_S_ACCESS) {
neorv32_uart_printf("ok\n");
cnt_ok++;
}
else {
neorv32_uart_printf("fail\n");
cnt_fail++;
}
exception_handler_answer = 0;
#endif
 
 
// ----------------------------------------------------------
// Environment call
// ----------------------------------------------------------
neorv32_uart_printf("EXC ENVCALL: ");
cnt_test++;
 
asm volatile("ECALL");
 
#if (DETAILED_EXCEPTION_DEBUG==0)
if (exception_handler_answer == ANSWER_ENVCALL) {
neorv32_uart_printf("ok\n");
cnt_ok++;
}
else {
neorv32_uart_printf("fail\n");
cnt_fail++;
}
exception_handler_answer = 0;
#endif
 
 
// ----------------------------------------------------------
// Machine software interrupt
// ----------------------------------------------------------
neorv32_uart_printf("IRQ MSI: ");
cnt_test++;
 
// trigger machine software interrupt
neorv32_cpu_sw_irq();
 
#if (DETAILED_EXCEPTION_DEBUG==0)
if (exception_handler_answer == ANSWER_MSI) {
neorv32_uart_printf("ok\n");
cnt_ok++;
}
else {
neorv32_uart_printf("fail\n");
cnt_fail++;
}
exception_handler_answer = 0;
#endif
 
 
// ----------------------------------------------------------
// Machine timer interrupt (MTIME)
// ----------------------------------------------------------
neorv32_uart_printf("IRQ MTI: ");
cnt_test++;
 
// force MTIME IRQ
neorv32_mtime_set_timecmp(0);
 
// wait some time for the IRQ to arrive the CPU
asm volatile("nop");
asm volatile("nop");
asm volatile("nop");
asm volatile("nop");
 
#if (DETAILED_EXCEPTION_DEBUG==0)
if (exception_handler_answer == ANSWER_MTI) {
neorv32_uart_printf("ok\n");
cnt_ok++;
}
else {
neorv32_uart_printf("fail\n");
cnt_fail++;
}
exception_handler_answer = 0;
#endif
 
 
// ----------------------------------------------------------
// Machine external interrupt (via CLIC)
// ----------------------------------------------------------
neorv32_uart_printf("IRQ MEI: ");
cnt_test++;
 
// manually trigger CLIC channel (watchdog interrupt)
neorv32_clic_trigger_irq(CLIC_CH_WDT);
 
// wait some time for the IRQ to arrive the CPU
asm volatile("nop");
asm volatile("nop");
asm volatile("nop");
asm volatile("nop");
 
#if (DETAILED_EXCEPTION_DEBUG==0)
if (exception_handler_answer == ANSWER_CLIC) {
neorv32_uart_printf("ok\n");
cnt_ok++;
}
else {
neorv32_uart_printf("fail\n");
cnt_fail++;
}
exception_handler_answer = 0;
#endif
 
 
// error report
neorv32_uart_printf("\n\nTests: %i\nOK: %i\nFAIL: %i\n\n", cnt_test, cnt_ok, cnt_fail);
 
// final result
if (cnt_fail == 0) {
neorv32_uart_printf("TEST OK!\n");
}
else {
neorv32_uart_printf("TEST FAILED!\n");
}
 
return 0;
}
 
 
/**********************************************************************//**
* Misaligned instruction address exception handler.
**************************************************************************/
void exc_handler_i_misalign(void) {
exception_handler_answer = ANSWER_I_MISALIGN;
}
 
/**********************************************************************//**
* Instruction access fault exception handler.
**************************************************************************/
void exc_handler_i_access(void) {
exception_handler_answer = ANSWER_I_ACCESS;
}
 
/**********************************************************************//**
* Illegal instruction exception handler.
**************************************************************************/
void exc_handler_i_illegal(void) {
exception_handler_answer = ANSWER_I_ILLEGAL;
}
 
/**********************************************************************//**
* Breakpoint exception handler.
**************************************************************************/
void exc_handler_breakpoint(void) {
exception_handler_answer = ANSWER_BREAKPOINT;
}
 
/**********************************************************************//**
* Misaligned load address exception handler.
**************************************************************************/
void exc_handler_l_misalign(void) {
exception_handler_answer = ANSWER_L_MISALIGN;
}
 
/**********************************************************************//**
* Load instruction access fault exception handler.
**************************************************************************/
void exc_handler_l_access(void) {
exception_handler_answer = ANSWER_L_ACCESS;
}
 
/**********************************************************************//**
* Misaligned store address exception handler.
**************************************************************************/
void exc_handler_s_misalign(void) {
exception_handler_answer = ANSWER_S_MISALIGN;
}
 
/**********************************************************************//**
* Store address access fault exception handler.
**************************************************************************/
void exc_handler_s_access(void) {
exception_handler_answer = ANSWER_S_ACCESS;
}
 
/**********************************************************************//**
* Environment call exception handler.
**************************************************************************/
void exc_handler_envcall(void) {
exception_handler_answer = ANSWER_ENVCALL;
}
 
/**********************************************************************//**
* Machine software interrupt exception handler.
**************************************************************************/
void exc_handler_msi(void) {
exception_handler_answer = ANSWER_MSI;
}
 
/**********************************************************************//**
* Machine timer interrupt exception handler.
**************************************************************************/
void exc_handler_mti(void) {
exception_handler_answer = ANSWER_MTI;
// set CMP of machine system timer MTIME to max to prevent an IRQ
neorv32_mtime_set_timecmp(-1);
}
 
/**********************************************************************//**
* CLIC interrupt handler for channel 0.
**************************************************************************/
void irq_handler_clic_ch0(void) {
exception_handler_answer = ANSWER_CLIC;
}
 
/sw/example/cpu_test/makefile
0,0 → 1,326
#################################################################################################
# << NEORV32 - Application Makefile >> #
# ********************************************************************************************* #
# Make sure to add the riscv GCC compiler's bin folder to your PATH environment variable. #
# ********************************************************************************************* #
# BSD 3-Clause License #
# #
# Copyright (c) 2020, Stephan Nolting. All rights reserved. #
# #
# Redistribution and use in source and binary forms, with or without modification, are #
# permitted provided that the following conditions are met: #
# #
# 1. Redistributions of source code must retain the above copyright notice, this list of #
# conditions and the following disclaimer. #
# #
# 2. Redistributions in binary form must reproduce the above copyright notice, this list of #
# conditions and the following disclaimer in the documentation and/or other materials #
# provided with the distribution. #
# #
# 3. Neither the name of the copyright holder nor the names of its contributors may be used to #
# endorse or promote products derived from this software without specific prior written #
# permission. #
# #
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS #
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF #
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE #
# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, #
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE #
# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED #
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING #
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED #
# OF THE POSSIBILITY OF SUCH DAMAGE. #
# ********************************************************************************************* #
# The NEORV32 Processor - https://github.com/stnolting/neorv32 (c) Stephan Nolting #
#################################################################################################
 
 
# *****************************************************************************
# USER CONFIGURATION
# *****************************************************************************
# Compiler effort
EFFORT = -Os
 
# User's application sources (add additional files here)
APP_SRC = $(wildcard *.c)
 
# User's application include folders (don't forget the '-I' before each entry)
APP_INC = -I .
 
# Compiler toolchain (use default if not set by user)
RISCV_TOOLCHAIN ?= riscv32-unknown-elf
 
# CPU architecture and ABI
MARCH = -march=rv32i
MABI = -mabi=ilp32
 
# Path to runtime c library (use default if not set by user)
LIBC_PATH ?= $(dir $(shell which $(CC)))../$(RISCV_TOOLCHAIN)/lib/libc.a
LIBGCC_PATH ?= $(dir $(shell which $(CC)))../lib/gcc/$(RISCV_TOOLCHAIN)/*/libgcc.a
 
# Relative or absolute path to the NEORV32 home folder (use default if not set by user)
NEORV32_HOME ?= ../../..
# *****************************************************************************
 
 
 
# -----------------------------------------------------------------------------
# NEORV32 framework
# -----------------------------------------------------------------------------
# Path to NEORV32 linker script and startup file
NEORV32_COM_PATH=$(NEORV32_HOME)/sw/common
# Path to main NEORV32 library include files
NEORV32_INC_PATH=$(NEORV32_HOME)/sw/lib/include
# Path to main NEORV32 library source files
NEORV32_SRC_PATH=$(NEORV32_HOME)/sw/lib/source
# Path to NEORV32 executable generator
NEORV32_EXG_PATH=$(NEORV32_HOME)/sw/image_gen
# Path to NEORV32 core rtl folder
NEORV32_RTL_PATH=$(NEORV32_HOME)/rtl/core
# Marker file to verify NEORV32 home folder
NEORV32_HOME_MARKER=$(NEORV32_INC_PATH)/neorv32.h
 
 
# -----------------------------------------------------------------------------
# NEORV32 core sources
# -----------------------------------------------------------------------------
CORE_SRC = $(wildcard $(NEORV32_SRC_PATH)/*.c)
 
 
# -----------------------------------------------------------------------------
# Make defaults
# -----------------------------------------------------------------------------
.DEFAULT_GOAL := help
 
 
# -----------------------------------------------------------------------------
# Application output definitions
# -----------------------------------------------------------------------------
APP_EXE = neorv32_exe.bin
APP_ASM = main.s
 
compile: $(APP_ASM) $(APP_EXE)
install: $(APP_ASM) neorv32_application_image.vhd
all: $(APP_ASM) $(APP_EXE) neorv32_application_image.vhd
 
# define all object files
OBJ = $(APP_SRC:.c=.o)
OBJ += $(CORE_SRC:.c=.o)
 
 
# -----------------------------------------------------------------------------
# Tools and flags
# -----------------------------------------------------------------------------
# compiler tools
CC = $(RISCV_TOOLCHAIN)-gcc
LD = $(RISCV_TOOLCHAIN)-ld
OBJDUMP = $(RISCV_TOOLCHAIN)-objdump
OBJCOPY = $(RISCV_TOOLCHAIN)-objcopy
SIZE = $(RISCV_TOOLCHAIN)-size
 
# NEORV32 executable image generator
IMAGE_GEN = $(NEORV32_EXG_PATH)/image_gen
 
# Compiler flags
CC_OPTS = $(MARCH) $(MABI) $(EFFORT) -Wall -ffunction-sections -fdata-sections -lm
 
# Linker flags
LD_OPTS = $(EFFORT) --gc-sections
 
# User flags for additional config
USER_FLAGS =
CC_OPTS += $(USER_FLAGS)
 
# Use embedded RISC-V CPU extension?
ifeq (,$(findstring rv32e,$(MARCH)))
CC_OPTS +=
else
CC_OPTS += -D__RISCV_EMBEDDED_CPU__
endif
 
# -----------------------------------------------------------------------------
# Host native compiler
# -----------------------------------------------------------------------------
CC_X86 = gcc -Wall -O -g
 
 
# -----------------------------------------------------------------------------
# Tool targets
# -----------------------------------------------------------------------------
# install/compile tools
$(IMAGE_GEN): $(NEORV32_EXG_PATH)/image_gen.cpp
@echo Compiling $(IMAGE_GEN)
@$(CC_X86) $< -o $(IMAGE_GEN)
 
 
# -----------------------------------------------------------------------------
# Application targets: Assemble, compile, link, dump
# -----------------------------------------------------------------------------
# Assemble startup code
crt0.elf: $(NEORV32_COM_PATH)/crt0.S
@$(CC) $(CC_OPTS) -c $< -o $@
 
# Compile app sources
$(OBJ): %.o : %.c crt0.elf
@$(CC) -c $(CC_OPTS) -I $(NEORV32_INC_PATH) $(APP_INC) $< -o $@
 
# Link object files and show memory utilization
main.elf: $(OBJ)
@$(LD) $(LD_OPTS) -I $(NEORV32_INC_PATH) $(APP_INC) -T $(NEORV32_COM_PATH)/neorv32.ld $(OBJ) $(LIBC_PATH) $(LIBGCC_PATH) -o $@
@echo "Memory utilization:"
@$(SIZE) main.elf
 
# Assembly listing file (for debugging)
$(APP_ASM): main.elf
@$(OBJDUMP) -D -S -z $< > $@
 
 
# -----------------------------------------------------------------------------
# Application targets: Generate binary executable, install (as VHDL file)
# -----------------------------------------------------------------------------
# Generate final executable: text, rodata, data (in THIS order!)
main.bin: main.elf
@$(OBJCOPY) -I elf32-little $< -j .text -O binary text.bin
@$(OBJCOPY) -I elf32-little $< -j .rodata -O binary rodata.bin
@$(OBJCOPY) -I elf32-little $< -j .data -O binary data.bin
@cat text.bin rodata.bin data.bin > $@
@rm -f text.bin rodata.bin data.bin
 
# Generate NEORV32 executable image for bootloader update
$(APP_EXE): main.bin $(IMAGE_GEN)
@set -e
@$(IMAGE_GEN) -app_bin $< $@ $(shell basename $(CURDIR))
@echo "Executable ($(APP_EXE)) size in bytes:"
@wc -c < $(APP_EXE)
 
# Generate NEORV32 executable VHDL boot image
neorv32_application_image.vhd: main.bin $(IMAGE_GEN)
@set -e
@$(IMAGE_GEN) -app_img $< $@ $(shell basename $(CURDIR))
@echo "Installing application image to $(NEORV32_RTL_PATH)/neorv32_application_image.vhd"
@cp neorv32_application_image.vhd $(NEORV32_RTL_PATH)/.
@rm -f neorv32_application_image.vhd
 
 
# -----------------------------------------------------------------------------
# Bootloader targets
# -----------------------------------------------------------------------------
# Assemble startup code
bootloader_crt0.elf: $(NEORV32_COM_PATH)/bootloader_crt0.S
@$(CC) $(CC_OPTS) -c $< -o $@
 
# Compile and install bootloader
bootloader: bootloader_crt0.elf $(OBJ) $(IMAGE_GEN)
@set -e
@$(LD) $(LD_OPTS) -I $(NEORV32_INC_PATH) $(APP_INC) -T $(NEORV32_COM_PATH)/bootloader_neorv32.ld $(OBJ) $(LIBC_PATH) $(LIBGCC_PATH) -o bootloader.elf
@echo "Memory utilization:"
@$(SIZE) bootloader.elf
@$(OBJDUMP) -D -S -z bootloader.elf > bootloader.s
@$(OBJCOPY) -I elf32-little bootloader.elf -j .text -O binary text.bin
@$(OBJCOPY) -I elf32-little bootloader.elf -j .rodata -O binary rodata.bin
@$(OBJCOPY) -I elf32-little bootloader.elf -j .data -O binary data.bin
@cat text.bin rodata.bin data.bin > bootloader.bin
@$(IMAGE_GEN) -bld_img bootloader.bin neorv32_bootloader_image.vhd $(shell basename $(CURDIR))
@echo "Installing bootloader image to $(NEORV32_RTL_PATH)/neorv32_bootloader_image.vhd"
@cp neorv32_bootloader_image.vhd $(NEORV32_RTL_PATH)/.
@rm -f neorv32_bootloader_image.vhd text.bin rodata.bin data.bin
 
 
# -----------------------------------------------------------------------------
# Check toolchain
# -----------------------------------------------------------------------------
check: $(IMAGE_GEN)
@echo "---------------- Check: NEORV32_HOME folder ----------------"
ifneq ($(shell [ -e $(NEORV32_HOME_MARKER) ] && echo 1 || echo 0 ), 1)
$(error NEORV32_HOME folder not found!)
endif
@echo "NEORV32_HOME: $(NEORV32_HOME)"
@echo "---------------- Check: $(CC) ----------------"
@$(CC) -v
@echo "---------------- Check: $(LD) ----------------"
@$(LD) -V
@echo "---------------- Check: $(OBJDUMP) ----------------"
@$(OBJDUMP) -V
@echo "---------------- Check: $(OBJCOPY) ----------------"
@$(OBJCOPY) -V
@echo "---------------- Check: $(SIZE) ----------------"
@$(SIZE) -V
@echo "---------------- Check: NEORV32 image_gen ----------------"
@$(IMAGE_GEN) -help
@echo "---------------- Check: native gcc ----------------"
@$(CC_X86) -v
@echo
@echo "Toolchain check OK"
 
 
# -----------------------------------------------------------------------------
# Show configuration
# -----------------------------------------------------------------------------
info:
@echo "---------------- Info: Project ----------------"
@echo "Project folder: $(shell basename $(CURDIR))"
@echo "Source files: $(APP_SRC)"
@echo "Include folder(s): $(APP_INC)"
@echo "---------------- Info: NEORV32 ----------------"
@echo "NEORV32 home folder (NEORV32_HOME): $(NEORV32_HOME)"
@echo "IMAGE_GEN: $(IMAGE_GEN)"
@echo "Core source files:"
@echo "$(CORE_SRC)"
@echo "Core include folder:"
@echo "$(NEORV32_INC_PATH)"
@echo "Project object files:"
@echo "$(OBJ)"
@echo "---------------- Info: RISC-V CPU ----------------"
@echo "MARCH: $(MARCH)"
@echo "MABI: $(MABI)"
@echo "---------------- Info: RISC-V Toolchain ----------------"
@echo "Toolchain: $(RISCV_TOLLCHAIN)"
@echo "CC: $(CC)"
@echo "LD: $(LD)"
@echo "OBJDUMP: $(OBJDUMP)"
@echo "OBJCOPY: $(OBJCOPY)"
@echo "SIZE: $(SIZE)"
@echo "---------------- Info: C Lib ----------------"
@echo "CLIB: $(LIBC_PATH)"
@echo "GCCLIB: $(LIBGCC_PATH)"
@echo "---------------- Info: Flags ----------------"
@echo "CC_OPTS: $(CC_OPTS)"
@echo "LD_OPTS: $(LD_OPTS)"
@echo "---------------- Info: Host Native GCC ----------------"
@echo "CC_X86: $(CC_X86)"
 
 
# -----------------------------------------------------------------------------
# Show final ELF details (just for debugging)
# -----------------------------------------------------------------------------
elf_info: main.elf
@$(OBJDUMP) -x main.elf
 
 
# -----------------------------------------------------------------------------
# Help
# -----------------------------------------------------------------------------
help:
@echo "<<< NEORV32 Application Makefile >>>"
@echo "Make sure to add the bin folder of RISC-V GCC to your PATH variable."
@echo "Targets:"
@echo " help - show this text"
@echo " check - check toolchain"
@echo " info - show makefile/toolchain configuration"
@echo " compile - compile and generate <neorv32_exe.bin> executable for upload via bootloader"
@echo " install - compile, generate and install VHDL IMEM boot image"
@echo " all - compile and generate <neorv32_exe.bin> executable for upload via bootloader and generate and install VHDL IMEM boot image"
@echo " clean - clean up project"
@echo " clean_all - clean up project, core libraries and image generator"
@echo " bootloader - compile, generate and install VHDL BOOTROM bott image (for bootloader only!)"
 
 
# -----------------------------------------------------------------------------
# Clean up
# -----------------------------------------------------------------------------
clean:
@rm -f *.elf *.o *.bin *.out *.s
 
clean_all: clean
@rm -f $(OBJ) $(IMAGE_GEN)
 
/sw/example/demo_pwm/makefile
82,16 → 82,14
 
 
# -----------------------------------------------------------------------------
# Add NEORV32 sources to input SRCs
# NEORV32 core sources
# -----------------------------------------------------------------------------
APP_SRC += $(wildcard $(NEORV32_SRC_PATH)/*.c)
CORE_SRC = $(wildcard $(NEORV32_SRC_PATH)/*.c)
 
 
# -----------------------------------------------------------------------------
# Make defaults
# -----------------------------------------------------------------------------
.SUFFIXES:
.PHONY: all
.DEFAULT_GOAL := help
 
 
106,7 → 104,8
all: $(APP_ASM) $(APP_EXE) neorv32_application_image.vhd
 
# define all object files
OBJ = $(APP_SRC:.c=.o)
OBJ = $(APP_SRC:.c=.o)
OBJ += $(CORE_SRC:.c=.o)
 
 
# -----------------------------------------------------------------------------
259,13 → 258,18
# -----------------------------------------------------------------------------
info:
@echo "---------------- Info: Project ----------------"
@echo "Project: $(shell basename $(CURDIR))"
@echo "Project source files: $(APP_SRC)"
@echo "Project include folders: $(NEORV32_INC_PATH) $(APP_INC)"
@echo "Project object files: $(OBJ)"
@echo "Project folder: $(shell basename $(CURDIR))"
@echo "Source files: $(APP_SRC)"
@echo "Include folder(s): $(APP_INC)"
@echo "---------------- Info: NEORV32 ----------------"
@echo "NEORV32 home folder (NEORV32_HOME): $(NEORV32_HOME)"
@echo "IMAGE_GEN: $(IMAGE_GEN)"
@echo "Core source files:"
@echo "$(CORE_SRC)"
@echo "Core include folder:"
@echo "$(NEORV32_INC_PATH)"
@echo "Project object files:"
@echo "$(OBJ)"
@echo "---------------- Info: RISC-V CPU ----------------"
@echo "MARCH: $(MARCH)"
@echo "MABI: $(MABI)"
/sw/example/demo_trng/makefile
82,16 → 82,14
 
 
# -----------------------------------------------------------------------------
# Add NEORV32 sources to input SRCs
# NEORV32 core sources
# -----------------------------------------------------------------------------
APP_SRC += $(wildcard $(NEORV32_SRC_PATH)/*.c)
CORE_SRC = $(wildcard $(NEORV32_SRC_PATH)/*.c)
 
 
# -----------------------------------------------------------------------------
# Make defaults
# -----------------------------------------------------------------------------
.SUFFIXES:
.PHONY: all
.DEFAULT_GOAL := help
 
 
106,7 → 104,8
all: $(APP_ASM) $(APP_EXE) neorv32_application_image.vhd
 
# define all object files
OBJ = $(APP_SRC:.c=.o)
OBJ = $(APP_SRC:.c=.o)
OBJ += $(CORE_SRC:.c=.o)
 
 
# -----------------------------------------------------------------------------
259,13 → 258,18
# -----------------------------------------------------------------------------
info:
@echo "---------------- Info: Project ----------------"
@echo "Project: $(shell basename $(CURDIR))"
@echo "Project source files: $(APP_SRC)"
@echo "Project include folders: $(NEORV32_INC_PATH) $(APP_INC)"
@echo "Project object files: $(OBJ)"
@echo "Project folder: $(shell basename $(CURDIR))"
@echo "Source files: $(APP_SRC)"
@echo "Include folder(s): $(APP_INC)"
@echo "---------------- Info: NEORV32 ----------------"
@echo "NEORV32 home folder (NEORV32_HOME): $(NEORV32_HOME)"
@echo "IMAGE_GEN: $(IMAGE_GEN)"
@echo "Core source files:"
@echo "$(CORE_SRC)"
@echo "Core include folder:"
@echo "$(NEORV32_INC_PATH)"
@echo "Project object files:"
@echo "$(OBJ)"
@echo "---------------- Info: RISC-V CPU ----------------"
@echo "MARCH: $(MARCH)"
@echo "MABI: $(MABI)"
/sw/example/demo_twi/makefile
82,16 → 82,14
 
 
# -----------------------------------------------------------------------------
# Add NEORV32 sources to input SRCs
# NEORV32 core sources
# -----------------------------------------------------------------------------
APP_SRC += $(wildcard $(NEORV32_SRC_PATH)/*.c)
CORE_SRC = $(wildcard $(NEORV32_SRC_PATH)/*.c)
 
 
# -----------------------------------------------------------------------------
# Make defaults
# -----------------------------------------------------------------------------
.SUFFIXES:
.PHONY: all
.DEFAULT_GOAL := help
 
 
106,7 → 104,8
all: $(APP_ASM) $(APP_EXE) neorv32_application_image.vhd
 
# define all object files
OBJ = $(APP_SRC:.c=.o)
OBJ = $(APP_SRC:.c=.o)
OBJ += $(CORE_SRC:.c=.o)
 
 
# -----------------------------------------------------------------------------
259,13 → 258,18
# -----------------------------------------------------------------------------
info:
@echo "---------------- Info: Project ----------------"
@echo "Project: $(shell basename $(CURDIR))"
@echo "Project source files: $(APP_SRC)"
@echo "Project include folders: $(NEORV32_INC_PATH) $(APP_INC)"
@echo "Project object files: $(OBJ)"
@echo "Project folder: $(shell basename $(CURDIR))"
@echo "Source files: $(APP_SRC)"
@echo "Include folder(s): $(APP_INC)"
@echo "---------------- Info: NEORV32 ----------------"
@echo "NEORV32 home folder (NEORV32_HOME): $(NEORV32_HOME)"
@echo "IMAGE_GEN: $(IMAGE_GEN)"
@echo "Core source files:"
@echo "$(CORE_SRC)"
@echo "Core include folder:"
@echo "$(NEORV32_INC_PATH)"
@echo "Project object files:"
@echo "$(OBJ)"
@echo "---------------- Info: RISC-V CPU ----------------"
@echo "MARCH: $(MARCH)"
@echo "MABI: $(MABI)"
/sw/example/demo_wdt/makefile
82,16 → 82,14
 
 
# -----------------------------------------------------------------------------
# Add NEORV32 sources to input SRCs
# NEORV32 core sources
# -----------------------------------------------------------------------------
APP_SRC += $(wildcard $(NEORV32_SRC_PATH)/*.c)
CORE_SRC = $(wildcard $(NEORV32_SRC_PATH)/*.c)
 
 
# -----------------------------------------------------------------------------
# Make defaults
# -----------------------------------------------------------------------------
.SUFFIXES:
.PHONY: all
.DEFAULT_GOAL := help
 
 
106,7 → 104,8
all: $(APP_ASM) $(APP_EXE) neorv32_application_image.vhd
 
# define all object files
OBJ = $(APP_SRC:.c=.o)
OBJ = $(APP_SRC:.c=.o)
OBJ += $(CORE_SRC:.c=.o)
 
 
# -----------------------------------------------------------------------------
259,13 → 258,18
# -----------------------------------------------------------------------------
info:
@echo "---------------- Info: Project ----------------"
@echo "Project: $(shell basename $(CURDIR))"
@echo "Project source files: $(APP_SRC)"
@echo "Project include folders: $(NEORV32_INC_PATH) $(APP_INC)"
@echo "Project object files: $(OBJ)"
@echo "Project folder: $(shell basename $(CURDIR))"
@echo "Source files: $(APP_SRC)"
@echo "Include folder(s): $(APP_INC)"
@echo "---------------- Info: NEORV32 ----------------"
@echo "NEORV32 home folder (NEORV32_HOME): $(NEORV32_HOME)"
@echo "IMAGE_GEN: $(IMAGE_GEN)"
@echo "Core source files:"
@echo "$(CORE_SRC)"
@echo "Core include folder:"
@echo "$(NEORV32_INC_PATH)"
@echo "Project object files:"
@echo "$(OBJ)"
@echo "---------------- Info: RISC-V CPU ----------------"
@echo "MARCH: $(MARCH)"
@echo "MABI: $(MABI)"
/sw/example/game_of_life/makefile
82,16 → 82,14
 
 
# -----------------------------------------------------------------------------
# Add NEORV32 sources to input SRCs
# NEORV32 core sources
# -----------------------------------------------------------------------------
APP_SRC += $(wildcard $(NEORV32_SRC_PATH)/*.c)
CORE_SRC = $(wildcard $(NEORV32_SRC_PATH)/*.c)
 
 
# -----------------------------------------------------------------------------
# Make defaults
# -----------------------------------------------------------------------------
.SUFFIXES:
.PHONY: all
.DEFAULT_GOAL := help
 
 
106,7 → 104,8
all: $(APP_ASM) $(APP_EXE) neorv32_application_image.vhd
 
# define all object files
OBJ = $(APP_SRC:.c=.o)
OBJ = $(APP_SRC:.c=.o)
OBJ += $(CORE_SRC:.c=.o)
 
 
# -----------------------------------------------------------------------------
259,13 → 258,18
# -----------------------------------------------------------------------------
info:
@echo "---------------- Info: Project ----------------"
@echo "Project: $(shell basename $(CURDIR))"
@echo "Project source files: $(APP_SRC)"
@echo "Project include folders: $(NEORV32_INC_PATH) $(APP_INC)"
@echo "Project object files: $(OBJ)"
@echo "Project folder: $(shell basename $(CURDIR))"
@echo "Source files: $(APP_SRC)"
@echo "Include folder(s): $(APP_INC)"
@echo "---------------- Info: NEORV32 ----------------"
@echo "NEORV32 home folder (NEORV32_HOME): $(NEORV32_HOME)"
@echo "IMAGE_GEN: $(IMAGE_GEN)"
@echo "Core source files:"
@echo "$(CORE_SRC)"
@echo "Core include folder:"
@echo "$(NEORV32_INC_PATH)"
@echo "Project object files:"
@echo "$(OBJ)"
@echo "---------------- Info: RISC-V CPU ----------------"
@echo "MARCH: $(MARCH)"
@echo "MABI: $(MABI)"
/sw/lib/include/neorv32.h
60,10 → 60,10
* Available CPU Control and Status Registers (CSRs)
**************************************************************************/
enum NEORV32_CPU_CSRS_enum {
CSR_MSTATUS = 0x300, /**< 0x300 - mstatus (r/w): Machine status register */
CSR_MISA = 0x301, /**< 0x301 - misa (r/-): CPU ISA and extensions */
CSR_MIE = 0x304, /**< 0x304 - mie (r/w): Machine interrupt-enable register */
CSR_MTVEC = 0x305, /**< 0x305 - mtvec (r/w): Machine trap-handler base address (for ALL traps) */
CSR_MSTATUS = 0x300, /**< 0x300 - mstatus (r/w): Machine status register */
CSR_MISA = 0x301, /**< 0x301 - misa (r/-): CPU ISA and extensions */
CSR_MIE = 0x304, /**< 0x304 - mie (r/w): Machine interrupt-enable register */
CSR_MTVEC = 0x305, /**< 0x305 - mtvec (r/w): Machine trap-handler base address (for ALL traps) */
 
CSR_MSCRATCH = 0x340, /**< 0x340 - mscratch (r/w): Machine scratch register */
CSR_MEPC = 0x341, /**< 0x341 - mepc (r/w): Machine exception program counter */
127,6 → 127,21
 
 
/**********************************************************************//**
* CPU <b>misa</b> CSR (r/w): Machine instruction set extensions (RISC-V spec.)
**************************************************************************/
enum NEORV32_CPU_MISA_enum {
CPU_MISA_C_EXT = 2, /**< CPU misa CSR (2): C: Compressed instructions CPU extension available (r/w), can be switched on/off */
CPU_MISA_E_EXT = 4, /**< CPU misa CSR (3): E: Embedded CPU extension available (r/-) */
CPU_MISA_I_EXT = 8, /**< CPU misa CSR (8): I: Base integer ISA CPU extension available (r/-) */
CPU_MISA_M_EXT = 12, /**< CPU misa CSR (12): M: Multiplier/divider CPU extension available (r/w), can be switched on/off */
CPU_MISA_X_EXT = 23, /**< CPU misa CSR (23): X: Non-standard CPU extension available (r/-) */
CPU_MISA_Z_EXT = 25, /**< CPU misa CSR (25): Z: Privileged architecture CPU extension available (r/-) */
CPU_MISA_MXL_LO_EXT = 30, /**< CPU misa CSR (30): MXL.lo: CPU data width (r/-) */
CPU_MISA_MXL_HI_EXT = 31 /**< CPU misa CSR (31): MXL.Hi: CPU data width (r/-) */
};
 
 
/**********************************************************************//**
* CPU <b>mfeatures</b> CSR (r/-): Implemented processor devices/features (CUSTOM)
**************************************************************************/
enum NEORV32_CPU_MFEATURES_enum {
135,6 → 150,7
CPU_MFEATURES_MEM_INT_IMEM = 2, /**< CPU mfeatures CSR (2) (r/-): Processor-internal instruction memory implemented when 1 (via MEM_INT_IMEM_USE generic) */
CPU_MFEATURES_MEM_INT_IMEM_ROM = 3, /**< CPU mfeatures CSR (3) (r/-): Processor-internal instruction memory implemented as ROM when 1 (via MEM_INT_IMEM_ROM generic) */
CPU_MFEATURES_MEM_INT_DMEM = 4, /**< CPU mfeatures CSR (4) (r/-): Processor-internal data memory implemented when 1 (via MEM_INT_DMEM_USE generic) */
CPU_MFEATURES_CSR_COUNTERS = 5, /**< CPU mfeatures CSR (5) (r/-): RISC-V performance counters implemented when 1 (via CSR_COUNTERS_USE generic) */
 
CPU_MFEATURES_IO_GPIO = 16, /**< CPU mfeatures CSR (16) (r/-): General purpose input/output port unit implemented when 1 (via IO_GPIO_USE generic) */
CPU_MFEATURES_IO_MTIME = 17, /**< CPU mfeatures CSR (17) (r/-): Machine system timer implemented when 1 (via IO_MTIME_USE generic) */
211,13 → 227,13
**************************************************************************/
/**@{*/
/** instruction memory base address (r/w/x) */
#define INSTR_MEM_BASE_ADDR 0x00000000
// -> use value from MEM_ISPACE_BASE CSR
/** data memory base address (r/w/x) */
#define DATA_MEM_BASE_ADDR 0x80000000
// -> use value from MEM_DSPACE_BASE CSR
/** bootloader memory base address (r/-/x) */
#define BOOTLOADER_BASE_ADDRESS 0xFFFF0000
#define BOOTLOADER_BASE_ADDRESS (0xFFFF0000UL)
/** peripheral/IO devices memory base address (r/w/x) */
#define IO_BASE_ADDRESS 0xFFFFFF80
#define IO_BASE_ADDRESS (0xFFFFFF80UL)
/**@}*/
 
 
226,9 → 242,9
**************************************************************************/
/**@{*/
/** GPIO parallel input port (r/-) */
#define GPIO_INPUT (*(IO_ROM32 0xFFFFFF80))
#define GPIO_INPUT (*(IO_ROM32 0xFFFFFF80UL))
/** GPIO parallel output port (r/w) */
#define GPIO_OUTPUT (*(IO_REG32 0xFFFFFF84))
#define GPIO_OUTPUT (*(IO_REG32 0xFFFFFF84UL))
/**@}*/
 
 
237,7 → 253,7
**************************************************************************/
/**@{*/
/** CLIC control register (r/w) */
#define CLIC_CT (*(IO_REG32 0xFFFFFF88))
#define CLIC_CT (*(IO_REG32 0xFFFFFF88UL))
 
/** CLIC control register bits */
enum NEORV32_CLIC_CT_enum {
284,7 → 300,7
**************************************************************************/
/**@{*/
/** Watchdog control register (r/w) */
#define WDT_CT (*(IO_REG32 0xFFFFFF8C))
#define WDT_CT (*(IO_REG32 0xFFFFFF8CUL))
 
/** WTD control register bits */
enum NEORV32_WDT_CT_enum {
310,13 → 326,13
**************************************************************************/
/**@{*/
/** MTIME (time register) low word (r/-) */
#define MTIME_LO (*(IO_ROM32 0xFFFFFF90))
#define MTIME_LO (*(IO_ROM32 0xFFFFFF90UL))
/** MTIME (time register) high word (r/-) */
#define MTIME_HI (*(IO_ROM32 0xFFFFFF94))
#define MTIME_HI (*(IO_ROM32 0xFFFFFF94UL))
/** MTIMECMP (time compare register) low word (r/w) */
#define MTIMECMP_LO (*(IO_REG32 0xFFFFFF98))
#define MTIMECMP_LO (*(IO_REG32 0xFFFFFF98UL))
/** MTIMECMP (time register) high word (r/w) */
#define MTIMECMP_HI (*(IO_REG32 0xFFFFFF9C))
#define MTIMECMP_HI (*(IO_REG32 0xFFFFFF9CUL))
 
/** MTIME (time register) 64-bit access (r/-) */
#define MTIME (*(IO_ROM64 (&MTIME_LO)))
330,9 → 346,9
**************************************************************************/
/**@{*/
/** UART control register (r/w) */
#define UART_CT (*(IO_REG32 0xFFFFFFA0))
#define UART_CT (*(IO_REG32 0xFFFFFFA0UL))
/** UART receive/transmit data register (r/w) */
#define UART_DATA (*(IO_REG32 0xFFFFFFA4))
#define UART_DATA (*(IO_REG32 0xFFFFFFA4UL))
 
/** UART control register bits */
enum NEORV32_UART_CT_enum {
373,9 → 389,9
**************************************************************************/
/**@{*/
/** SPI control register (r/w) */
#define SPI_CT (*(IO_REG32 0xFFFFFFA8))
#define SPI_CT (*(IO_REG32 0xFFFFFFA8UL))
/** SPI receive/transmit data register (r/w) */
#define SPI_DATA (*(IO_REG32 0xFFFFFFAC))
#define SPI_DATA (*(IO_REG32 0xFFFFFFACUL))
 
/** SPI control register bits */
enum NEORV32_SPI_CT_enum {
409,9 → 425,9
**************************************************************************/
/**@{*/
/** TWI control register (r/w) */
#define TWI_CT (*(IO_REG32 0xFFFFFFB0))
#define TWI_CT (*(IO_REG32 0xFFFFFFB0UL))
/** TWI receive/transmit data register (r/w) */
#define TWI_DATA (*(IO_REG32 0xFFFFFFB4))
#define TWI_DATA (*(IO_REG32 0xFFFFFFB4UL))
 
/** TWI control register bits */
enum NEORV32_TWI_CT_enum {
441,9 → 457,9
**************************************************************************/
/**@{*/
/** PWM control register (r/w) */
#define PWM_CT (*(IO_REG32 0xFFFFFFB8)) // r/w: control register
#define PWM_CT (*(IO_REG32 0xFFFFFFB8UL)) // r/w: control register
/** PWM duty cycle register (4-channels) (r/w) */
#define PWM_DUTY (*(IO_REG32 0xFFFFFFBC)) // r/w: duty cycle channel 1 and 0
#define PWM_DUTY (*(IO_REG32 0xFFFFFFBCUL)) // r/w: duty cycle channel 1 and 0
 
/** PWM control register bits */
enum NEORV32_PWM_CT_enum {
472,9 → 488,9
**************************************************************************/
/**@{*/
/** TRNG control register (r/w) */
#define TRNG_CT (*(IO_REG32 0xFFFFFFC0))
#define TRNG_CT (*(IO_REG32 0xFFFFFFC0UL))
/** TRNG data register (r/-) */
#define TRNG_DATA (*(IO_ROM32 0xFFFFFFC4))
#define TRNG_DATA (*(IO_ROM32 0xFFFFFFC4UL))
 
/** TRNG control register bits */
enum NEORV32_TRNG_CT_enum {
496,8 → 512,8
* @name IO Device: Dummy Device (DEVNULL)
**************************************************************************/
/**@{*/
/** TRNG data register (r/w) */
#define DEVNULL_DATA (*(IO_REG32 0xFFFFFFFC))
/** DEVNULL data register (r/w) */
#define DEVNULL_DATA (*(IO_REG32 0xFFFFFFFCUL))
/**@}*/
 
 
/sw/lib/include/neorv32_cpu.h
64,7 → 64,7
 
register uint32_t csr_data;
 
asm volatile ("csrrw %[result], %[input_i], zero" : [result] "=r" (csr_data) : [input_i] "i" (csr_id));
asm volatile ("csrr %[result], %[input_i]" : [result] "=r" (csr_data) : [input_i] "i" (csr_id));
return csr_data;
}
80,7 → 80,7
 
register uint32_t csr_data = data;
 
asm volatile ("csrrw zero, %[input_i], %[input_j]" : : [input_i] "i" (csr_id), [input_j] "r" (csr_data));
asm volatile ("csrw %[input_i], %[input_j]" : : [input_i] "i" (csr_id), [input_j] "r" (csr_data));
}
 
#endif // neorv32_cpu_h
/sw/lib/include/neorv32_rte.h
44,7 → 44,8
 
// prototypes
void neorv32_rte_enable_debug_mode(void);
int neorv32_rte_exception_install(uint8_t exc_id, void (*handler)(void));
int neorv32_rte_exception_uninstall(uint8_t exc_id);
int neorv32_rte_exception_install(uint8_t exc_id, void (*handler)(void));
int neorv32_rte_exception_uninstall(uint8_t exc_id);
void neorv32_rte_print_hw_config(void);
 
#endif // neorv32_rte_h
/sw/lib/source/neorv32_rte.c
43,8 → 43,10
#include "neorv32_rte.h"
 
// Privates
static void __neorv32_rte_dummy_exc_handler(void) __attribute__((unused));
static void __neorv32_rte_debug_exc_handler(void) __attribute__((unused));
static void __neorv32_rte_dummy_exc_handler(void) __attribute__((unused));
static void __neorv32_rte_debug_exc_handler(void) __attribute__((unused));
static void __neorv32_rte_print_true_false(int state) __attribute__((unused));
static void __neorv32_rte_print_hw_version(void) __attribute__((unused));
 
 
/**********************************************************************//**
151,11 → 153,13
**************************************************************************/
static void __neorv32_rte_debug_exc_handler(void) {
 
neorv32_uart_printf("\n\n\n<<< NEORV32 Runtime Environment >>>\n");
neorv32_uart_printf("\n\n<< NEORV32 Runtime Environment >>\n");
 
neorv32_uart_printf("System time: 0x%x_%x\n", neorv32_cpu_csr_read(CSR_TIMEH), neorv32_cpu_csr_read(CSR_TIME));
 
uint32_t exc_cause = neorv32_cpu_csr_read(CSR_MCAUSE);
register uint32_t exc_cause = neorv32_cpu_csr_read(CSR_MCAUSE);
register uint32_t return_addr = neorv32_cpu_csr_read(CSR_MEPC);
register uint32_t trans_cmd = neorv32_cpu_csr_read(CSR_MTINST);
 
if (exc_cause & 0x80000000) {
neorv32_uart_printf("INTERRUPT");
162,8 → 166,14
}
else {
neorv32_uart_printf("EXCEPTION");
if ((trans_cmd & (1 << 1)) == 0) {
return_addr -= 4;
}
else {
return_addr -= 2;
}
}
neorv32_uart_printf(" at instruction address: 0x%x\n", neorv32_cpu_csr_read(CSR_MEPC));
neorv32_uart_printf(" at instruction address: 0x%x\n", return_addr);
 
neorv32_uart_printf("Cause: ");
switch (exc_cause) {
190,18 → 200,179
neorv32_uart_printf("\nFaulting address");
}
neorv32_uart_printf(": 0x%x\n", neorv32_cpu_csr_read(CSR_MTVAL));
uint32_t trans_cmd = neorv32_cpu_csr_read(CSR_MTINST);
neorv32_uart_printf("Transf. instruction: 0x%x ", trans_cmd);
 
if (trans_cmd & (1 << 1)) {
neorv32_uart_printf("(uncompr.)\n");
if ((trans_cmd & (1 << 1)) == 0) {
neorv32_uart_printf("(decompressed)\n");
}
 
neorv32_uart_printf("Trying to resume application @ 0x%x...", neorv32_cpu_csr_read(CSR_MEPC));
 
neorv32_uart_printf("\n<</NEORV32 Runtime Environment >>\n\n");
}
 
 
/**********************************************************************//**
* NEORV32 runtime environment: Print hardware configuration information via UART
**************************************************************************/
void neorv32_rte_print_hw_config(void) {
 
uint32_t tmp;
int i;
char c;
 
neorv32_uart_printf("\n\n<< NEORV32 Hardware Configuration Overview >>\n");
 
// CPU configuration
neorv32_uart_printf("\n-- Central Processing Unit --\n");
 
// Hart ID
neorv32_uart_printf("Hart ID: 0x%x\n", neorv32_cpu_csr_read(CSR_MHARTID));
 
// HW version
neorv32_uart_printf("Hardware version: ");
__neorv32_rte_print_hw_version();
neorv32_uart_printf(" (0x%x)\n", neorv32_cpu_csr_read(CSR_MIMPID));
 
// CPU architecture
neorv32_uart_printf("Architecture: ");
tmp = neorv32_cpu_csr_read(CSR_MISA);
tmp = (tmp >> 30) & 0x03;
if (tmp == 0) {
neorv32_uart_printf("unknown");
}
if (tmp == 1) {
neorv32_uart_printf("RV32");
}
if (tmp == 2) {
neorv32_uart_printf("RV64");
}
if (tmp == 3) {
neorv32_uart_printf("RV128");
}
// CPU extensions
neorv32_uart_printf("\nCPU extensions: ");
tmp = neorv32_cpu_csr_read(CSR_MISA);
for (i=0; i<26; i++) {
if (tmp & (1 << i)) {
c = (char)('A' + i);
neorv32_uart_putc(c);
neorv32_uart_putc(' ');
}
}
neorv32_uart_printf("(0x%x)\n", tmp);
 
// Performance counters
neorv32_uart_printf("CNT & time CSRs: ");
__neorv32_rte_print_true_false(neorv32_cpu_csr_read(CSR_MFEATURES) & (1 << CPU_MFEATURES_CSR_COUNTERS));
 
// Clock speed
neorv32_uart_printf("Clock speed: %u Hz\n", neorv32_cpu_csr_read(CSR_MCLOCK));
 
// Memory configuration
neorv32_uart_printf("\n-- Memory Configuration --\n");
 
uint32_t size = neorv32_cpu_csr_read(CSR_MISPACESIZE);
uint32_t base = neorv32_cpu_csr_read(CSR_MISPACEBASE);
neorv32_uart_printf("Instruction memory: %u bytes @ 0x%x\n", size, base);
neorv32_uart_printf("Internal IMEM: ");
__neorv32_rte_print_true_false(neorv32_cpu_csr_read(CSR_MFEATURES) & (1 << CPU_MFEATURES_MEM_INT_IMEM));
neorv32_uart_printf("Internal IMEM as ROM: ");
__neorv32_rte_print_true_false(neorv32_cpu_csr_read(CSR_MFEATURES) & (1 << CPU_MFEATURES_MEM_INT_IMEM_ROM));
 
size = neorv32_cpu_csr_read(CSR_MDSPACESIZE);
base = neorv32_cpu_csr_read(CSR_MDSPACEBASE);
neorv32_uart_printf("Data memory: %u bytes @ 0x%x\n", size, base);
neorv32_uart_printf("Internal DMEM: ");
__neorv32_rte_print_true_false(neorv32_cpu_csr_read(CSR_MFEATURES) & (1 << CPU_MFEATURES_MEM_INT_DMEM));
 
neorv32_uart_printf("Bootloader: ");
__neorv32_rte_print_true_false(neorv32_cpu_csr_read(CSR_MFEATURES) & (1 << CPU_MFEATURES_BOOTLOADER));
 
neorv32_uart_printf("External interface: ");
__neorv32_rte_print_true_false(neorv32_cpu_csr_read(CSR_MFEATURES) & (1 << CPU_MFEATURES_MEM_EXT));
 
// peripherals
neorv32_uart_printf("\n-- Peripherals --\n");
tmp = neorv32_cpu_csr_read(CSR_MFEATURES);
 
neorv32_uart_printf("GPIO: ");
__neorv32_rte_print_true_false(tmp & (1 << CPU_MFEATURES_IO_GPIO));
 
neorv32_uart_printf("MTIME: ");
__neorv32_rte_print_true_false(tmp & (1 << CPU_MFEATURES_IO_MTIME));
 
neorv32_uart_printf("UART: ");
__neorv32_rte_print_true_false(tmp & (1 << CPU_MFEATURES_IO_UART));
 
neorv32_uart_printf("SPI: ");
__neorv32_rte_print_true_false(tmp & (1 << CPU_MFEATURES_IO_SPI));
 
neorv32_uart_printf("TWI: ");
__neorv32_rte_print_true_false(tmp & (1 << CPU_MFEATURES_IO_TWI));
 
neorv32_uart_printf("PWM: ");
__neorv32_rte_print_true_false(tmp & (1 << CPU_MFEATURES_IO_PWM));
 
neorv32_uart_printf("WDT: ");
__neorv32_rte_print_true_false(tmp & (1 << CPU_MFEATURES_IO_WDT));
 
neorv32_uart_printf("CLIC: ");
__neorv32_rte_print_true_false(tmp & (1 << CPU_MFEATURES_IO_CLIC));
 
neorv32_uart_printf("TRNG: ");
__neorv32_rte_print_true_false(tmp & (1 << CPU_MFEATURES_IO_TRNG));
 
neorv32_uart_printf("DEVNULL: ");
__neorv32_rte_print_true_false(tmp & (1 << CPU_MFEATURES_IO_DEVNULL));
}
 
 
/**********************************************************************//**
* NEORV32 runtime environment: Private function to print true or false.
* @note This function is used by neorv32_rte_print_hw_config(void) only.
*
* @param[in] state Print TRUE when !=0, print FALSE when 0
**************************************************************************/
static void __neorv32_rte_print_true_false(int state) {
 
if (state) {
neorv32_uart_printf("True\n");
}
else {
neorv32_uart_printf("(compr.)\n");
neorv32_uart_printf("False\n");
}
}
 
neorv32_uart_printf("Trying to resume application @ 0x%x...", neorv32_cpu_csr_read(CSR_MSCRATCH));
 
neorv32_uart_printf("\n<<</NEORV32 Runtime Environment >>>\n\n\n");
/**********************************************************************//**
* NEORV32 runtime environment: Private function to show the processor version in human-readable format.
* @note This function is used by neorv32_rte_print_hw_config(void) only.
**************************************************************************/
static void __neorv32_rte_print_hw_version(void) {
 
uint32_t i;
char tmp, cnt;
uint32_t version = neorv32_cpu_csr_read(CSR_MIMPID);
 
for (i=0; i<4; i++) {
 
tmp = (char)(version >> (24 - 8*i));
 
// serial division
cnt = 0;
while (tmp >= 10) {
tmp = tmp - 10;
cnt++;
}
 
if (cnt) {
neorv32_uart_putc('0' + cnt);
}
neorv32_uart_putc('0' + tmp);
if (i < 3) {
neorv32_uart_putc('.');
}
}
}
 
/README.md
56,10 → 56,15
 
### Status
 
![processor status](https://img.shields.io/badge/processor%20status-beta-orange)
The processor is synthesizable (tested with Intel Quartus Prime, Xilinx Vivado and Lattice Radiant/LSE) and can successfully execute
all the [provided example programs](https://github.com/stnolting/neorv32/tree/master/sw/example) including the CoreMark benchmark.
 
The processor is synthesizable (tested with Intel Quartus Prime and Lattice Radiant/Synplify) and can successfully execute all the [provided example programs](https://github.com/stnolting/neorv32/tree/master/sw/example).
The processor passes the `rv32i`, `rv32im`, `rv32imc` and `rv32Zicsr` *RISC-V compliance tests*.
 
[RISC-V compliance test](https://github.com/stnolting/neorv32_compliance_test):
[![Build Status](https://travis-ci.com/stnolting/neorv32_riscv_compliance.svg?branch=master)](https://travis-ci.com/stnolting/neorv32_riscv_compliance)
 
 
## Features
 
![neorv32 Overview](https://raw.githubusercontent.com/stnolting/neorv32/master/docs/figures/neorv32_overview.png)
73,7 → 78,7
- Completely described in behavioral, platform-independent VHDL – no primitives, macros, etc.
- Fully synchronous design, no latches, no gated clocks
- Small hardware footprint and high operating frequency
- Highly customizable processor configuration
- Customizable processor configuration
- Optional processor-internal data and instruction memories (DMEM/IMEM)
- Optional internal bootloader with UART console and automatic SPI flash boot option
- Optional machine system timer (MTIME), RISC-V-compliant
135,8 → 140,8
* Machine external interrupt (via `CLIC` unit)
 
**General**:
* No hardware support of unaligned accesses (except for instructions in `C` extension that still have to be aligned on 16-bit boundaries)
* Multi-cycle in-order instruction execution
* No hardware support of unaligned accesses - they will trigger and exception
* Two stages in-order pipeline (FETCH, EXECUTE); each stage uses a multi-cycle execution
 
More information including a detailed list of the available CSRs can be found in
the [![NEORV32 datasheet](https://raw.githubusercontent.com/stnolting/neorv32/master/docs/figures/PDF_32.png) NEORV32 datasheet](https://raw.githubusercontent.com/stnolting/neorv32/master/docs/NEORV32.pdf).
144,11 → 149,11
 
### To-Do / Wish List
 
- Testing, testing and even more testing
- Port official [RISC-V compliance test](https://github.com/riscv/riscv-compliance)
- No exception is triggered in `E`-mode when using reg >x15 yet
- Port Dhrystone benchmark
- Implement atomic extensions (`A` extension)
- Implement co-processor for single-precision floating-point (`F` extension)
- Implement atomic operations (`A` extension)
- Implement `Zifence` extension
- Implement co-processor for single-precision floating-point operations (`F` extension)
- Implement user mode (`U` extension)
- Make a 64-bit branch
- Maybe port an RTOS (like [freeRTOS](https://www.freertos.org/) or [RIOT](https://www.riot-os.org/))
162,39 → 167,46
information is derived from the Timing Analyzer / Slow 1200mV 0C Model. If not otherwise specified, the default configuration
of the processor's generics is assumed. No constraints were used.
 
Results generated for hardware version: `0.0.2.3`
Results generated for hardware version: `1.0.0.0`
 
### CPU
 
| CPU Configuration | LEs | FFs | Memory bits | DSPs | f_max |
|:--------------------|:----------:|:--------:|:-----------:|:------:|:-------:|
| `rv32i` | 852 (4%) | 326 (1%) | 2048 (>1%) | 0 (0%) | 111 MHz |
| `rv32i` + `Zicsr` | 1488 (7%) | 694 (3%) | 2048 (>1%) | 0 (0%) | 107 MHz |
| `rv32im` + `Zicsr` | 2057 (9%) | 941 (4%) | 2048 (>1%) | 0 (0%) | 102 MHz |
| `rv32imc` + `Zicsr` | 2209 (10%) | 958 (4%) | 2048 (>1%) | 0 (0%) | 102 MHz |
| `rv32e` | 848 (4%) | 326 (1%) | 1024 (>1%) | 0 (0%) | 111 MHz |
| `rv32e` + `Zicsr` | 1316 (6%) | 594 (3%) | 1024 (>1%) | 0 (0%) | 106 MHz |
| `rv32em` + `Zicsr` | 1879 (8%) | 841 (4%) | 1024 (>1%) | 0 (0%) | 101 MHz |
| `rv32emc` + `Zicsr` | 2065 (9%) | 858 (4%) | 1024 (>1%) | 0 (0%) | 100 MHz |
| `rv32i` | 1027 | 474 | 2048 | 0 (0%) | 111 MHz |
| `rv32i` + `Zicsr` | 1721 | 868 | 2048 | 0 (0%) | 104 MHz |
| `rv32im` + `Zicsr` | 2298 | 1115 | 2048 | 0 (0%) | 103 MHz |
| `rv32imc` + `Zicsr` | 2557 | 1138 | 2048 | 0 (0%) | 103 MHz |
| `rv32emc` + `Zicsr` | 2342 | 1005 | 1024 | 0 (0%) | 100 MHz |
 
### Peripherals / Others
### Processor-Internal Peripherals and Memories
 
| Module | Description | LEs | FFs | Memory bits | DSPs |
|:---------|:------------------------------------------------|:---:|:---:|:-----------:|:----:|
| BOOT ROM | Bootloader ROM (4kB) | 3 | 1 | 32 768 | 0 |
| DEVNULL | Dummy device | 2 | 1 | 0 | 0 |
| DEVNULL | Dummy device | 3 | 1 | 0 | 0 |
| DMEM | Processor-internal data memory (8kB) | 12 | 2 | 65 536 | 0 |
| GPIO | General purpose input/output ports | 37 | 33 | 0 | 0 |
| GPIO | General purpose input/output ports | 38 | 33 | 0 | 0 |
| IMEM | Processor-internal instruction memory (16kb) | 7 | 2 | 131 072 | 0 |
| MTIME | Machine system timer | 369 | 168 | 0 | 0 |
| PWM | Pulse-width modulation controller | 77 | 69 | 0 | 0 |
| SPI | Serial peripheral interface | 198 | 125 | 0 | 0 |
| TRNG | True random number generator | 103 | 93 | 0 | 0 |
| TWI | Two-wire interface | 76 | 44 | 0 | 0 |
| UART | Universal asynchronous receiver/transmitter | 154 | 108 | 0 | 0 |
| MTIME | Machine system timer | 270 | 167 | 0 | 0 |
| PWM | Pulse-width modulation controller | 76 | 69 | 0 | 0 |
| SPI | Serial peripheral interface | 206 | 125 | 0 | 0 |
| TRNG | True random number generator | 104 | 93 | 0 | 0 |
| TWI | Two-wire interface | 78 | 44 | 0 | 0 |
| UART | Universal asynchronous receiver/transmitter | 151 | 108 | 0 | 0 |
| WDT | Watchdog timer | 57 | 45 | 0 | 0 |
 
### CPU + Peripheral
 
The following table shows the implementation results for an _Intel Cyclone IV EP4CE22F17C6N_ FPGA.
The design was synthesized using Intel Quartus Prime Lite 19.1 (“balanced implementation”).
IMEM uses 16kB and DMEM uses 8kB memory space.
 
| CPU Configuration | LEs | REGs | DSPs | Memory Bits | f_max |
|:--------------------|:----------:|:---------:|:------:|:------------:|:-------:|
| `rv32imc` + `Zicsr` | 3724 (17%) | 1899 (9%) | 0 (0%) | 231424 (38%) | 103 MHz |
 
 
### Lattice iCE40 UltraPlus 5k
 
The following table shows the hardware utilization for a [iCE40 UP5K](http://www.latticesemi.com/en/Products/FPGAandCPLD/iCE40UltraPlus) FPGA.
205,13 → 217,11
Place & route reports generated with **Lattice Radiant 2.1** using Lattice LSE. The clock frequency
is constrained and generated via the PLL from the internal HF oscillator running at 12 MHz.
 
Results generated for hardware version: `0.0.2.5`
| CPU Configuration | LUTs | REGs | DSPs | SPRAM | EBR | f |
|:--------------------|:----------:|:----------:|:------:|:--------:|:--------:|:---------:|
| `rv32imc` + `Zicsr` | 4985 (94%) | 1982 (38%) | 0 (0%) | 4 (100%) | 12 (40%) | 20.25 MHz |
 
| CPU Configuration | Slices | LUT | REG | DSPs | SPRAM | EBR | f |
|:--------------------|:----------:|:----------:|:----------:|:------:|:--------:|:--------:|:---------:|
| `rv32imc` + `Zicsr` | 2405 (91%) | 4642 (87%) | 1810 (34%) | 0 (0%) | 4 (100%) | 12 (40%) | 20.25 MHz |
 
 
## Performance
 
### CoreMark Benchmark
220,7 → 230,7
[sw/example/coremark](https://github.com/stnolting/neorv32/blob/master/sw/example/coremark) project folder. This benchmark
tests the capabilities of a CPU itself rather than the functions provided by the whole system / SoC.
 
Results generated for hardware version: `0.0.2.3`
Results generated for hardware version: `1.0.0.0`
 
~~~
**Configuration**
232,12 → 242,12
 
| __Configuration__ | __Optimization__ | __Executable Size__ | __CoreMark Score__ | __CoreMarks/MHz__ |
|:------------------|:----------------:|:-------------------:|:------------------:|:-----------------:|
| `rv32i` | `-Os` | 17 944 bytes | 23.26 | 0.232 |
| `rv32i` | `-O2` | 20 264 bytes | 25.64 | 0.256 |
| `rv32im` | `-Os` | 16 880 bytes | 40.81 | 0.408 |
| `rv32im` | `-O2` | 19 312 bytes | 47.62 | 0.476 |
| `rv32imc` | `-Os` | 13 000 bytes | 32.78 | 0.327 |
| `rv32imc` | `-O2` | 15 004 bytes | 37.04 | 0.370 |
| `rv32i` | `-Os` | 18 044 bytes | 21.98 | 0.21 |
| `rv32i` | `-O2` | 20 388 bytes | 25 | 0.25 |
| `rv32im` | `-Os` | 16 980 bytes | 40 | 0.40 |
| `rv32im` | `-O2` | 19 436 bytes | 51.28 | 0.51 |
| `rv32imc` | `-Os` | 13 076 bytes | 39.22 | 0.39 |
| `rv32imc` | `-O2` | 15 208 bytes | 50 | 0.50 |
 
 
### Instruction Cycles
250,7 → 260,7
Please note that the CPU-internal shifter (e.g. for the `SLL` instruction) as well as the multiplier and divider of the
`M` extension use a bit-serial approach and require several cycles for completion.
 
The following table shows the performance results for successfully (!) running 2000 CoreMark
The following table shows the performance results for successfully running 2000 CoreMark
iterations. The average CPI is computed by dividing the total number of required clock cycles (all of CoreMark
– not only the timed core) by the number of executed instructions (`instret[h]` CSRs). The executables
were generated using optimization `-O2`.
257,27 → 267,12
 
| CPU / Toolchain Config. | Required Clock Cycles | Executed Instructions | Average CPI |
|:------------------------|----------------------:|----------------------:|:-----------:|
| `rv32i` | 10 385 023 697 | 1 949 310 506 | 5.3 |
| `rv32im` | 6 276 943 488 | 995 011 883 | 6.3 |
| `rv32imc` | 7 340 734 652 | 934 952 588 | 7.6 |
| `rv32i` | 19 355 607 369 | 2 995 064 579 | 6.5 |
| `rv32im` | 5 809 384 583 | 867 377 291 | 6.7 |
| `rv32imc` | 5 560 220 723 | 825 898 407 | 6.7 |
 
 
### Evaluation
 
Based on the provided performance measurement and the hardware utilization for the
different CPU configurations, the following configurations are suggested:
 
 
| Design Goal | NEORV32 CPU Config. |
|:-------------------------------|:--------------------|
| Highest performance: | `rv32im` |
| Lowest memory requirements: | `rv32imc` |
| Lowest hardware requirements*: | `rv32ec` |
 
*) Including on-chip memory hardware requirements.
 
 
 
## Top Entity
 
The top entity of the processor is [**neorv32_top.vhd**](https://github.com/stnolting/neorv32/blob/master/rtl/core/neorv32_top.vhd) (from the `rtl/core` folder).
294,6 → 289,7
CLOCK_FREQUENCY : natural := 0; -- clock frequency of clk_i in Hz
HART_ID : std_ulogic_vector(31 downto 0) := x"00000000"; -- custom hardware thread ID
BOOTLOADER_USE : boolean := true; -- implement processor-internal bootloader?
CSR_COUNTERS_USE : boolean := true; -- implement RISC-V perf. counters ([m]instret[h], [m]cycle[h], time[h])?
-- RISC-V CPU Extensions --
CPU_EXTENSION_RISCV_C : boolean := false; -- implement compressed extension?
CPU_EXTENSION_RISCV_E : boolean := false; -- implement embedded RF extension?
347,9 → 343,9
uart_txd_o : out std_ulogic; -- UART send data
uart_rxd_i : in std_ulogic := '0'; -- UART receive data
-- SPI (available if IO_SPI_USE = true) --
spi_sclk_o : out std_ulogic; -- serial clock line
spi_mosi_o : out std_ulogic; -- serial data line out
spi_miso_i : in std_ulogic := '0'; -- serial data line in
spi_sck_o : out std_ulogic; -- serial clock line
spi_sdo_o : out std_ulogic; -- serial data line out
spi_sdi_i : in std_ulogic := '0'; -- serial data line in
spi_csn_o : out std_ulogic_vector(07 downto 0); -- SPI CS
-- TWI (available if IO_TWI_USE = true) --
twi_sda_io : inout std_logic := 'H'; -- twi serial data line
412,7 → 408,7
$ git clone https://github.com/stnolting/neorv32.git
 
Create a new HW project with your FPGA synthesis tool of choice. Add all files from the [`rtl/core`](https://github.com/stnolting/neorv32/blob/master/rtl)
Create a new HW project with your FPGA design tool of choice. Add all files from the [`rtl/core`](https://github.com/stnolting/neorv32/blob/master/rtl)
folder to this project and add them to a **new library** called `neorv32`.
 
You can either instantiate the [processor's top entity](https://github.com/stnolting/neorv32#top-entity) in you own project, or you
464,30 → 460,6
 
Use the bootloader console to upload and execute your application image.
 
```
<< NEORV32 Bootloader >>
BLDV: Jun 22 2020
HWV: 0.0.2.3
CLK: 0x0134FD90 Hz
MISA: 0x42801104
CONF: 0x01FF0015
IMEM: 0x00010000 bytes @ 0x00000000
DMEM: 0x00010000 bytes @ 0x80000000
Autoboot in 8s. Press key to abort.
Aborted.
Available commands:
h: Help
r: Restart
u: Upload
s: Store to flash
l: Load from flash
e: Execute
CMD:>
```
 
Going further: Take a look at the [![NEORV32 datasheet](https://raw.githubusercontent.com/stnolting/neorv32/master/docs/figures/PDF_32.png) NEORV32 datasheet](https://raw.githubusercontent.com/stnolting/neorv32/master/docs/NEORV32.pdf).
 
 
512,6 → 484,7
## Legal
 
This is a hobby project released under the BSD 3-Clause license. No copyright infringement intended.
Other implied/used projects might have different licensing - see their documentation to get more information.
 
**BSD 3-Clause License**
 
561,4 → 534,4
This project is not affiliated with or endorsed by the Open Source Initiative (https://www.oshwa.org / https://opensource.org).
 
 
Made with :heart: in Hannover, Germany.
Made with :coffee: in Hannover, Germany.

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.