diff options
362 files changed, 138299 insertions, 0 deletions
diff --git a/ext/systemc/AUTHORS b/ext/systemc/AUTHORS new file mode 100644 index 000000000..c19bf35aa --- /dev/null +++ b/ext/systemc/AUTHORS @@ -0,0 +1,26 @@ + + Authors of SystemC + ------------------ + + John Aynsley Doulos, Inc. + Bishnupriya Bhattacharya Cadence Design Systems, Inc. + David Black Doulos, Inc. + Gene Bushuyev Synopsys, Inc. + Jerome Cornet STMicroelectronics + Ali Dasdan Synopsys, Inc. + Alan Fitch Doulos, Inc. + Abhijit Ghosh Synopsys, Inc. + Andy Goodrich Forte Design Systems, Inc. + Philipp A.Hartmann OFFIS Institute for Information Technology + Ulrich Holtmann Synopsys, Inc. + Martin Janssen Synopsys, Inc. + Vijay Kumar CoWare, Inc. + Stan Y. Liao Synopsys, Inc. + David Long Doulos, Inc. + Torsten Maehne Université Pierre et Marie Curie, Paris + Eric Paire STMicroelectronics + Cesar Quiroz CoWare, Inc. + Amit Rao Synopsys, Inc. + Harish Sarin CoWare, Inc. + Stuart Swan Cadence Design Systems, Inc. + Dirk Vermeersch CoWare, Inc. diff --git a/ext/systemc/ChangeLog b/ext/systemc/ChangeLog new file mode 100644 index 000000000..cdd59ddc0 --- /dev/null +++ b/ext/systemc/ChangeLog @@ -0,0 +1,51 @@ +See also docs/tlm/ChangeLog. + +2014-04-17 Philipp A. Hartmann <philipp.hartmann@offis.de> + + * Combined SystemC 2.3.1 / TLM 2.0.3 officially released. + +2012-07-01 Andy Goodrich <acg@forteds.com> + + * Combined SystemC 2.3.0 / TLM-2.0.2 officially released. + +2007-03-14 Andy Goodrich <acg@forteds.com> + + * SystemC 2.2 released. + +2006-06-05 Andy Goodrich <acg@forteds.com> + + * SystemC 2.2 Beta released to the public. + +2005-07-14 Andy Goodrich <acg@forteds.com> + + * SystemC 2.1v1 released. + +2003-12-02 Andy Goodrich <acg@forteds.com> + + * SystemC 2.1 Beta-7 released. + +2003-06-13 Andy Goodrich <acg@forteds.com> + + * SystemC 2.1 Beta-1 released. + +2002-04-05 Martin Janssen <martin.janssen@synopsys.com> + + * SystemC 2.0.1 released. + +2001-10-05 Martin Janssen <mjanssen@synopsys.com> + + * SystemC 2.0 released. + +2001-09-05 Martin Janssen <mjanssen@synopsys.com> + + * SystemC 2.0 Beta-2 released. + +2001-07-13 Martin Janssen <mjanssen@synopsys.com> + + * SystemC 2.0 Beta-1 released. + +2001-02-23 Release 1.0.2 of SystemC +2000-09-26 Release 1.0.1 of SystemC +2000-03-28 Release 1.0 of SystemC +2000-01-31 Release 0.91 of SystemC +1999-09-27 Release 0.9 of SystemC diff --git a/ext/systemc/INSTALL b/ext/systemc/INSTALL new file mode 100644 index 000000000..a5231d489 --- /dev/null +++ b/ext/systemc/INSTALL @@ -0,0 +1,765 @@ + INSTALL NOTES FOR SystemC Release 2.3 + ------------------------------------- + +Contents: + + 1. Installation Notes for Unix + + 2. Installation Notes for Windows + + 3. SystemC Library Configuration Switches + + +1. Installation Notes for Unix +------------------------------ + + +System Requirements +=================== + +SystemC can be installed on the following UNIX, or UNIX-like platforms: + + o Linux + * Architectures + - x86 (32-bit) + - x86_64 (64-bit) + - x86 (32-bit) application running on x86_64 (64-bit) kernel + (../configure --host=i686-linux-gnu) + * Compilers + - GNU C++ compiler + - Clang C++ compiler + - or compatible + + o Mac OS X + * Architectures + - x86 (32-bit) + - x86_64 (64-bit) + - powerpc (32-bit) [deprecated] + - powerpc64 (64-bit) [deprecated] + * Compilers + - GNU C++ compiler + - Clang C++ compiler + - or compatible + + o Solaris + * Architectures + - SPARC (32-bit) + * Compilers + - GNU C++ compiler + - Sun/Solaris Studio + + o BSD + * Architectures + - x86 (32-bit) + - x86_64 (64-bit) + * Compilers + - GNU C++ compiler + - Clang C++ compiler + - or compatible + + o Windows + * Compatibility layer + - Cygwin + - MinGW / MSYS + * Architectures + - x86 (32-bit) + - x86_64 (64-bit) + * Compilers + - GNU C++ compiler + - or compatible + +Note: Not all combinations are equally well-tested and some combinations + may not work as expected. Please report your findings by following + the instructions in the README file. + +The README file contains a list of detailed platforms, architectures, +and compiler versions that have been used for testing this release. + + +Sources for Compilers and Related Tools +======================================= + +To build, install, and use SystemC on UNIX platforms, you need +the following tools: + + 1. GNU C++ compiler, version 3.4 or later + or + Clang C++ compiler version 3.0 or later + + 2. GNU Make (gmake) + +GCC, Clang, and gmake are free software that you can +obtain from the following sources: + + GCC http://www.gnu.org/software/gcc/gcc.html + + Clang http://clang.llvm.org/ + + gmake http://www.gnu.org/software/make/make.html + + +Basic SystemC Installation +========================== + +To install SystemC on a UNIX system, do the following steps: + + 1. Change to the top level directory (systemc-2.3.1) + + 2. Create a temporary directory, e.g., + + > mkdir objdir + + 3. Change to the temporary directory, e.g., + + > cd objdir + + 4. Choose your compiler by setting the CXX environment variable + (the configure script tries to guess the default compiler, if + this step is omitted): + + If you use a POSIX-compatible shell (e.g. bash): + + > export CXX="<compiler>" + + e.g. for GCC compilers + + > export CXX=g++ + + The Clang compiler is usually named 'clang++', thus e.g. + + > export CXX=clang++ + + When using a C shell (e.g. csh/tcsh), the syntax to set the + environment variable is different: + + > setenv CXX g++ + + For the Sun/Solaris Studio compilers, use + + > setenv CXX CC + + You can also specify an absolute path to the compiler of your choice. + + See also the Section "Compilation and Linking Options" below. + + + 5. Configure the package for your system, e.g., + (The configure script is explained below.) + + > ../configure + + While the 'configure' script is running, which takes a few moments, + it prints messages to inform you of the features it is checking. + It also detects the platform. + + Note for System V users: + If you are using `csh' on an older version of System V, you might + need to use the `sh ../configure' command instead of '../configure'. + Otherwise, `csh' will attempt to `configure' itself. + + SystemC 2.3 includes a fixed-point package that is always built. + When compiling your applications with fixed-point types, you still have + to use compiler flag -DSC_INCLUDE_FX. Note that compile times increase + significantly when using this compiler flag. + + In case you want to install the package in another place than the + top level directory (systemc-2.3.1), configure the package e.g. as + follows: + + > ../configure --prefix=/usr/local/systemc-2.3.1 + + Note: make sure you have created the target directory before installing + the package. Do _not_ use /usr/local as a prefix, unless you + follow the Unix/FHS directory layouts (see below). + + A fine grained configuration of the installation directories can + be achieved via additional options, given to the configure script. + + By default, the files are installed directly to the PREFIX directory + root and the library is installed to PREFIX/lib-<TARGETARCH>, + depending on the current target architecture. This may be undesired + in cases where the package is meant to be installed in a system-wide + location as part of shared (default) library and include hierarchies + (e.g. /usr/local, /usr, /opt, ...). To follow the Unix/FHS directory + standards, you can use the following options: + + --with-unix-layout use Unix directory layout for installation + [default=no] + when "yes", the following (fine-grained) settings will be used: + + --includedir=DIR C++ header files [PREFIX/include] + --libdir=DIR object code libraries [EPREFIX/lib] + --docdir=DIR documentation root [DATAROOTDIR/doc/systemc] + + The library destination itself can be further and separately configured + by using the following option: + + --with-arch-suffix add suffix to library installation directory + [default=-<TARGETARCH>] + + With this option, one can easily follow e.g. the "multi-arch" + conventions on some platforms: + + ../configure --with-arch-suffix=32 # lib32 + ../configure --with-arch-suffix=/x86_64-linux-gnu # lib/x86_64-linux-gnu + + + + Several options are available to the configure script to modify + the compiler configuration and the selection of certain features: + + --disable-shared do not build shared library (libsystemc.so) + --enable-debug include debugging symbols + --disable-optimize disable compiler optimization + --disable-async-updates disable request_async_update support + --enable-pthreads use POSIX threads for SystemC processes + --enable-phase-callbacks + enable simulation phase callbacks (experimental) + + + See the section on the general usage of the configure script and + "../configure --help" for more information. + + Note: If you change the configuration after having compiled the + package already, you should run a "gmake clean" before + recompiling. + + 6. Compile the package. + + > gmake + + Note: The explicit gmake targets "opt" and "debug", etc. have + been removed in this package. Use the corresponding + options to the configure script instead. + + 7. At this point you may wish to verify the compiled package by + testing the example suite. + + > gmake check + + This will compile and run the examples in the subdirectory + examples. + + 8. Install the package. + + > gmake install + + 9. You can now remove the temporary directory, .e.g, + + > cd .. + > rm -rf objdir + + Alternatively, you can keep the temporary directory to allow you to: + + a) Experiment with the examples. + + b) Later uninstall the package. To clean up the temporary + directory, enter: + + > gmake clean + + To uninstall the package, enter: + + > gmake uninstall + + +Running the Examples +==================== + +Copies of the examples reside in the temporary directory - see +instruction 7 above for details on building and running them. + +In addition, a copy of the example code resides in the directory +examples at the highest level of the installation (or in the +shared documentation install directory). + +Use the makefiles provided in the 'examples' directory as templates +for makefiles you need for compiling your own examples. + + +Using the Configure Script +========================== + +The `configure' shell script tries to determine the correct values for +various system-dependent variables used during compilation. It uses +these values to create a `Makefile' in each directory of the package. +It also creates one or more `.h' files containing system-dependent +definitions if needed. Then, it creates the following files: + + config.status A shell script that you can run at another time to + recreate the current configuration. + + config.cache A file in which the configure test results are + saved to speed up reconfiguration. + + Data is appended to the config.cache file. + You can remove unwanted data. + + config.log A file in which compiler output is saved. + This is used to debug the configure script. + +If you need to use other commands to successfully compile the package +on your system, please try to determine if the configure script can be used +for these commands. Then, send either a diff file or instructions about +the commands you used to the email address provided in the README file. +This information will be used to improve the installation process in +the next release. + +The `configure.ac' file is provided in case you want to change or regenerate +the `configure' script, for example to use a newer version of `autoconf'. +The `configure.ac' file is used by the `autoconf' program to create the +`configure' script. + +Note for (key) developers: + + In case you have changed the `configure.ac' file or one of the + `Makefile.am' files: + + - Use the `config/distclean' script to remove the generated `configure' + script, the generated `aclocal.m4' file and the generated `Makefile.in' + files. + + - Use the `config/bootstrap' script to generate the `configure' script + and the necessary `Makefile.in' files. This script makes use of the + GNU auto-tools `aclocal', `automake', and `autoconf'. + + +Compilation and Linking Options +=============================== + +Some systems require compilation or linking options that the `configure' +script does not define. You can define the initial values for these +options by setting them in your environment before running the +`configure' script. + +Instead of passing the variables via the environment, it is preferred +to pass the values as options to the configure script: + + > ../configure CXX=g++-4.4 LIBS=-lposix + + +Specifying the System Type +========================== + +Some features cannot be automatically determined by `configure' unless +it can detect the host type on which the package will run. +If it prints a message that it cannot determine the host type, +use the `--host=TYPE' option to define it. TYPE can either be a +short system name, such as `sun4', or a canonical name with three fields: + + CPU-COMPANY-SYSTEM + +See the `config.sub' file for details about the values of each field. If +the `config.sub' file is not included in the package, the package does not +need to know the host type. + +If you are building compiler tools for cross-compiling, you can also +use the `--target=TYPE' option to select the type of system for which +the code is produced and the `--build=TYPE' option to select the type of +system on which you are compiling the package. + + +Sharing Defaults +================ + +You can set the default values that `configure' scripts share by +creating a site shell script called `config.site'. This file contains the +default values for variables like `CC', `cache_file', and `prefix'. +The `configure' script looks for the `config.site' file in the following +search precedence: + + 1. PREFIX/share/config.site + + 2. PREFIX/etc/config.site + +Alternatively, you can set the `CONFIG_SITE' environment variable to the +site script path. + +Note: The `configure' script for some systems does not look for a site script. + + +Operation Controls +================== + +The `configure' script recognizes the following additional options to control +its operation: + +`--cache-file=FILE' + Use and save the test results in FILE instead of + `./config.cache'. Set FILE to `/dev/null' to disable caching + when debugging `configure'. + +`--help' + Print a summary of `configure' options and exit. + +`--quiet' +`--silent' +`-q' + Do not print messages about checks being made. + To suppress all normal output, redirect it to `/dev/null'. + Error messages continue to print. + +`--srcdir=DIR' + Look for the package's source code in directory DIR. + Typically `configure' determines the directory automatically. + +`--version' + Print the version of `autoconf' used to generate the `configure' + script and exit. + +Other options that are rarely used are available in the `configure' script. +Use the `--help' option to print a list. + + + +2. Installation Notes for Windows +--------------------------------- + +This release has been tested on Visual C++ versions 2005 through 2013, +running on Windows 7. + + +Note: This section covers the installation based on Microsoft Visual C++. + For Cygwin or MinGW-based installations, see Section 1. + + +Note: If you experience spurious errors about missing files in the + downloaded archive, please make sure to either download the + ZIP archive from accellera.org or use a reliable archive software, + fully supporting modern tar archive versions. + + Some paths in the SystemC archive are longer than the historical + 99 character limit, and several Windows archivers (e.g. WinZip) + have been reported to trip over this. The open source archiver + 7-zip (http://7-zip.org) is known to work. + + +Microsoft Visual C++ 2005 (compiler version 8.0) or later +--------------------------------------------------------- + +The download directory contains two subdirectories: 'msvc80' and +'examples'. + +The 'msvc80' directory contains the project and workspace files to +compile the 'systemc.lib' library. Double-click on the 'SystemC.sln' +file to launch Visual C++ 2005 with the workspace file. The workspace file +will have the proper switches set to compile for Visual C++ 2005. +Select `Build SystemC' under the Build menu or press F7 to build +`systemc.lib'. + +The `examples' directory contains the project and workspace files to +compile the SystemC examples. Go to one of the examples subdirectories +and double-click on the .vcproj file to launch Visual C++ with the +workspace file. The workspace file will have the proper switches set +to compile for Visual C++ 2005. Select 'Build <example>.exe' under the +Build menu or press F7 to build the example executable. + +For convenience, a combined solution file 'SystemC-examples.sln' with +all example projects can be found in the 'msvc80' directory. A similar +solution file for the TLM examples is located in 'examples/tlm/build-msvc'. + +The provided project files are prepared for both the 32-bit 'Win32' and +64-bit 'x64' configurations. Please refer to the Microsoft Visual Studio +documentation for details about 64-bit builds. + + +Creating SystemC Applications +----------------------------- + +1. Start Visual Studio. From the Start Page select New Project and Win32 + Console Project. Type the project name and select a suitable location + then click OK. + +2. Select the Application Settings page of the Win32 Application Wizard + and make sure the 'Empty project' box is ticked. Click 'Finish' to + complete the wizard. + +3. Add new/existing C++ files to the project and edit code. + +4. Display the project Property Pages by selecting 'Properties...' from + the Project menu. + +5. From the C/C++ tab, select the General properties and set + 'Detect 64-bit Portability Issues' to No + +6. From the C/C++ tab, select the Language properties and set + 'Enable Run-Time Type Info' to Yes + +7. From the C/C++ tab, select the Command Line properties and add /vmg + to the 'Additional Options:' box. + +8. From the Linker tab, select the Input properties and type 'systemc.lib' + in the 'Additional Dependencies' box. + +9. Click OK + + +Also make sure that the compiler and linker can find the SystemC header +and library files respectively. There are two ways to do this: + +To update the include file and library directory search paths for all +projects: + +1. Select Tools -> Options... and the Projects -> VC++ Directories tab + +2. Select show directories for: Library files + +3. Select the 'New' icon and browse to: C:\systemc-2.3.1\msvc80\systemc\debug + +4. Select show directories for: Include files + +5. Select the 'New' icon and browse to: C:\systemc-2.3.1\src + +To add the include file and library directory search paths for the current +project only: + +1. Display the project Property Pages by selecting 'Properties...' from + the Project menu. + +2. From the C/C++ tab, select the General properties and type the path to the + SystemC 'src' directory in the text entry field labeled + 'Additional include directories' (e.g. the examples use '..\..\..\src'). + +3. From the Linker tab, select the General properties and type the path to + the SystemC library: ...\systemc-2.3.1\msvc80\systemc\debug'systemc.lib' + in the 'Additional Library Directories:' box. + +9. Click OK + + + + +3. SystemC Library Configuration Switches +----------------------------------------- + +In addition to the explicitly selectable feature given as options to +the `configure' script (see 1.), some aspects of the library +implementation can be controlled via + + - preprocessor switches given during library build + - preprocessor switches added while building a SystemC application + - environment variables + +The currently supported switches are documented in this section. + +Preprocessor switches +===================== + +Additional preprocessor switches for the library build can be passed +to the configure script via the CXXFLAGS variable: + + ../configure CXXFLAGS="-DSC_OVERRIDE_DEFAULT_STACK_SIZE=0x80000" + +In Visual C++, the preprocessor symbols can be added to the project +configuration via the 'C/C++' tab under the 'Preprocessor' properties +in the 'Preprocessor definitions' setting. + + + * SC_DEFAULT_WRITER_POLICY=<sc_writer_policy> - + Override default value for the signal writer policy + + This setting allows deactivating the multiple writer checks for + sc_signals at (application) compile time. This mechanism supersedes + the old environment variable SC_SIGNAL_WRITE_CHECK (see below). + + Supported values: + SC_ONE_WRITER (default) + SC_MANY_WRITERS (allow multiple writers in different deltas) + SC_UNCHECKED_WRITERS (non-standard, disable all checks) + + Note: Only effective when building an application. + + Note: This setting needs to be consistently set across all + translation units of an application. + + + * SC_DISABLE_ASYNC_UPDATES - + Exclude the "async_request_update" support + + Note: This option is usually set by the `configure` option + --disable-async-update, or + --enable-async-update=no + + On non-Automake platforms (e.g. Visual C++), this preprocessor + symbol can be used to manually build the library with this feature. + + Note: Only effective during library build. + + + * SC_DISABLE_VIRTUAL_BIND - + Keep the "bind" function of sc_ports non-virtual + + When this symbol is defined, the "bind" function in sc_ports is + kept non-virtual (although it is required to be 'virtual' since + IEEE 1666-2011). + + Note: This symbol needs to be consistently defined in the library + and any application linking against the built library. + + + * SC_DISABLE_COPYRIGHT_MESSAGE - + Do not print the copyright message when starting the application + + Note: This does not remove the copyright from the binary. + sc_core::sc_copyright() still works as expected. + Note: Only effective during library build. + See : Environment variable SC_COPYRIGHT_MESSAGE + + + * SC_ENABLE_IMMEDIATE_SELF_NOTIFICATIONS - + Allow a process to trigger itself immediately + + Allow a method process to trigger itself immediately by using + next_trigger( ev ); // or a static sensitivity + ev.notify(); + + This behaviour has been disabled by default in IEEE 1666-2011 and + can be reenabled by this option. + + Note: Only effective during library build. + + + * SC_ENABLE_EARLY_MAXTIME_CREATION - + Allow creation of sc_time objects with a value of sc_max_time() + before finalizing the time resolution + + In IEEE 1666-2011, it is not allowed to create sc_time objects with + a non-SC_ZERO_TIME value before setting/changing the time resolution. + + This preprocessor switch activates an extension to allow the + initialization of sc_time variables with sc_max_time() while + still accepting changes to the time resolution afterwards. + + sc_time t = sc_max_time(); + sc_set_time_resolution( 1, SC_NS ); // OK, with this extension + + The time resolution will still be fixed, once you have explicitly or + implicitly relied on the physical value (i.e. the relation to seconds) + of any sc_time object. + + Note: Only effective during library build. + + + * SC_ENABLE_SIMULATION_PHASE_CALLBACKS (experimental) + SC_ENABLE_SIMULATION_PHASE_CALLBACKS_TRACING (experimental) - + Enable a generic simulation phase callback mechanism. + + Note: This option is usually set by the `configure` option + --enable-phase-callbacks, or + --enable-phase-callbacks=tracing + + See the RELEASENOTES for more information about this feature. + + The *_TRACING variant of this flag enables the sc_trace + implementation use these callbacks, instead of hard-coded updates + from the main simulator loop. + + Note: Setting tracing flag includes the generic phase callback + infrastructure automatically. + Note: Only effective during library build. + + + * SC_INCLUDE_DYNAMIC_PROCESSES - + Enable dynamic process support (sc_spawn, sc_bind) + + To improve compilation times, the functions for spawing dynamic + processes are not included by default in an SystemC application. + + Define this symbol before including the SystemC header in your + application, if you want to use dynamically spawned processes. + + Note: Can be optionally set per translation unit in an application. + + Note: Some TLM convenience sockets require this feature and define + the symbol for you if needed. + + + * SC_INCLUDE_FX - + Enable SystemC fix-point datatypes + + To improve compilation times, the fixpoint datatypes are not enabled + by default in an SystemC application. + + Define this symbol before including the SystemC header in your + application, if you want to use the SystemC fixpoint types. + + Note: Is by default always defined during the library build to enable + later use of the fixpoint datatypes in an application. + + Note: Can be optionally set per translation unit in an application. + + + * SC_INCLUDE_STRSTREAM - + Include (deprecated) <strstream> header from <systemc.h> + + Pre-standard C++ compilers had support for an old stringstream + implementation called 'strstream'. In the unlikely case that your + application still relies on this deprecated class and that <systemc.h> + includes this header for you automatically, you now need to define this + symbol when building your application. + + Note: Only effective when building an application. + + + * SC_INCLUDE_WINDOWS_H - + Explicitly include <windows.h> header from <systemc> header + + Previous versions of SystemC always included the full <windows.h> + header on all Windows platforms. This adds unnecessary bloat to + many SystemC applications, reducing compilation times. + + If you rely on the inclusion of the <windows.h> header in your + application, you can add this symbol to the list of preprocessor + switches for your compiler. + + Note: Only effective when building an application. + + + * SC_OVERRIDE_DEFAULT_STACK_SIZE=<size> - + Define the default stack size used for SystemC (thread) processes + + Note: Only effective during library build. + + + * SC_USE_SC_STRING_OLD / SC_USE_STD_STRING - + Define 'sc_string' symbol. + + Pre-IEEE-1666 versions of SystemC included an 'sc_string' class for + string objects. This class has been superseeded by 'std::string' these + days. + + If your application still relies on 'sc_string' being available, set one + of the two supported preprocessor switches to provide it: + + SC_USE_SC_STRING_OLD - + Uses old implementation `sc_string_old' to provide `sc_string': + typedef sc_string_old sc_string; + + SC_USE_STD_STRING - + Provide `sc_string' as an alias to `std::string': + typedef std::string sc_string; + + +Influential environment variables +================================= + +Currently, three environment variables are checked at library load time +and influence the SystemC library's behaviour: + + 1) SC_COPYRIGHT_MESSAGE=DISABLE - + Run-time alternative to SC_DISABLE_COPYRIGHT_MESSAGE (see above). + + 2) SC_SIGNAL_WRITE_CHECK=DISABLE + Run-time alternative to SC_DEFAULT_WRITER_POLICY=SC_UNCHECKED_WRITERS + (see above) + + 3) SC_DEPRECATION_WARNINGS=DISABLE + Do not issue warnings about using deprecated features as of + IEEE 1666-2011. + +Usually, it is not recommended to use any of these variables in new or +on-going projects. They have been added to simplify the transition of +legacy code. + + +// Taf! diff --git a/ext/systemc/LICENSE b/ext/systemc/LICENSE new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/ext/systemc/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/ext/systemc/NEWS b/ext/systemc/NEWS new file mode 100644 index 000000000..49aa2fdc7 --- /dev/null +++ b/ext/systemc/NEWS @@ -0,0 +1,107 @@ +* SystemC 2.3.1a + Relicensed under Apache License, Version 2.0. + No functional changes. + +* SystemC 2.3.1 + Release of SystemC 2.3.1 + - Bug fixes. + - Code cleanup. + - Some experimental new features. + +* SystemC 2.3.0 + Release of SystemC 2.3.0 + - Compliance to IEEE Std 1666-2011 + - Per LRM, includes TLM-2.0.2 + - Bug fixes. + - Code cleanup. + +* SystemC 2.2 + Production release of SystemC 2.2 + - Compliance to IEEE Std 1666-2005 + +* SystemC 2.2 Beta + Beta release of SystemC 2.2 + - Bug fixes. + - Code cleanup. + - Major new functionality + o Compliance with the IEEE 1666 SystemC Language reference module. + - Platforms and compilers supported (added since 2.1): + o Support for 64-bit Linux systems gcc-3.4.3. + o Linux with GNU C++ compiler version gcc-4.0.1. + o MacOS X with GNU C++ compiler version gcc-4.0.0. + +* SystemC 2.1 + Release of SystemC 2.1 + - Bug fixes. + - Code cleanup. + - Major new functionality + o Dynamic process support, including synchronization primitives. + o Mixed concatenation and concatenation of long types. + o Event queue support. + o Exported interfaces: sc_export. + o New error reporting API. + - Platforms and compilers supported (added since 2.0.1 Production): + o Solaris 2.8 with Sun CC compiler version Forte 7 and gcc-3.2.3 + o Linux (Redhat 9.0) with GNU C++ compiler version gcc-3.2.2 + o Linux (Redhat 8.0) with GNU C++ compiler version gcc-2.95.3 and gcc-3.2.3 + o MacOS X with GNU C++ compiler version gcc-3.1 and gcc-3.3. + o Windows NT 4.0 (SP6a) with VC++ 7.0 + +* SystemC 2.0.1 + Production release of SystemC 2.0.1 + - Bug fixes. + - Code cleanup. + - Simple bus example included. + - Platforms supported (changed from 2.0 Production): + o Sun Solaris 2.7 and 2.8 with GNU C++ compiler version gcc-2.95.3 + o Linux (Redhat 6.2) with GNU C++ compiler version gcc-2.95.3 + o Linux (Redhat 7.2) with GNU C++ compiler version gcc-2.95.3 + o HP-UX 11.00 with HP C++ compiler version A.03.33 + (Note: +O1 is the highest safe optimization level) + o Windows NT 4.0 (SP6a) with VC++ 6.0 (SP5) + - First release of a regression test suite for SystemC. + The SystemC regression test suite is released separately. + +* SystemC 2.0 + Production release of SystemC 2.0. + - All new SystemC 2.0 core language features. + - All SystemC 1.0.2 functionality (except obsoleted SystemC 0.9 features). + - No methodology-specific channels as in SystemC 1.2.1 beta. + (Note: starting with this release, the 2.0 Core Language Features + will be released separately from the methodology-specific libraries, + an example of which is the Master-Slave Library of 1.2.1 beta. + The release of the Master-Slave Library will follow this release. + You would be able to use the Master-Slave Library in conjunction with + this release). + - Dynamic thread creation example provided. + - Directory structure changed from 1.0.2, but same as 2.0 beta-2. + - Build process changed from 1.0.2 but same as 2.0 beta-2. + - Bug fixes for 2.0 beta-2. + - Platforms supported (changed from 2.0 beta-2): + o Sun Solaris 2.7 and 2.8 with GNU C++ compiler version 2.95.2 + o Sun Solaris 2.7 and 2.8 with SC6.1 and SC6.2 + o Linux (Redhat 6.2) with GNU C++ compiler version 2.95.2 + o HP-UX 11.00 with aCC C++ compiler versions A.03.31 and A.03.15 + (Note: +O1 is the highest safe optimization level) + o Windows NT 4.0 (SP3 and higher) with VC++6.0 + +* SystemC 2.0 Beta-2 + Second beta release of SystemC 2.0. + +* SystemC 2.0 Beta-1 + First beta release of SystemC 2.0. + +* SystemC 1.0.2 + Bug fix release. + +* SystemC 1.0.1 + Bug fix release. + +* SystemC 1.0 + First release of new SystemC syntax and fixed-point package. + +* SystemC 0.91 + Second release of SystemC. + +* SystemC 0.9 + This is the first release of SystemC. diff --git a/ext/systemc/NOTICE b/ext/systemc/NOTICE new file mode 100644 index 000000000..b42be393f --- /dev/null +++ b/ext/systemc/NOTICE @@ -0,0 +1,66 @@ +========================================================================= +== NOTICE file corresponding to section 4 d of the Apache License, == +== Version 2.0, in this case for the SystemC Class Library == +== Proof of Concept implementation == +========================================================================= + +This product includes software developed by Accellera Systems Initiative +8698 Elk Grove Bldv Suite 1, #114, Elk Grove, CA 95624, USA +Copyright 2011-2016 Accellera Systems Initiative Inc. (Accellera) +All rights reserved. + +This product includes software developed by Cadence Design Systems Inc. +2655 Seely Ave., San Jose, CA, USA +Copyright 2006-2016 Cadence Design Systems Inc. +All rights reserved. + +This product includes software developed by Circuitsutra Technologies Pvt Ltd. +Regus, Ground Floor, Tapasya Corp Heights, Sector 126, Noida, 201303, UP, India +Copyright 2011-2016 Circuitsutra Technologies Pvt Ltd. +All rights reserved. + +This product includes software developed by Doulos +Church Hatch, 22 Market Place, Ringwood, Hampshire, BH24 1AW, United Kingdom +Copyright 2006-2016 Doulos +All rights reserved. + +This product includes software developed by Fraunhofer-Gesellschaft +Postfach 20 07 33, 80007 Munich, Germany +Copyright 2014-2016 Fraunhofer-Gesellschaft +All rights reserved. + +This product includes software developed by Intel Corp. +2200 Mission College Blvd., Santa Clara, CA 95054-1549, USA +Copyright 2007-2016 Intel Corp. +All rights reserved. + +This product includes software developed by Mentor Graphics Corporation +8005 SW Boeckman Road, Wilsonville, OR 97070, USA +Copyright 2006-2016 Mentor Graphics Corporation +All rights reserved. + +This product includes software developed by OFFIS eV +Escherweg 2, 26121 Oldenburg, Germany +Copyright 2009-2016 OFFIS eV +All rights reserved. + +This product includes software developed by STMicroelectronics International NV +39, Chemin de Champ-des-Filles, Plan-Les-Ouates, Geneva, Switzerland +Copyright 2011-2016 STMicroelectronics International NV +All rights reserved. + +This product includes software developed by Synopsys, Inc. +690 East Middlefield Road Mountain View, CA 94043, USA +Copyright 1999-2016 Synopsys, Inc. +All rights reserved. + +This product includes software developed by Universite Pierre et Marie Curie +b.c. 167, 4 place Jussieu, 75252 Paris, France +Copyright 2011-2016 Universite Pierre et Marie Curie (UPMC) +All rights reserved. + +This product includes software developed by XtremeEDA Corporation +201-1339 Wellington St. West, Ottowa, Ontario K1Y3B8, Canada +Copyright 2011-2016 XtremeEDA Corporation. All rights reserved. + + diff --git a/ext/systemc/README.gem5.md b/ext/systemc/README.gem5.md new file mode 100644 index 000000000..b966b7d65 --- /dev/null +++ b/ext/systemc/README.gem5.md @@ -0,0 +1,21 @@ +Overview +======== + +This subfolder (/ext/systemc) is a custom redistribution of the Accellera +SystemC 2.3.1 library [[1]][sysc]. This distribution replaces Accellera's +Autoconf build system with a SCons build system, which is used by gem5. + +In the past it happened several times that some changes in gem5 broke the +SystemC coupling. Recently Accelera has changed the licence for SystemC from +their own licence to Apache2.0, which is compatible with gem5. However, SystemC +usually relies on the Boost library. The repository contains all the source +files from the Accellera distribution, but strips down the boost dependencies, +shown here:[[3]][strip]. All references to the boost library are replaced by +calls to the C++11 STL. This repository also contains the TLM 2.0 +protocol-checker from Doulos [[4]][doulos]. + + +[sysc]: http://accellera.org/downloads/standards/systemc +[gem5]: http://www.gem5.org/Main_Page +[doulos]: https://www.doulos.com/knowhow/systemc/tlm2/base_protocol_checker/ +[strip]: https://github.com/tud-ccc/systemc-scons/commit/913a7451939dc4d4bd752df7081064f9f870517a diff --git a/ext/systemc/README.md b/ext/systemc/README.md new file mode 100644 index 000000000..d4b084591 --- /dev/null +++ b/ext/systemc/README.md @@ -0,0 +1,43 @@ +Overview +======== + +This repository is a redistribution of the Accellera SystemC 2.3.1 library +[[1]][sysc]. This distribution replaces Accellera's Autoconf build system with +a SCons build system, which is very useful for integration of SystemC in other +SCons based projects, e.g., gem5 [[2]][gem5]. + +The repository contains all the source files from the Accellera distribution, +but strips down the boost dependencies. All references to the boost library +are replaced by calls to the C++11 STL. This repository also contains the +TLM 2.0 protocl checker from Doulos [[3]][doulos]. + +Build +===== + +To build libsystemc-2.3.1.so, simply type scons. Optionally you can specify the +number of jobs. + +``` +scons -j N +``` + +To build and link to SystemC from another SCons project, simply call the +SConscript located in `src/`. Be sure to add `-std=c++11` to the `CXXFLAGS` of +your environment and to export the environment as `'env'`. In case you build on +OS X, you will need to add `-undefined dynamic lookup` to your `LINKFLAGS`. +This is how a minimal SConstruct for your SystemC project could look: + +```python +env = Environment() + +env.Append(CXXFLAGS=['-std=c++11']) +if env['PLATFORM'] == 'darwin': + env.Append(LINKFLAGS=['-undefined', 'dynamic_lookup']) + +systemc = env.SConscript('<path_to_systemc>/src/SConscript', exports=['env']) +env.Program('example', ['example.cc', systemc]) +``` + +[sysc]: http://accellera.org/downloads/standards/systemc +[gem5]: http://www.gem5.org/Main_Page +[doulos]: https://www.doulos.com/knowhow/systemc/tlm2/base_protocol_checker/ diff --git a/ext/systemc/README.sysc b/ext/systemc/README.sysc new file mode 100644 index 000000000..a2729db83 --- /dev/null +++ b/ext/systemc/README.sysc @@ -0,0 +1,132 @@ + SystemC Class Library (Rel. 2.3.1) + ================================== + +This is the release of the SystemC 2.3.1 Class Library. +This release includes TLM 2.0.3 (Transaction Level Modeling) code, +as described in the IEEE 1666-2011 Language Reference Manual. + +------------------------------------------------------------------------------- + IMPORTANT + +1. This is the release of SystemC 2.3.1. This release contains bug fixes + for SystemC 2.3.0 as well as adding some minor and experimental features. + +2. This release is supported on the following platform combinations for + which it has been well tested: + + o 64-bit Linux (x86_64) + (RedHat Enterprise Linux 5, 6; Scientific Linux 5, 6; Debian 7; Ubuntu 12) + - GNU C++ compiler versions gcc-3.4.6 through gcc-4.9.0; + - Clang C++ compiler versions clang-3.0 through clang-3.5 + + o 64-bit Linux (x86_64) with 32-bit compiler (--host=i686-linux-gnu) + (RedHat Enterprise Linux 5, 6; Debian 7; Ubuntu 12) + - GNU C++ compiler versions gcc-4.4.7 through gcc-4.9.0; + - Clang C++ compiler versions clang-3.0 through clang-3.5 + + o 32-bit Linux (x86) + (Scientific Linux 5, 6; Debian 6, 7; Ubuntu 12) + - GNU C++ compiler versions gcc-3.4.6 through gcc-4.9.0; + - Clang C++ compiler versions clang-3.0 through clang-3.4 + + o 64-bit Mac OS X (x86_64) + (10.6 Snow Leopard, 10.8 Mountain Lion, 10.9 Mavericks) + - Apple LLVM version 5.0 (based on LLVM 3.3svn); + - Apple GNU C++ compiler version gcc-4.2.1 + + o 32-bit Mac OS X (x86) + (10.6 Snow Leopard, 10.8 Mountain Lion) + - Apple LLVM version 5.0 (based on LLVM 3.3svn); + - Apple GNU C++ compiler version gcc-4.2.1 + + o 32-bit Mac OS X (powerpc) + (10.6 Snow Leopard, executed with Rosetta) + - Apple GNU C++ compiler version gcc-4.2.1 + + o 64-bit FreeBSD 9.0 (x86_64) + - GNU C++ compiler versions gcc-4.2.1 through gcc-4.8.2; + - Clang C++ compiler version clang-3.3 + + o 32-bit FreeBSD 9.0 (x86) + - GNU C++ compiler versions gcc-4.2.1 through gcc-4.8.2; + - Clang C++ compiler version clang-3.3 + + o 32-bit Solaris (SPARC) + (Sun Solaris 10, Oracle Solaris 11) + - GNU C++ compiler versions gcc-3.4.3 through gcc-4.8.1; + - Sun/Solaris Studio compiler versions 12, 12.1, 12.2, 12.3 + + o Windows 7 SP1 (WoW64) + - Microsoft Visual Studio 2005 SP1 (8.0) (Win32 and x64); + - Microsoft Visual Studio 2008 Express SP1 (9.0) (Win32); + - Microsoft Visual Studio 2010 Express SP1 (10.0) (Win32); + - Microsoft Visual Studio 2012 Express Update 4 (11.0) (Win32 and x64) + - Microsoft Visual Studio 2013 Express Update 1 (12.0) (Win32 and x64) + + o Windows 7 SP1 (WoW64), (Cygwin 1.7.17) + - GNU C++ compiler versions gcc-3.4.4 through gcc-4.3.4 (x86) + + o Windows 7 SP1 (WoW64), Msys 1.0.17(0.48/3/2) + - MinGW32 GNU C++ compiler versions 4.5.2 through 4.7.0 (x86); + - MinGW-w64 GNU C++ compiler version 4.8.1 (x86 and x86_64) + + + This release has not yet been tested or is known not to work as expected + on the following formerly supported platforms: + + o GNU C++ compiler versions prior to 3.4.x (all platforms) + o HP-UX 11.00 or later with GNU C++ or HP C++ compiler + o Sun/Oracle Solaris with Sun Studio C++ compiler prior to 12.x + o Mac OS X prior 10.6 Snow Leopard with GNU C++ compiler + o Microsoft Visual C++ versions prior to 8.0 (2005) + + +------------------------------------------------------------------------------- + +For details, see the separate RELEASENOTES file. + + +Licensing and Copyright + + See the separate LICENSE file to determine your rights + and responsiblities for using SystemC. + +User Documentation + + You can find documentation for this release in the docs directory. + +Installation + + See the separate INSTALL file that provides system + information and installation instructions. + +Release Notes + + See the separate RELEASENOTES file that provides upto date + information about this release of SystemC. + +Additional information + + SystemC has a web site at + + http://www.accellera.org + + Discussion forum: http://forums.accellera.org/forum/9-systemc/ + + You can post the bugs and suggestions of general interest to the forum. + When reporting bugs please specify the following information (if + applicable): + + 1) SystemC version + 2) platform, compiler, flags + 3) description of the problem + 4) steps to reproduce the problem + 5) compile/runtime warnings and errors + 6) code sample, not more than 100 lines to demonstrate the problem + + Note: All bugs will only be tested against the latest publicly available + version of the product. + + Note: All C++ compilers that SystemC supports have bugs of different + degree of severity. We cannot fix those bugs. Please report them + to the compiler vendor. diff --git a/ext/systemc/RELEASENOTES b/ext/systemc/RELEASENOTES new file mode 100644 index 000000000..2dd93b34c --- /dev/null +++ b/ext/systemc/RELEASENOTES @@ -0,0 +1,685 @@ + Release Notes for SystemC 2.3.1 + =============================== + + Andrew C. Goodrich, Forte Design Systems + Philipp A. Hartmann, OFFIS Institute for Information Technology + +CONTENTS +======== + + 1) What's new in this release? + + 2) Bug fixes and enhancements + + 3) New features + + 4) Incompatibitilies with previous releases + + 5) Expanded dynamic process support + + 6) Experimental features + + 7) Known problems + + 8) Fixed-point library + + 9) TLM Release Notes + + +1) What's new in this release? +============================== + +This version of SystemC contains the "Proof of Concept" simulator +for the IEEE 1666-2011 SystemC standard. Please consult the IEEE Std +1666-2011 SystemC Language Reference Manual for details about the +current SystemC standard. + +TLM-2.0 is merged into the main SystemC release since 2.3.0. +Please see section 9) below for more details related to TLM. + +Compared to the 2.3.0, this release has the following new items: + + - New features, partly beyond the current IEEE 1666-2011 standard, + see section 3. + + - Experimental features (disabled by default), see section 5. + Testing and feedback welcome via the Accellera SystemC forums + at http://forums.accellera.org/forum/9-systemc/. + + - Bug fixes, see section 2. + + - Expanded platform support, see the README. + + + +2) Bug fixes and enhancements +============================= + +Following is the list of bug fixes and enhancements for this release: + + - For fixes and enhancements of the embedded TLM-2.0 implementation, + please see section 9. + + - Additional changes and cleanups leading to incompatibilities with + previous versions of SystemC are described in section 4. + + - Fix nested SC_METHOD preemptions caused by resetting a method, which + throws an exception in a thread process. The control now correctly + goes back to the throwing method. + + - Handle the case of a suppressed multiple-writer error in sc_signal + (and related channels) consistently with SystemC 2.2.0 again. + + - The 'sc_buffer<bool>' and 'sc_buffer<sc_logic>' channels now correctly + notify their (pos|neg)edge_events, if someone is waiting on them. + + - Cleanup the renaming of the internal Boost namespaces. The embedded + Boost implementation resides in the (renamed) top-level namespaces + - sc_boost + - sc_unnamed (for placeholders, part of IEEE 1666-2011) + - sc_mpl_ (internal ADL barrier) + + - Minor fixes in sc_vector-related classes + - correctly determine instantiation context + - sc_vector_iter: addition/substraction operators fixed + - sc_vector_assembly: add swap, fix missing return statement in + assignment + + - WIF tracing of 64-bit integers: fix widths and masks on some + 64-bit platforms. + + - Suppressed a warning in case of calling sc_start in case of pending + delta notifications without any pending (or resulting) process + activations afterwards (1666-2011 compatbility). + + - Fix sc_string_old implementation to handle very long strings (>1024) + (known issue in <=2.3.0). Note, that sc_string_old is no longer + included by default, see section 4. + + - Add "risc_cpu" example to Automake build system ("make check"). + + - Add missing files to the MS Visual C++ SystemC.vcproj project file. + + - Add a missing "break" statement to "scfx_utils.h" in the "SC_CSD" + format parsing logic. + + - Fix several integer conversion warnings raised by some compilers + throughout the SystemC implementation. + + - Fixed incorrect GCC i386/x86_64 function call stack alignment when + using the QuickThreads/WinFiber-based process implementations (16-byte + boundary). This avoids segmentation faults in some cases where the + stricter stack requirement is implicitly assumed by the compiler. + + - The default stack size for threads, SC_DEFAULT_STACK_SIZE, has been + increased on 64-bit platforms and is overridable at library build + time (see INSTALL). + + - The sc_report implementation now correctly handles empty and NULL + message type arguments (avoiding a segmentation fault in these cases). + The sc_report default constructor is made private to follow IEEE 1666. + + - Missing namespace qualifiers added to all reporting macros, namely + - SC_DEFAULT_*_ACTIONS + - SC_REPORT_INFO_VERB + to make them usable again while including <systemc> instead of + <systemc.h> + + - VCD/WIF tracing: fix support for very long values + + The sc_(un)signed and sc_fxnum(_fast) data types can potentially hold + longer values than 1000 bit, which used to be the fixed size of the + intermediate buffers in sc_(vcd,wif)_trace for these types. + + - Cleanup systemc.h + + - Drop any in-library dependencies on the old 'sc_string' class, + removing the need to provide the corresponding header externally + (see section 4). + - Drop explicit in-header dependencies on <windows.h> on Windows + platforms, removing the automatic inclusion from <systemc[.h]> + (see section 4). + - Drop inclusion of 'strstream' by default on some platforms + (see section 4) + - assume working C++ standard library on all platforms + - assume working argument-dependent lookup on MSVC + (which should be working since MSVC 2003 already) + - see section 4 and INSTALL file + + - Improved compile/runtime check of the SystemC library config + + Some preprocessor switches need to be consistent between the application + and the library (e.g. if sizes of classes are affected or other parts of + the ABI are affected). These can now be checked at link-time. + + Secondly, some preprocessor switches need to be consistent between + different translation units of an application, which is checked at + runtime startup. + + - sc_context: avoid reinterpret_cast from integer to pointer + + - The SC_VERSION_ORIGINATOR has been renamed from "ASI" to "Accellera" + to follow the naming policies of the Accellera Systems Initiative. + + - Cleanups of the VCD/WIF tracing implementation + + - Removal of internal files from the public headers (see section 4) + - Report any information (infos, warnings, errors) via the SystemC + reporting mechanism instead of directl printing to std::cout/cerr + - Automatically unregister trace updates when closing a trace file + during the simulation + + - Drop the 'register' storage class specifier, which has been + deprecated in the C++11 standard (and therefore might cause warnings + on some compilers). + + - Expanded naming of traced objects in VCD traces to use 5 characters + rather than 3 to accommodate more signals (incomplete in 2.3.0). + + - Fix sc_signed/sc_unsigned conversion bug on GCC 4.8 or later, coming + from its aggressive optimization in case of integer over/underflows + (by avoiding the C++ undefined behaviour in the implementation). + + - An output stream operator<< for sc_status is added to enable + pretty-printing of sc_status values (and bitwise combinations of + such values). + + - Various minor code cleanups and compiler warning fixes + - removal of some workarounds for very old versions of some + compilers (e.g. MSVC < 8.0). + - removal of unused variables and macros + - some deduplication of redundant code paths + + +3) New features +=============== + +Here is an overview of changes in 2.3.1 compared to 2.3.0. + +Note: These features partly add functionality beyond the current + IEEE Std. 1666-2011. + + + - Major rewrite of the Autoconf/Automake build system + - better control of the installation directories + - improved libtool library dependency detection, especially + in cross-compilation scenarios (--host=...) + - support for pkg-config for SystemC and TLM + (see http://www.freedesktop.org/wiki/Software/pkg-config/) + - accept arbitrary GCC-compatible compilers + (e.g. Clang, Intel compiler, compiler-wrappers like scan-build) + - avoid deprecation warnings, cleanup implementation + - less recursive build, silent rules by default + - improved "make check" test handling + + + - Updated MS Visual C++ project and solution files to include + support for Visual Studio 2012 and 64-bit builds on Windows + platforms. + + + - Improved conversion between the underlying integral time + representation and sc_time objects: + + - Add a nested typedef "value_type" to sc_time to enable an + implementation-independent use of the underlying integral + time representation (see IEEE 1666-2011, 5.11.1). + + - Adding an inverse to the 'sc_time::value()' function to + convert a plain value back to an sc_time object: + static sc_time sc_time::from_value( value_type t ); + + - Adding modulus operators (%, %=) to compute time offsets from + clock or quantum boundaries: + + sc_time operator%(const sc_time& lhs, const sc_time& rhs); + + sc_time& sc_time::operator%=(); + + Note: These operators are missing from IEEE 1666-2011, which + make e.g. the tlm_global_quantum implementation nearly + impossible within the limits of the SystemC standard. + + + - Add function to determine the current object hierarchy: + + sc_object* sc_core::sc_get_current_object() + + Returns a pointer to the sc_object instance (or NULL) that would + currently become the parent object of a newly created sc_object + instance (i.e. the current module during elaboration, and the + currently active process during simulation). + + + - Add compile-time configurable default signal writer policy + (see INSTALL). + + Defining SC_DEFAULT_WRITER_POLICY to one of the sc_writer_policy + values before including systemc(.h) allows application-wide selection + of the default sc_writer_policy used for signals. + + Defining SC_NO_WRITE_CHECK is equivalent to + SC_DEFAULT WRITER_POLICY=SC_UNCHECKED_WRITERS + + By default, the writer policy still disallows multiple + writers (SC_ONE_WRITER). + + + - Add an sc_signal initialization which does not create an event + via newly provided constructors to the signal classes: + + sc_signal<T>::sc_signal( const char* name + , const T& initial_value ); + + (similarly for sc_buffer and sc_signal_resolved) + + Compared to calling the "write()" function on a signal during + the elaboration, these constructors will set the initial value + of the signal without triggering an event at the beginning of the + simulation (and therefore may avoid triggering sensitive processes). + + + - Add a static function to sc_report_handler to query the current + report handler function: + + static sc_report_handler_proc sc_report_handler::get_handler(); + + Additionally, sc_report_handler::set_handler() now returns the + previously set handler (c.f. sc_report_handler::set_actions). + + + - Improved conversion from bitvector element references to bool + + As it is surprising to the user that a reference to an explicit + element of a sc_bv could not be used in a boolean context, a safe + conversion has been added to this release. + + This enables the following coding style: + + sc_bv<8> mybits; + // ... + if( mybits[0] ) // no longer a compiler error here! + /* do something */ ; + + Note: For logic vectors, the bit-references still need to be + converted to bool explicitly (e.g. via the "to_bool()" + function. + + + +4) Incompatibilities with previous releases +=========================================== + +Here is a list of known incompatibilities between this release and +2.3.0 (or earlier): + + - The non-standard sc_time constructors + - sc_time( uint64, bool scale ) + - sc_time( double, bool scale ) + have been deprecated and issue a warning when being used. + Use the new 'sc_time::from_value' function instead (see section 3). + + - The non-standard function 'sc_object::get_parent()' has been + deprecated, use 'sc_object::get_parent_object()' instead. + + - The non-standard function 'sc_signal::get_new_value()' has been + deprecated (as required by IEEE 1666-2011). + + - The non-standard implementation classes for the VCD and WIF tracing + (vcd_trace_file, wif_trace_file) are now hidden from an application + and no longer part of the public headers. + Use the IEEE 1666-2011 functions + - sc_trace + - sc_create_[vcd|wif]_trace_file + - sc_close_[vcd|wif]_trace_file + - sc_trace_file::set_time_unit + to set up the tracing in your application. + + - The non-standard header 'src/sysc/communication/sc_reset.h' is + no longer part of the public headers. + + - The 'sc_string_old' class is no longer available by default. + Define 'SC_USE_SC_STRING_OLD' before including "systemc.h", + see INSTALL. + + - The implicit inclusion of the system-headers "windows.h" (on Windows) + and (deprecated) "strstream" have been removed. See INSTALL. + + - The incomplete implementation of old "W_*" watching macros and the + non-standard struct sc_watch have been removed. + +Here is a list of known incompatibilities between this release and 2.2.0: + + - The order that processes (SC_METHODs and SC_THREADs) are dispatched + for execution may be different than the order with SystemC 2.2.0 for + some SystemC programs. This is related to the new starvation policy + support for the sc_start() function introduced with IEEE 1666_2011. + + - The various bind() functions for ports and exports are "virtual" as + of IEEE 1666-2011. This leads to an incompatibility with the + TLM 2.0.x release. To use SystemC 2.3 together with TLM 2.0.{0,1}, + define SC_DISABLE_VIRTUAL_BIND during the build of the simulator and + before including systemc.h (see INSTALL). + + +5) Expanded Dynamic Process Support +=================================== + +This version implements the dynamic process extensions described in the +IEEE Std 1666-2011 Language Reference Manual. + +Compared to SystemC 2.3.0, some bugs in corner cases of the +specification have been fixed (see section 2). + + +6) Experimental features +======================== + +In this section the experimental features of this release are listed. + +Note: These features are not enabled in the default library + configuration and need to be explicitly activated during at + library build time. See INSTALL file. + + + - Extended Simulation Phase Callbacks + + This release adds an optional mechanism to register callbacks + to several simulation phases. This can be used to integrate + custom introspection techniques in a non-invasive manner. + + New phases are added to the sc_status enumeration: + + SC_END_OF_INITIALIZATION, + SC_END_OF_UPDATE, + SC_BEFORE_TIMESTEP + + to enable a more fine-grained view to the SystemC simulation phases. + + When the phase callback mechanism is activated (see the INSTALL file), + any sc_object can subscribe to a (set of) elaboration/simulation phases + for dynamic callbacks explicitly: + + // trigger current object before updating the simulation time + this->register_simulation_phase_callback( SC_BEFORE_TIMESTEP ); + + // trigger current object before returning to "sc_start" + this->register_simulation_phase_callback( SC_PAUSED | SC_STOPPED ); + + Unsubscribing from any simulation phase is possible via the corresponding + unregister_simulation_phase_callback( phase_cb_mask ) + function. + + Both functions return the effective mask after the requested callback mask + update. Therefore, querying the currently active mask can be achieved by + calling the (un)registration functions with an empty mask: + + sc_object::phase_cb_mask current_cb_mask = + this->register_simulation_phase_callback( 0u ); + + To enable the external (un)registration of callbacks for a user-defined + sc_object class, the (un)registration functions can be made public by + adding the following using directives to a 'public:' section of the + class definition: + + using sc_core::sc_object::register_simulation_phase_callback; + using sc_core::sc_object::unregister_simulation_phase_callback; + + When the simulation passes a phase where dynamic callbacks are registered, + the subscribed objects are triggered via the function: + + virtual void sc_object::simulation_phase_callback(); + + which should then be implemented by the subscribing object's class. + + Within a simulation callback, the triggering phase can be determined + via the IEEE 1666-2011 'sc_get_status()' function: + + void simulation_phase_callback() { + std::cout << sc_core::sc_get_status() << std::endl; + } + + A related feature is the triggering of sc_trace updates via these + simulation phase callbacks instead of the hard-coded calls in various + places of the simulation loop. This feature has to be enabled separately, + see INSTALL file. + + + - Allow creation of sc_max_time() objects before fixing the sc_time + resolution + + Currently. IEEE 1666-2011 requires that any call to + + sc_core::sc_set_time_resolution( double, sc_time_unit ) + + happens before the construction of the first non-SC_ZERO_TIME + sc_time object. + + This can be inconvenient in cases, where an "uninitialized sc_time value" + is needed, which needs to be separate from SC_ZERO_TIME in some cases. + + A relaxation of the strict sc_time construction rules wrt. to + the simulation time resolution can be optionally enabled via the + preprocessor switch SC_ENABLE_EARLY_MAXTIME_CREATION (see INSTALL). + + When this option is enabled, the creation of time objects with the + values SC_ZERO_TIME and 'sc_max_time()' are allowed before fixing the + time resolution. The resolution is still fixed once the actual + relationship between the internal time representation and the physical + time units (SC_FS, SC_PS, ...) is used or observed by the application. + + + + +7) Known Problems +================= + + - When building the SystemC library with QuickThreads support, the + resulting shared library is marked as requiring an executable stack + by certain compilers/assemblers (or rather not marked as not needing + one). As a result, some system security systems (like SELinux) might + refuse to load the library. As a workaround for GNU (compatible) + assemblers, pass the assembler flags variable with the option + CCASFLAGS="-Wa,--noexecstack" + to the `configure' script call before building the SystemC library. + + + - IEEE 1666-2011 does not explicitly define the behaviour in the corner + cases of attempting to create sc_time objects smaller than the time + resolution or bigger than sc_max_time(). This implementation currently + truncates "small" sc_time objects to SC_ZERO_TIME, while "too big" + objects wrap-around sc_max_time() and lead to a value modulo the + maximum time. In both cases, no warning is generated. + + + - The sign-extension of mixed-signedness logic expressions (&,|) + involving one sc_bigint<> operand and C++ builtin integral types + (int, short, etc.) is inconsistent between 32-bit and 64-bit + platforms in some cases. Convert both operands to sc_bigint<> first. + + + - The definition of sc_dt::(u)int64 differs from std::(u)int64_t types + on some platforms. This may lead to problems with function overloads + and/or format-string placeholders. As a workaround, convert these + values explicitly to the correct type before passing them to functions + expecting one of these types. For sc_time, use the new nested type + sc_time::value_type to hold values of the underlying representation. + + + - Bit/logic-vector reductions (or_reduce, and_reduce, etc.) return an + 'sc_logic_value_t' enum value, instead of a bool or sc_logic (as required + by IEEE 1666-2011). Using the return value of these functions in a + boolean context, e.g. + if( lv.or_reduce() ) { /* ... */ } + might lead to wrong results in case of 'X' or 'Z' bits in the vector. + Avoid this by converting the result to an 'sc_logic' first and perform + a safe conversion to bool: + if( sc_logic( lv.or_reduce() ).to_bool() ) { /* ... */ } + + + - The use of the DEBUG_SYSTEMC macro does not work properly with certain + compilers (e.g., gcc 2.95.x) if it was not also specified when the + SystemC library was built. The problem is caused by the use of the + library compiled version of some inline methods. This problem does not + appear to be present in the gcc 3.3, Solaris, and aCC compilers. + The work-around is to specify DEBUG_SYSTEMC when the SystemC library + is built. + + + - On some recent compilers (e.g. Clang, Solaris Studio), warnings are + generated about the "hidden overloaded virtual function" bind of the + sc_port(_b) class templates in the 'specialized_signals' example. + These warnings are caused by the introduction of the virtual bind + implementation in IEEE 1666-2011. + As a workaround, check your compiler documentation how to suppress + the warning (e.g. 'CXXFLAGS=-Wno-overloaded-virtual') or mark + the SystemC include directory as "system directory" by using + '-isystem ${SYSTEMC_HOME}/include' (or equivalent) instead of + the usual '-I'. + + This also affects the TLM-2.0 sockets, see Section 9.3. + + + - Some paths in this release are longer than the historical 99 character + limit of tar archives, and several Windows archivers (e.g. WinZip) + have been reported to trip over this. The open source archiver 7-zip + (http://7-zip.org) is known to work. + + +8) Fixed-point library +====================== + +SystemC contains a fixed-point datatypes package. + +Changes compared to SystemC 2.0.1 + + - support for explicit construction from "float" values + + - removing a conversion ambiguity by marking some constructors of + sc_fxval[_fast] classes as 'explicit' + +Compile-time macro SC_INCLUDE_FX must be defined in order to build +applications that use fixed point types. You can specify a compiler +flag, e.g., g++ -DSC_INCLUDE_FX ... or use a define statement before +you include systemc.h, e.g.: + + #define SC_INCLUDE_FX + #include "systemc.h" + +Due to the large size of the fixed-point datatypes header files, +compilation can take considerably more time. + +If you want to use the fixed-point data types only (i.e., not data- +types sc_int, sc_uint, sc_bigint, sc_biguint), compilation time can be +reduced by defining compile-time macro SC_FX_EXCLUDE_OTHER (in addition +to SC_INCLUDE_FX). + + +9) TLM Release Notes +==================== + +CONTENTS +======== + + 1) Supported SystemC versions + 2) What's changed in this kit? + 3) Known issues + + +9.1) Supported SystemC versions +=============================== + +SystemC 2.2.0 and 2.3.x are supported and have been tested. +SystemC 2.1.v1 is still supported in principle, but has not +been tested extensively. + + +9.2) What's changed in this kit? +================================ + +Compared to TLM 2.0.2 kit (part of SystemC 2.3.0), the following has changed: + + + - The tlm_utils headers have been cleaned up to include <tlm>, + instead of <tlm.h> + + + - The convenience sockets with base-protocol NB/B conversion support + now automatically define the required SC_INCLUDE_DYNAMIC_PROCESSES, + if not already provided by the user (since the B/NB conversion + depends on the SystemC dynamic process support). + + + - Improve the NB/B conversion in the simple_target_socket to avoid + the dynamic allocation (and deletion) of sc_event instances in the + use of the spawned helper processes for the converesion. + + + - Fix a bug in the same simple_target_socket NB/B conversion thread, + where the target socket may not detect the early completion of the + response phase via a "TLM_UPDATED" return value and a "TLM_END_RESP" + phase (base protocol violation). + + + - Fix the "get_base_interface()" implementation provided by the + multi_passthrough_target_socket. Prior to this release, a + dummy interface object has been used as a return value in case + of a hierarchical bind. Return the first bound interface instead. + + + - Fixed missing initialization of some member variables in the + callback_binder_fw|bw implementations, that caused segfaults + in some cases. + + + - The implementation-defined tlm::circular_buffer class has been + updated with the following changes + - now provides a "clear()" member function to drop the current + contents, + - fix a segmentation fault due to freeing invalid memory in + "resize()", which could happen in some cases, + - work around a parsing error on some EDG-based C++ frontends. + + + - tlm_global_quantum: use sc_time::operator% + + Instead of relying on a manual remainder calculation based on + sc_time::value and the non-standard backwards conversion, the new + sc_time::operator% is used to compute the remaining time in the + current quantum (see section 3). + + + - The internal tlm_array class (to hold payload extensions) has been + reimplemented based on std::vector (fixes copy constructor bug). + + + - The TLM_VERSION_ORIGINATOR has been renamed from "ASI" to "Accellera" + to follow the naming policies of the Accellera Systems Initiative. + + + + +9.3) Known issues +================= + +a. The tlm_simple_target_socket in tlm_utils does not obey the END_REQ rule + when only an nb_ call is registered, an b_ call is being handled in the + socket and there is an nb_ call coming in at the same time. In this case + the incoming nb_ call will be forwarded to the registered nb_ call without + checking whether the earlier b_ call has passed the END_REQ timing point. + +b. The implementation of the PEQ 'peq_with_get' in tlm_utils does not properly + distinguish between immediate notifications and delta notifications. In the + case that a immediate and delta notification happen at the same simulation + time both types of notifications emerge from the PEQ in the same evaluation + phase. This is wrong immediate notifications should overtake delta + notifications. + +c. On some recent compilers (e.g. Clang, Solaris Studio), warnings are generated + about the "hidden overloaded virtual function" bind of the sc_port(_b) + class templates when using the TLM-2.0 sockets. These warnings are caused by + the introduction of the virtual bind implementation in IEEE 1666-2011. + As a workaround in your application, check your compiler documentation how to + suppress the warning (e.g. adding the flag -Wno-overloaded-virtual), or mark + the SystemC include directory as "system directory" by using + '-isystem ${SYSTEMC_HOME}/include' (or equivalent) instead of the usual '-I'. diff --git a/ext/systemc/SConscript b/ext/systemc/SConscript new file mode 100644 index 000000000..804f7abfc --- /dev/null +++ b/ext/systemc/SConscript @@ -0,0 +1,64 @@ +# Copyright (c) 2017, TU Dresden +# Copyright (c) 2017, University of Kaiserslautern +# All rights reserved. + +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# +# Authors: Christian Menard +# Matthias Jung + +import os + +Import('main') + +main.Prepend(CPPPATH=Dir('./src')) +main.Prepend(CPATH=Dir('./src')) + +main.Prepend(CXXFLAGS=['-DSC_INCLUDE_FX', '-pthread']) +main.Prepend(CFLAGS=['-DSC_INCLUDE_FX', '-pthread']) + +conf = Configure(main) + +if main['PLATFORM'] == 'darwin': + main.Append(LINKFLAGS=['-undefined', 'dynamic_lookup']) + +s_file = None +if conf.CheckDeclaration("__i386__"): + s_file = 'i386.s' +if conf.CheckDeclaration("__x86_64__"): + s_file = 'iX86_64.s' +conf.Finish() + +if s_file is None: + print 'Unsupported CPU architecture!' + Exit(1) + +systemc_files = Glob('src/sysc/kernel/*.cpp') +systemc_files += ['src/sysc/qt/qt.c', 'src/sysc/qt/md/' + s_file] +systemc_files += Glob('src/sysc/communication/*.cpp') +systemc_files += Glob('src/sysc/tracing/*.cpp') +systemc_files += Glob('src/sysc/utils/*.cpp') +systemc_files += Glob('src/sysc/datatypes/bit/*.cpp') +systemc_files += Glob('src/sysc/datatypes/fx/*.cpp') +systemc_files += Glob('src/sysc/datatypes/int/*.cpp') +systemc_files += Glob('src/sysc/datatypes/misc/*.cpp') + +main.Library('libsystemc', systemc_files) +main.SharedLibrary('libsystemc', systemc_files) + diff --git a/ext/systemc/src/README_TLM.txt b/ext/systemc/src/README_TLM.txt new file mode 100644 index 000000000..f8174e7a0 --- /dev/null +++ b/ext/systemc/src/README_TLM.txt @@ -0,0 +1,33 @@ + +TLM-2.0 standard header files +============================= + +Dir: include/ + +SubDirs: tlm_core/ + tlm_1/ + tlm_2/ + tlm_utils/ + +Files: README.txt + tlm + tlm.h + + +Comments +======== + +To use the TLM-2.0 interoperability standard, a user should only include the tlm +or tlm.h header file. The same holds for the TLM-1.0 implementation that is +included as part of this kit; only include tlm or tlm.h. These header files +refer to all the header files within the tlm_core/ subdirectory, everything +within tlm or tlm.h is contained in the tlm namespace. + +The tlm_utils subdirectory contains a set of additional definitions supported +by the TLM-2.0 standard, but which are not part of the interoperability +requirements. It contains ease-of-use and convenience implementations for the +interoperability standard. All objects defined in the tlm_utils directory are +contained in the tlm_util namespace. + +See the README.txt files in the subdirectories for an explanation of the +internal organization of the header files. diff --git a/ext/systemc/src/sysc/communication/sc_buffer.h b/ext/systemc/src/sysc/communication/sc_buffer.h new file mode 100644 index 000000000..e91c1a7c9 --- /dev/null +++ b/ext/systemc/src/sysc/communication/sc_buffer.h @@ -0,0 +1,194 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_buffer.h -- The sc_buffer<T> primitive channel class. + Like sc_signal<T>, but *every* write causes an event. + + Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21 + + CHANGE LOG IS AT THE END OF THE FILE + *****************************************************************************/ + +#ifndef SC_BUFFER_H +#define SC_BUFFER_H + + +#include "sysc/communication/sc_signal.h" + +namespace sc_core { + +// ---------------------------------------------------------------------------- +// CLASS : sc_buffer<T> +// +// The sc_buffer<T> primitive channel class. +// ---------------------------------------------------------------------------- + +template< typename T, sc_writer_policy POL = SC_DEFAULT_WRITER_POLICY > +class sc_buffer +: public sc_signal<T,POL> +{ +public: + + // typedefs + + typedef sc_buffer<T,POL> this_type; + typedef sc_signal<T,POL> base_type; + +public: + + // constructors + + sc_buffer() + : base_type( sc_gen_unique_name( "buffer" ) ) + {} + + explicit sc_buffer( const char* name_ ) + : base_type( name_ ) + {} + + sc_buffer( const char* name_, const T& initial_value_ ) + : base_type( name_, initial_value_ ) + {} + + // interface methods + + // write the new value + virtual void write( const T& ); + + + // other methods + + this_type& operator = ( const T& a ) + { write( a ); return *this; } + + this_type& operator = ( const sc_signal_in_if<T>& a ) + { write( a.read() ); return *this; } + + this_type& operator = ( const this_type& a ) + { write( a.read() ); return *this; } + + virtual const char* kind() const + { return "sc_buffer"; } + +protected: + + virtual void update(); + +private: + + // disabled + sc_buffer( const this_type& ); +}; + + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + +// write the new value + +template< typename T, sc_writer_policy POL > +inline +void +sc_buffer<T,POL>::write( const T& value_ ) +{ + if( !base_type::policy_type::check_write(this,true) ) + return; + + this->m_new_val = value_; + this->request_update(); +} + + +template< typename T, sc_writer_policy POL > +inline +void +sc_buffer<T,POL>::update() +{ + base_type::policy_type::update(); + base_type::do_update(); +} + +} // namespace sc_core + +#endif + +//$Log: sc_buffer.h,v $ +//Revision 1.7 2011/08/26 20:45:39 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +//Revision 1.6 2011/04/08 18:22:45 acg +// Philipp A. Hartmann: use the context of the primitive channel to get +// the change stamp value. +// +//Revision 1.5 2011/04/05 20:48:09 acg +// Andy Goodrich: changes to make sure that event(), posedge() and negedge() +// only return true if the clock has not moved. +// +//Revision 1.4 2011/04/05 06:15:18 acg +// Philipp A. Hartmann: sc_writer_policy: ignore no-ops in delta check. +// +//Revision 1.3 2011/02/18 20:23:45 acg +// Andy Goodrich: Copyright update. +// +//Revision 1.2 2010/12/07 19:50:36 acg +// Andy Goodrich: addition of writer policies, courtesy of Philipp Hartmann. +// +//Revision 1.1.1.1 2006/12/15 20:20:04 acg +//SystemC 2.3 +// +//Revision 1.8 2006/03/13 20:19:43 acg +// Andy Goodrich: changed sc_event instances into pointers to sc_event instances +// that are allocated as needed. This saves considerable storage for large +// numbers of signals, etc. +// +//Revision 1.7 2006/01/26 21:00:49 acg +// Andy Goodrich: conversion to use sc_event::notify(SC_ZERO_TIME) instead of +// sc_event::notify_delayed() +// +//Revision 1.6 2006/01/24 20:46:31 acg +//Andy Goodrich: changes to eliminate use of deprecated features. For instance, +//using notify(SC_ZERO_TIME) in place of notify_delayed(). +// +//Revision 1.5 2006/01/19 19:18:25 acg +//Andy Goodrich: eliminated check_writer in favor of inline code within the +//write() method since we always execute the check_writer code even when +//check writing is turned off. +// +//Revision 1.4 2006/01/19 00:30:57 acg +//Andy Goodrich: Yet another implementation for disabling write checks on +//signals. This version uses an environment variable, SC_SIGNAL_WRITE_CHECK, +//that when set to DISABLE will turn off write checking. +// +//Revision 1.3 2006/01/13 18:47:20 acg +//Reversed sense of multiwriter signal check. It now defaults to ON unless the +//user defines SC_NO_WRITE_CHEK before inclusion of the file. +// +//Revision 1.2 2006/01/03 23:18:26 acg +//Changed copyright to include 2006. +// +//Revision 1.1.1.1 2005/12/19 23:16:43 acg +//First check in of SystemC 2.1 into its own archive. +// +//Revision 1.9 2005/06/10 22:43:55 acg +//Added CVS change log annotation. +// + +// Taf! diff --git a/ext/systemc/src/sysc/communication/sc_clock.cpp b/ext/systemc/src/sysc/communication/sc_clock.cpp new file mode 100644 index 000000000..158d54b7a --- /dev/null +++ b/ext/systemc/src/sysc/communication/sc_clock.cpp @@ -0,0 +1,409 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_clock.cpp -- The clock channel. + + Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21 + + CHANGE LOG IS AT THE END OF THE FILE + *****************************************************************************/ + +// using notify_delayed(). +// +// Revision 1.4 2006/01/18 21:42:26 acg +// Andy Goodrich: Changes for check writer support, and tightening up sc_clock +// port usage. +// +// Revision 1.3 2006/01/13 18:47:41 acg +// Added $Log command so that CVS comments are reproduced in the source. +// + +#include "sysc/communication/sc_clock.h" +#include "sysc/communication/sc_communication_ids.h" +#include "sysc/kernel/sc_simcontext.h" +#include "sysc/kernel/sc_process.h" +#include "sysc/kernel/sc_spawn.h" +#include "sysc/utils/sc_utils_ids.h" + +namespace sc_core { + +// ---------------------------------------------------------------------------- +// CLASS : sc_clock +// +// The clock channel. +// ---------------------------------------------------------------------------- + +// constructors + +sc_clock::sc_clock() : + base_type( sc_gen_unique_name( "clock" ) ), + m_period(), m_duty_cycle(), m_start_time(), m_posedge_first(), + m_posedge_time(), m_negedge_time(), + m_next_posedge_event( (std::string(SC_KERNEL_EVENT_PREFIX) + + "_next_posedge_event").c_str()), + m_next_negedge_event( (std::string(SC_KERNEL_EVENT_PREFIX) + + "_next_negedge_event").c_str()) + +{ + init( sc_time::from_value(simcontext()->m_time_params->default_time_unit), + 0.5, + SC_ZERO_TIME, + true ); + + m_next_posedge_event.notify_internal( m_start_time ); +} + +sc_clock::sc_clock( const char* name_ ) : + base_type( name_ ), + m_period(), m_duty_cycle(), m_start_time(), m_posedge_first(), + m_posedge_time(), m_negedge_time(), + m_next_posedge_event( (std::string(SC_KERNEL_EVENT_PREFIX) + + std::string(name_) + "_next_posedge_event").c_str()), + m_next_negedge_event( (std::string(SC_KERNEL_EVENT_PREFIX) + + std::string(name_) + "_next_negedge_event").c_str()) +{ + init( sc_time::from_value(simcontext()->m_time_params->default_time_unit), + 0.5, + SC_ZERO_TIME, + true ); + + m_next_posedge_event.notify_internal( m_start_time ); +} + +sc_clock::sc_clock( const char* name_, + const sc_time& period_, + double duty_cycle_, + const sc_time& start_time_, + bool posedge_first_ ) : + base_type( name_ ), + m_period(), m_duty_cycle(), m_start_time(), m_posedge_first(), + m_posedge_time(), m_negedge_time(), + m_next_posedge_event( (std::string(SC_KERNEL_EVENT_PREFIX) + + std::string(name_) + "_next_posedge_event").c_str()), + m_next_negedge_event( (std::string(SC_KERNEL_EVENT_PREFIX) + + std::string(name_) + "_next_negedge_event").c_str()) +{ + init( period_, + duty_cycle_, + start_time_, + posedge_first_ ); + + if( posedge_first_ ) { + // posedge first + m_next_posedge_event.notify_internal( m_start_time ); + } else { + // negedge first + m_next_negedge_event.notify_internal( m_start_time ); + } +} + +sc_clock::sc_clock( const char* name_, + double period_v_, + sc_time_unit period_tu_, + double duty_cycle_ ) : + base_type( name_ ), + m_period(), m_duty_cycle(), m_start_time(), m_posedge_first(), + m_posedge_time(), m_negedge_time(), + m_next_posedge_event( (std::string(SC_KERNEL_EVENT_PREFIX) + + std::string(name_) + "_next_posedge_event").c_str()), + m_next_negedge_event( (std::string(SC_KERNEL_EVENT_PREFIX) + + std::string(name_) + "_next_negedge_event").c_str()) +{ + init( sc_time( period_v_, period_tu_, simcontext() ), + duty_cycle_, + SC_ZERO_TIME, + true ); + + // posedge first + m_next_posedge_event.notify_internal( m_start_time ); +} + +sc_clock::sc_clock( const char* name_, + double period_v_, + sc_time_unit period_tu_, + double duty_cycle_, + double start_time_v_, + sc_time_unit start_time_tu_, + bool posedge_first_ ) : + base_type( name_ ), + m_period(), m_duty_cycle(), m_start_time(), m_posedge_first(), + m_posedge_time(), m_negedge_time(), + m_next_posedge_event( (std::string(SC_KERNEL_EVENT_PREFIX) + + std::string(name_) + "_next_posedge_event").c_str()), + m_next_negedge_event( (std::string(SC_KERNEL_EVENT_PREFIX) + + std::string(name_) + "_next_negedge_event").c_str()) +{ + init( sc_time( period_v_, period_tu_, simcontext() ), + duty_cycle_, + sc_time( start_time_v_, start_time_tu_, simcontext() ), + posedge_first_ ); + + if( posedge_first_ ) { + // posedge first + m_next_posedge_event.notify_internal( m_start_time ); + } else { + // negedge first + m_next_negedge_event.notify_internal( m_start_time ); + } +} + +// for backward compatibility with 1.0 +sc_clock::sc_clock( const char* name_, + double period_, // in default time units + double duty_cycle_, + double start_time_, // in default time units + bool posedge_first_ ) : + base_type( name_ ), + m_period(), m_duty_cycle(), m_start_time(), m_posedge_first(), + m_posedge_time(), m_negedge_time(), + m_next_posedge_event( (std::string(SC_KERNEL_EVENT_PREFIX) + + std::string(name_) + "_next_posedge_event").c_str()), + m_next_negedge_event( (std::string(SC_KERNEL_EVENT_PREFIX) + + std::string(name_) + "_next_negedge_event").c_str()) +{ + static bool warn_sc_clock=true; + if ( warn_sc_clock ) + { + warn_sc_clock = false; + SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, + "\n sc_clock(const char*, double, double, double, bool)\n" + " is deprecated use a form that includes sc_time or\n" + " sc_time_unit"); + } + + sc_time default_time = + sc_time::from_value( simcontext()->m_time_params->default_time_unit ); + + init( ( period_ * default_time ), + duty_cycle_, + ( start_time_ * default_time ), + posedge_first_ ); + + if( posedge_first_ ) { + // posedge first + m_next_posedge_event.notify_internal( m_start_time ); + } else { + // negedge first + m_next_negedge_event.notify_internal( m_start_time ); + } +} + + +//------------------------------------------------------------------------------ +//"sc_clock::before_end_of_elaboration" +// +// This callback is used to spawn the edge processes for this object instance. +// The processes are created here rather than the constructor for the object +// so that the processes are registered with the global simcontext rather +// than the scope of the clock's parent. +//------------------------------------------------------------------------------ +#if ( defined(_MSC_VER) && _MSC_VER < 1300 ) //VC++6.0 doesn't support sc_spawn with functor. +# define sc_clock_posedge_callback(ptr) sc_clock_posedge_callback + +# define sc_clock_negedge_callback(ptr) sc_clock_negedge_callback + +# define sc_spawn(a,b,c) { \ + sc_process_handle result(new sc_spawn_object<a>(a(this),b,c)); \ + } +#endif // ( defined(_MSC_VER) && _MSC_VER < 1300 ) + +void sc_clock::before_end_of_elaboration() +{ + std::string gen_base; + sc_spawn_options posedge_options; // Options for posedge process. + sc_spawn_options negedge_options; // Options for negedge process. + + posedge_options.spawn_method(); + posedge_options.dont_initialize(); + posedge_options.set_sensitivity(&m_next_posedge_event); + gen_base = basename(); + gen_base += "_posedge_action"; + sc_spawn(sc_clock_posedge_callback(this), + sc_gen_unique_name( gen_base.c_str() ), &posedge_options); + + negedge_options.spawn_method(); + negedge_options.dont_initialize(); + negedge_options.set_sensitivity(&m_next_negedge_event); + gen_base = basename(); + gen_base += "_negedge_action"; + sc_spawn( sc_clock_negedge_callback(this), + sc_gen_unique_name( gen_base.c_str() ), &negedge_options ); +} + +//clear VC++6.0 macros +#undef sc_clock_posedge_callback +#undef sc_clock_negedge_callback +#undef sc_spawn + +// destructor (does nothing) + +sc_clock::~sc_clock() +{} + +void sc_clock::register_port( sc_port_base& /*port*/, const char* if_typename_ ) +{ + std::string nm( if_typename_ ); + if( nm == typeid( sc_signal_inout_if<bool> ).name() ) { + SC_REPORT_ERROR(SC_ID_ATTEMPT_TO_BIND_CLOCK_TO_OUTPUT_, ""); + } +} + +void +sc_clock::write( const bool& /* value */ ) +{ + SC_REPORT_ERROR(SC_ID_ATTEMPT_TO_WRITE_TO_CLOCK_, ""); +} + +// interface methods + +// get the current time + +const sc_time& +sc_clock::time_stamp() +{ + return sc_time_stamp(); +} + + +// error reporting + +void +sc_clock::report_error( const char* id, const char* add_msg ) const +{ + char msg[BUFSIZ]; + if( add_msg != 0 ) { + std::sprintf( msg, "%s: clock '%s'", add_msg, name() ); + } else { + std::sprintf( msg, "clock '%s'", name() ); + } + SC_REPORT_ERROR( id, msg ); +} + + +void +sc_clock::init( const sc_time& period_, + double duty_cycle_, + const sc_time& start_time_, + bool posedge_first_ ) +{ + if( period_ == SC_ZERO_TIME ) { + report_error( SC_ID_CLOCK_PERIOD_ZERO_, + "increase the period" ); + } + m_period = period_; + m_posedge_first = posedge_first_; + + if( duty_cycle_ <= 0.0 || duty_cycle_ >= 1.0 ) { + m_duty_cycle = 0.5; + } else { + m_duty_cycle = duty_cycle_; + } + + m_negedge_time = m_period * m_duty_cycle; + m_posedge_time = m_period - m_negedge_time; + + if( m_negedge_time == SC_ZERO_TIME ) { + report_error( SC_ID_CLOCK_HIGH_TIME_ZERO_, + "increase the period or increase the duty cycle" ); + } + if( m_posedge_time == SC_ZERO_TIME ) { + report_error( SC_ID_CLOCK_LOW_TIME_ZERO_, + "increase the period or decrease the duty cycle" ); + } + + if( posedge_first_ ) { + this->m_cur_val = false; + this->m_new_val = false; + } else { + this->m_cur_val = true; + this->m_new_val = true; + } + + m_start_time = start_time_; + +} + +} // namespace sc_core + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: Bishnupriya Bhattacharya, Cadence Design Systems, + Andy Goodrich, Forte Design Systems, + 3 October, 2003 + Description of Modification: sc_clock inherits from sc_signal<bool> only + instead of sc_signal_in_if<bool> and sc_module. + The 2 methods posedge_action() and + negedge_action() are created using sc_spawn(). + boost::bind() is not required, instead a local + bind function can be used since the signatures + of the spawned functions are statically known. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + +// $Log: sc_clock.cpp,v $ +// Revision 1.7 2011/08/26 20:45:39 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +// Revision 1.6 2011/08/24 22:05:35 acg +// Torsten Maehne: initialization changes to remove warnings. +// +// Revision 1.5 2011/08/15 16:43:24 acg +// Torsten Maehne: changes to remove unused argument warnings. +// +// Revision 1.4 2011/03/12 21:07:42 acg +// Andy Goodrich: changes to kernel generated event support. +// +// Revision 1.3 2011/03/06 15:55:08 acg +// Andy Goodrich: Changes for named events. +// +// Revision 1.2 2011/02/18 20:23:45 acg +// Andy Goodrich: Copyright update. +// +// Revision 1.1.1.1 2006/12/15 20:20:04 acg +// SystemC 2.3 +// +// Revision 1.8 2006/04/18 23:36:50 acg +// Andy Goodrich: made add_trace_internal public until I can figure out +// how to do a friend specification for sc_trace in an environment where +// there are partial template and full template specifications for its +// arguments. +// +// Revision 1.7 2006/04/17 16:38:42 acg +// Andy Goodrich: added more context to the deprecation message for the +// sc_clock constructor. +// +// Revision 1.6 2006/01/25 00:31:11 acg +// Andy Goodrich: Changed over to use a standard message id of +// SC_ID_IEEE_1666_DEPRECATION for all deprecation messages. +// +// Revision 1.5 2006/01/24 20:43:24 acg +// Andy Goodrich: convert notify_delayed() calls into notify_internal() calls. +// notify_internal() is an implementation dependent version of notify_delayed() +// that is simpler, and does not trigger the deprecation warning one would get + +// Taf! diff --git a/ext/systemc/src/sysc/communication/sc_clock.h b/ext/systemc/src/sysc/communication/sc_clock.h new file mode 100644 index 000000000..634936ce6 --- /dev/null +++ b/ext/systemc/src/sysc/communication/sc_clock.h @@ -0,0 +1,275 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_clock.h -- The clock channel. + + Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21 + + CHANGE LOG IS AT THE END OF THE FILE + *****************************************************************************/ + +#ifndef SC_CLOCK_H +#define SC_CLOCK_H + + +#include "sysc/kernel/sc_module.h" +#include "sysc/communication/sc_signal.h" +#include "sysc/tracing/sc_trace.h" + +namespace sc_core { + +// ---------------------------------------------------------------------------- +// CLASS : sc_clock +// +// The clock channel. +// ---------------------------------------------------------------------------- + +class sc_clock + : public sc_signal<bool,SC_ONE_WRITER> +{ + typedef sc_signal<bool,SC_ONE_WRITER> base_type; +public: + + friend class sc_clock_posedge_callback; + friend class sc_clock_negedge_callback; + + // constructors + + sc_clock(); + + explicit sc_clock( const char* name_ ); + + sc_clock( const char* name_, + const sc_time& period_, + double duty_cycle_ = 0.5, + const sc_time& start_time_ = SC_ZERO_TIME, + bool posedge_first_ = true ); + + sc_clock( const char* name_, + double period_v_, + sc_time_unit period_tu_, + double duty_cycle_ = 0.5 ); + + sc_clock( const char* name_, + double period_v_, + sc_time_unit period_tu_, + double duty_cycle_, + double start_time_v_, + sc_time_unit start_time_tu_, + bool posedge_first_ = true ); + + // for backward compatibility with 1.0 + sc_clock( const char* name_, + double period_, // in default time units + double duty_cycle_ = 0.5, + double start_time_ = 0.0, // in default time units + bool posedge_first_ = true ); + + // destructor (does nothing) + virtual ~sc_clock(); + + virtual void register_port( sc_port_base&, const char* if_type ); + virtual void write( const bool& ); + + // get the period + const sc_time& period() const + { return m_period; } + + // get the duty cycle + double duty_cycle() const + { return m_duty_cycle; } + + + // get the current time / clock characteristics + + bool posedge_first() const + { return m_posedge_first; } + + sc_time start_time() const + { return m_start_time; } + + static const sc_time& time_stamp(); + + virtual const char* kind() const + { return "sc_clock"; } + + +#if 0 // @@@@#### REMOVE + // for backward compatibility with 1.0 + + sc_signal_in_if<bool>& signal() + { return *this; } + + const sc_signal_in_if<bool>& signal() const + { return *this; } + + static void start( const sc_time& duration ) + { sc_start( duration ); } + + static void start( double v, sc_time_unit tu ) + { sc_start( sc_time(v, tu) ); } + + static void start( double duration = -1 ) + { sc_start( duration ); } + + static void stop() + { sc_stop(); } +#endif + +protected: + + void before_end_of_elaboration(); + + // processes + void posedge_action(); + void negedge_action(); + + + // error reporting + void report_error( const char* id, const char* add_msg = 0 ) const; + + + void init( const sc_time&, double, const sc_time&, bool ); + + bool is_clock() const { return true; } + +protected: + + sc_time m_period; // the period of this clock + double m_duty_cycle; // the duty cycle (fraction of period) + sc_time m_start_time; // the start time of the first edge + bool m_posedge_first; // true if first edge is positive + sc_time m_posedge_time; // time till next positive edge + sc_time m_negedge_time; // time till next negative edge + + sc_event m_next_posedge_event; + sc_event m_next_negedge_event; + +private: + + // disabled + sc_clock( const sc_clock& ); + sc_clock& operator = ( const sc_clock& ); +}; + + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + +// processes + +inline +void +sc_clock::posedge_action() +{ + m_next_negedge_event.notify_internal( m_negedge_time ); + m_new_val = true; + request_update(); +} + +inline +void +sc_clock::negedge_action() +{ + m_next_posedge_event.notify_internal( m_posedge_time ); + m_new_val = false; + request_update(); +} + + +// ---------------------------------------------------------------------------- + +class sc_clock_posedge_callback { +public: + sc_clock_posedge_callback(sc_clock* target_p) : m_target_p(target_p) {} + inline void operator () () { m_target_p->posedge_action(); } + protected: + sc_clock* m_target_p; +}; + +class sc_clock_negedge_callback { + public: + sc_clock_negedge_callback(sc_clock* target_p) : m_target_p(target_p) {} + inline void operator () () { m_target_p->negedge_action(); } + protected: + sc_clock* m_target_p; +}; + + +} // namespace sc_core + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: Bishnupriya Bhattacharya, Cadence Design Systems, + 3 October, 2003 + Description of Modification: sc_clock inherits from sc_signal<bool> only + instead of sc_signal_in_if<bool> and sc_module. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ +//$Log: sc_clock.h,v $ +//Revision 1.5 2011/08/26 20:45:39 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +//Revision 1.4 2011/08/24 22:05:35 acg +// Torsten Maehne: initialization changes to remove warnings. +// +//Revision 1.3 2011/02/18 20:23:45 acg +// Andy Goodrich: Copyright update. +// +//Revision 1.2 2011/01/20 16:52:15 acg +// Andy Goodrich: changes for IEEE 1666 2011. +// +//Revision 1.1.1.1 2006/12/15 20:20:04 acg +//SystemC 2.3 +// +//Revision 1.5 2006/01/25 00:31:11 acg +// Andy Goodrich: Changed over to use a standard message id of +// SC_ID_IEEE_1666_DEPRECATION for all deprecation messages. +// +//Revision 1.4 2006/01/24 20:43:25 acg +// Andy Goodrich: convert notify_delayed() calls into notify_internal() calls. +// notify_internal() is an implementation dependent version of notify_delayed() +// that is simpler, and does not trigger the deprecation warning one would get +// using notify_delayed(). +// +//Revision 1.3 2006/01/18 21:42:26 acg +//Andy Goodrich: Changes for check writer support, and tightening up sc_clock +//port usage. +// +//Revision 1.2 2006/01/03 23:18:26 acg +//Changed copyright to include 2006. +// +//Revision 1.1.1.1 2005/12/19 23:16:43 acg +//First check in of SystemC 2.1 into its own archive. +// +//Revision 1.14 2005/06/10 22:43:55 acg +//Added CVS change log annotation. +// + +#endif + +// Taf! diff --git a/ext/systemc/src/sysc/communication/sc_clock_ports.h b/ext/systemc/src/sysc/communication/sc_clock_ports.h new file mode 100644 index 000000000..70ac80c1d --- /dev/null +++ b/ext/systemc/src/sysc/communication/sc_clock_ports.h @@ -0,0 +1,72 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_clock_ports.h -- The clock ports. + + Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21 + + CHANGE LOG IS AT THE END OF THE FILE + *****************************************************************************/ + +#ifndef SC_CLOCK_PORTS_H +#define SC_CLOCK_PORTS_H + + +#include "sysc/communication/sc_signal_ports.h" + +namespace sc_core { + +// ---------------------------------------------------------------------------- +// The clock ports. +// +// (Provided for backward compatibility reasons.) +// ---------------------------------------------------------------------------- + +typedef sc_in<bool> sc_in_clk; +typedef sc_inout<bool> sc_inout_clk; +typedef sc_out<bool> sc_out_clk; + +} // namespace sc_core + +//$Log: sc_clock_ports.h,v $ +//Revision 1.3 2011/08/26 20:45:39 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +//Revision 1.2 2011/02/18 20:23:45 acg +// Andy Goodrich: Copyright update. +// +//Revision 1.1.1.1 2006/12/15 20:20:04 acg +//SystemC 2.3 +// +//Revision 1.2 2006/01/03 23:18:26 acg +//Changed copyright to include 2006. +// +//Revision 1.1.1.1 2005/12/19 23:16:43 acg +//First check in of SystemC 2.1 into its own archive. +// +//Revision 1.8 2005/06/10 22:43:55 acg +//Added CVS change log annotation. +// + +#endif + +// Taf! diff --git a/ext/systemc/src/sysc/communication/sc_communication_ids.h b/ext/systemc/src/sysc/communication/sc_communication_ids.h new file mode 100644 index 000000000..fe9995775 --- /dev/null +++ b/ext/systemc/src/sysc/communication/sc_communication_ids.h @@ -0,0 +1,164 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_communication_ids.h -- Report ids for the communication code. + + Original Author: Martin Janssen, Synopsys, Inc., 2002-01-17 + + CHANGE LOG IS AT THE END OF THE FILE + *****************************************************************************/ + +#ifndef SC_COMMUNICATION_IDS_H +#define SC_COMMUNICATION_IDS_H + + +#include "sysc/utils/sc_report.h" + + +// ---------------------------------------------------------------------------- +// Report ids (communication) +// +// Report ids in the range of 100-199. +// ---------------------------------------------------------------------------- + +#ifndef SC_DEFINE_MESSAGE +#define SC_DEFINE_MESSAGE(id,unused1,unused2) \ + namespace sc_core { extern const char id[]; } +namespace sc_core { + extern const char SC_ID_REGISTER_ID_FAILED_[]; // in sc_report_handler.cpp +} // namespace sc_core +#endif + +SC_DEFINE_MESSAGE( SC_ID_PORT_OUTSIDE_MODULE_, 100, + "port specified outside of module" ) +SC_DEFINE_MESSAGE( SC_ID_CLOCK_PERIOD_ZERO_, 101, + "sc_clock period is zero" ) +SC_DEFINE_MESSAGE( SC_ID_CLOCK_HIGH_TIME_ZERO_, 102, + "sc_clock high time is zero" ) +SC_DEFINE_MESSAGE( SC_ID_CLOCK_LOW_TIME_ZERO_, 103, + "sc_clock low time is zero" ) +SC_DEFINE_MESSAGE( SC_ID_MORE_THAN_ONE_FIFO_READER_, 104, + "sc_fifo<T> cannot have more than one reader" ) +SC_DEFINE_MESSAGE( SC_ID_MORE_THAN_ONE_FIFO_WRITER_, 105, + "sc_fifo<T> cannot have more than one writer" ) +SC_DEFINE_MESSAGE( SC_ID_INVALID_FIFO_SIZE_, 106, + "sc_fifo<T> must have a size of at least 1" ) +SC_DEFINE_MESSAGE( SC_ID_BIND_IF_TO_PORT_, 107, + "bind interface to port failed" ) +SC_DEFINE_MESSAGE( SC_ID_BIND_PORT_TO_PORT_, 108, + "bind parent port to port failed" ) +SC_DEFINE_MESSAGE( SC_ID_COMPLETE_BINDING_, 109, + "complete binding failed" ) +SC_DEFINE_MESSAGE( SC_ID_INSERT_PORT_, 110, + "insert port failed" ) +SC_DEFINE_MESSAGE( SC_ID_REMOVE_PORT_, 111, + "remove port failed" ) +SC_DEFINE_MESSAGE( SC_ID_GET_IF_, 112, + "get interface failed" ) +SC_DEFINE_MESSAGE( SC_ID_INSERT_PRIM_CHANNEL_, 113, + "insert primitive channel failed" ) +SC_DEFINE_MESSAGE( SC_ID_REMOVE_PRIM_CHANNEL_, 114, + "remove primitive channel failed" ) +SC_DEFINE_MESSAGE( SC_ID_MORE_THAN_ONE_SIGNAL_DRIVER_, 115, + "sc_signal<T> cannot have more than one driver" ) +SC_DEFINE_MESSAGE( SC_ID_NO_DEFAULT_EVENT_, 116, + "channel doesn't have a default event" ) +SC_DEFINE_MESSAGE( SC_ID_RESOLVED_PORT_NOT_BOUND_, 117, + "resolved port not bound to resolved signal" ) +SC_DEFINE_MESSAGE( SC_ID_FIND_EVENT_, 118, + "find event failed" ) +SC_DEFINE_MESSAGE( SC_ID_INVALID_SEMAPHORE_VALUE_, 119, + "sc_semaphore requires an initial value >= 0" ) +SC_DEFINE_MESSAGE( SC_ID_SC_EXPORT_HAS_NO_INTERFACE_, 120, + "sc_export instance has no interface" ) +SC_DEFINE_MESSAGE( SC_ID_INSERT_EXPORT_, 121, + "insert sc_export failed" ) +SC_DEFINE_MESSAGE( SC_ID_SC_EXPORT_NOT_REGISTERED_, 123, + "remove sc_export failed, sc_export not registered" ) +SC_DEFINE_MESSAGE( SC_ID_SC_EXPORT_NOT_BOUND_AFTER_CONSTRUCTION_, 124, + "sc_export instance not bound to interface at end of construction" ) +SC_DEFINE_MESSAGE( SC_ID_ATTEMPT_TO_WRITE_TO_CLOCK_, 125, + "attempt to write the value of an sc_clock instance" ) +SC_DEFINE_MESSAGE( SC_ID_SC_EXPORT_ALREADY_BOUND_, 126, + "sc_export instance already bound" ) +SC_DEFINE_MESSAGE( SC_ID_OPERATION_ON_NON_SPECIALIZED_SIGNAL_, 127, + "attempted specalized signal operation on non-specialized signal" ) +SC_DEFINE_MESSAGE( SC_ID_ATTEMPT_TO_BIND_CLOCK_TO_OUTPUT_, 128, + "attempted to bind sc_clock instance to sc_inout or sc_out" ) +SC_DEFINE_MESSAGE( SC_ID_NO_ASYNC_UPDATE_, 129, + "this build has no asynchronous update support" ) + +/* +$Log: sc_communication_ids.h,v $ +Revision 1.5 2011/08/26 20:45:39 acg + Andy Goodrich: moved the modification log to the end of the file to + eliminate source line number skew when check-ins are done. + +Revision 1.4 2011/04/19 02:36:26 acg + Philipp A. Hartmann: new aysnc_update and mutex support. + +Revision 1.3 2011/02/18 20:23:45 acg + Andy Goodrich: Copyright update. + +Revision 1.2 2011/02/14 17:50:16 acg + Andy Goodrich: testing for sc_port and sc_export instantiations during + end of elaboration and issuing appropriate error messages. + +Revision 1.1.1.1 2006/12/15 20:20:04 acg +SystemC 2.3 + +Revision 1.5 2006/01/25 00:31:11 acg + Andy Goodrich: Changed over to use a standard message id of + SC_ID_IEEE_1666_DEPRECATION for all deprecation messages. + +Revision 1.4 2006/01/24 20:46:31 acg +Andy Goodrich: changes to eliminate use of deprecated features. For instance, +using notify(SC_ZERO_TIME) in place of notify_delayed(). + +Revision 1.3 2006/01/18 21:42:26 acg +Andy Goodrich: Changes for check writer support, and tightening up sc_clock +port usage. + +Revision 1.2 2006/01/03 23:18:26 acg +Changed copyright to include 2006. + +Revision 1.1.1.1 2005/12/19 23:16:43 acg +First check in of SystemC 2.1 into its own archive. + +Revision 1.12 2005/04/03 22:52:51 acg +Namespace changes. + +Revision 1.11 2005/03/21 22:31:32 acg +Changes to sc_core namespace. + +Revision 1.10 2004/10/28 00:21:48 acg +Added check that sc_export instances are not bound twice. + +Revision 1.9 2004/09/27 21:02:54 acg +Andy Goodrich - Forte Design Systems, Inc. + - Added a $Log comment so that CVS checkin comments will appear in + checked out source. + +*/ + +#endif + +// Taf! diff --git a/ext/systemc/src/sysc/communication/sc_event_finder.cpp b/ext/systemc/src/sysc/communication/sc_event_finder.cpp new file mode 100644 index 000000000..25d16a1f5 --- /dev/null +++ b/ext/systemc/src/sysc/communication/sc_event_finder.cpp @@ -0,0 +1,113 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_event_finder.cpp -- + + Original Author: Martin Janssen, Synopsys, Inc. + Stan Y. Liao, Synopsys, Inc., 2001-05-21 + + CHANGE LOG IS AT THE END OF THE FILE + *****************************************************************************/ + +#include "sysc/communication/sc_event_finder.h" + +namespace sc_core { + +// ---------------------------------------------------------------------------- +// CLASS : sc_event_finder +// +// Event finder base class. +// ---------------------------------------------------------------------------- + +// error reporting + +void +sc_event_finder::report_error( const char* id, const char* add_msg ) const +{ + char msg[BUFSIZ]; + if( add_msg != 0 ) { + std::sprintf( msg, "%s: port '%s' (%s)", + add_msg, m_port.name(), m_port.kind() ); + } else { + std::sprintf( msg, "port '%s' (%s)", m_port.name(), m_port.kind() ); + } + SC_REPORT_ERROR( id, msg ); +} + + +// constructor + +sc_event_finder::sc_event_finder( const sc_port_base& port_ ) +: m_port( port_ ) +{ +} + + +// destructor (does nothing) + +sc_event_finder::~sc_event_finder() +{} + +} // namespace sc_core + +// $Log: sc_event_finder.cpp,v $ +// Revision 1.3 2011/08/26 20:45:39 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +// Revision 1.2 2011/02/18 20:23:45 acg +// Andy Goodrich: Copyright update. +// +// Revision 1.1.1.1 2006/12/15 20:20:04 acg +// SystemC 2.3 +// +// Revision 1.7 2006/02/02 23:42:37 acg +// Andy Goodrich: implemented a much better fix to the sc_event_finder +// proliferation problem. This new version allocates only a single event +// finder for each port for each type of event, e.g., pos(), neg(), and +// value_change(). The event finder persists as long as the port does, +// which is what the LRM dictates. Because only a single instance is +// allocated for each event type per port there is not a potential +// explosion of storage as was true in the 2.0.1/2.1 versions. +// +// Revision 1.6 2006/02/02 21:26:34 acg +// Andy Goodrich: pulled out the check I just stuck into the +// sc_event_finder::free_instances() method. It turns out the LRM says that +// sc_event_finder instances are valid as long as the sc_module hierarchy is +// valid, so we can't give the user a call to free the instances. +// +// Revision 1.5 2006/02/02 21:10:52 acg +// Andy Goodrich: added check for end of elaboration to the static method +// sc_event_finder::free_instances(). This will allow the method to be +// made public if that is desired. +// +// Revision 1.4 2006/02/02 20:43:09 acg +// Andy Goodrich: Added an existence linked list to sc_event_finder so that +// the dynamically allocated instances can be freed after port binding +// completes. This replaces the individual deletions in ~sc_bind_ef, as these +// caused an exception if an sc_event_finder instance was used more than +// once, due to a double freeing of the instance. +// +// Revision 1.3 2006/01/13 18:47:41 acg +// Added $Log command so that CVS comments are reproduced in the source. +// + +// Taf! diff --git a/ext/systemc/src/sysc/communication/sc_event_finder.h b/ext/systemc/src/sysc/communication/sc_event_finder.h new file mode 100644 index 000000000..15205553f --- /dev/null +++ b/ext/systemc/src/sysc/communication/sc_event_finder.h @@ -0,0 +1,178 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_event_finder.h -- + + Original Author: Martin Janssen, Synopsys, Inc. + Stan Y. Liao, Synopsys, Inc., 2001-05-21 + + CHANGE LOG IS AT THE END OF THE FILE + *****************************************************************************/ + +#ifndef SC_EVENT_FINDER +#define SC_EVENT_FINDER + + +#include "sysc/communication/sc_port.h" + +namespace sc_core { + +// ---------------------------------------------------------------------------- +// CLASS : sc_event_finder +// +// Event finder base class. +// ---------------------------------------------------------------------------- + +class sc_event_finder +{ + friend class sc_simcontext; + +public: + + const sc_port_base& port() const + { return m_port; } + + // destructor (does nothing) + virtual ~sc_event_finder(); + + virtual const sc_event& find_event( sc_interface* if_p = 0 ) const = 0; + +protected: + + // constructor + sc_event_finder( const sc_port_base& ); + + // error reporting + void report_error( const char* id, const char* add_msg = 0 ) const; + + +private: + const sc_port_base& m_port; // port providing the event. + +private: + + // disabled + sc_event_finder(); + sc_event_finder( const sc_event_finder& ); + sc_event_finder& operator = ( const sc_event_finder& ); +}; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_event_finder_t<IF> +// +// Interface specific event finder class. +// ---------------------------------------------------------------------------- + +template <class IF> +class sc_event_finder_t +: public sc_event_finder +{ +public: + + // constructor + + sc_event_finder_t( const sc_port_base& port_, + const sc_event& (IF::*event_method_) () const ) + : sc_event_finder( port_ ), m_event_method( event_method_ ) + {} + + // destructor (does nothing) + + virtual ~sc_event_finder_t() + {} + + virtual const sc_event& find_event( sc_interface* if_p = 0 ) const; + +private: + + const sc_event& (IF::*m_event_method) () const; + +private: + + // disabled + sc_event_finder_t(); + sc_event_finder_t( const sc_event_finder_t<IF>& ); + sc_event_finder_t<IF>& operator = ( const sc_event_finder_t<IF>& ); +}; + + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + +template <class IF> +inline +const sc_event& +sc_event_finder_t<IF>::find_event( sc_interface* if_p ) const +{ + const IF* iface = ( if_p ) ? DCAST<const IF*>( if_p ) : + DCAST<const IF*>( port().get_interface() ); + if( iface == 0 ) { + report_error( SC_ID_FIND_EVENT_, "port is not bound" ); + } + return (CCAST<IF*>( iface )->*m_event_method) (); +} + +} // namespace sc_core + +//$Log: sc_event_finder.h,v $ +//Revision 1.3 2011/08/26 20:45:39 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +//Revision 1.2 2011/02/18 20:23:45 acg +// Andy Goodrich: Copyright update. +// +//Revision 1.1.1.1 2006/12/15 20:20:04 acg +//SystemC 2.3 +// +//Revision 1.4 2006/02/02 23:42:37 acg +// Andy Goodrich: implemented a much better fix to the sc_event_finder +// proliferation problem. This new version allocates only a single event +// finder for each port for each type of event, e.g., pos(), neg(), and +// value_change(). The event finder persists as long as the port does, +// which is what the LRM dictates. Because only a single instance is +// allocated for each event type per port there is not a potential +// explosion of storage as was true in the 2.0.1/2.1 versions. +// +//Revision 1.3 2006/02/02 20:43:09 acg +// Andy Goodrich: Added an existence linked list to sc_event_finder so that +// the dynamically allocated instances can be freed after port binding +// completes. This replaces the individual deletions in ~sc_bind_ef, as these +// caused an exception if an sc_event_finder instance was used more than +// once, due to a double freeing of the instance. +// +//Revision 1.2 2006/01/03 23:18:26 acg +//Changed copyright to include 2006. +// +//Revision 1.1.1.1 2005/12/19 23:16:43 acg +//First check in of SystemC 2.1 into its own archive. +// +//Revision 1.10 2005/09/15 23:01:51 acg +//Added std:: prefix to appropriate methods and types to get around +//issues with the Edison Front End. +// +//Revision 1.9 2005/06/10 22:43:55 acg +//Added CVS change log annotation. +// + +#endif + +// Taf! diff --git a/ext/systemc/src/sysc/communication/sc_event_queue.cpp b/ext/systemc/src/sysc/communication/sc_event_queue.cpp new file mode 100644 index 000000000..7e1ebc864 --- /dev/null +++ b/ext/systemc/src/sysc/communication/sc_event_queue.cpp @@ -0,0 +1,146 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_event_queue.cpp -- Event Queue Support + + Original Author: Stuart Swan, Cadence Inc. + + CHANGE LOG IS AT THE END OF THE FILE + *****************************************************************************/ + +#include "sysc/communication/sc_event_queue.h" +#include "sysc/kernel/sc_method_process.h" + +namespace sc_core { + +static int +sc_time_compare( const void* p1, const void* p2 ) +{ + const sc_time* t1 = static_cast<const sc_time*>( p1 ); + const sc_time* t2 = static_cast<const sc_time*>( p2 ); + + if( *t1 < *t2 ) { + return 1; + } else if( *t1 > *t2 ) { + return -1; + } else { + return 0; + } +} + +sc_event_queue::sc_event_queue( sc_module_name name_ ) + : sc_module( name_ ), + m_ppq( 128, sc_time_compare ), + m_e( (std::string(SC_KERNEL_EVENT_PREFIX)+"_event").c_str() ), + m_change_stamp(0), + m_pending_delta(0) +{ + SC_METHOD( fire_event ); + sensitive << m_e; + dont_initialize(); +} + +sc_event_queue::~sc_event_queue() +{ + while (m_ppq.size() > 0) { + delete m_ppq.extract_top(); + } +} + +void sc_event_queue::cancel_all() +{ + m_pending_delta = 0; + while( m_ppq.size() > 0 ) + delete m_ppq.extract_top(); + m_e.cancel(); +} + +void sc_event_queue::notify (const sc_time& when) +{ + m_change_stamp = simcontext()->change_stamp(); + sc_time* t = new sc_time( when+sc_time_stamp() ); + if ( m_ppq.size()==0 || *t < *m_ppq.top() ) { + m_e.notify( when ); + } + m_ppq.insert( t ); +} + +void sc_event_queue::fire_event() +{ + if ( m_ppq.empty() ) { // event has been cancelled + return; + } + sc_time* t = m_ppq.extract_top(); + assert( *t==sc_time_stamp() ); + delete t; + + if ( m_ppq.size() > 0 ) { + m_e.notify( *m_ppq.top() - sc_time_stamp() ); + } +} + +} // namespace sc_core + +// $Log: sc_event_queue.cpp,v $ +// Revision 1.9 2011/08/26 22:45:53 acg +// Torsten Maehne: remove redundant initialization assignment. +// +// Revision 1.8 2011/08/26 21:44:58 acg +// Andy Goodrich: fix internal event naming. +// +// Revision 1.7 2011/08/26 20:45:39 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +// Revision 1.6 2011/08/24 22:05:35 acg +// Torsten Maehne: initialization changes to remove warnings. +// +// Revision 1.5 2011/04/08 18:22:46 acg +// Philipp A. Hartmann: use the context of the primitive channel to get +// the change stamp value. +// +// Revision 1.4 2011/04/05 20:48:09 acg +// Andy Goodrich: changes to make sure that event(), posedge() and negedge() +// only return true if the clock has not moved. +// +// Revision 1.3 2011/02/18 20:23:45 acg +// Andy Goodrich: Copyright update. +// +// Revision 1.2 2010/07/22 20:02:30 acg +// Andy Goodrich: bug fixes. +// +// Revision 1.1.1.1 2006/12/15 20:20:04 acg +// SystemC 2.3 +// +// Revision 1.5 2006/11/28 20:30:48 acg +// Andy Goodrich: updated from 2.2 source. sc_event_queue constructors +// collapsed into a single constructor with an optional argument to get +// the sc_module_name stack done correctly. Class name prefixing added +// to sc_semaphore calls to wait() to keep gcc 4.x happy. +// +// Revision 1.4 2006/01/26 21:00:50 acg +// Andy Goodrich: conversion to use sc_event::notify(SC_ZERO_TIME) instead of +// sc_event::notify_delayed() +// +// Revision 1.3 2006/01/13 18:47:42 acg +// Added $Log command so that CVS comments are reproduced in the source. + +// taf diff --git a/ext/systemc/src/sysc/communication/sc_event_queue.h b/ext/systemc/src/sysc/communication/sc_event_queue.h new file mode 100644 index 000000000..4438de9ef --- /dev/null +++ b/ext/systemc/src/sysc/communication/sc_event_queue.h @@ -0,0 +1,181 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_event_queue.h -- Event Queue Facility Definitions + + Original Author: Ulli Holtmann, Synopsys, Inc. + + CHANGE LOG IS AT THE END OF THE FILE + *****************************************************************************/ + +#ifndef SC_EVENT_QUEUE_H +#define SC_EVENT_QUEUE_H + + +/* + Class sc_event_queue + + A queue that can contain any number of pending notifications. + The queue has a similiar interface like an sc_event but has different + semantics: it can carry any number of pending notification. The + general rule is that _every_ call to notify() will cause a + corresponding trigger at the specified wall-clock time that can be + observed (the only exception is when notifications are explicitly + cancelled). + + If multiple notifications are pending at the same wall-clock + time, then the event queue will trigger in different delta cycles + in order to ensure that sensitive processes can notice each + trigger. The first trigger happens in the earliest delta cycle + possible which is the same behavior as a normal timed event. + +*/ + +#include "sysc/communication/sc_interface.h" +#include "sysc/kernel/sc_module.h" +#include "sysc/kernel/sc_event.h" +#include "sysc/communication/sc_port.h" + +namespace sc_core { + + +// --------------------------------------------------------------------------- +// sc_event_queue_if +// --------------------------------------------------------------------------- + +class sc_event_queue_if : public virtual sc_interface +{ +public: + virtual void notify (double when, sc_time_unit base) =0; + virtual void notify (const sc_time& when) =0; + virtual void cancel_all() =0; +}; + +// --------------------------------------------------------------------------- +// sc_event_queue: a queue that can contain any number of pending +// delta, or timed events. +// --------------------------------------------------------------------------- + +class sc_event_queue: + public sc_event_queue_if, + public sc_module +{ + public: + + SC_HAS_PROCESS( sc_event_queue ); + + sc_event_queue( sc_module_name name_ = sc_gen_unique_name("event_queue") ); + ~sc_event_queue(); + + // API of sc_object + inline virtual const char* kind() const { return "sc_event_queue"; } + + // + // API of sc_event_queue_if + // + inline virtual void notify (double when, sc_time_unit base); + virtual void notify (const sc_time& when); + virtual void cancel_all(); + + // + // API for using the event queue in processes + // + + // get the default event + inline virtual const sc_event& default_event() const; + +/* + // + // Possible extensions: + // + + // Cancel an events at a specific time + void cancel (const sc_time& when); + void cancel (double when, sc_time_unit base); + + // How many events are pending altogether? + unsigned pending() const; + + // How many events are pending at the specific time? + unsigned pending(const sc_time& when) const; + unsigned pending(double when, sc_time_unit base) const; +*/ + + private: + void fire_event(); + + private: + sc_ppq<sc_time*> m_ppq; + sc_event m_e; + sc_dt::uint64 m_change_stamp; + unsigned m_pending_delta; +}; + +inline +void sc_event_queue::notify (double when, sc_time_unit base ) +{ + notify( sc_time(when,base) ); +} + +inline +const sc_event& sc_event_queue::default_event() const +{ + return m_e; +} + + +// +// Using event queue as a port +// +typedef sc_port<sc_event_queue_if,1,SC_ONE_OR_MORE_BOUND> sc_event_queue_port; + +} // namespace sc_core + +// $Log: sc_event_queue.h,v $ +// Revision 1.5 2011/08/26 20:45:40 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +// Revision 1.4 2011/04/05 20:48:09 acg +// Andy Goodrich: changes to make sure that event(), posedge() and negedge() +// only return true if the clock has not moved. +// +// Revision 1.3 2011/02/18 20:23:45 acg +// Andy Goodrich: Copyright update. +// +// Revision 1.2 2008/05/20 16:45:52 acg +// Andy Goodrich: changed which unique name generator is used from the +// global one to the one for sc_modules. +// +// Revision 1.1.1.1 2006/12/15 20:20:04 acg +// SystemC 2.3 +// +// Revision 1.4 2006/11/28 20:30:48 acg +// Andy Goodrich: updated from 2.2 source. sc_event_queue constructors +// collapsed into a single constructor with an optional argument to get +// the sc_module_name stack done correctly. Class name prefixing added +// to sc_semaphore calls to wait() to keep gcc 4.x happy. +// +// Revision 1.3 2006/01/13 18:47:42 acg +// Added $Log command so that CVS comments are reproduced in the source. +// + +#endif // SC_EVENT_QUEUE_H diff --git a/ext/systemc/src/sysc/communication/sc_export.cpp b/ext/systemc/src/sysc/communication/sc_export.cpp new file mode 100644 index 000000000..2da7a1533 --- /dev/null +++ b/ext/systemc/src/sysc/communication/sc_export.cpp @@ -0,0 +1,305 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_export.cpp -- + + Original Author: Bishnupriya Bhattachary, Cadence, Design Systems, + 25 August, 2003 + + CHANGE LOG IS AT THE END OF THE FILE + *****************************************************************************/ + +#include "sysc/communication/sc_export.h" +#include "sysc/kernel/sc_simcontext.h" +#include "sysc/kernel/sc_module.h" +#include "sysc/kernel/sc_object_int.h" + +namespace sc_core { + +// ---------------------------------------------------------------------------- +// CLASS : sc_export_base +// +// ---------------------------------------------------------------------------- + +sc_export_base::sc_export_base() : sc_object(sc_gen_unique_name("export")) +{ + simcontext()->get_export_registry()->insert(this); +} + +sc_export_base::sc_export_base(const char* name_) : sc_object(name_) +{ + simcontext()->get_export_registry()->insert(this); +} + +sc_export_base::~sc_export_base() +{ + simcontext()->get_export_registry()->remove(this); +} + +// called by construction_done() (does nothing by default) + +void +sc_export_base::before_end_of_elaboration() +{ +} + +// called when construction is done + +void +sc_export_base::construction_done() +{ + if ( get_interface() == 0 ) + { + report_error( SC_ID_SC_EXPORT_NOT_BOUND_AFTER_CONSTRUCTION_, 0); + } + + sc_module* parent = static_cast<sc_module*>( get_parent_object() ); + sc_object::hierarchy_scope scope( parent ); + before_end_of_elaboration(); +} + +// called by elaboration_done() (does nothing by default) + +void +sc_export_base::end_of_elaboration() +{} + +// called when elaboration is done + +void +sc_export_base::elaboration_done() +{ + sc_module* parent = static_cast<sc_module*>( get_parent_object() ); + sc_object::hierarchy_scope scope( parent ); + end_of_elaboration(); +} + +// called by start_simulation (does nothing) + +void +sc_export_base::start_of_simulation() +{} + +// called before simulation starts + +void +sc_export_base::start_simulation() +{ + sc_module* parent = static_cast<sc_module*>( get_parent_object() ); + sc_object::hierarchy_scope scope( parent ); + start_of_simulation(); +} + +// called by simulation_done (does nothing) + +void +sc_export_base::end_of_simulation() +{} + +// called after simulation ends + +void +sc_export_base::simulation_done() +{ + sc_module* parent = static_cast<sc_module*>( get_parent_object() ); + sc_object::hierarchy_scope scope( parent ); + end_of_simulation(); +} + +void +sc_export_base::report_error( const char* id, const char* add_msg ) const +{ + char msg[BUFSIZ]; + if( add_msg != 0 ) { + std::sprintf( msg, "%s: export '%s' (%s)", add_msg, name(), kind() ); + } else { + std::sprintf( msg, "export '%s' (%s)", name(), kind() ); + } + SC_REPORT_ERROR( id, msg ); +} + + +// ---------------------------------------------------------------------------- +// CLASS : sc_export_registry +// +// Registry for all exports. +// FOR INTERNAL USE ONLY! +// ---------------------------------------------------------------------------- + +void +sc_export_registry::insert( sc_export_base* export_ ) +{ + if( sc_is_running() ) { + export_->report_error(SC_ID_INSERT_EXPORT_, "simulation running"); + } + + if( m_simc->elaboration_done() ) { + export_->report_error(SC_ID_INSERT_EXPORT_, "elaboration done"); + } + + +#ifdef DEBUG_SYSTEMC + // check if port_ is already inserted + for( int i = size() - 1; i >= 0; -- i ) { + if( export_ == m_export_vec[i] ) { + export_->report_error( SC_ID_INSERT_EXPORT_, + "export already inserted "); + } + } +#endif + +/* + //TBD: maybe we want to do this stuf for later + + // append the port to the current module's vector of ports + sc_module* curr_module = m_simc->hierarchy_curr(); + if( curr_module == 0 ) { + port_->report_error( SC_ID_PORT_OUTSIDE_MODULE_ ); + } + curr_module->append_port( port_ ); +*/ + + // insert + m_export_vec.push_back( export_ ); +} + +void +sc_export_registry::remove( sc_export_base* export_ ) +{ + if (size()==0) return; + int i; + for( i = size() - 1; i >= 0; -- i ) { + if( export_ == m_export_vec[i] ) { + break; + } + } + if( i == -1 ) { + export_->report_error( SC_ID_SC_EXPORT_NOT_REGISTERED_ ); + } + + // remove + m_export_vec[i] = m_export_vec[size() - 1]; + m_export_vec.resize(size()-1); +} + +// constructor + +sc_export_registry::sc_export_registry( sc_simcontext& simc_ ) +: m_construction_done(0), + m_export_vec(), + m_simc( &simc_ ) +{ +} + + +// destructor + +sc_export_registry::~sc_export_registry() +{ +} + +// called when construction is done + +bool +sc_export_registry::construction_done() +{ + if( m_construction_done == size() ) + // nothing has been updated + return true; + + for( int i = size()-1; i >= m_construction_done; --i ) { + m_export_vec[i]->construction_done(); + } + + m_construction_done = size(); + return false; +} + +// called when elaboration is done + +void +sc_export_registry::elaboration_done() +{ + for( int i = size() - 1; i >= 0; -- i ) { + m_export_vec[i]->elaboration_done(); + } +} + +// called before simulation begins + +void +sc_export_registry::start_simulation() +{ + for( int i = size() - 1; i >= 0; -- i ) { + m_export_vec[i]->start_simulation(); + } +} + +void +sc_export_registry::simulation_done() +{ + for( int i = size() - 1; i >= 0; -- i ) { + m_export_vec[i]->simulation_done(); + } +} + +} // namespace sc_core + +// $Log: sc_export.cpp,v $ +// Revision 1.8 2011/08/26 20:45:40 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +// Revision 1.7 2011/08/24 22:05:36 acg +// Torsten Maehne: initialization changes to remove warnings. +// +// Revision 1.6 2011/05/09 04:07:37 acg +// Philipp A. Hartmann: +// (1) Restore hierarchy in all phase callbacks. +// (2) Ensure calls to before_end_of_elaboration. +// +// Revision 1.5 2011/02/18 20:31:05 acg +// Philipp A. Hartmann: added error messages for calls that cannot be done +// after elaboration. +// +// Revision 1.4 2011/02/18 20:23:45 acg +// Andy Goodrich: Copyright update. +// +// Revision 1.3 2011/02/18 20:07:04 acg +// Philipp A. Hartmann: Patch to revert to sprintf from snprintf to keep +// some versions of MSVC happy. +// +// Revision 1.2 2011/02/14 17:50:16 acg +// Andy Goodrich: testing for sc_port and sc_export instantiations during +// end of elaboration and issuing appropriate error messages. +// +// Revision 1.1.1.1 2006/12/15 20:20:04 acg +// SystemC 2.3 +// +// Revision 1.4 2006/01/26 21:00:50 acg +// Andy Goodrich: conversion to use sc_event::notify(SC_ZERO_TIME) instead of +// sc_event::notify_delayed() +// +// Revision 1.3 2006/01/13 18:47:42 acg +// Added $Log command so that CVS comments are reproduced in the source. +// + +// Taf! diff --git a/ext/systemc/src/sysc/communication/sc_export.h b/ext/systemc/src/sysc/communication/sc_export.h new file mode 100644 index 000000000..81edc8cc2 --- /dev/null +++ b/ext/systemc/src/sysc/communication/sc_export.h @@ -0,0 +1,299 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_export.h -- Base classes of all export classes. + + Original Author: Andy Goodrich, Forte Design Systems + Bishnupriya Bhattacharya, Cadence Design Systems + + CHANGE LOG IS AT THE END OF THE FILE + *****************************************************************************/ + +#ifndef SC_EXPORT_H +#define SC_EXPORT_H +#include <typeinfo> + +#include "sysc/communication/sc_communication_ids.h" +#include "sysc/communication/sc_interface.h" +#include "sysc/kernel/sc_object.h" + +#if ! defined( SC_DISABLE_VIRTUAL_BIND ) +# define SC_VIRTUAL_ virtual +#else +# define SC_VIRTUAL_ /* non-virtual */ +#endif + +namespace sc_core { + +//============================================================================= +// CLASS : sc_export_base +// +// Abstract base class for class sc_export<IF>. +//============================================================================= + +class sc_export_base : public sc_object +{ + friend class sc_export_registry; +public: + + // typedefs + + typedef sc_export_base this_type; + +public: + + virtual sc_interface* get_interface() = 0; + virtual const sc_interface* get_interface() const = 0; + +protected: + + // constructors + + sc_export_base(); + sc_export_base(const char* name); + + // destructor + + virtual ~sc_export_base(); + +protected: + + // called when construction is done + virtual void before_end_of_elaboration(); + + // called when elaboration is done (does nothing by default) + virtual void end_of_elaboration(); + + // called before simulation starts (does nothing by default) + virtual void start_of_simulation(); + + // called after simulation ends (does nothing) + virtual void end_of_simulation(); + + virtual const char* if_typename() const = 0; + + // error reporting + void report_error( const char* id, const char* add_msg = 0) const; + +private: + + void construction_done(); + void elaboration_done(); + void start_simulation(); + void simulation_done(); + + // disabled + sc_export_base(const this_type&); + this_type& operator = (const this_type& ); + +}; + +//============================================================================= +// CLASS : sc_export +// +// Generic export class for other export classes. This +// class provides a binding point for access to an interface. +//============================================================================= +template<class IF> +class sc_export : public sc_export_base +{ + typedef sc_export<IF> this_type; + +public: // constructors: + sc_export() : sc_export_base() + { + m_interface_p = 0; + } + + explicit sc_export( const char* name_ ) : sc_export_base(name_) + { + m_interface_p = 0; + } + +public: // destructor: + virtual ~sc_export() + { + } + +public: // interface access: + + virtual sc_interface* get_interface() + { + return m_interface_p; + } + + virtual const sc_interface* get_interface() const + { + return m_interface_p; + } + + const IF* operator -> () const { + if ( m_interface_p == 0 ) + { + SC_REPORT_ERROR(SC_ID_SC_EXPORT_HAS_NO_INTERFACE_,name()); + } + return m_interface_p; + } + + IF* operator -> () { + if ( m_interface_p == 0 ) + { + SC_REPORT_ERROR(SC_ID_SC_EXPORT_HAS_NO_INTERFACE_,name()); + } + return m_interface_p; + } + + operator IF& () + { + if ( m_interface_p == 0 ) + { + SC_REPORT_ERROR(SC_ID_SC_EXPORT_HAS_NO_INTERFACE_,name()); + } + return *m_interface_p; + } + operator const IF&() const + { return *const_cast<this_type*>(this); } + + +public: // binding: + SC_VIRTUAL_ void bind( IF& interface_ ) + { + if ( m_interface_p ) + { + SC_REPORT_ERROR(SC_ID_SC_EXPORT_ALREADY_BOUND_,name()); + } + else + { + m_interface_p = &interface_; + } + } + + void operator () ( IF& interface_ ) + { + this->bind(interface_); + } + +public: // identification: + virtual const char* kind() const { return "sc_export"; } + +protected: + const char* if_typename() const { + return typeid( IF ).name(); + } + +private: // disabled + sc_export( const this_type& ); + this_type& operator = ( const this_type& ); + +protected: // data fields: + IF* m_interface_p; // Interface this port provides. +}; + +// ---------------------------------------------------------------------------- +// CLASS : sc_export_registry +// +// Registry for all exports. +// FOR INTERNAL USE ONLY! +// ---------------------------------------------------------------------------- + +class sc_export_registry +{ + friend class sc_simcontext; + +public: + + void insert( sc_export_base* ); + void remove( sc_export_base* ); + + int size() const + { return m_export_vec.size(); } + +private: + + // constructor + explicit sc_export_registry( sc_simcontext& simc_ ); + + // destructor + ~sc_export_registry(); + + // called when construction is done + bool construction_done(); + + // called when elaboration is done + void elaboration_done(); + + // called before simulation starts + void start_simulation(); + + // called after simulation ends + void simulation_done(); + +private: + + int m_construction_done; + std::vector<sc_export_base*> m_export_vec; + sc_simcontext* m_simc; + +private: + + // disabled + sc_export_registry(); + sc_export_registry( const sc_export_registry& ); + sc_export_registry& operator = ( const sc_export_registry& ); +}; + +} // namespace sc_core + +#undef SC_VIRTUAL_ + +// $Log: sc_export.h,v $ +// Revision 1.7 2011/08/26 20:45:40 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +// Revision 1.6 2011/05/09 04:07:37 acg +// Philipp A. Hartmann: +// (1) Restore hierarchy in all phase callbacks. +// (2) Ensure calls to before_end_of_elaboration. +// +// Revision 1.5 2011/04/02 00:02:14 acg +// Philipp A. Hartmann: add const overload for sc_export::operator IF& +// +// Revision 1.4 2011/02/18 20:23:45 acg +// Andy Goodrich: Copyright update. +// +// Revision 1.3 2011/02/14 17:50:16 acg +// Andy Goodrich: testing for sc_port and sc_export instantiations during +// end of elaboration and issuing appropriate error messages. +// +// Revision 1.2 2011/01/20 16:52:15 acg +// Andy Goodrich: changes for IEEE 1666 2011. +// +// Revision 1.1.1.1 2006/12/15 20:20:04 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:47:42 acg +// Added $Log command so that CVS comments are reproduced in the source. +// + +#endif + +// Taf! diff --git a/ext/systemc/src/sysc/communication/sc_fifo.h b/ext/systemc/src/sysc/communication/sc_fifo.h new file mode 100644 index 000000000..868c0304e --- /dev/null +++ b/ext/systemc/src/sysc/communication/sc_fifo.h @@ -0,0 +1,479 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_fifo.h -- The sc_fifo<T> primitive channel class. + + Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21 + + CHANGE LOG IS AT THE END OF THE FILE + *****************************************************************************/ + +#ifndef SC_FIFO_H +#define SC_FIFO_H + + +#include "sysc/communication/sc_communication_ids.h" +#include "sysc/communication/sc_prim_channel.h" +#include "sysc/communication/sc_fifo_ifs.h" +#include "sysc/kernel/sc_event.h" +#include "sysc/kernel/sc_simcontext.h" +#include "sysc/tracing/sc_trace.h" +#include <typeinfo> + +namespace sc_core { + +// ---------------------------------------------------------------------------- +// CLASS : sc_fifo<T> +// +// The sc_fifo<T> primitive channel class. +// ---------------------------------------------------------------------------- + +template <class T> +class sc_fifo +: public sc_fifo_in_if<T>, + public sc_fifo_out_if<T>, + public sc_prim_channel +{ +public: + + // constructors + + explicit sc_fifo( int size_ = 16 ) + : sc_prim_channel( sc_gen_unique_name( "fifo" ) ), + m_data_read_event( + (std::string(SC_KERNEL_EVENT_PREFIX)+"_read_event").c_str()), + m_data_written_event( + (std::string(SC_KERNEL_EVENT_PREFIX)+"_write_event").c_str()) + { init( size_ ); } + + explicit sc_fifo( const char* name_, int size_ = 16 ) + : sc_prim_channel( name_ ), + m_data_read_event( + (std::string(SC_KERNEL_EVENT_PREFIX)+"_read_event").c_str()), + m_data_written_event( + (std::string(SC_KERNEL_EVENT_PREFIX)+"_write_event").c_str()) + { init( size_ ); } + + + // destructor + + virtual ~sc_fifo() + { delete [] m_buf; } + + + // interface methods + + virtual void register_port( sc_port_base&, const char* ); + + + // blocking read + virtual void read( T& ); + virtual T read(); + + // non-blocking read + virtual bool nb_read( T& ); + + + // get the number of available samples + + virtual int num_available() const + { return ( m_num_readable - m_num_read ); } + + + // get the data written event + + virtual const sc_event& data_written_event() const + { return m_data_written_event; } + + + // blocking write + virtual void write( const T& ); + + // non-blocking write + virtual bool nb_write( const T& ); + + + // get the number of free spaces + + virtual int num_free() const + { return ( m_size - m_num_readable - m_num_written ); } + + + // get the data read event + + virtual const sc_event& data_read_event() const + { return m_data_read_event; } + + + // other methods + + operator T () + { return read(); } + + + sc_fifo<T>& operator = ( const T& a ) + { write( a ); return *this; } + + + void trace( sc_trace_file* tf ) const; + + + virtual void print( ::std::ostream& = ::std::cout ) const; + virtual void dump( ::std::ostream& = ::std::cout ) const; + + virtual const char* kind() const + { return "sc_fifo"; } + +protected: + + virtual void update(); + + // support methods + + void init( int ); + + void buf_init( int ); + bool buf_write( const T& ); + bool buf_read( T& ); + +protected: + + int m_size; // size of the buffer + T* m_buf; // the buffer + int m_free; // number of free spaces + int m_ri; // index of next read + int m_wi; // index of next write + + sc_port_base* m_reader; // used for static design rule checking + sc_port_base* m_writer; // used for static design rule checking + + int m_num_readable; // #samples readable + int m_num_read; // #samples read during this delta cycle + int m_num_written; // #samples written during this delta cycle + + sc_event m_data_read_event; + sc_event m_data_written_event; + +private: + + // disabled + sc_fifo( const sc_fifo<T>& ); + sc_fifo& operator = ( const sc_fifo<T>& ); +}; + + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + +template <class T> +inline +void +sc_fifo<T>::register_port( sc_port_base& port_, + const char* if_typename_ ) +{ + std::string nm( if_typename_ ); + if( nm == typeid( sc_fifo_in_if<T> ).name() || + nm == typeid( sc_fifo_blocking_in_if<T> ).name() + ) { + // only one reader can be connected + if( m_reader != 0 ) { + SC_REPORT_ERROR( SC_ID_MORE_THAN_ONE_FIFO_READER_, 0 ); + } + m_reader = &port_; + } else if( nm == typeid( sc_fifo_out_if<T> ).name() || + nm == typeid( sc_fifo_blocking_out_if<T> ).name() + ) { + // only one writer can be connected + if( m_writer != 0 ) { + SC_REPORT_ERROR( SC_ID_MORE_THAN_ONE_FIFO_WRITER_, 0 ); + } + m_writer = &port_; + } + else + { + SC_REPORT_ERROR( SC_ID_BIND_IF_TO_PORT_, + "sc_fifo<T> port not recognized" ); + } +} + + +// blocking read + +template <class T> +inline +void +sc_fifo<T>::read( T& val_ ) +{ + while( num_available() == 0 ) { + sc_core::wait( m_data_written_event ); + } + m_num_read ++; + buf_read( val_ ); + request_update(); +} + +template <class T> +inline +T +sc_fifo<T>::read() +{ + T tmp; + read( tmp ); + return tmp; +} + +// non-blocking read + +template <class T> +inline +bool +sc_fifo<T>::nb_read( T& val_ ) +{ + if( num_available() == 0 ) { + return false; + } + m_num_read ++; + buf_read( val_ ); + request_update(); + return true; +} + + +// blocking write + +template <class T> +inline +void +sc_fifo<T>::write( const T& val_ ) +{ + while( num_free() == 0 ) { + sc_core::wait( m_data_read_event ); + } + m_num_written ++; + buf_write( val_ ); + request_update(); +} + +// non-blocking write + +template <class T> +inline +bool +sc_fifo<T>::nb_write( const T& val_ ) +{ + if( num_free() == 0 ) { + return false; + } + m_num_written ++; + buf_write( val_ ); + request_update(); + return true; +} + + +template <class T> +inline +void +sc_fifo<T>::trace( sc_trace_file* tf ) const +{ +#if defined(DEBUG_SYSTEMC) + char buf[32]; + std::string nm = name(); + for( int i = 0; i < m_size; ++ i ) { + std::sprintf( buf, "_%d", i ); + sc_trace( tf, m_buf[i], nm + buf ); + } +#endif +} + + +template <class T> +inline +void +sc_fifo<T>::print( ::std::ostream& os ) const +{ + if( m_free != m_size ) { + int i = m_ri; + do { + os << m_buf[i] << ::std::endl; + i = ( i + 1 ) % m_size; + } while( i != m_wi ); + } +} + +template <class T> +inline +void +sc_fifo<T>::dump( ::std::ostream& os ) const +{ + os << "name = " << name() << ::std::endl; + if( m_free != m_size ) { + int i = m_ri; + int j = 0; + do { + os << "value[" << i << "] = " << m_buf[i] << ::std::endl; + i = ( i + 1 ) % m_size; + j ++; + } while( i != m_wi ); + } +} + + +template <class T> +inline +void +sc_fifo<T>::update() +{ + if( m_num_read > 0 ) { + m_data_read_event.notify(SC_ZERO_TIME); + } + + if( m_num_written > 0 ) { + m_data_written_event.notify(SC_ZERO_TIME); + } + + m_num_readable = m_size - m_free; + m_num_read = 0; + m_num_written = 0; +} + + +// support methods + +template <class T> +inline +void +sc_fifo<T>::init( int size_ ) +{ + buf_init( size_ ); + + m_reader = 0; + m_writer = 0; + + m_num_readable = 0; + m_num_read = 0; + m_num_written = 0; +} + + +template <class T> +inline +void +sc_fifo<T>::buf_init( int size_ ) +{ + if( size_ <= 0 ) { + SC_REPORT_ERROR( SC_ID_INVALID_FIFO_SIZE_, 0 ); + } + m_size = size_; + m_buf = new T[m_size]; + m_free = m_size; + m_ri = 0; + m_wi = 0; +} + +template <class T> +inline +bool +sc_fifo<T>::buf_write( const T& val_ ) +{ + if( m_free == 0 ) { + return false; + } + m_buf[m_wi] = val_; + m_wi = ( m_wi + 1 ) % m_size; + m_free --; + return true; +} + +template <class T> +inline +bool +sc_fifo<T>::buf_read( T& val_ ) +{ + if( m_free == m_size ) { + return false; + } + val_ = m_buf[m_ri]; + m_buf[m_ri] = T(); // clear entry for boost::shared_ptr, et al. + m_ri = ( m_ri + 1 ) % m_size; + m_free ++; + return true; +} + + +// ---------------------------------------------------------------------------- + +template <class T> +inline +::std::ostream& +operator << ( ::std::ostream& os, const sc_fifo<T>& a ) +{ + a.print( os ); + return os; +} + +} // namespace sc_core + +//$Log: sc_fifo.h,v $ +//Revision 1.6 2011/08/26 20:45:40 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +//Revision 1.5 2011/03/23 16:17:22 acg +// Andy Goodrich: hide the sc_events that are kernel related. +// +//Revision 1.4 2011/02/18 20:23:45 acg +// Andy Goodrich: Copyright update. +// +//Revision 1.3 2009/10/14 19:05:40 acg +// Andy Goodrich: added check for blocking interfaces in addition to the +// combined blocking/nonblocking interface. +// +//Revision 1.2 2009/05/22 16:06:24 acg +// Andy Goodrich: process control updates. +// +//Revision 1.1.1.1 2006/12/15 20:20:04 acg +//SystemC 2.3 +// +//Revision 1.4 2006/01/24 20:46:31 acg +//Andy Goodrich: changes to eliminate use of deprecated features. For instance, +//using notify(SC_ZERO_TIME) in place of notify_delayed(). +// +//Revision 1.3 2006/01/13 20:41:59 acg +//Andy Goodrich: Changes to add port registration to the things that are +//checked when SC_NO_WRITE_CHECK is not defined. +// +//Revision 1.2 2006/01/03 23:18:26 acg +//Changed copyright to include 2006. +// +//Revision 1.1.1.1 2005/12/19 23:16:43 acg +//First check in of SystemC 2.1 into its own archive. +// +//Revision 1.12 2005/09/15 23:01:51 acg +//Added std:: prefix to appropriate methods and types to get around +//issues with the Edison Front End. +// +//Revision 1.11 2005/06/10 22:43:55 acg +//Added CVS change log annotation. +// + +#endif + +// Taf! diff --git a/ext/systemc/src/sysc/communication/sc_fifo_ifs.h b/ext/systemc/src/sysc/communication/sc_fifo_ifs.h new file mode 100644 index 000000000..915fc9f0c --- /dev/null +++ b/ext/systemc/src/sysc/communication/sc_fifo_ifs.h @@ -0,0 +1,209 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_fifo_ifs.h -- The sc_fifo<T> interface classes. + + Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21 + + CHANGE LOG IS AT THE END OF THE FILE + *****************************************************************************/ + +#ifndef SC_FIFO_IFS_H +#define SC_FIFO_IFS_H + + +#include "sysc/communication/sc_interface.h" + +namespace sc_core { + +// ---------------------------------------------------------------------------- +// CLASS : sc_fifo_nonblocking_in_if<T> +// +// The sc_fifo<T> input nonblocking interface class. +// ---------------------------------------------------------------------------- + +template <class T> +class sc_fifo_nonblocking_in_if +: virtual public sc_interface +{ +public: + + // non-blocking read + virtual bool nb_read( T& ) = 0; + + // get the data written event + virtual const sc_event& data_written_event() const = 0; +}; + +// ---------------------------------------------------------------------------- +// CLASS : sc_fifo_blocking_in_if<T> +// +// The sc_fifo<T> input blocking interface class. +// ---------------------------------------------------------------------------- + +template <class T> +class sc_fifo_blocking_in_if +: virtual public sc_interface +{ +public: + + // blocking read + virtual void read( T& ) = 0; + virtual T read() = 0; +}; + +// ---------------------------------------------------------------------------- +// CLASS : sc_fifo_in_if<T> +// +// The sc_fifo<T> input interface class. +// ---------------------------------------------------------------------------- + +template <class T> +class sc_fifo_in_if +: public sc_fifo_nonblocking_in_if<T>, + public sc_fifo_blocking_in_if<T> +{ +public: + + // get the number of available samples + virtual int num_available() const = 0; + +protected: + + // constructor + + sc_fifo_in_if() + {} + +private: + + // disabled + sc_fifo_in_if( const sc_fifo_in_if<T>& ); + sc_fifo_in_if<T>& operator = ( const sc_fifo_in_if<T>& ); +}; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_fifo_nonblocking_out_if<T> +// +// The sc_fifo<T> nonblocking output interface class. +// ---------------------------------------------------------------------------- + +template <class T> +class sc_fifo_nonblocking_out_if +: virtual public sc_interface +{ +public: + + // non-blocking write + virtual bool nb_write( const T& ) = 0; + + // get the data read event + virtual const sc_event& data_read_event() const = 0; +}; + +// ---------------------------------------------------------------------------- +// CLASS : sc_fifo_blocking_out_if<T> +// +// The sc_fifo<T> blocking output interface class. +// ---------------------------------------------------------------------------- + +template <class T> +class sc_fifo_blocking_out_if +: virtual public sc_interface +{ +public: + + // blocking write + virtual void write( const T& ) = 0; + +}; + +// ---------------------------------------------------------------------------- +// CLASS : sc_fifo_out_if<T> +// +// The sc_fifo<T> output interface class. +// ---------------------------------------------------------------------------- + +template <class T> +class sc_fifo_out_if +: public sc_fifo_nonblocking_out_if<T>, + public sc_fifo_blocking_out_if<T> +{ +public: + + // get the number of free spaces + virtual int num_free() const = 0; + +protected: + + // constructor + + sc_fifo_out_if() + {} + +private: + + // disabled + sc_fifo_out_if( const sc_fifo_out_if<T>& ); + sc_fifo_out_if<T>& operator = ( const sc_fifo_out_if<T>& ); +}; + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: Bishnupriya Bhattacharye, Cadence Design Systems, + 30 Jan, 2004 + Description of Modification: Split up the interfaces into blocking and + non blocking parts + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ +//$Log: sc_fifo_ifs.h,v $ +//Revision 1.3 2011/08/26 20:45:40 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +//Revision 1.2 2011/02/18 20:23:45 acg +// Andy Goodrich: Copyright update. +// +//Revision 1.1.1.1 2006/12/15 20:20:04 acg +//SystemC 2.3 +// +//Revision 1.2 2006/01/03 23:18:26 acg +//Changed copyright to include 2006. +// +//Revision 1.1.1.1 2005/12/19 23:16:43 acg +//First check in of SystemC 2.1 into its own archive. +// +//Revision 1.10 2005/06/10 22:43:55 acg +//Added CVS change log annotation. +// + +} // namespace sc_core + +#endif + +// Taf! diff --git a/ext/systemc/src/sysc/communication/sc_fifo_ports.h b/ext/systemc/src/sysc/communication/sc_fifo_ports.h new file mode 100644 index 000000000..72727d4be --- /dev/null +++ b/ext/systemc/src/sysc/communication/sc_fifo_ports.h @@ -0,0 +1,296 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_fifo_ports.h -- The sc_fifo<T> port classes. + + Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21 + + CHANGE LOG IS AT THE END OF THE FILE + *****************************************************************************/ + +#ifndef SC_FIFO_PORTS_H +#define SC_FIFO_PORTS_H + + +#include "sysc/communication/sc_port.h" +#include "sysc/communication/sc_fifo_ifs.h" + +namespace sc_core { + +// ---------------------------------------------------------------------------- +// CLASS : sc_fifo_in<T> +// +// The sc_fifo<T> input port class. +// ---------------------------------------------------------------------------- + +template <class T> +class sc_fifo_in +: public sc_port<sc_fifo_in_if<T>,0,SC_ONE_OR_MORE_BOUND> +{ +public: + + // typedefs + + typedef T data_type; + + typedef sc_fifo_in_if<data_type> if_type; + typedef sc_port<if_type,0,SC_ONE_OR_MORE_BOUND> base_type; + typedef sc_fifo_in<data_type> this_type; + + typedef if_type in_if_type; + typedef sc_port_b<in_if_type> in_port_type; + +public: + + // constructors + + sc_fifo_in() + : base_type() + {} + + explicit sc_fifo_in( const char* name_ ) + : base_type( name_ ) + {} + + explicit sc_fifo_in( in_if_type& interface_ ) + : base_type( interface_ ) + {} + + sc_fifo_in( const char* name_, in_if_type& interface_ ) + : base_type( name_, interface_ ) + {} + + explicit sc_fifo_in( in_port_type& parent_ ) + : base_type( parent_ ) + {} + + sc_fifo_in( const char* name_, in_port_type& parent_ ) + : base_type( name_, parent_ ) + {} + + sc_fifo_in( this_type& parent_ ) + : base_type( parent_ ) + {} + + sc_fifo_in( const char* name_, this_type& parent_ ) + : base_type( name_, parent_ ) + {} + + + // destructor (does nothing) + + virtual ~sc_fifo_in() + {} + + + // interface access shortcut methods + + // blocking read + + void read( data_type& value_ ) + { (*this)->read( value_ ); } + + data_type read() + { return (*this)->read(); } + + + // non-blocking read + + bool nb_read( data_type& value_ ) + { return (*this)->nb_read( value_ ); } + + + // get the number of available samples + + int num_available() const + { return (*this)->num_available(); } + + + // get the data written event + + const sc_event& data_written_event() const + { return (*this)->data_written_event(); } + + + // use for static sensitivity to data written event + + sc_event_finder& data_written() const + { + return *new sc_event_finder_t<in_if_type>( + *this, &in_if_type::data_written_event ); + } + + virtual const char* kind() const + { return "sc_fifo_in"; } + +private: + + // disabled + sc_fifo_in( const this_type& ); + this_type& operator = ( const this_type& ); +}; + + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + +// ---------------------------------------------------------------------------- +// CLASS : sc_fifo_out<T> +// +// The sc_fifo<T> output port class. +// ---------------------------------------------------------------------------- + +template <class T> +class sc_fifo_out +: public sc_port<sc_fifo_out_if<T>,0,SC_ONE_OR_MORE_BOUND> +{ +public: + + // typedefs + + typedef T data_type; + + typedef sc_fifo_out_if<data_type> if_type; + typedef sc_port<if_type,0,SC_ONE_OR_MORE_BOUND> base_type; + typedef sc_fifo_out<data_type> this_type; + + typedef if_type out_if_type; + typedef sc_port_b<out_if_type> out_port_type; + +public: + + // constructors + + sc_fifo_out() + : base_type() + {} + + explicit sc_fifo_out( const char* name_ ) + : base_type( name_ ) + {} + + explicit sc_fifo_out( out_if_type& interface_ ) + : base_type( interface_ ) + {} + + sc_fifo_out( const char* name_, out_if_type& interface_ ) + : base_type( name_, interface_ ) + {} + + explicit sc_fifo_out( out_port_type& parent_ ) + : base_type( parent_ ) + {} + + sc_fifo_out( const char* name_, out_port_type& parent_ ) + : base_type( name_, parent_ ) + {} + + sc_fifo_out( this_type& parent_ ) + : base_type( parent_ ) + {} + + sc_fifo_out( const char* name_, this_type& parent_ ) + : base_type( name_, parent_ ) + {} + + + // destructor (does nothing) + + virtual ~sc_fifo_out() + {} + + + // interface access shortcut methods + + // blocking write + + void write( const data_type& value_ ) + { (*this)->write( value_ ); } + + + // non-blocking write + + bool nb_write( const data_type& value_ ) + { return (*this)->nb_write( value_ ); } + + + // get the number of free spaces + + int num_free() const + { return (*this)->num_free(); } + + + // get the data read event + + const sc_event& data_read_event() const + { return (*this)->data_read_event(); } + + + // use for static sensitivity to data read event + + sc_event_finder& data_read() const + { + return *new sc_event_finder_t<out_if_type>( + *this, &out_if_type::data_read_event ); + } + + virtual const char* kind() const + { return "sc_fifo_out"; } + +private: + + // disabled + sc_fifo_out( const this_type& ); + this_type& operator = ( const this_type& ); +}; + + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + +} // namespace sc_core + +//$Log: sc_fifo_ports.h,v $ +//Revision 1.3 2011/08/26 20:45:40 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +//Revision 1.2 2011/02/18 20:23:45 acg +// Andy Goodrich: Copyright update. +// +//Revision 1.1.1.1 2006/12/15 20:20:04 acg +//SystemC 2.3 +// +//Revision 1.2 2006/01/03 23:18:26 acg +//Changed copyright to include 2006. +// +//Revision 1.1.1.1 2005/12/19 23:16:43 acg +//First check in of SystemC 2.1 into its own archive. +// +//Revision 1.10 2005/09/15 23:01:51 acg +//Added std:: prefix to appropriate methods and types to get around +//issues with the Edison Front End. +// +//Revision 1.9 2005/06/10 22:43:55 acg +//Added CVS change log annotation. +// + +#endif + +// Taf! diff --git a/ext/systemc/src/sysc/communication/sc_host_mutex.h b/ext/systemc/src/sysc/communication/sc_host_mutex.h new file mode 100644 index 000000000..58f1c4c3a --- /dev/null +++ b/ext/systemc/src/sysc/communication/sc_host_mutex.h @@ -0,0 +1,160 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_host_mutex.h -- A "real" mutex for the underlying host system + + Original Author: Philipp A. Hartmann, OFFIS + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + +#ifndef SC_HOST_MUTEX_H_INCLUDED_ +#define SC_HOST_MUTEX_H_INCLUDED_ + +#ifndef SC_INCLUDE_WINDOWS_H +# define SC_INCLUDE_WINDOWS_H // include Windows.h, if needed +#endif +#include "sysc/kernel/sc_cmnhdr.h" +#include "sysc/communication/sc_mutex_if.h" + +#if defined(WIN32) || defined(_WIN32) + +#define SC_MTX_TYPE_ CRITICAL_SECTION + +#define SC_MTX_INIT_( Mutex ) \ + InitializeCriticalSection( &(Mutex) ) +#define SC_MTX_LOCK_( Mutex ) \ + EnterCriticalSection( &(Mutex) ) +#define SC_MTX_UNLOCK_( Mutex ) \ + LeaveCriticalSection( &(Mutex) ) +#define SC_MTX_TRYLOCK_( Mutex ) \ + ( TryEnterCriticalSection( &(Mutex) ) != 0 ) +#define SC_MTX_DESTROY_( Mutex ) \ + DeleteCriticalSection( &(Mutex) ) + +#else // use pthread mutex + +#include <pthread.h> +#define SC_MTX_TYPE_ pthread_mutex_t + +#if defined(__hpux) +# define SC_PTHREAD_NULL_ cma_c_null +#else // !defined(__hpux) +# define SC_PTHREAD_NULL_ NULL +#endif + +#define SC_MTX_INIT_( Mutex ) \ + pthread_mutex_init( &(Mutex), SC_PTHREAD_NULL_ ) +#define SC_MTX_LOCK_( Mutex ) \ + pthread_mutex_lock( &(Mutex) ) +#define SC_MTX_UNLOCK_( Mutex ) \ + pthread_mutex_unlock( &(Mutex) ) + +#ifdef _XOPEN_SOURCE +# define SC_MTX_TRYLOCK_( Mutex ) \ + ( pthread_mutex_trylock( &(Mutex) ) == 0 ) +#else // no try_lock available +# define SC_MTX_TRYLOCK_( Mutex ) \ + ( false ) +#endif + +#define SC_MTX_DESTROY_( Mutex ) \ + pthread_mutex_destroy( &(Mutex) ) + +#endif + +namespace sc_core { + +// ---------------------------------------------------------------------------- +// CLASS : sc_host_mutex +// +// The sc_host_mutex class, wrapping an OS mutex on the simulation host +// ---------------------------------------------------------------------------- + +class sc_host_mutex : public sc_mutex_if +{ + typedef SC_MTX_TYPE_ underlying_type; +public: + + // constructors and destructor + + sc_host_mutex() + { SC_MTX_INIT_(m_mtx); } + virtual ~sc_host_mutex() + { SC_MTX_DESTROY_(m_mtx); } + + + // interface methods + + // blocks until mutex could be locked + virtual int lock() + { SC_MTX_LOCK_(m_mtx); return 0; } + + // returns -1 if mutex could not be locked + virtual int trylock() + { return SC_MTX_TRYLOCK_(m_mtx) ? 0 : -1; } + + // should return -1 if mutex was not locked by caller, + // but is not yet able to check this + virtual int unlock() + { SC_MTX_UNLOCK_(m_mtx); return 0; } + +private: + underlying_type m_mtx; +}; + +} // namespace sc_core + +#undef SC_MTX_TYPE_ +#undef SC_MTX_INIT_ +#undef SC_MTX_DESTROY_ +#undef SC_MTX_LOCK_ +#undef SC_MTX_TRYLOCK_ +#undef SC_MTX_UNLOCK_ +#undef SC_PTHREAD_NULL_ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + *****************************************************************************/ +//$Log: sc_host_mutex.h,v $ +//Revision 1.4 2011/08/30 21:53:23 acg +// Jerome Cornet: include window.h for gnu c in windows case. +// +//Revision 1.3 2011/08/07 19:08:01 acg +// Andy Goodrich: moved logs to end of file so line number synching works +// better between versions. +// +//Revision 1.2 2011/06/25 17:08:38 acg +// Andy Goodrich: Jerome Cornet's changes to use libtool to build the +// library. +// +//Revision 1.1 2011/04/18 19:04:11 acg +// Philipp A. Hartmann: first check in of file. +// + +#endif + +// Taf! diff --git a/ext/systemc/src/sysc/communication/sc_interface.cpp b/ext/systemc/src/sysc/communication/sc_interface.cpp new file mode 100644 index 000000000..eabe870e9 --- /dev/null +++ b/ext/systemc/src/sysc/communication/sc_interface.cpp @@ -0,0 +1,100 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_interface.cpp -- Abstract base class of all interface classes. + + Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21 + + CHANGE LOG IS AT THE END OF THE FILE + *****************************************************************************/ + +#include "sysc/communication/sc_interface.h" +#include "sysc/communication/sc_communication_ids.h" +#include "sysc/kernel/sc_event.h" + + +namespace sc_core { + +// ---------------------------------------------------------------------------- +// CLASS : sc_interface +// +// Abstract base class of all interface classes. +// BEWARE: Direct inheritance from this class must be done virtual. +// ---------------------------------------------------------------------------- + +// register a port with this interface (does nothing by default) + +void +sc_interface::register_port( sc_port_base&, const char* ) +{} + + +// get the default event + +const sc_event& +sc_interface::default_event() const +{ + SC_REPORT_WARNING( SC_ID_NO_DEFAULT_EVENT_, 0 ); + return m_never_notified; +} + + +// destructor (does nothing) + +sc_interface::~sc_interface() +{} + + +// constructor (does nothing) + +sc_interface::sc_interface() +{} + + +// special event for never notified cases, note the special name to keep +// it out of the named event structures. + +sc_event sc_interface::m_never_notified(SC_KERNEL_EVENT_PREFIX); + +} // namespace sc_core + +// $Log: sc_interface.cpp,v $ +// Revision 1.5 2011/08/26 20:45:40 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +// Revision 1.4 2011/03/12 21:07:42 acg +// Andy Goodrich: changes to kernel generated event support. +// +// Revision 1.3 2011/03/06 15:55:08 acg +// Andy Goodrich: Changes for named events. +// +// Revision 1.2 2011/02/18 20:23:45 acg +// Andy Goodrich: Copyright update. +// +// Revision 1.1.1.1 2006/12/15 20:20:04 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:47:42 acg +// Added $Log command so that CVS comments are reproduced in the source. +// + +// Taf! diff --git a/ext/systemc/src/sysc/communication/sc_interface.h b/ext/systemc/src/sysc/communication/sc_interface.h new file mode 100644 index 000000000..b21d3c27d --- /dev/null +++ b/ext/systemc/src/sysc/communication/sc_interface.h @@ -0,0 +1,107 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_interface.h -- Abstract base class of all interface classes. + + Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21 + + CHANGE LOG IS AT THE END OF THE FILE + *****************************************************************************/ + +#ifndef SC_INTERFACE_H +#define SC_INTERFACE_H + +namespace sc_core { + +class sc_event; +class sc_port_base; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_interface +// +// Abstract base class of all interface classes. +// BEWARE: Direct inheritance from this class must be done virtual. +// ---------------------------------------------------------------------------- + +class sc_interface +{ +public: + + // register a port with this interface (does nothing by default) + virtual void register_port( sc_port_base& port_, + const char* if_typename_ ); + + // get the default event + virtual const sc_event& default_event() const; + + // destructor (does nothing) + virtual ~sc_interface(); + +protected: + + // constructor (does nothing) + sc_interface(); + +private: + + // disabled + sc_interface( const sc_interface& ); + sc_interface& operator = ( const sc_interface& ); + +private: + + static sc_event m_never_notified; + +#if defined(__SUNPRO_CC) && (__SUNPRO_CC == 0x520) + // Workaround for a bug in the Sun WorkShop 6 update 2 compiler. + // An empty virtual base class can cause the optimizer to + // generate wrong code. + char dummy; +#endif +}; + +} // namespace sc_core + +//$Log: sc_interface.h,v $ +//Revision 1.3 2011/08/26 20:45:40 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +//Revision 1.2 2011/02/18 20:23:45 acg +// Andy Goodrich: Copyright update. +// +//Revision 1.1.1.1 2006/12/15 20:20:04 acg +//SystemC 2.3 +// +//Revision 1.2 2006/01/03 23:18:26 acg +//Changed copyright to include 2006. +// +//Revision 1.1.1.1 2005/12/19 23:16:43 acg +//First check in of SystemC 2.1 into its own archive. +// +//Revision 1.7 2005/06/10 22:43:55 acg +//Added CVS change log annotation. +// + +#endif + +// Taf! diff --git a/ext/systemc/src/sysc/communication/sc_mutex.cpp b/ext/systemc/src/sysc/communication/sc_mutex.cpp new file mode 100644 index 000000000..d2c43244c --- /dev/null +++ b/ext/systemc/src/sysc/communication/sc_mutex.cpp @@ -0,0 +1,140 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_mutex.cpp -- The sc_mutex primitive channel class. + + Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21 + + CHANGE LOG IS AT THE END OF THE FILE + *****************************************************************************/ + +#include "sysc/communication/sc_mutex.h" +#include "sysc/kernel/sc_simcontext.h" + +namespace sc_core { + +// ---------------------------------------------------------------------------- +// CLASS : sc_mutex +// +// The sc_mutex primitive channel class. +// ---------------------------------------------------------------------------- + +// constructors + +sc_mutex::sc_mutex() +: sc_object( sc_gen_unique_name( "mutex" ) ), + m_owner( 0 ), + m_free( (std::string(SC_KERNEL_EVENT_PREFIX)+"_free_event").c_str() ) +{} + +sc_mutex::sc_mutex( const char* name_ ) +: sc_object( name_ ), + m_owner( 0 ), + m_free( (std::string(SC_KERNEL_EVENT_PREFIX)+"_free_event").c_str() ) +{} + + +// destructor + +sc_mutex::~sc_mutex() +{} + +// interface methods + +// blocks until mutex could be locked + +int +sc_mutex::lock() +{ + if ( m_owner == sc_get_current_process_b()) return 0; + while( in_use() ) { + sc_core::wait( m_free, sc_get_curr_simcontext() ); + } + m_owner = sc_get_current_process_b(); + return 0; +} + + +// returns -1 if mutex could not be locked + +int +sc_mutex::trylock() +{ + if ( m_owner == sc_get_current_process_b()) return 0; + if( in_use() ) { + return -1; + } + m_owner = sc_get_current_process_b(); + return 0; +} + + +// returns -1 if mutex was not locked by caller + +int +sc_mutex::unlock() +{ + if( m_owner != sc_get_current_process_b() ) { + return -1; + } + m_owner = 0; + m_free.notify(); + return 0; +} + +} // namespace sc_core + +// $Log: sc_mutex.cpp,v $ +// Revision 1.7 2011/08/26 20:45:40 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +// Revision 1.6 2011/03/28 13:02:29 acg +// Andy Goodrich: removed sc_event in sc_mutex class from the object +// hierarchy since it is considered a "kernel" event. +// +// Revision 1.5 2011/02/18 20:23:45 acg +// Andy Goodrich: Copyright update. +// +// Revision 1.4 2010/11/02 16:31:01 acg +// Andy Goodrich: changed object derivation to use sc_object rather than +// sc_prim_channel as the parent class. +// +// Revision 1.3 2008/11/13 15:29:46 acg +// David C. Black, ESLX, Inc: lock & trylock now allow owner to apply +// lock more than once without incident. Previous behavior locked up the +// owning process. +// +// Revision 1.2 2008/05/20 16:46:18 acg +// Andy Goodrich: added checks for multiple writers. +// +// Revision 1.1.1.1 2006/12/15 20:20:04 acg +// SystemC 2.3 +// +// Revision 1.4 2006/03/21 00:00:27 acg +// Andy Goodrich: changed name of sc_get_current_process_base() to be +// sc_get_current_process_b() since its returning an sc_process_b instance. +// +// Revision 1.3 2006/01/13 18:47:42 acg +// Added $Log command so that CVS comments are reproduced in the source. +// + +// Taf! diff --git a/ext/systemc/src/sysc/communication/sc_mutex.h b/ext/systemc/src/sysc/communication/sc_mutex.h new file mode 100644 index 000000000..e3cef36c3 --- /dev/null +++ b/ext/systemc/src/sysc/communication/sc_mutex.h @@ -0,0 +1,124 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_mutex.h -- The sc_mutex primitive channel class. + + Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21 + + CHANGE LOG IS AT THE END OF THE FILE + *****************************************************************************/ + +#ifndef SC_MUTEX_H +#define SC_MUTEX_H + +#include "sysc/kernel/sc_event.h" +#include "sysc/kernel/sc_object.h" +#include "sysc/kernel/sc_wait.h" +#include "sysc/communication/sc_mutex_if.h" + +namespace sc_core { + +// ---------------------------------------------------------------------------- +// CLASS : sc_mutex +// +// The sc_mutex primitive channel class. +// ---------------------------------------------------------------------------- + +class sc_mutex +: public sc_mutex_if, + public sc_object +{ +public: + + // constructors and destructor + + sc_mutex(); + explicit sc_mutex( const char* name_ ); + virtual ~sc_mutex(); + + + // interface methods + + // blocks until mutex could be locked + virtual int lock(); + + // returns -1 if mutex could not be locked + virtual int trylock(); + + // returns -1 if mutex was not locked by caller + virtual int unlock(); + + virtual const char* kind() const + { return "sc_mutex"; } + +protected: + + // support methods + + bool in_use() const + { return ( m_owner != 0 ); } + +protected: + + sc_process_b* m_owner; + sc_event m_free; + +private: + + // disabled + sc_mutex( const sc_mutex& ); + sc_mutex& operator = ( const sc_mutex& ); +}; + +} // namespace sc_core + +//$Log: sc_mutex.h,v $ +//Revision 1.4 2011/08/26 20:45:41 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +//Revision 1.3 2011/02/18 20:23:45 acg +// Andy Goodrich: Copyright update. +// +//Revision 1.2 2010/11/02 16:31:01 acg +// Andy Goodrich: changed object derivation to use sc_object rather than +// sc_prim_channel as the parent class. +// +//Revision 1.1.1.1 2006/12/15 20:20:04 acg +//SystemC 2.3 +// +//Revision 1.2 2006/01/03 23:18:26 acg +//Changed copyright to include 2006. +// +//Revision 1.1.1.1 2005/12/19 23:16:43 acg +//First check in of SystemC 2.1 into its own archive. +// +//Revision 1.10 2005/09/15 23:01:51 acg +//Added std:: prefix to appropriate methods and types to get around +//issues with the Edison Front End. +// +//Revision 1.9 2005/06/10 22:43:55 acg +//Added CVS change log annotation. +// + +#endif + +// Taf! diff --git a/ext/systemc/src/sysc/communication/sc_mutex_if.h b/ext/systemc/src/sysc/communication/sc_mutex_if.h new file mode 100644 index 000000000..6fa934135 --- /dev/null +++ b/ext/systemc/src/sysc/communication/sc_mutex_if.h @@ -0,0 +1,146 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_mutex_if.h -- The sc_mutex_if interface class. + + Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21 + + CHANGE LOG IS AT THE END OF THE FILE + *****************************************************************************/ + +#ifndef SC_MUTEX_IF_H +#define SC_MUTEX_IF_H + +#include "sysc/communication/sc_interface.h" + +namespace sc_core { + +// ---------------------------------------------------------------------------- +// CLASS : sc_mutex_if +// +// The sc_mutex_if interface class. +// ---------------------------------------------------------------------------- + +class sc_mutex_if +: virtual public sc_interface +{ +public: + + // the classical operations: lock(), trylock(), and unlock() + + // blocks until mutex could be locked + virtual int lock() = 0; + + // returns -1 if mutex could not be locked + virtual int trylock() = 0; + + // returns -1 if mutex was not locked by caller + virtual int unlock() = 0; + +protected: + + // constructor + + sc_mutex_if() + {} + +private: + + // disabled + sc_mutex_if( const sc_mutex_if& ); + sc_mutex_if& operator = ( const sc_mutex_if& ); +}; + +// ---------------------------------------------------------------------------- +// CLASS : sc_scoped_lock +// +// The sc_scoped_lock class to lock (and automatically release) a mutex. +// ---------------------------------------------------------------------------- + +//template< typename Lockable = sc_mutex_if > +class sc_scoped_lock +{ +public: + //typedef Lockable lockable_type; + typedef sc_mutex_if lockable_type; + + explicit + sc_scoped_lock( lockable_type& mtx ) + : m_ref(mtx) + , m_active(true) + { + m_ref.lock(); + } + + bool release() + { + if( m_active ) + { + m_ref.unlock(); + m_active = false; + return true; + } + return false; + } + + ~sc_scoped_lock() + { + release(); + } + +private: + // disabled + sc_scoped_lock( const sc_scoped_lock& ); + sc_scoped_lock& operator=( const sc_scoped_lock& ); + + lockable_type& m_ref; + bool m_active; +}; + +} // namespace sc_core + +//$Log: sc_mutex_if.h,v $ +//Revision 1.4 2011/08/26 20:45:41 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +//Revision 1.3 2011/04/19 02:36:26 acg +// Philipp A. Hartmann: new aysnc_update and mutex support. +// +//Revision 1.2 2011/02/18 20:23:45 acg +// Andy Goodrich: Copyright update. +// +//Revision 1.1.1.1 2006/12/15 20:20:04 acg +//SystemC 2.3 +// +//Revision 1.2 2006/01/03 23:18:26 acg +//Changed copyright to include 2006. +// +//Revision 1.1.1.1 2005/12/19 23:16:43 acg +//First check in of SystemC 2.1 into its own archive. +// +//Revision 1.8 2005/06/10 22:43:55 acg +//Added CVS change log annotation. +// + +#endif + +// Taf! diff --git a/ext/systemc/src/sysc/communication/sc_port.cpp b/ext/systemc/src/sysc/communication/sc_port.cpp new file mode 100644 index 000000000..01291e6b5 --- /dev/null +++ b/ext/systemc/src/sysc/communication/sc_port.cpp @@ -0,0 +1,835 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_port.cpp -- Base classes of all port classes. + + Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21 + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + +#include "sysc/kernel/sc_simcontext.h" +#include "sysc/kernel/sc_module.h" +#include "sysc/kernel/sc_object_int.h" +#include "sysc/kernel/sc_method_process.h" +#include "sysc/kernel/sc_thread_process.h" +#include "sysc/communication/sc_communication_ids.h" +#include "sysc/utils/sc_utils_ids.h" +#include "sysc/communication/sc_event_finder.h" +#include "sysc/communication/sc_port.h" +#include "sysc/communication/sc_signal_ifs.h" + +namespace sc_core { + +// ---------------------------------------------------------------------------- +// STRUCT : sc_bind_elem +// ---------------------------------------------------------------------------- + +struct sc_bind_elem +{ + // constructors + sc_bind_elem(); + explicit sc_bind_elem( sc_interface* interface_ ); + explicit sc_bind_elem( sc_port_base* parent_ ); + + sc_interface* iface; + sc_port_base* parent; +}; + + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + +// constructors + +sc_bind_elem::sc_bind_elem() +: iface( 0 ), + parent( 0 ) +{} + +sc_bind_elem::sc_bind_elem( sc_interface* interface_ ) +: iface( interface_ ), + parent( 0 ) +{} + +sc_bind_elem::sc_bind_elem( sc_port_base* parent_ ) +: iface( 0 ), + parent( parent_ ) +{} + + +// ---------------------------------------------------------------------------- +// STRUCT : sc_bind_ef +// ---------------------------------------------------------------------------- + +struct sc_bind_ef +{ + // constructor + sc_bind_ef( sc_process_b* , sc_event_finder* ); + + // destructor + ~sc_bind_ef(); + + sc_process_b* handle; + sc_event_finder* event_finder; +}; + + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + +// constructor + +sc_bind_ef::sc_bind_ef( sc_process_b* handle_, + sc_event_finder* event_finder_ ) +: handle( handle_ ), + event_finder( event_finder_ ) +{} + + +// destructor + +sc_bind_ef::~sc_bind_ef() +{ +} + + +// ---------------------------------------------------------------------------- +// STRUCT : sc_bind_info +// ---------------------------------------------------------------------------- + +struct sc_bind_info +{ + // constructor + explicit sc_bind_info( int max_size_, + sc_port_policy policy_=SC_ONE_OR_MORE_BOUND ); + + // destructor + ~sc_bind_info(); + + int max_size() const; + sc_port_policy policy() const; + int size() const; + + int m_max_size; + sc_port_policy m_policy; + std::vector<sc_bind_elem*> vec; + bool has_parent; + int last_add; + bool is_leaf; + bool complete; + + std::vector<sc_bind_ef*> thread_vec; + std::vector<sc_bind_ef*> method_vec; +}; + + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + +// constructor + +sc_bind_info::sc_bind_info( int max_size_, sc_port_policy policy_ ) +: m_max_size( max_size_ ), + m_policy( policy_ ), + vec(), + has_parent( false ), + last_add( -1 ), + is_leaf( true ), + complete( false ), + thread_vec(), + method_vec() +{} + + +// destructor + +sc_bind_info::~sc_bind_info() +{ + for( int i = size() - 1; i >= 0; -- i ) { + delete vec[i]; + } +} + + +int +sc_bind_info::max_size() const +{ + return m_max_size ? m_max_size : (int) vec.size(); +} + +sc_port_policy +sc_bind_info::policy() const +{ + return m_policy; +} + +int +sc_bind_info::size() const +{ + return vec.size(); +} + + + +// ---------------------------------------------------------------------------- +// CLASS : sc_port_base +// +// Abstract base class for class sc_port_b. +// ---------------------------------------------------------------------------- + +// This method exists to get around a problem in VCC 6.0 where you cannot +// have a friend class that is templated. So sc_port_b<IF> calls this class +// instead of sc_process_b::add_static_event. + +void sc_port_base::add_static_event( + sc_method_handle process_p, const sc_event& event ) const +{ + process_p->add_static_event( event ); +} + +void sc_port_base::add_static_event( + sc_thread_handle process_p, const sc_event& event ) const +{ + process_p->add_static_event( event ); +} + +// return number of interfaces that will be bound, or are bound: + +int sc_port_base::bind_count() +{ + if ( m_bind_info ) + return m_bind_info->size(); + else + return interface_count(); +} + +// error reporting + +void +sc_port_base::report_error( const char* id, const char* add_msg ) const +{ + char msg[BUFSIZ]; + if( add_msg != 0 ) { + std::sprintf( msg, "%s: port '%s' (%s)", add_msg, name(), kind() ); + } else { + std::sprintf( msg, "port '%s' (%s)", name(), kind() ); + } + SC_REPORT_ERROR( id, msg ); +} + + +// constructors + +sc_port_base::sc_port_base( + int max_size_, sc_port_policy policy +) : + sc_object( sc_gen_unique_name( "port" ) ), + m_bind_info(NULL) +{ + simcontext()->get_port_registry()->insert( this ); + m_bind_info = new sc_bind_info( max_size_, policy ); +} + +sc_port_base::sc_port_base( + const char* name_, int max_size_, sc_port_policy policy +) : + sc_object( name_ ), + m_bind_info(NULL) +{ + simcontext()->get_port_registry()->insert( this ); + m_bind_info = new sc_bind_info( max_size_, policy ); +} + + +// destructor + +sc_port_base::~sc_port_base() +{ + simcontext()->get_port_registry()->remove( this ); + delete m_bind_info; +} + + +// bind interface to this port + +void +sc_port_base::bind( sc_interface& interface_ ) +{ + if( m_bind_info == 0 ) { + // cannot bind an interface after elaboration + report_error( SC_ID_BIND_IF_TO_PORT_, "simulation running" ); + } + + m_bind_info->vec.push_back( new sc_bind_elem( &interface_ ) ); + + if( ! m_bind_info->has_parent ) { + // add (cache) the interface + add_interface( &interface_ ); + m_bind_info->last_add ++; + } +} + + +// bind parent port to this port + +void +sc_port_base::bind( this_type& parent_ ) +{ + if( m_bind_info == 0 ) { + // cannot bind a parent port after elaboration + report_error( SC_ID_BIND_PORT_TO_PORT_, "simulation running" ); + } + + if( &parent_ == this ) { + report_error( SC_ID_BIND_PORT_TO_PORT_, "same port" ); + } + + // check if parent port is already bound to this port +#if 0 + for( int i = m_bind_info->size() - 1; i >= 0; -- i ) { + if( &parent_ == m_bind_info->vec[i]->parent ) { + report_error( SC_ID_BIND_PORT_TO_PORT_, "already bound" ); + } + } +#endif // + + m_bind_info->vec.push_back( new sc_bind_elem( &parent_ ) ); + m_bind_info->has_parent = true; + parent_.m_bind_info->is_leaf = false; +} + +// called by construction_done (null by default) + +void sc_port_base::before_end_of_elaboration() +{} + +// called by elaboration_done (does nothing) + +void +sc_port_base::end_of_elaboration() +{} + +// called by sc_port_registry::start_simulation (does nothing by default) + +void sc_port_base::start_of_simulation() +{} + +// called by sc_port_registry::simulation_done (does nothing by default) + +void sc_port_base::end_of_simulation() +{} + + +// called by class sc_module for positional binding + +int +sc_port_base::pbind( sc_interface& interface_ ) +{ + if( m_bind_info == 0 ) { + // cannot bind an interface after elaboration + report_error( SC_ID_BIND_IF_TO_PORT_, "simulation running" ); + } + + if( m_bind_info->size() != 0 ) { + // first interface already bound + return 1; + } + + return vbind( interface_ ); +} + +int +sc_port_base::pbind( sc_port_base& parent_ ) +{ + if( m_bind_info == 0 ) { + // cannot bind a parent port after elaboration + report_error( SC_ID_BIND_PORT_TO_PORT_, "simulation running" ); + } + + if( m_bind_info->size() != 0 ) { + // first interface already bound + return 1; + } + + return vbind( parent_ ); +} + + +// called by the sc_sensitive* classes + +void +sc_port_base::make_sensitive( sc_thread_handle handle_, + sc_event_finder* event_finder_ ) const +{ + assert( m_bind_info != 0 ); + m_bind_info->thread_vec.push_back( + new sc_bind_ef( (sc_process_b*)handle_, event_finder_ ) ); +} + +void +sc_port_base::make_sensitive( sc_method_handle handle_, + sc_event_finder* event_finder_ ) const +{ + assert( m_bind_info != 0 ); + m_bind_info->method_vec.push_back( + new sc_bind_ef( (sc_process_b*)handle_, event_finder_ ) ); +} + + +// support methods + +int +sc_port_base::first_parent() +{ + for( int i = 0; i < m_bind_info->size(); ++ i ) { + if( m_bind_info->vec[i]->parent != 0 ) { + return i; + } + } + return -1; +} + +void +sc_port_base::insert_parent( int i ) +{ + std::vector<sc_bind_elem*>& vec = m_bind_info->vec; + + this_type* parent = vec[i]->parent; + + + // IF OUR PARENT HAS NO BINDING THEN IGNORE IT: + // + // Note that the zeroing of the parent pointer must occur before this + // test + + vec[i]->parent = 0; + if ( parent->m_bind_info->vec.size() == 0 ) return; + + vec[i]->iface = parent->m_bind_info->vec[0]->iface; + int n = parent->m_bind_info->size() - 1; + if( n > 0 ) { + // resize the bind vector (by adding new elements) + for( int k = 0; k < n; ++ k ) { + vec.push_back( new sc_bind_elem() ); + } + // move elements in the bind vector + for( int k = m_bind_info->size() - n - 1; k > i; -- k ) { + vec[k + n]->iface = vec[k]->iface; + vec[k + n]->parent = vec[k]->parent; + } + // insert parent interfaces into the bind vector + for( int k = i + 1; k <= i + n; ++ k ) { + vec[k]->iface = parent->m_bind_info->vec[k - i]->iface; + vec[k]->parent = 0; + } + } +} + + +// called when elaboration is done + +void +sc_port_base::complete_binding() +{ + char msg_buffer[128]; // For error message construction. + + // IF BINDING HAS ALREADY BEEN COMPLETED IGNORE THIS CALL: + + assert( m_bind_info != 0 ); + if( m_bind_info->complete ) { + return; + } + + // COMPLETE BINDING OF OUR PARENT PORTS SO THAT WE CAN USE THAT INFORMATION: + + int i = first_parent(); + while( i >= 0 ) { + m_bind_info->vec[i]->parent->complete_binding(); + insert_parent( i ); + i = first_parent(); + } + + // LOOP OVER BINDING INFORMATION TO COMPLETE THE BINDING PROCESS: + + int size; + for( int j = 0; j < m_bind_info->size(); ++ j ) { + sc_interface* iface = m_bind_info->vec[j]->iface; + + // if the interface is zero this was for an unbound port. + if ( iface == 0 ) continue; + + // add (cache) the interface + if( j > m_bind_info->last_add ) { + add_interface( iface ); + } + + // only register "leaf" ports (ports without children) + if( m_bind_info->is_leaf ) { + iface->register_port( *this, if_typename() ); + } + + // complete static sensitivity for methods + size = m_bind_info->method_vec.size(); + for( int k = 0; k < size; ++ k ) { + sc_bind_ef* p = m_bind_info->method_vec[k]; + const sc_event& event = ( p->event_finder != 0 ) + ? p->event_finder->find_event(iface) + : iface->default_event(); + p->handle->add_static_event( event ); + } + + // complete static sensitivity for threads + size = m_bind_info->thread_vec.size(); + for( int k = 0; k < size; ++ k ) { + sc_bind_ef* p = m_bind_info->thread_vec[k]; + const sc_event& event = ( p->event_finder != 0 ) + ? p->event_finder->find_event(iface) + : iface->default_event(); + p->handle->add_static_event( event ); + } + + } + + // MAKE SURE THE PROPER NUMBER OF BINDINGS OCCURRED: + // + // Make sure there are enough bindings, and not too many. + + int actual_binds = interface_count(); + + if ( actual_binds > m_bind_info->max_size() ) + { + sprintf(msg_buffer, "%d binds exceeds maximum of %d allowed", + actual_binds, m_bind_info->max_size() ); + report_error( SC_ID_COMPLETE_BINDING_, msg_buffer ); + } + switch ( m_bind_info->policy() ) + { + case SC_ONE_OR_MORE_BOUND: + if ( actual_binds < 1 ) { + report_error( SC_ID_COMPLETE_BINDING_, "port not bound" ); + } + break; + case SC_ALL_BOUND: + if ( actual_binds < m_bind_info->max_size() || actual_binds < 1 ) { + sprintf(msg_buffer, "%d actual binds is less than required %d", + actual_binds, m_bind_info->max_size() ); + report_error( SC_ID_COMPLETE_BINDING_, msg_buffer ); + } + break; + default: // SC_ZERO_OR_MORE_BOUND: + break; + } + + + // CLEAN UP: FREE BINDING STORAGE: + + size = m_bind_info->method_vec.size(); + for( int k = 0; k < size; ++ k ) { + delete m_bind_info->method_vec[k]; + } + m_bind_info->method_vec.resize(0); + + size = m_bind_info->thread_vec.size(); + for( int k = 0; k < size; ++ k ) { + delete m_bind_info->thread_vec[k]; + } + m_bind_info->thread_vec.resize(0); + + m_bind_info->complete = true; +} + +void +sc_port_base::construction_done() +{ + sc_module* parent = static_cast<sc_module*>( get_parent_object() ); + sc_object::hierarchy_scope scope( parent ); + before_end_of_elaboration(); +} + +void +sc_port_base::elaboration_done() +{ + assert( m_bind_info != 0 && m_bind_info->complete ); + delete m_bind_info; + m_bind_info = 0; + + sc_module* parent = static_cast<sc_module*>( get_parent_object() ); + sc_object::hierarchy_scope scope( parent ); + end_of_elaboration(); +} + +void +sc_port_base::start_simulation() +{ + sc_module* parent = static_cast<sc_module*>( get_parent_object() ); + sc_object::hierarchy_scope scope( parent ); + start_of_simulation(); +} + +void +sc_port_base::simulation_done() +{ + sc_module* parent = static_cast<sc_module*>( get_parent_object() ); + sc_object::hierarchy_scope scope( parent ); + end_of_simulation(); +} + + +// ---------------------------------------------------------------------------- +// CLASS : sc_port_registry +// +// Registry for all ports. +// FOR INTERNAL USE ONLY! +// ---------------------------------------------------------------------------- + +void +sc_port_registry::insert( sc_port_base* port_ ) +{ + if( sc_is_running() ) { + port_->report_error( SC_ID_INSERT_PORT_, "simulation running" ); + } + + if( m_simc->elaboration_done() ) { + port_->report_error( SC_ID_INSERT_PORT_, "elaboration done" ); + } + +#if defined(DEBUG_SYSTEMC) + // check if port_ is already inserted + for( int i = size() - 1; i >= 0; -- i ) { + if( port_ == m_port_vec[i] ) { + port_->report_error( SC_ID_INSERT_PORT_, "port already inserted" ); + } + } +#endif + + // append the port to the current module's vector of ports + sc_module* curr_module = m_simc->hierarchy_curr(); + if( curr_module == 0 ) { + port_->report_error( SC_ID_PORT_OUTSIDE_MODULE_ ); + } + curr_module->append_port( port_ ); + + // insert + m_port_vec.push_back( port_ ); +} + +void +sc_port_registry::remove( sc_port_base* port_ ) +{ + int i; + for( i = size() - 1; i >= 0; -- i ) { + if( port_ == m_port_vec[i] ) { + break; + } + } + if( i == -1 ) { + port_->report_error( SC_ID_REMOVE_PORT_, "port not registered" ); + } + + // remove + m_port_vec[i] = m_port_vec[size() - 1]; + m_port_vec.resize(size()-1); +} + + +// constructor + +sc_port_registry::sc_port_registry( sc_simcontext& simc_ ) +: m_construction_done(0), + m_port_vec(), + m_simc( &simc_ ) +{ +} + + +// destructor + +sc_port_registry::~sc_port_registry() +{ +} + +// called when construction is done + +bool +sc_port_registry::construction_done() +{ + if( size() == m_construction_done ) + // nothing has been updated + return true; + + for( int i = size()-1; i >= m_construction_done; --i ) { + m_port_vec[i]->construction_done(); + } + + m_construction_done = size(); + return false; +} + +// called when when elaboration is done + +void +sc_port_registry::complete_binding() +{ + for( int i = size() - 1; i >= 0; -- i ) { + m_port_vec[i]->complete_binding(); + } +} + + +// called when elaboration is done + +void +sc_port_registry::elaboration_done() +{ + complete_binding(); + + for( int i = size() - 1; i >= 0; -- i ) { + m_port_vec[i]->elaboration_done(); + } +} + +// called before simulation begins + +void +sc_port_registry::start_simulation() +{ + for( int i = size() - 1; i >= 0; -- i ) { + m_port_vec[i]->start_simulation(); + } +} + +// called after simulation ends + +void +sc_port_registry::simulation_done() +{ + for( int i = size() - 1; i >= 0; -- i ) { + m_port_vec[i]->simulation_done(); + } +} + +// This is a static member function. + +void +sc_port_registry::replace_port( sc_port_registry* /* registry */ ) +{ +} + +void sc_warn_port_constructor() +{ + static bool warn_port_constructor=true; + if ( warn_port_constructor ) + { + warn_port_constructor = false; + SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, + "interface and/or port binding in port constructors is deprecated" + ); + } +} + +} // namespace sc_core + + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: Andy Goodrich, Forte Design Systems + Bishnupriya Bhattacharya, Cadence Design Systems, + 25 August, 2003 + Description of Modification: phase callbacks + + Name, Affiliation, Date: Andy Goodrich, Forte Design Systems + 12 December, 2005 + Description of Modification: multiport binding policy changes + + *****************************************************************************/ + + +// $Log: sc_port.cpp,v $ +// Revision 1.8 2011/08/24 22:05:36 acg +// Torsten Maehne: initialization changes to remove warnings. +// +// Revision 1.7 2011/08/15 16:43:24 acg +// Torsten Maehne: changes to remove unused argument warnings. +// +// Revision 1.6 2011/08/07 19:08:01 acg +// Andy Goodrich: moved logs to end of file so line number synching works +// better between versions. +// +// Revision 1.5 2011/08/07 18:53:09 acg +// Philipp A. Hartmann: add virtual instances of the bind function for +// base classes to eliminate warning messages for clang platforms. +// +// Revision 1.4 2011/05/09 04:07:37 acg +// Philipp A. Hartmann: +// (1) Restore hierarchy in all phase callbacks. +// (2) Ensure calls to before_end_of_elaboration. +// +// Revision 1.3 2011/02/18 20:23:45 acg +// Andy Goodrich: Copyright update. +// +// Revision 1.2 2011/02/14 17:50:16 acg +// Andy Goodrich: testing for sc_port and sc_export instantiations during +// end of elaboration and issuing appropriate error messages. +// +// Revision 1.1.1.1 2006/12/15 20:20:04 acg +// SystemC 2.3 +// +// Revision 1.11 2006/08/29 23:34:59 acg +// Andy Goodrich: added bind_count() method to allow users to determine which +// ports are connected in before_end_of_elaboration(). +// +// Revision 1.10 2006/05/08 17:52:47 acg +// Andy Goodrich: +// (1) added David Long's forward declarations for friend functions, +// methods, and operators to keep the Microsoft compiler happy. +// (2) Added delta_count() method to sc_prim_channel for use by +// sc_signal so that the friend declaration in sc_simcontext.h +// can be for a non-templated class (i.e., sc_prim_channel.) +// +// Revision 1.9 2006/02/02 20:43:09 acg +// Andy Goodrich: Added an existence linked list to sc_event_finder so that +// the dynamically allocated instances can be freed after port binding +// completes. This replaces the individual deletions in ~sc_bind_ef, as these +// caused an exception if an sc_event_finder instance was used more than +// once, due to a double freeing of the instance. +// +// Revision 1.7 2006/01/26 21:00:50 acg +// Andy Goodrich: conversion to use sc_event::notify(SC_ZERO_TIME) instead of +// sc_event::notify_delayed() +// +// Revision 1.6 2006/01/25 00:31:11 acg +// Andy Goodrich: Changed over to use a standard message id of +// SC_ID_IEEE_1666_DEPRECATION for all deprecation messages. +// +// Revision 1.5 2006/01/24 20:46:31 acg +// Andy Goodrich: changes to eliminate use of deprecated features. For instance, +// using notify(SC_ZERO_TIME) in place of notify_delayed(). +// +// Revision 1.4 2006/01/13 20:41:59 acg +// Andy Goodrich: Changes to add port registration to the things that are +// checked when SC_NO_WRITE_CHECK is not defined. +// +// Revision 1.3 2006/01/13 18:47:42 acg +// Added $Log command so that CVS comments are reproduced in the source. +// + +// Taf! diff --git a/ext/systemc/src/sysc/communication/sc_port.h b/ext/systemc/src/sysc/communication/sc_port.h new file mode 100644 index 000000000..a126657e6 --- /dev/null +++ b/ext/systemc/src/sysc/communication/sc_port.h @@ -0,0 +1,732 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_port.h -- Base classes of all port classes. + + Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21 + + CHANGE LOG IS AT THE END OF THE FILE + *****************************************************************************/ + +#ifndef SC_PORT_H +#define SC_PORT_H + + +#include "sysc/communication/sc_communication_ids.h" +#include "sysc/communication/sc_interface.h" +#include "sysc/kernel/sc_event.h" +#include "sysc/kernel/sc_object.h" +#include "sysc/kernel/sc_process.h" +#include <typeinfo> + +#if ! defined( SC_DISABLE_VIRTUAL_BIND ) +# define SC_VIRTUAL_ virtual +#else +# define SC_VIRTUAL_ /* non-virtual */ +#endif + +namespace sc_core { + +class sc_event_finder; + +struct sc_bind_info; + +enum sc_port_policy +{ + SC_ONE_OR_MORE_BOUND, // Default + SC_ZERO_OR_MORE_BOUND, + SC_ALL_BOUND +}; + + +// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +// BEWARE: Ports can only be created and bound during elaboration. +// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + + +// ---------------------------------------------------------------------------- +// CLASS : sc_port_base +// +// Abstract base class for class sc_port_b. +// ---------------------------------------------------------------------------- + +class sc_port_base +: public sc_object +{ + friend class sc_module; + friend class sc_port_registry; + friend class sc_sensitive; + friend class sc_sensitive_pos; + friend class sc_sensitive_neg; + +public: + + // typedefs + + typedef sc_port_base this_type; + +public: + + int bind_count(); + + // get the first interface without checking for nil + virtual sc_interface* get_interface() = 0; + virtual const sc_interface* get_interface() const = 0; + + virtual const char* kind() const + { return "sc_port_base"; } + +protected: + + // constructors + explicit sc_port_base( int max_size_, + sc_port_policy policy=SC_ONE_OR_MORE_BOUND ); + sc_port_base( const char* name_, int max_size_, + sc_port_policy policy=SC_ONE_OR_MORE_BOUND ); + + // destructor + virtual ~sc_port_base(); + + // bind interface to this port + void bind( sc_interface& interface_ ); + + // bind parent port to this port + void bind( this_type& parent_ ); + + // called by pbind (for internal use only) + virtual int vbind( sc_interface& ) = 0; + virtual int vbind( sc_port_base& ) = 0; + + // called by complete_binding (for internal use only) + virtual void add_interface( sc_interface* ) = 0; + virtual int interface_count() = 0; + virtual const char* if_typename() const = 0; + + // called by construction_done (does nothing by default) + virtual void before_end_of_elaboration(); + + // called by elaboration_done (does nothing) + virtual void end_of_elaboration(); + + // called by start_simulation (does nothing by default) + virtual void start_of_simulation(); + + // called by simulation_done (does nothing by default) + virtual void end_of_simulation(); + + // error reporting + void report_error( const char* id, const char* add_msg = 0) const; + +protected: + // called by the sc_sensitive* classes + virtual void make_sensitive( sc_thread_handle, sc_event_finder* = 0 ) const; + virtual void make_sensitive( sc_method_handle, sc_event_finder* = 0 ) const; + void add_static_event( + sc_method_handle process_p, const sc_event& event) const; + void add_static_event( + sc_thread_handle process_p, const sc_event& event) const; + +private: + + // called by class sc_module for positional binding + int pbind( sc_interface& ); + int pbind( sc_port_base& ); + + + // support methods + int first_parent(); + void insert_parent( int ); + + // called when construction is done + void construction_done(); + + // called when elaboration is done + void complete_binding(); + void elaboration_done(); + + // called before simulation starts + void start_simulation(); + + // called after simulation ends + void simulation_done(); + +protected: + + sc_bind_info* m_bind_info; + +private: + + // disabled + sc_port_base(); + sc_port_base( const this_type& ); + this_type& operator = ( const this_type& ); +}; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_port_registry +// +// Registry for all ports. +// FOR INTERNAL USE ONLY! +// ---------------------------------------------------------------------------- + +class sc_port_registry +{ + friend class sc_simcontext; + +public: + + void insert( sc_port_base* ); + void remove( sc_port_base* ); + + int size() const + { return m_port_vec.size(); } + +private: + + // constructor + explicit sc_port_registry( sc_simcontext& simc_ ); + + // destructor + ~sc_port_registry(); + + // called when by construction_done and elaboration done + void complete_binding(); + + // called when construction is done + bool construction_done(); + + // called when elaboration is done + void elaboration_done(); + + // called before simulation starts + void start_simulation(); + + // called after simulation ends + void simulation_done(); + + static void replace_port( sc_port_registry* ); + +private: + + int m_construction_done; + std::vector<sc_port_base*> m_port_vec; + sc_simcontext* m_simc; + +private: + + // disabled + sc_port_registry(); + sc_port_registry( const sc_port_registry& ); + sc_port_registry& operator = ( const sc_port_registry& ); +}; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_port_b +// +// Abstract base class for class sc_port. +// ---------------------------------------------------------------------------- + +template <class IF> +class sc_port_b +: public sc_port_base +{ +public: + + friend class sc_sensitive; + friend class sc_sensitive_neg; + friend class sc_sensitive_pos; + + // typedefs + + typedef sc_port_base base_type; + typedef sc_port_b<IF> this_type; + typedef this_type port_type; + +public: + + // bind an interface of type IF to this port + + SC_VIRTUAL_ void bind( IF& interface_ ) + { base_type::bind( interface_ ); } + + void operator () ( IF& interface_ ) + { this->bind( interface_ ); } + + + // bind a parent port with type IF to this port + + SC_VIRTUAL_ void bind( port_type& parent_ ) + { base_type::bind( parent_ ); } + + void operator () ( port_type& parent_ ) + { this->bind( parent_ ); } + + + // number of connected interfaces + + int size() const + { return m_interface_vec.size(); } + + + // allow to call methods provided by the first interface + IF* operator -> (); + const IF* operator -> () const; + + + // allow to call methods provided by interface at index + inline const IF* get_interface( int iface_i ) const; + inline IF* get_interface( int iface_i ); + IF* operator [] ( int index_ ) + { return get_interface( index_ ); } + const IF* operator [] ( int index_ ) const + { return get_interface( index_ ); } + + + // get the first interface without checking for nil + + virtual sc_interface* get_interface() + { return m_interface; } + + virtual const sc_interface* get_interface() const + { return m_interface; } + +protected: + + // constructors + + explicit sc_port_b( int max_size_, + sc_port_policy policy=SC_ONE_OR_MORE_BOUND ) : + base_type( max_size_, policy ), m_interface( 0 ), m_interface_vec() + {} + + sc_port_b( const char* name_, int max_size_, + sc_port_policy policy=SC_ONE_OR_MORE_BOUND ) : + base_type( name_, max_size_, policy ), m_interface( 0 ), + m_interface_vec() + {} + + + // destructor (does nothing) + + virtual ~sc_port_b() + {} + + + // called by pbind (for internal use only) + virtual int vbind( sc_interface& ); + virtual int vbind( sc_port_base& ); + +protected: + + // called by the sc_sensitive* classes + virtual void make_sensitive( sc_thread_handle, sc_event_finder* = 0 ) const; + virtual void make_sensitive( sc_method_handle, sc_event_finder* = 0 ) const; + +private: + + // called by complete_binding (for internal use only) + virtual void add_interface( sc_interface* ); + virtual const char* if_typename() const; + virtual int interface_count(); + + // disabled + sc_port_b(); + sc_port_b( const this_type& ); + this_type& operator = ( const this_type& ); + +private: + + IF* m_interface; // first interface in interface vec + std::vector<IF*> m_interface_vec; +}; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_port +// +// Generic port class and base class for other port classes. +// N is the maximum number of channels (with interface IF) that can be bound +// to this port. N <= 0 means no maximum. +// ---------------------------------------------------------------------------- + +extern void sc_warn_port_constructor(); + +template <class IF, int N = 1, sc_port_policy P=SC_ONE_OR_MORE_BOUND> +class sc_port +: public sc_port_b<IF> +{ + // typdefs + + typedef sc_port_b<IF> base_type; + typedef sc_port<IF,N,P> this_type; + +public: + + // constructors + + sc_port() + : base_type( N, P ) + {} + + explicit sc_port( const char* name_ ) + : base_type( name_, N, P ) + {} + + explicit sc_port( IF& interface_ ) + : base_type( N, P ) + { sc_warn_port_constructor(); base_type::bind( interface_ ); } + + sc_port( const char* name_, IF& interface_ ) + : base_type( name_, N, P ) + { sc_warn_port_constructor(); base_type::bind( interface_ ); } + + explicit sc_port( base_type& parent_ ) + : base_type( N, P ) + { sc_warn_port_constructor(); base_type::bind( parent_ ); } + + sc_port( const char* name_, base_type& parent_ ) + : base_type( name_, N, P ) + { sc_warn_port_constructor(); base_type::bind( parent_ ); } + + sc_port( this_type& parent_ ) + : base_type( N, P ) + { sc_warn_port_constructor(); base_type::bind( parent_ ); } + + sc_port( const char* name_, this_type& parent_ ) + : base_type( name_, N, P ) + { sc_warn_port_constructor(); base_type::bind( parent_ ); } + + + // destructor (does nothing) + + virtual ~sc_port() + {} + + virtual const char* kind() const + { return "sc_port"; } + +private: + + // disabled + sc_port( const this_type& ); + this_type& operator = ( const this_type& ); +}; + + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + +// ---------------------------------------------------------------------------- +// CLASS : sc_port_b +// +// Abstract base class for class sc_port. +// ---------------------------------------------------------------------------- + +// allow to call methods provided by the first interface + +template <class IF> +inline +IF* +sc_port_b<IF>::operator -> () +{ + if( m_interface == 0 ) { + report_error( SC_ID_GET_IF_, "port is not bound" ); + } + return m_interface; +} + +template <class IF> +inline +const IF* +sc_port_b<IF>::operator -> () const +{ + if( m_interface == 0 ) { + report_error( SC_ID_GET_IF_, "port is not bound" ); + } + return m_interface; +} + + +// allow to call methods provided by interface at index +// +// note that we special-case index of zero, since the method may be +// called before binding has occurred, and we need to return a zero +// in that case not an error. + +template <class IF> +inline +IF* +sc_port_b<IF>::get_interface( int index_ ) +{ + if ( index_ == 0 ) { + return m_interface; + } + else if( index_ < 0 || index_ >= size() ) { + report_error( SC_ID_GET_IF_, "index out of range" ); + } + return m_interface_vec[index_]; +} + +template <class IF> +inline +const IF* +sc_port_b<IF>::get_interface( int index_ ) const +{ + if ( index_ == 0 ) { + return m_interface; + } + else if( index_ < 0 || index_ >= size() ) { + report_error( SC_ID_GET_IF_, "index out of range" ); + } + return m_interface_vec[index_]; +} + + +// called by pbind (for internal use only) + +template <class IF> +inline +int +sc_port_b<IF>::vbind( sc_interface& interface_ ) +{ + IF* iface = DCAST<IF*>( &interface_ ); + if( iface == 0 ) { + // type mismatch + return 2; + } + base_type::bind( *iface ); + return 0; +} + +template <class IF> +inline +int +sc_port_b<IF>::vbind( sc_port_base& parent_ ) +{ + this_type* parent = DCAST<this_type*>( &parent_ ); + if( parent == 0 ) { + // type mismatch + return 2; + } + base_type::bind( *parent ); + return 0; +} + + +// called by complete_binding (for internal use only) + +template <class IF> +inline +void +sc_port_b<IF>::add_interface( sc_interface* interface_ ) +{ + IF* iface = DCAST<IF*>( interface_ ); + assert( iface != 0 ); + + // make sure that the interface is not already bound: + + int size = m_interface_vec.size(); + for ( int i = 0; i < size; i++ ) + { + if ( iface == m_interface_vec[i] ) + { + report_error( SC_ID_BIND_IF_TO_PORT_, + "interface already bound to port" ); + } + } + + // "bind" the interface and make sure our short cut for 0 is set up. + + m_interface_vec.push_back( iface ); + m_interface = m_interface_vec[0]; +} + +template <class IF> +inline +const char* +sc_port_b<IF>::if_typename() const +{ + return typeid( IF ).name(); +} + +template <class IF> +inline +int +sc_port_b<IF>::interface_count() +{ + return m_interface_vec.size(); +} + +template <class IF> +void +sc_port_b<IF>::make_sensitive( sc_thread_handle handle_p, + sc_event_finder* event_finder_ ) const +{ + if ( m_bind_info == 0 ) + { + int if_n = m_interface_vec.size(); + for ( int if_i = 0; if_i < if_n; if_i++ ) + { + IF* iface_p = m_interface_vec[if_i]; + assert( iface_p != 0 ); + add_static_event( handle_p, iface_p->default_event() ); + } + } + else + { + sc_port_base::make_sensitive( handle_p, event_finder_ ); + } +} + +template <class IF> +void +sc_port_b<IF>::make_sensitive( sc_method_handle handle_p, + sc_event_finder* event_finder_ ) const +{ + if ( m_bind_info == 0 ) + { + int if_n = m_interface_vec.size(); + for ( int if_i = 0; if_i < if_n; if_i++ ) + { + IF* iface_p = m_interface_vec[if_i]; + assert( iface_p != 0 ); + add_static_event( handle_p, iface_p->default_event() ); + } + } + else + { + sc_port_base::make_sensitive( handle_p, event_finder_ ); + } +} + +// ---------------------------------------------------------------------------- +// CLASS : sc_port +// +// Generic port class and base class for other port classes. +// N is the maximum number of channels (with interface IF) that can be bound +// to this port. N <= 0 means no maximum. +// ---------------------------------------------------------------------------- + +} // namespace sc_core + +#undef SC_VIRTUAL_ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: Andy Goodrich, Forte, + Bishnupriya Bhattacharya, Cadence Design Systems, + 25 August, 2003 + Description of Modification: phase callbacks + + Name, Affiliation, Date: Andy Goodrich, Forte Design Systems + 12 December, 2005 + Description of Modification: multiport binding policy changes + + + *****************************************************************************/ + +/* +$Log: sc_port.h,v $ +Revision 1.10 2011/08/26 20:45:41 acg + Andy Goodrich: moved the modification log to the end of the file to + eliminate source line number skew when check-ins are done. + +Revision 1.9 2011/08/24 22:05:36 acg + Torsten Maehne: initialization changes to remove warnings. + +Revision 1.8 2011/08/07 19:08:01 acg + Andy Goodrich: moved logs to end of file so line number synching works + better between versions. + +Revision 1.7 2011/08/07 18:53:09 acg + Philipp A. Hartmann: add virtual instances of the bind function for + base classes to eliminate warning messages for clang platforms. + +Revision 1.6 2011/05/09 04:07:37 acg + Philipp A. Hartmann: + (1) Restore hierarchy in all phase callbacks. + (2) Ensure calls to before_end_of_elaboration. + +Revision 1.5 2011/03/30 16:46:10 acg + Andy Goodrich: added a signature and removed a virtual specification + to eliminate warnings with certain compilers. + +Revision 1.4 2011/02/18 20:23:45 acg + Andy Goodrich: Copyright update. + +Revision 1.3 2011/01/20 16:52:15 acg + Andy Goodrich: changes for IEEE 1666 2011. + +Revision 1.2 2010/08/03 18:01:11 acg + Andy Goodrich: formatting. + +Revision 1.1.1.1 2006/12/15 20:20:04 acg +SystemC 2.3 + +Revision 1.5 2006/08/29 23:35:00 acg + Andy Goodrich: added bind_count() method to allow users to determine which + ports are connected in before_end_of_elaboration(). + +Revision 1.4 2006/05/08 17:52:47 acg + Andy Goodrich: + (1) added David Long's forward declarations for friend functions, + methods, and operators to keep the Microsoft compiler happy. + (2) Added delta_count() method to sc_prim_channel for use by + sc_signal so that the friend declaration in sc_simcontext.h + can be for a non-templated class (i.e., sc_prim_channel.) + +Revision 1.3 2006/01/24 20:46:31 acg +Andy Goodrich: changes to eliminate use of deprecated features. For instance, +using notify(SC_ZERO_TIME) in place of notify_delayed(). + +Revision 1.2 2006/01/03 23:18:26 acg +Changed copyright to include 2006. + +Revision 1.1.1.1 2005/12/19 23:16:43 acg +First check in of SystemC 2.1 into its own archive. + +Revision 1.10 2005/09/15 23:01:51 acg +Added std:: prefix to appropriate methods and types to get around +issues with the Edison Front End. + +Revision 1.9 2005/08/10 01:35:59 acg +Changes for 64-bit support. + +Revision 1.8 2005/04/03 22:52:51 acg +Namespace changes. + +Revision 1.7 2005/03/21 22:31:32 acg +Changes to sc_core namespace. + +Revision 1.6 2004/09/27 21:02:54 acg +Andy Goodrich - Forte Design Systems, Inc. + - Added a $Log comment so that CVS checkin comments will appear in + checked out source. + +*/ + +#endif + +// Taf! diff --git a/ext/systemc/src/sysc/communication/sc_prim_channel.cpp b/ext/systemc/src/sysc/communication/sc_prim_channel.cpp new file mode 100644 index 000000000..067884281 --- /dev/null +++ b/ext/systemc/src/sysc/communication/sc_prim_channel.cpp @@ -0,0 +1,429 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_prim_channel.cpp -- Abstract base class of all primitive channel + classes. + + Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21 + + CHANGE LOG IS AT THE END OF THE FILE + *****************************************************************************/ + +#include "sysc/communication/sc_prim_channel.h" +#include "sysc/communication/sc_communication_ids.h" +#include "sysc/kernel/sc_simcontext.h" +#include "sysc/kernel/sc_module.h" +#include "sysc/kernel/sc_object_int.h" + +#ifndef SC_DISABLE_ASYNC_UPDATES +# include "sysc/communication/sc_host_mutex.h" +#endif + +namespace sc_core { + +// ---------------------------------------------------------------------------- +// CLASS : sc_prim_channel +// +// Abstract base class of all primitive channel classes. +// ---------------------------------------------------------------------------- + +// constructors + +sc_prim_channel::sc_prim_channel() +: sc_object( 0 ), + m_registry( simcontext()->get_prim_channel_registry() ), + m_update_next_p( 0 ) +{ + m_registry->insert( *this ); +} + +sc_prim_channel::sc_prim_channel( const char* name_ ) +: sc_object( name_ ), + m_registry( simcontext()->get_prim_channel_registry() ), + m_update_next_p( 0 ) +{ + m_registry->insert( *this ); +} + + +// destructor + +sc_prim_channel::~sc_prim_channel() +{ + m_registry->remove( *this ); +} + + +// the update method (does nothing by default) + +void +sc_prim_channel::update() +{} + + +// called by construction_done (does nothing by default) + +void sc_prim_channel::before_end_of_elaboration() +{} + +// called when construction is done + +void +sc_prim_channel::construction_done() +{ + sc_object::hierarchy_scope scope( get_parent_object() ); + before_end_of_elaboration(); +} + +// called by elaboration_done (does nothing by default) + +void +sc_prim_channel::end_of_elaboration() +{} + + +// called when elaboration is done + +void +sc_prim_channel::elaboration_done() +{ + sc_object::hierarchy_scope scope( get_parent_object() ); + end_of_elaboration(); +} + +// called by start_simulation (does nothing) + +void +sc_prim_channel::start_of_simulation() +{} + +// called before simulation begins + +void +sc_prim_channel::start_simulation() +{ + sc_object::hierarchy_scope scope( get_parent_object() ); + start_of_simulation(); +} + +// called by simulation_done (does nothing) + +void +sc_prim_channel::end_of_simulation() +{} + +// called after simulation ends + +void +sc_prim_channel::simulation_done() +{ + sc_object::hierarchy_scope scope( get_parent_object() ); + end_of_simulation(); +} + +// ---------------------------------------------------------------------------- +// CLASS : sc_prim_channel_registry::async_update_list +// +// Thread-safe list of pending external updates +// FOR INTERNAL USE ONLY! +// ---------------------------------------------------------------------------- + +class sc_prim_channel_registry::async_update_list +{ +#ifndef SC_DISABLE_ASYNC_UPDATES +public: + + bool pending() const + { + return m_push_queue.size() != 0; + } + + void append( sc_prim_channel& prim_channel_ ) + { + sc_scoped_lock lock( m_mutex ); + m_push_queue.push_back( &prim_channel_ ); + // return releases the mutex + } + + void accept_updates() + { + sc_assert( ! m_pop_queue.size() ); + { + sc_scoped_lock lock( m_mutex ); + m_push_queue.swap( m_pop_queue ); + // leaving the block releases the mutex + } + + std::vector< sc_prim_channel* >::const_iterator + it = m_pop_queue.begin(), end = m_pop_queue.end(); + while( it!= end ) + { + // we use request_update instead of perform_update + // to skip duplicates + (*it++)->request_update(); + } + m_pop_queue.clear(); + } + +private: + sc_host_mutex m_mutex; + std::vector< sc_prim_channel* > m_push_queue; + std::vector< sc_prim_channel* > m_pop_queue; + +#endif // ! SC_DISABLE_ASYNC_UPDATES +}; + +// ---------------------------------------------------------------------------- +// CLASS : sc_prim_channel_registry +// +// Registry for all primitive channels. +// FOR INTERNAL USE ONLY! +// ---------------------------------------------------------------------------- + +void +sc_prim_channel_registry::insert( sc_prim_channel& prim_channel_ ) +{ + if( sc_is_running() ) { + SC_REPORT_ERROR( SC_ID_INSERT_PRIM_CHANNEL_, "simulation running" ); + } + + if( m_simc->elaboration_done() ) { + + SC_REPORT_ERROR( SC_ID_INSERT_PRIM_CHANNEL_, "elaboration done" ); + } + +#ifdef DEBUG_SYSTEMC + // check if prim_channel_ is already inserted + for( int i = 0; i < size(); ++ i ) { + if( &prim_channel_ == m_prim_channel_vec[i] ) { + SC_REPORT_ERROR( SC_ID_INSERT_PRIM_CHANNEL_, "already inserted" ); + } + } +#endif + + // insert + m_prim_channel_vec.push_back( &prim_channel_ ); + +} + +void +sc_prim_channel_registry::remove( sc_prim_channel& prim_channel_ ) +{ + int i; + for( i = 0; i < size(); ++ i ) { + if( &prim_channel_ == m_prim_channel_vec[i] ) { + break; + } + } + if( i == size() ) { + SC_REPORT_ERROR( SC_ID_REMOVE_PRIM_CHANNEL_, 0 ); + } + + // remove + m_prim_channel_vec[i] = m_prim_channel_vec[size() - 1]; + m_prim_channel_vec.resize(size()-1); +} + +bool +sc_prim_channel_registry::pending_async_updates() const +{ +#ifndef SC_DISABLE_ASYNC_UPDATES + return m_async_update_list_p->pending(); +#else + return false; +#endif +} + +void +sc_prim_channel_registry::async_request_update( sc_prim_channel& prim_channel_ ) +{ +#ifndef SC_DISABLE_ASYNC_UPDATES + m_async_update_list_p->append( prim_channel_ ); +#else + SC_REPORT_ERROR( SC_ID_NO_ASYNC_UPDATE_, prim_channel_.name() ); +#endif +} + +// +---------------------------------------------------------------------------- +// |"sc_prim_channel_registry::perform_update" +// | +// | This method updates the values of the primitive channels in its update +// | lists. +// +---------------------------------------------------------------------------- +void +sc_prim_channel_registry::perform_update() +{ + // Update the values for the primitive channels set external to the + // simulator. + +#ifndef SC_DISABLE_ASYNC_UPDATES + if( m_async_update_list_p->pending() ) + m_async_update_list_p->accept_updates(); +#endif + + sc_prim_channel* next_p; // Next update to perform. + sc_prim_channel* now_p; // Update now performing. + + // Update the values for the primitive channels in the simulator's list. + + now_p = m_update_list_p; + m_update_list_p = (sc_prim_channel*)sc_prim_channel::list_end; + for ( ; now_p != (sc_prim_channel*)sc_prim_channel::list_end; + now_p = next_p ) + { + next_p = now_p->m_update_next_p; + now_p->perform_update(); + } +} + +// constructor + +sc_prim_channel_registry::sc_prim_channel_registry( sc_simcontext& simc_ ) + : m_async_update_list_p(0) + , m_construction_done(0) + , m_prim_channel_vec() + , m_simc( &simc_ ) + , m_update_list_p((sc_prim_channel*)sc_prim_channel::list_end) +{ +# ifndef SC_DISABLE_ASYNC_UPDATES + m_async_update_list_p = new async_update_list(); +# endif +} + + +// destructor + +sc_prim_channel_registry::~sc_prim_channel_registry() +{ + delete m_async_update_list_p; +} + +// called when construction is done + +bool +sc_prim_channel_registry::construction_done() +{ + if( size() == m_construction_done ) + // nothing has been updated + return true; + + for( ; m_construction_done < size(); ++m_construction_done ) { + m_prim_channel_vec[m_construction_done]->construction_done(); + } + + return false; +} + + +// called when elaboration is done + +void +sc_prim_channel_registry::elaboration_done() +{ + for( int i = 0; i < size(); ++ i ) { + m_prim_channel_vec[i]->elaboration_done(); + } +} + +// called before simulation begins + +void +sc_prim_channel_registry::start_simulation() +{ + for( int i = 0; i < size(); ++ i ) { + m_prim_channel_vec[i]->start_simulation(); + } +} + +// called after simulation ends + +void +sc_prim_channel_registry::simulation_done() +{ + for( int i = 0; i < size(); ++ i ) { + m_prim_channel_vec[i]->simulation_done(); + } +} + +} // namespace sc_core + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: Andy Goodrich, Forte, + Bishnupriya Bhattacharya, Cadence Design Systems, + 25 August, 2003 + + Description of Modification: phase callbacks + + *****************************************************************************/ + + +// $Log: sc_prim_channel.cpp,v $ +// Revision 1.11 2011/08/26 21:38:32 acg +// Philipp A. Hartmann: removed unused switch m_construction_done. +// +// Revision 1.10 2011/08/26 20:45:41 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +// Revision 1.9 2011/08/24 22:05:36 acg +// Torsten Maehne: initialization changes to remove warnings. +// +// Revision 1.8 2011/05/09 04:07:37 acg +// Philipp A. Hartmann: +// (1) Restore hierarchy in all phase callbacks. +// (2) Ensure calls to before_end_of_elaboration. +// +// Revision 1.7 2011/04/19 02:36:26 acg +// Philipp A. Hartmann: new aysnc_update and mutex support. +// +// Revision 1.6 2011/02/18 20:31:05 acg +// Philipp A. Hartmann: added error messages for calls that cannot be done +// after elaboration. +// +// Revision 1.5 2011/02/18 20:23:45 acg +// Andy Goodrich: Copyright update. +// +// Revision 1.4 2011/02/14 17:50:16 acg +// Andy Goodrich: testing for sc_port and sc_export instantiations during +// end of elaboration and issuing appropriate error messages. +// +// Revision 1.3 2010/12/07 20:36:49 acg +// Andy Goodrich: fix pointer that should have been initialized to zero. +// +// Revision 1.2 2010/12/07 19:50:36 acg +// Andy Goodrich: addition of writer policies, courtesy of Philipp Hartmann. +// +// Revision 1.1.1.1 2006/12/15 20:20:04 acg +// SystemC 2.3 +// +// Revision 1.4 2006/01/26 21:00:50 acg +// Andy Goodrich: conversion to use sc_event::notify(SC_ZERO_TIME) instead of +// sc_event::notify_delayed() +// +// Revision 1.3 2006/01/13 18:47:42 acg +// Added $Log command so that CVS comments are reproduced in the source. +// + +// Taf! diff --git a/ext/systemc/src/sysc/communication/sc_prim_channel.h b/ext/systemc/src/sysc/communication/sc_prim_channel.h new file mode 100644 index 000000000..4a52fe7cb --- /dev/null +++ b/ext/systemc/src/sysc/communication/sc_prim_channel.h @@ -0,0 +1,420 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_prim_channel.h -- Abstract base class of all primitive channel classes. + + Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21 + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + +#ifndef SC_PRIM_CHANNEL_H +#define SC_PRIM_CHANNEL_H + +#include "sysc/kernel/sc_object.h" +#include "sysc/kernel/sc_wait.h" +#include "sysc/kernel/sc_wait_cthread.h" + +namespace sc_core { + +// ---------------------------------------------------------------------------- +// CLASS : sc_prim_channel +// +// Abstract base class of all primitive channel classes. +// ---------------------------------------------------------------------------- + +class sc_prim_channel +: public sc_object +{ + friend class sc_prim_channel_registry; + +public: + enum { list_end = 0xdb }; +public: + virtual const char* kind() const + { return "sc_prim_channel"; } + + inline bool update_requested() + { return m_update_next_p != (sc_prim_channel*)list_end; } + + // request the update method to be executed during the update phase + inline void request_update(); + + // request the update method to be executed during the update phase + // from a process external to the simulator. + void async_request_update(); + +protected: + + // constructors + sc_prim_channel(); + explicit sc_prim_channel( const char* ); + + // destructor + virtual ~sc_prim_channel(); + + // the update method (does nothing by default) + virtual void update(); + + // called by construction_done (does nothing by default) + virtual void before_end_of_elaboration(); + + // called by elaboration_done (does nothing by default) + virtual void end_of_elaboration(); + + // called by start_simulation (does nothing by default) + virtual void start_of_simulation(); + + // called by simulation_done (does nothing by default) + virtual void end_of_simulation(); + +protected: + + // to avoid calling sc_get_curr_simcontext() + + // static sensitivity for SC_THREADs and SC_CTHREADs + + void wait() + { sc_core::wait( simcontext() ); } + + + // dynamic sensitivity for SC_THREADs and SC_CTHREADs + + void wait( const sc_event& e ) + { sc_core::wait( e, simcontext() ); } + + void wait( const sc_event_or_list& el ) + { sc_core::wait( el, simcontext() ); } + + void wait( const sc_event_and_list& el ) + { sc_core::wait( el, simcontext() ); } + + void wait( const sc_time& t ) + { sc_core::wait( t, simcontext() ); } + + void wait( double v, sc_time_unit tu ) + { sc_core::wait( sc_time( v, tu, simcontext() ), simcontext() ); } + + void wait( const sc_time& t, const sc_event& e ) + { sc_core::wait( t, e, simcontext() ); } + + void wait( double v, sc_time_unit tu, const sc_event& e ) + { sc_core::wait( sc_time( v, tu, simcontext() ), e, simcontext() ); } + + void wait( const sc_time& t, const sc_event_or_list& el ) + { sc_core::wait( t, el, simcontext() ); } + + void wait( double v, sc_time_unit tu, const sc_event_or_list& el ) + { sc_core::wait( sc_time( v, tu, simcontext() ), el, simcontext() ); } + + void wait( const sc_time& t, const sc_event_and_list& el ) + { sc_core::wait( t, el, simcontext() ); } + + void wait( double v, sc_time_unit tu, const sc_event_and_list& el ) + { sc_core::wait( sc_time( v, tu, simcontext() ), el, simcontext() ); } + + void wait( int n ) + { sc_core::wait( n, simcontext() ); } + + + // static sensitivity for SC_METHODs + + void next_trigger() + { sc_core::next_trigger( simcontext() ); } + + + // dynamic sensitivity for SC_METHODs + + void next_trigger( const sc_event& e ) + { sc_core::next_trigger( e, simcontext() ); } + + void next_trigger( const sc_event_or_list& el ) + { sc_core::next_trigger( el, simcontext() ); } + + void next_trigger( const sc_event_and_list& el ) + { sc_core::next_trigger( el, simcontext() ); } + + void next_trigger( const sc_time& t ) + { sc_core::next_trigger( t, simcontext() ); } + + void next_trigger( double v, sc_time_unit tu ) + {sc_core::next_trigger( sc_time( v, tu, simcontext() ), simcontext() );} + + void next_trigger( const sc_time& t, const sc_event& e ) + { sc_core::next_trigger( t, e, simcontext() ); } + + void next_trigger( double v, sc_time_unit tu, const sc_event& e ) + { sc_core::next_trigger( + sc_time( v, tu, simcontext() ), e, simcontext() ); } + + void next_trigger( const sc_time& t, const sc_event_or_list& el ) + { sc_core::next_trigger( t, el, simcontext() ); } + + void next_trigger( double v, sc_time_unit tu, const sc_event_or_list& el ) + { sc_core::next_trigger( + sc_time( v, tu, simcontext() ), el, simcontext() ); } + + void next_trigger( const sc_time& t, const sc_event_and_list& el ) + { sc_core::next_trigger( t, el, simcontext() ); } + + void next_trigger( double v, sc_time_unit tu, const sc_event_and_list& el ) + { sc_core::next_trigger( + sc_time( v, tu, simcontext() ), el, simcontext() ); } + + + // for SC_METHODs and SC_THREADs and SC_CTHREADs + + bool timed_out() + { return sc_core::timed_out( simcontext() ); } + + +#if 0 // @@@@#### + // delta count maintenance + sc_dt::uint64 delta_count() + { return simcontext()->m_delta_count; } +#endif + +private: + + // called during the update phase of a delta cycle (if requested) + void perform_update(); + + // called when construction is done + void construction_done(); + + // called when elaboration is done + void elaboration_done(); + + // called before simulation starts + void start_simulation(); + + // called after simulation ends + void simulation_done(); + + // disabled + sc_prim_channel( const sc_prim_channel& ); + sc_prim_channel& operator = ( const sc_prim_channel& ); + +private: + + sc_prim_channel_registry* m_registry; // Update list manager. + sc_prim_channel* m_update_next_p; // Next entry in update list. +}; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_prim_channel_registry +// +// Registry for all primitive channels. +// FOR INTERNAL USE ONLY! +// ---------------------------------------------------------------------------- + +class sc_prim_channel_registry +{ + friend class sc_simcontext; + +public: + + void insert( sc_prim_channel& ); + void remove( sc_prim_channel& ); + + + int size() const + { return m_prim_channel_vec.size(); } + + inline void request_update( sc_prim_channel& ); + void async_request_update( sc_prim_channel& ); + + bool pending_updates() const + { + return m_update_list_p != (sc_prim_channel*)sc_prim_channel::list_end + || pending_async_updates(); + } + + bool pending_async_updates() const; + +private: + + // constructor + explicit sc_prim_channel_registry( sc_simcontext& simc_ ); + + // destructor + ~sc_prim_channel_registry(); + + // called during the update phase of a delta cycle + void perform_update(); + + // called when construction is done + bool construction_done(); + + // called when elaboration is done + void elaboration_done(); + + // called before simulation starts + void start_simulation(); + + // called after simulation ends + void simulation_done(); + + // disabled + sc_prim_channel_registry(); + sc_prim_channel_registry( const sc_prim_channel_registry& ); + sc_prim_channel_registry& operator = ( const sc_prim_channel_registry& ); + +private: + class async_update_list; + + async_update_list* m_async_update_list_p; // external updates. + int m_construction_done; // # of constructs. + std::vector<sc_prim_channel*> m_prim_channel_vec; // existing channels. + sc_simcontext* m_simc; // simulator context. + sc_prim_channel* m_update_list_p; // internal updates. +}; + + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + +// ---------------------------------------------------------------------------- +// CLASS : sc_prim_channel_registry +// +// Registry for all primitive channels. +// FOR INTERNAL USE ONLY! +// ---------------------------------------------------------------------------- + +inline +void +sc_prim_channel_registry::request_update( sc_prim_channel& prim_channel_ ) +{ + prim_channel_.m_update_next_p = m_update_list_p; + m_update_list_p = &prim_channel_; +} + +// ---------------------------------------------------------------------------- +// CLASS : sc_prim_channel +// +// Abstract base class of all primitive channel classes. +// ---------------------------------------------------------------------------- + +// request the update method (to be executed during the update phase) + +inline +void +sc_prim_channel::request_update() +{ + if( ! m_update_next_p ) { + m_registry->request_update( *this ); + } +} + +// request the update method from external to the simulator (to be executed +// during the update phase) + +inline +void +sc_prim_channel::async_request_update() +{ + m_registry->async_request_update(*this); +} + + +// called during the update phase of a delta cycle (if requested) + +inline +void +sc_prim_channel::perform_update() +{ + update(); + m_update_next_p = 0; +} + + +} // namespace sc_core + + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: Andy Goodrich, Forte, + Bishnupriya Bhattacharya, Cadence Design Systems, + 25 August, 2003 + Description of Modification: phase callbacks + + *****************************************************************************/ +//$Log: sc_prim_channel.h,v $ +//Revision 1.10 2011/08/26 21:38:32 acg +// Philipp A. Hartmann: removed unused switch m_construction_done. +// +//Revision 1.9 2011/08/07 19:08:01 acg +// Andy Goodrich: moved logs to end of file so line number synching works +// better between versions. +// +//Revision 1.8 2011/05/09 04:07:37 acg +// Philipp A. Hartmann: +// (1) Restore hierarchy in all phase callbacks. +// (2) Ensure calls to before_end_of_elaboration. +// +//Revision 1.7 2011/05/05 17:44:01 acg +// Philip A. Hartmann: change in the name of pending_async_updates. +// +//Revision 1.6 2011/04/19 15:03:48 acg +// Philipp A. Hartmann: remove ASYNC_UPDATE preprocessor check from header. +// +//Revision 1.5 2011/04/19 02:36:26 acg +// Philipp A. Hartmann: new aysnc_update and mutex support. +// +//Revision 1.4 2011/04/05 20:48:09 acg +// Andy Goodrich: changes to make sure that event(), posedge() and negedge() +// only return true if the clock has not moved. +// +//Revision 1.3 2011/02/18 20:23:45 acg +// Andy Goodrich: Copyright update. +// +//Revision 1.2 2011/01/20 16:52:15 acg +// Andy Goodrich: changes for IEEE 1666 2011. +// +//Revision 1.1.1.1 2006/12/15 20:20:04 acg +//SystemC 2.3 +// +//Revision 1.3 2006/05/08 17:52:47 acg +// Andy Goodrich: +// (1) added David Long's forward declarations for friend functions, +// methods, and operators to keep the Microsoft compiler happy. +// (2) Added delta_count() method to sc_prim_channel for use by +// sc_signal so that the friend declaration in sc_simcontext.h +// can be for a non-templated class (i.e., sc_prim_channel.) +// +//Revision 1.2 2006/01/03 23:18:26 acg +//Changed copyright to include 2006. +// +//Revision 1.1.1.1 2005/12/19 23:16:43 acg +//First check in of SystemC 2.1 into its own archive. +// +//Revision 1.10 2005/07/30 03:44:11 acg +//Changes from 2.1. +// +//Revision 1.9 2005/06/10 22:43:55 acg +//Added CVS change log annotation. + +#endif + +// Taf! diff --git a/ext/systemc/src/sysc/communication/sc_semaphore.cpp b/ext/systemc/src/sysc/communication/sc_semaphore.cpp new file mode 100644 index 000000000..d90424431 --- /dev/null +++ b/ext/systemc/src/sysc/communication/sc_semaphore.cpp @@ -0,0 +1,148 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_semaphore.cpp -- The sc_semaphore primitive channel class. + + Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21 + + CHANGE LOG IS AT THE END OF THE FILE + *****************************************************************************/ + +#include "sysc/communication/sc_communication_ids.h" +#include "sysc/communication/sc_semaphore.h" +#include "sysc/kernel/sc_simcontext.h" +#include "sysc/kernel/sc_wait.h" + +namespace sc_core { + +// ---------------------------------------------------------------------------- +// CLASS : sc_semaphore +// +// The sc_semaphore primitive channel class. +// ---------------------------------------------------------------------------- + +// error reporting + +void +sc_semaphore::report_error( const char* id, const char* add_msg ) const +{ + char msg[BUFSIZ]; + if( add_msg != 0 ) { + std::sprintf( msg, "%s: semaphore '%s'", add_msg, name() ); + } else { + std::sprintf( msg, "semaphore '%s'", name() ); + } + SC_REPORT_ERROR( id, msg ); +} + + +// constructors + +sc_semaphore::sc_semaphore( int init_value_ ) +: sc_object( sc_gen_unique_name( "semaphore" ) ), + m_free( (std::string(SC_KERNEL_EVENT_PREFIX)+"_free_event").c_str() ), + m_value( init_value_ ) +{ + if( m_value < 0 ) { + report_error( SC_ID_INVALID_SEMAPHORE_VALUE_ ); + } +} + +sc_semaphore::sc_semaphore( const char* name_, int init_value_ ) +: sc_object( name_ ), + m_free( (std::string(SC_KERNEL_EVENT_PREFIX)+"_free_event").c_str() ), + m_value( init_value_ ) +{ + if( m_value < 0 ) { + report_error( SC_ID_INVALID_SEMAPHORE_VALUE_ ); + } +} + + +// interface methods + +// lock (take) the semaphore, block if not available + +int +sc_semaphore::wait() +{ + while( in_use() ) { + sc_core::wait( m_free, sc_get_curr_simcontext() ); + } + -- m_value; + return 0; +} + + +// lock (take) the semaphore, return -1 if not available + +int +sc_semaphore::trywait() +{ + if( in_use() ) { + return -1; + } + -- m_value; + return 0; +} + + +// unlock (give) the semaphore + +int +sc_semaphore::post() +{ + ++m_value; + m_free.notify(); + return 0; +} + +} // namespace sc_core + +// $Log: sc_semaphore.cpp,v $ +// Revision 1.5 2011/08/26 20:45:42 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +// Revision 1.4 2011/03/23 16:17:22 acg +// Andy Goodrich: hide the sc_events that are kernel related. +// +// Revision 1.3 2011/02/18 20:23:45 acg +// Andy Goodrich: Copyright update. +// +// Revision 1.2 2010/11/02 16:31:01 acg +// Andy Goodrich: changed object derivation to use sc_object rather than +// sc_prim_channel as the parent class. +// +// Revision 1.1.1.1 2006/12/15 20:20:04 acg +// SystemC 2.3 +// +// Revision 1.6 2006/11/28 20:30:49 acg +// Andy Goodrich: updated from 2.2 source. sc_event_queue constructors +// collapsed into a single constructor with an optional argument to get +// the sc_module_name stack done correctly. Class name prefixing added +// to sc_semaphore calls to wait() to keep gcc 4.x happy. +// +// Revision 1.3 2006/01/13 18:47:42 acg +// Added $Log command so that CVS comments are reproduced in the source. +// + +// Taf! diff --git a/ext/systemc/src/sysc/communication/sc_semaphore.h b/ext/systemc/src/sysc/communication/sc_semaphore.h new file mode 100644 index 000000000..3ce991ebf --- /dev/null +++ b/ext/systemc/src/sysc/communication/sc_semaphore.h @@ -0,0 +1,133 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_semaphore.h -- The sc_semaphore primitive channel class. + + Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21 + + CHANGE LOG IS AT THE END OF THE FILE + *****************************************************************************/ + +#ifndef SC_SEMAPHORE_H +#define SC_SEMAPHORE_H + + +#include "sysc/kernel/sc_event.h" +#include "sysc/kernel/sc_object.h" +#include "sysc/communication/sc_semaphore_if.h" + +namespace sc_core { + +// ---------------------------------------------------------------------------- +// CLASS : sc_semaphore +// +// The sc_semaphore primitive channel class. +// ---------------------------------------------------------------------------- + +class sc_semaphore +: public sc_semaphore_if, + public sc_object +{ +public: + + // constructors + + explicit sc_semaphore( int init_value_ ); + sc_semaphore( const char* name_, int init_value_ ); + + + // interface methods + + // lock (take) the semaphore, block if not available + virtual int wait(); + + // lock (take) the semaphore, return -1 if not available + virtual int trywait(); + + // unlock (give) the semaphore + virtual int post(); + + // get the value of the semaphore + virtual int get_value() const + { return m_value; } + + virtual const char* kind() const + { return "sc_semaphore"; } + +protected: + + // support methods + + bool in_use() const + { return ( m_value <= 0 ); } + + + // error reporting + void report_error( const char* id, const char* add_msg = 0 ) const; + +protected: + + sc_event m_free; // event to block on when m_value is negative + int m_value; // current value of the semaphore + +private: + + // disabled + sc_semaphore( const sc_semaphore& ); + sc_semaphore& operator = ( const sc_semaphore& ); +}; + +} // namespace sc_core + +//$Log: sc_semaphore.h,v $ +//Revision 1.4 2011/08/26 20:45:42 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +//Revision 1.3 2011/02/18 20:23:45 acg +// Andy Goodrich: Copyright update. +// +//Revision 1.2 2010/11/02 16:31:01 acg +// Andy Goodrich: changed object derivation to use sc_object rather than +// sc_prim_channel as the parent class. +// +//Revision 1.1.1.1 2006/12/15 20:20:04 acg +//SystemC 2.3 +// +//Revision 1.4 2006/11/28 20:30:49 acg +// Andy Goodrich: updated from 2.2 source. sc_event_queue constructors +// collapsed into a single constructor with an optional argument to get +// the sc_module_name stack done correctly. Class name prefixing added +// to sc_semaphore calls to wait() to keep gcc 4.x happy. +// +//Revision 1.2 2006/01/03 23:18:26 acg +//Changed copyright to include 2006. +// +//Revision 1.1.1.1 2005/12/19 23:16:43 acg +//First check in of SystemC 2.1 into its own archive. +// +//Revision 1.9 2005/06/10 22:43:55 acg +//Added CVS change log annotation. +// + +#endif + +// Taf! diff --git a/ext/systemc/src/sysc/communication/sc_semaphore_if.h b/ext/systemc/src/sysc/communication/sc_semaphore_if.h new file mode 100644 index 000000000..b0839e40a --- /dev/null +++ b/ext/systemc/src/sysc/communication/sc_semaphore_if.h @@ -0,0 +1,100 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_semaphore_if.h -- The sc_semaphore_if interface class. + + Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21 + + CHANGE LOG IS AT THE END OF THE FILE + *****************************************************************************/ + +#ifndef SC_SEMAPHORE_IF_H +#define SC_SEMAPHORE_IF_H + +#include "sysc/communication/sc_interface.h" + +namespace sc_core { + +// ---------------------------------------------------------------------------- +// CLASS : sc_semaphore_if +// +// The sc_semaphore_if interface class. +// ---------------------------------------------------------------------------- + +class sc_semaphore_if +: virtual public sc_interface +{ +public: + + // the classical operations: wait(), trywait(), and post() + + // lock (take) the semaphore, block if not available + virtual int wait() = 0; + + // lock (take) the semaphore, return -1 if not available + virtual int trywait() = 0; + + // unlock (give) the semaphore + virtual int post() = 0; + + // get the value of the semphore + virtual int get_value() const = 0; + +protected: + + // constructor + + sc_semaphore_if() + {} + +private: + + // disabled + sc_semaphore_if( const sc_semaphore_if& ); + sc_semaphore_if& operator = ( const sc_semaphore_if& ); +}; + +} // namespace sc_core + +//$Log: sc_semaphore_if.h,v $ +//Revision 1.3 2011/08/26 20:45:42 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +//Revision 1.2 2011/02/18 20:23:45 acg +// Andy Goodrich: Copyright update. +// +//Revision 1.1.1.1 2006/12/15 20:20:04 acg +//SystemC 2.3 +// +//Revision 1.2 2006/01/03 23:18:26 acg +//Changed copyright to include 2006. +// +//Revision 1.1.1.1 2005/12/19 23:16:43 acg +//First check in of SystemC 2.1 into its own archive. +// +//Revision 1.8 2005/06/10 22:43:55 acg +//Added CVS change log annotation. +// + +#endif + +// Taf! diff --git a/ext/systemc/src/sysc/communication/sc_signal.cpp b/ext/systemc/src/sysc/communication/sc_signal.cpp new file mode 100644 index 000000000..3b2df8a7c --- /dev/null +++ b/ext/systemc/src/sysc/communication/sc_signal.cpp @@ -0,0 +1,456 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_signal.cpp -- The sc_signal<T> primitive channel class. + + Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21 + + CHANGE LOG IS AT THE END OF THE FILE + *****************************************************************************/ + + +#include "sysc/communication/sc_communication_ids.h" +#include "sysc/utils/sc_utils_ids.h" +#include "sysc/communication/sc_signal.h" +#include "sysc/datatypes/int/sc_signed.h" +#include "sysc/datatypes/int/sc_unsigned.h" +#include "sysc/datatypes/bit/sc_lv_base.h" +#include "sysc/kernel/sc_reset.h" + +#include <sstream> + +using sc_dt::sc_lv_base; +using sc_dt::sc_signed; +using sc_dt::sc_unsigned; +using sc_dt::int64; +using sc_dt::uint64; + +namespace sc_core { + +// to avoid code bloat in sc_signal<T> + +void +sc_signal_invalid_writer( sc_object* target, sc_object* first_writer, + sc_object* second_writer, bool check_delta ) +{ + if ( second_writer ) + { + std::stringstream msg; + + msg + << "\n signal " + "`" << target->name() << "' " + "(" << target->kind() << ")" + << "\n first driver " + "`" << first_writer->name() << "' " + " (" << first_writer->kind() << ")" + << "\n second driver " + "`" << second_writer->name() << "' " + "(" << second_writer->kind() << ")"; + + if( check_delta ) + { + msg << "\n first conflicting write in delta cycle " + << sc_delta_count(); + } + SC_REPORT_ERROR( SC_ID_MORE_THAN_ONE_SIGNAL_DRIVER_, + msg.str().c_str() ); + } +} + +bool +sc_writer_policy_check_port:: + check_port( sc_object* target, sc_port_base * port_, bool is_output ) +{ + if ( is_output && sc_get_curr_simcontext()->write_check() ) + { + // an out or inout port; only one can be connected + if( m_output != 0) { + sc_signal_invalid_writer( target, m_output, port_, false ); + return false; + } else { + m_output = port_; + } + } + return true; +} + +void sc_deprecated_get_data_ref() +{ + static bool warn_get_data_ref_deprecated=true; + if ( warn_get_data_ref_deprecated ) + { + warn_get_data_ref_deprecated=false; + SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, + "get_data_ref() is deprecated, use read() instead" ); + } +} + +void sc_deprecated_get_new_value() +{ + static bool warn_new_value=true; + if ( warn_new_value ) + { + warn_new_value=false; + SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, + "sc_signal<T>::get_new_value() is deprecated"); + } +} + +void sc_deprecated_trace() +{ + static bool warn_trace_deprecated=true; + if ( warn_trace_deprecated ) + { + warn_trace_deprecated=false; + SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, + "sc_signal<T>::trace() is deprecated"); + } +} + +sc_event* +sc_lazy_kernel_event( sc_event** ev, const char* name ) +{ + if ( !*ev ) { + std::string kernel_name = SC_KERNEL_EVENT_PREFIX "_"; + kernel_name.append( name ); + *ev = new sc_event( kernel_name.c_str() ); + } + return *ev; + +} + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + +template< sc_writer_policy POL > +void +sc_signal<bool,POL>::register_port( sc_port_base& port_, + const char* if_typename_ ) +{ + bool is_output = std::string( if_typename_ ) == typeid(if_type).name(); + if( !policy_type::check_port( this, &port_, is_output ) ) + ((void)0); // fallback? error has been suppressed ... +} + + +// write the new value + +template< sc_writer_policy POL > +void +sc_signal<bool,POL>::write( const bool& value_ ) +{ + bool value_changed = !( m_cur_val == value_ ); + if ( !policy_type::check_write(this, value_changed) ) + return; + m_new_val = value_; + if( value_changed ) { + request_update(); + } +} + +template< sc_writer_policy POL > +inline +void +sc_signal<bool,POL>::print( ::std::ostream& os ) const +{ + os << m_cur_val; +} + +template< sc_writer_policy POL > +void +sc_signal<bool,POL>::dump( ::std::ostream& os ) const +{ + os << " name = " << name() << ::std::endl; + os << " value = " << m_cur_val << ::std::endl; + os << "new value = " << m_new_val << ::std::endl; +} + + +template< sc_writer_policy POL > +void +sc_signal<bool,POL>::update() +{ + policy_type::update(); + if( !( m_new_val == m_cur_val ) ) { + do_update(); + } +} + +template< sc_writer_policy POL > +void +sc_signal<bool,POL>::do_update() +{ + // order of execution below is important, the notify_processes() call + // must come after the update of m_cur_val for things to work properly! + + m_cur_val = m_new_val; + + if ( m_reset_p ) m_reset_p->notify_processes(); + + if ( m_change_event_p ) m_change_event_p->notify_next_delta(); + + sc_event* event_p = this->m_cur_val + ? m_posedge_event_p : m_negedge_event_p; + if ( event_p ) event_p->notify_next_delta(); + + m_change_stamp = simcontext()->change_stamp(); +} + +// (edge) event methods + +template< sc_writer_policy POL > +const sc_event& +sc_signal<bool,POL>::value_changed_event() const +{ + return *sc_lazy_kernel_event(&m_change_event_p,"value_changed_event"); +} + +template< sc_writer_policy POL > +const sc_event& +sc_signal<bool,POL>::posedge_event() const +{ + return *sc_lazy_kernel_event(&m_posedge_event_p,"posedge_event"); +} + +template< sc_writer_policy POL > +const sc_event& +sc_signal<bool,POL>::negedge_event() const +{ + return *sc_lazy_kernel_event(&m_negedge_event_p,"negedge_event"); +} + + +// reset support: + +template< sc_writer_policy POL > +sc_reset* +sc_signal<bool,POL>::is_reset() const +{ + sc_reset* result_p; + if ( !m_reset_p ) m_reset_p = new sc_reset( this ); + result_p = m_reset_p; + return result_p; +} + +// destructor + +template< sc_writer_policy POL > +sc_signal<bool,POL>::~sc_signal() +{ + delete m_change_event_p; + delete m_negedge_event_p; + delete m_posedge_event_p; + delete m_reset_p; +} + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + +template< sc_writer_policy POL > +void +sc_signal<sc_dt::sc_logic,POL>::register_port( sc_port_base& port_, + const char* if_typename_ ) +{ + bool is_output = std::string( if_typename_ ) == typeid(if_type).name(); + if( !policy_type::check_port( this, &port_, is_output ) ) + ((void)0); // fallback? error has been suppressed ... +} + + +// write the new value + +template< sc_writer_policy POL > +inline +void +sc_signal<sc_dt::sc_logic,POL>::write( const sc_dt::sc_logic& value_ ) +{ + bool value_changed = !( m_cur_val == value_ ); + if ( !policy_type::check_write(this, value_changed) ) + return; + + m_new_val = value_; + if( value_changed ) { + request_update(); + } +} + +template< sc_writer_policy POL > +inline +void +sc_signal<sc_dt::sc_logic,POL>::print( ::std::ostream& os ) const +{ + os << m_cur_val; +} + +template< sc_writer_policy POL > +void +sc_signal<sc_dt::sc_logic,POL>::dump( ::std::ostream& os ) const +{ + os << " name = " << name() << ::std::endl; + os << " value = " << m_cur_val << ::std::endl; + os << "new value = " << m_new_val << ::std::endl; +} + + +template< sc_writer_policy POL > +void +sc_signal<sc_dt::sc_logic,POL>::update() +{ + policy_type::update(); + if( !( m_new_val == m_cur_val ) ) { + do_update(); + } +} + +template< sc_writer_policy POL > +void +sc_signal<sc_dt::sc_logic,POL>::do_update() +{ + m_cur_val = m_new_val; + + if ( m_change_event_p ) m_change_event_p->notify_next_delta(); + + if( m_posedge_event_p && (this->m_cur_val == sc_dt::SC_LOGIC_1) ) { + m_posedge_event_p->notify_next_delta(); + } + else if( m_negedge_event_p && (this->m_cur_val == sc_dt::SC_LOGIC_0) ) { + m_negedge_event_p->notify_next_delta(); + } + + m_change_stamp = simcontext()->change_stamp(); +} + +// (edge) event methods + +template< sc_writer_policy POL > +const sc_event& +sc_signal<sc_dt::sc_logic,POL>::value_changed_event() const +{ + return *sc_lazy_kernel_event(&m_change_event_p,"value_changed_event"); +} + +template< sc_writer_policy POL > +const sc_event& +sc_signal<sc_dt::sc_logic,POL>::posedge_event() const +{ + return *sc_lazy_kernel_event(&m_posedge_event_p,"posedge_event"); +} + +template< sc_writer_policy POL > +const sc_event& +sc_signal<sc_dt::sc_logic,POL>::negedge_event() const +{ + return *sc_lazy_kernel_event(&m_negedge_event_p,"negedge_event"); +} + + +// template instantiations for writer policies + +template class sc_signal<bool,SC_ONE_WRITER>; +template class sc_signal<bool,SC_MANY_WRITERS>; +template class sc_signal<bool,SC_UNCHECKED_WRITERS>; + +template class sc_signal<sc_dt::sc_logic,SC_ONE_WRITER>; +template class sc_signal<sc_dt::sc_logic,SC_MANY_WRITERS>; +template class sc_signal<sc_dt::sc_logic,SC_UNCHECKED_WRITERS>; + +} // namespace sc_core + +/* +$Log: sc_signal.cpp,v $ +Revision 1.9 2011/08/26 20:45:42 acg + Andy Goodrich: moved the modification log to the end of the file to + eliminate source line number skew when check-ins are done. + +Revision 1.8 2011/02/18 20:23:45 acg + Andy Goodrich: Copyright update. + +Revision 1.7 2011/02/18 20:08:14 acg + Philipp A. Hartmann: addition of include for sstream for MSVC. + +Revision 1.6 2011/01/25 20:50:37 acg + Andy Goodrich: changes for IEEE 1666 2011. + +Revision 1.5 2010/12/07 19:50:36 acg + Andy Goodrich: addition of writer policies, courtesy of Philipp Hartmann. + +Revision 1.3 2007/04/09 21:59:49 acg + Andy Goodrich: fixed multiple write notification bug where writes + done outside the simulator were being treated as multiple writes. + +Revision 1.2 2007/04/02 17:24:01 acg + Andy Goodrich: added check for null writer pointers in sc_signal invalid + writer method. + +Revision 1.1.1.1 2006/12/15 20:20:04 acg +SystemC 2.3 + +Revision 1.7 2006/04/11 23:11:57 acg + Andy Goodrich: Changes for reset support that only includes + sc_cthread_process instances. + +Revision 1.6 2006/03/13 20:19:44 acg + Andy Goodrich: changed sc_event instances into pointers to sc_event instances + that are allocated as needed. This saves considerable storage for large + numbers of signals, etc. + +Revision 1.5 2006/01/25 00:31:11 acg + Andy Goodrich: Changed over to use a standard message id of + SC_ID_IEEE_1666_DEPRECATION for all deprecation messages. + +Revision 1.4 2006/01/24 20:46:32 acg +Andy Goodrich: changes to eliminate use of deprecated features. For instance, +using notify(SC_ZERO_TIME) in place of notify_delayed(). + +Revision 1.3 2006/01/18 21:42:26 acg +Andy Goodrich: Changes for check writer support, and tightening up sc_clock +port usage. + +Revision 1.2 2006/01/03 23:18:26 acg +Changed copyright to include 2006. + +Revision 1.1.1.1 2005/12/19 23:16:43 acg +First check in of SystemC 2.1 into its own archive. + +Revision 1.14 2005/09/15 23:01:51 acg +Added std:: prefix to appropriate methods and types to get around +issues with the Edison Front End. + +Revision 1.13 2005/05/08 19:04:06 acg +Fix bug in concat_set(int64,off). Other changes from 2.1 examples usage. + +Revision 1.12 2005/04/04 00:15:51 acg +Changes for directory name change to sys from systemc. +Changes for sc_string going to std::string. +Changes for sc_pvector going to std::vector. +Changes for reference pools for bit and part selections. +Changes for const sc_concatref support. + +Revision 1.10 2005/03/21 22:31:32 acg +Changes to sc_core namespace. + +Revision 1.9 2004/09/27 21:02:54 acg +Andy Goodrich - Forte Design Systems, Inc. + - Added a $Log comment so that CVS checkin comments will appear in + checked out source. + +*/ + +// Taf! diff --git a/ext/systemc/src/sysc/communication/sc_signal.h b/ext/systemc/src/sysc/communication/sc_signal.h new file mode 100644 index 000000000..2a72ef55e --- /dev/null +++ b/ext/systemc/src/sysc/communication/sc_signal.h @@ -0,0 +1,741 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_signal.h -- The sc_signal<T> primitive channel class. + + Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21 + + CHANGE LOG IS AT THE END OF THE FILE + *****************************************************************************/ + +#ifndef SC_SIGNAL_H +#define SC_SIGNAL_H + +#include "sysc/communication/sc_port.h" +#include "sysc/communication/sc_prim_channel.h" +#include "sysc/communication/sc_signal_ifs.h" +#include "sysc/communication/sc_writer_policy.h" +#include "sysc/kernel/sc_event.h" +#include "sysc/kernel/sc_process.h" +#include "sysc/kernel/sc_simcontext.h" +#include "sysc/datatypes/bit/sc_logic.h" +#include "sysc/tracing/sc_trace.h" +#include <typeinfo> + +namespace sc_core { + +// to avoid code bloat in sc_signal<T> + +extern void sc_deprecated_get_data_ref(); +extern void sc_deprecated_get_new_value(); +extern void sc_deprecated_trace(); +extern sc_event * sc_lazy_kernel_event( sc_event**, const char* name ); + +inline +bool +sc_writer_policy_check_write::check_write( sc_object* target, bool ) +{ + sc_object* writer_p = sc_get_curr_simcontext()->get_current_writer(); + if( SC_UNLIKELY_(m_writer_p == 0) ) { + m_writer_p = writer_p; + } else if( SC_UNLIKELY_(m_writer_p != writer_p && writer_p != 0) ) { + sc_signal_invalid_writer( target, m_writer_p, writer_p, m_check_delta ); + // error has been suppressed, ignore check as well + // return false; + } + return true; +} + +// ---------------------------------------------------------------------------- +// CLASS : sc_signal<T> +// +// The sc_signal<T> primitive channel class. +// ---------------------------------------------------------------------------- + +template< class T, sc_writer_policy POL /* = SC_DEFAULT_WRITER_POLICY */ > +class sc_signal + : public sc_signal_inout_if<T> + , public sc_prim_channel + , protected sc_writer_policy_check<POL> +{ +protected: + typedef sc_signal_inout_if<T> if_type; + typedef sc_signal<T,POL> this_type; + typedef sc_writer_policy_check<POL> policy_type; + +public: // constructors and destructor: + + sc_signal() + : sc_prim_channel( sc_gen_unique_name( "signal" ) ), + m_change_event_p( 0 ), m_cur_val( T() ), + m_change_stamp( ~sc_dt::UINT64_ONE ), m_new_val( T() ) + {} + + explicit sc_signal( const char* name_) + : sc_prim_channel( name_ ), + m_change_event_p( 0 ), m_cur_val( T() ), + m_change_stamp( ~sc_dt::UINT64_ONE ), m_new_val( T() ) + {} + + sc_signal( const char* name_, const T& initial_value_ ) + : sc_prim_channel( name_ ) + , m_change_event_p( 0 ) + , m_cur_val( initial_value_ ) + , m_change_stamp( ~sc_dt::UINT64_ONE ) + , m_new_val( initial_value_ ) + {} + + virtual ~sc_signal() + { + delete m_change_event_p; + } + + + // interface methods + + virtual void register_port( sc_port_base&, const char* ); + + virtual sc_writer_policy get_writer_policy() const + { return POL; } + + // get the default event + virtual const sc_event& default_event() const + { return value_changed_event(); } + + // get the value changed event + virtual const sc_event& value_changed_event() const + { + return *sc_lazy_kernel_event( &m_change_event_p + , "value_changed_event"); + } + + + // read the current value + virtual const T& read() const + { return m_cur_val; } + + // get a reference to the current value (for tracing) + virtual const T& get_data_ref() const + { sc_deprecated_get_data_ref(); return m_cur_val; } + + + // was there an event? + virtual bool event() const + { return simcontext()->event_occurred(m_change_stamp); } + + // write the new value + virtual void write( const T& ); + + + // other methods + + operator const T& () const + { return read(); } + + + this_type& operator = ( const T& a ) + { write( a ); return *this; } + + this_type& operator = ( const sc_signal_in_if<T>& a ) + { write( a.read() ); return *this; } + + this_type& operator = ( const this_type& a ) + { write( a.read() ); return *this; } + + + const T& get_new_value() const + { sc_deprecated_get_new_value(); return m_new_val; } + + + void trace( sc_trace_file* tf ) const + { + sc_deprecated_trace(); +# ifdef DEBUG_SYSTEMC + sc_trace( tf, read(), name() ); +# else + if ( tf ) {} +# endif + } + + + virtual void print( ::std::ostream& = ::std::cout ) const; + virtual void dump( ::std::ostream& = ::std::cout ) const; + + virtual const char* kind() const + { return "sc_signal"; } + +protected: + + virtual void update(); + void do_update(); + +protected: + + mutable sc_event* m_change_event_p; + T m_cur_val; + sc_dt::uint64 m_change_stamp; // delta of last event + T m_new_val; + +private: + + // disabled + sc_signal( const this_type& ); +}; + + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + + +template< class T, sc_writer_policy POL > +inline +void +sc_signal<T,POL>::register_port( sc_port_base& port_ + , const char* if_typename_ ) +{ + + bool is_output = std::string( if_typename_ ) == typeid(if_type).name(); + if( !policy_type::check_port( this, &port_, is_output ) ) + ((void)0); // fallback? error has been suppressed ... +} + + +// write the new value + +template< class T, sc_writer_policy POL > +inline +void +sc_signal<T,POL>::write( const T& value_ ) +{ + bool value_changed = !( m_cur_val == value_ ); + if ( !policy_type::check_write(this, value_changed) ) + return; + + m_new_val = value_; + if( value_changed ) { + request_update(); + } +} + + +template< class T, sc_writer_policy POL > +inline +void +sc_signal<T,POL>::print( ::std::ostream& os ) const +{ + os << m_cur_val; +} + +template< class T, sc_writer_policy POL > +void +sc_signal<T,POL>::dump( ::std::ostream& os ) const +{ + os << " name = " << name() << ::std::endl; + os << " value = " << m_cur_val << ::std::endl; + os << "new value = " << m_new_val << ::std::endl; +} + + +template< class T, sc_writer_policy POL > +void +sc_signal<T,POL>::update() +{ + policy_type::update(); + if( !( m_new_val == m_cur_val ) ) { + do_update(); + } +} + +template< class T, sc_writer_policy POL > +void +sc_signal<T,POL>::do_update() +{ + m_cur_val = m_new_val; + if ( m_change_event_p ) m_change_event_p->notify_next_delta(); + m_change_stamp = simcontext()->change_stamp(); +} + +// ---------------------------------------------------------------------------- +// CLASS : sc_signal<bool> +// +// Specialization of sc_signal<T> for type bool. +// ---------------------------------------------------------------------------- + +class sc_reset; + +template< sc_writer_policy POL > +class sc_signal<bool,POL> + : public sc_signal_inout_if<bool> + , public sc_prim_channel + , protected sc_writer_policy_check<POL> +{ +protected: + typedef sc_signal_inout_if<bool> if_type; + typedef sc_signal<bool,POL> this_type; + typedef sc_writer_policy_check<POL> policy_type; + +public: // constructors and destructor: + + sc_signal() + : sc_prim_channel( sc_gen_unique_name( "signal" ) ), + m_change_event_p( 0 ), + m_cur_val( false ), + m_change_stamp( ~sc_dt::UINT64_ONE ), + m_negedge_event_p( 0 ), + m_new_val( false ), + m_posedge_event_p( 0 ), + m_reset_p( 0 ) + {} + + explicit sc_signal( const char* name_ ) + : sc_prim_channel( name_ ), + m_change_event_p( 0 ), + m_cur_val( false ), + m_change_stamp( ~sc_dt::UINT64_ONE ), + m_negedge_event_p( 0 ), + m_new_val( false ), + m_posedge_event_p( 0 ), + m_reset_p( 0 ) + {} + + sc_signal( const char* name_, bool initial_value_ ) + : sc_prim_channel( name_ ) + , m_change_event_p( 0 ) + , m_cur_val( initial_value_ ) + , m_change_stamp( ~sc_dt::UINT64_ONE ) + , m_negedge_event_p( 0 ) + , m_new_val( initial_value_ ) + , m_posedge_event_p( 0 ) + , m_reset_p( 0 ) + {} + + virtual ~sc_signal(); + + + // interface methods + + virtual void register_port( sc_port_base&, const char* ); + + virtual sc_writer_policy get_writer_policy() const + { return POL; } + + // get the default event + virtual const sc_event& default_event() const + { return value_changed_event(); } + + // get the value changed event + virtual const sc_event& value_changed_event() const; + + // get the positive edge event + virtual const sc_event& posedge_event() const; + + // get the negative edge event + virtual const sc_event& negedge_event() const; + + + // read the current value + virtual const bool& read() const + { return m_cur_val; } + + // get a reference to the current value (for tracing) + virtual const bool& get_data_ref() const + { sc_deprecated_get_data_ref(); return m_cur_val; } + + + // was there a value changed event? + virtual bool event() const + { return simcontext()->event_occurred(m_change_stamp); } + + // was there a positive edge event? + virtual bool posedge() const + { return ( event() && m_cur_val ); } + + // was there a negative edge event? + virtual bool negedge() const + { return ( event() && ! m_cur_val ); } + + // write the new value + virtual void write( const bool& ); + + // other methods + + operator const bool& () const + { return read(); } + + + this_type& operator = ( const bool& a ) + { write( a ); return *this; } + + this_type& operator = ( const sc_signal_in_if<bool>& a ) + { write( a.read() ); return *this; } + + this_type& operator = ( const this_type& a ) + { write( a.read() ); return *this; } + + + const bool& get_new_value() const + { sc_deprecated_get_new_value(); return m_new_val; } + + + void trace( sc_trace_file* tf ) const + { + sc_deprecated_trace(); +# ifdef DEBUG_SYSTEMC + sc_trace( tf, read(), name() ); +# else + if ( tf ) {} +# endif + } + + + virtual void print( ::std::ostream& = ::std::cout ) const; + virtual void dump( ::std::ostream& = ::std::cout ) const; + + virtual const char* kind() const + { return "sc_signal"; } + +protected: + + virtual void update(); + void do_update(); + + virtual bool is_clock() const { return false; } + +protected: + mutable sc_event* m_change_event_p; // value change event if present. + bool m_cur_val; // current value of object. + sc_dt::uint64 m_change_stamp; // delta of last event + mutable sc_event* m_negedge_event_p; // negative edge event if present. + bool m_new_val; // next value of object. + mutable sc_event* m_posedge_event_p; // positive edge event if present. + mutable sc_reset* m_reset_p; // reset mechanism if present. + +private: + + // reset creation + virtual sc_reset* is_reset() const; + + // disabled + sc_signal( const this_type& ); +}; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_signal<sc_dt::sc_logic> +// +// Specialization of sc_signal<T> for type sc_dt::sc_logic. +// ---------------------------------------------------------------------------- + +template< sc_writer_policy POL > +class sc_signal<sc_dt::sc_logic,POL> + : public sc_signal_inout_if<sc_dt::sc_logic> + , public sc_prim_channel + , protected sc_writer_policy_check<POL> +{ +protected: + typedef sc_signal_inout_if<sc_dt::sc_logic> if_type; + typedef sc_signal<sc_dt::sc_logic,POL> this_type; + typedef sc_writer_policy_check<POL> policy_type; + +public: // constructors and destructor: + + sc_signal() + : sc_prim_channel( sc_gen_unique_name( "signal" ) ), + m_change_event_p( 0 ), + m_cur_val(), + m_change_stamp( ~sc_dt::UINT64_ONE ), + m_negedge_event_p( 0 ), + m_new_val(), + m_posedge_event_p( 0 ) + {} + + explicit sc_signal( const char* name_ ) + : sc_prim_channel( name_ ), + m_change_event_p( 0 ), + m_cur_val(), + m_change_stamp( ~sc_dt::UINT64_ONE ), + m_negedge_event_p( 0 ), + m_new_val(), + m_posedge_event_p( 0 ) + {} + + sc_signal( const char* name_, sc_dt::sc_logic initial_value_ ) + : sc_prim_channel( name_ ) + , m_change_event_p( 0 ) + , m_cur_val( initial_value_ ) + , m_change_stamp( ~sc_dt::UINT64_ONE ) + , m_negedge_event_p( 0 ) + , m_new_val( initial_value_ ) + , m_posedge_event_p( 0 ) + {} + + virtual ~sc_signal() + { + delete m_change_event_p; + delete m_negedge_event_p; + delete m_posedge_event_p; + } + + + // interface methods + + virtual void register_port( sc_port_base&, const char* ); + + virtual sc_writer_policy get_writer_policy() const + { return POL; } + + // get the default event + virtual const sc_event& default_event() const + { return value_changed_event(); } + + // get the value changed event + virtual const sc_event& value_changed_event() const; + + // get the positive edge event + virtual const sc_event& posedge_event() const; + + // get the negative edge event + virtual const sc_event& negedge_event() const; + + + // read the current value + virtual const sc_dt::sc_logic& read() const + { return m_cur_val; } + + // get a reference to the current value (for tracing) + virtual const sc_dt::sc_logic& get_data_ref() const + { sc_deprecated_get_data_ref(); return m_cur_val; } + + + // was there an event? + virtual bool event() const + { return simcontext()->event_occurred(m_change_stamp); } + + // was there a positive edge event? + virtual bool posedge() const + { return ( event() && m_cur_val == sc_dt::SC_LOGIC_1 ); } + + // was there a negative edge event? + virtual bool negedge() const + { return ( event() && m_cur_val == sc_dt::SC_LOGIC_0 ); } + + + // write the new value + virtual void write( const sc_dt::sc_logic& ); + + + // other methods + + operator const sc_dt::sc_logic& () const + { return read(); } + + + this_type& operator = ( const sc_dt::sc_logic& a ) + { write( a ); return *this; } + + this_type& operator = ( const sc_signal_in_if<sc_dt::sc_logic>& a ) + { write( a.read() ); return *this; } + + this_type& operator = (const this_type& a) + { write( a.read() ); return *this; } + + + const sc_dt::sc_logic& get_new_value() const + { sc_deprecated_get_new_value(); return m_new_val; } + + + void trace( sc_trace_file* tf ) const + { + sc_deprecated_trace(); +# ifdef DEBUG_SYSTEMC + sc_trace( tf, read(), name() ); +# else + if ( tf ) {} +# endif + } + + virtual void print( ::std::ostream& = ::std::cout ) const; + virtual void dump( ::std::ostream& = ::std::cout ) const; + + virtual const char* kind() const + { return "sc_signal"; } + +protected: + + virtual void update(); + void do_update(); + +protected: + + mutable sc_event* m_change_event_p; // value change event if present. + sc_dt::sc_logic m_cur_val; // current value of object. + sc_dt::uint64 m_change_stamp; // delta of last event + mutable sc_event* m_negedge_event_p; // negative edge event if present. + sc_dt::sc_logic m_new_val; // next value of object. + mutable sc_event* m_posedge_event_p; // positive edge event if present. + +private: + + // disabled + sc_signal( const this_type& ); +}; + +// ---------------------------------------------------------------------------- + +template< typename T, sc_writer_policy POL > +inline +::std::ostream& +operator << ( ::std::ostream& os, const sc_signal<T,POL>& a ) +{ + return ( os << a.read() ); +} + + + +} // namespace sc_core + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ +//$Log: sc_signal.h,v $ +//Revision 1.16 2011/08/26 20:45:42 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +//Revision 1.15 2011/08/15 16:43:24 acg +// Torsten Maehne: changes to remove unused argument warnings. +// +//Revision 1.14 2011/06/25 17:08:38 acg +// Andy Goodrich: Jerome Cornet's changes to use libtool to build the +// library. +// +//Revision 1.13 2011/04/13 02:59:09 acg +// Andy Goodrich: made events internal to signals into kernel events. +// +//Revision 1.12 2011/04/08 18:22:46 acg +// Philipp A. Hartmann: use the context of the primitive channel to get +// the change stamp value. +// +//Revision 1.11 2011/04/05 20:48:09 acg +// Andy Goodrich: changes to make sure that event(), posedge() and negedge() +// only return true if the clock has not moved. +// +//Revision 1.10 2011/04/05 07:10:55 acg +// Andy Goodrich: added line that I dropped in sc_signal<sc_dt::sc_logic>. +// +//Revision 1.9 2011/04/05 06:15:18 acg +// Philipp A. Hartmann: sc_writer_policy: ignore no-ops in delta check. +// +//Revision 1.8 2011/03/23 16:17:22 acg +// Andy Goodrich: hide the sc_events that are kernel related. +// +//Revision 1.7 2011/03/06 15:55:08 acg +// Andy Goodrich: Changes for named events. +// +//Revision 1.6 2011/02/18 20:23:45 acg +// Andy Goodrich: Copyright update. +// +//Revision 1.5 2011/02/07 19:16:50 acg +// Andy Goodrich: changes for handling multiple writers. +// +//Revision 1.4 2011/01/25 20:50:37 acg +// Andy Goodrich: changes for IEEE 1666 2011. +// +//Revision 1.3 2010/12/07 19:50:37 acg +// Andy Goodrich: addition of writer policies, courtesy of Philipp Hartmann. +// +//Revision 1.1.1.1 2006/12/15 20:20:04 acg +//SystemC 2.3 +// +//Revision 1.14 2006/05/08 17:52:47 acg +// Andy Goodrich: +// (1) added David Long's forward declarations for friend functions, +// methods, and operators to keep the Microsoft compiler happy. +// (2) Added delta_count() method to sc_prim_channel for use by +// sc_signal so that the friend declaration in sc_simcontext.h +// can be for a non-templated class (i.e., sc_prim_channel.) +// +//Revision 1.12 2006/04/11 23:11:57 acg +// Andy Goodrich: Changes for reset support that only includes +// sc_cthread_process instances. +// +//Revision 1.11 2006/03/13 20:19:44 acg +// Andy Goodrich: changed sc_event instances into pointers to sc_event instances +// that are allocated as needed. This saves considerable storage for large +// numbers of signals, etc. +// +//Revision 1.10 2006/01/26 21:00:50 acg +// Andy Goodrich: conversion to use sc_event::notify(SC_ZERO_TIME) instead of +// sc_event::notify_delayed() +// +//Revision 1.9 2006/01/24 20:45:41 acg +//Andy Goodrich: converted notify_delayed() calls into notify_next_delta() calls +//to eliminate deprecation warnings. notify_next_delta() is an implemenation- +//dependent method of sc_event. It is simpler than notify_delayed(), and should +//speed up simulation speeds. +// +//Revision 1.8 2006/01/19 19:18:25 acg +//Andy Goodrich: eliminated check_writer in favor of inline code within the +//write() method since we always execute the check_writer code even when +//check writing is turned off. +// +//Revision 1.7 2006/01/19 00:30:57 acg +//Andy Goodrich: Yet another implementation for disabling write checks on +//signals. This version uses an environment variable, SC_SIGNAL_WRITE_CHECK, +//that when set to DISABLE will turn off write checking. +// +//Revision 1.6 2006/01/18 21:42:26 acg +//Andy Goodrich: Changes for check writer support, and tightening up sc_clock +//port usage. +// +//Revision 1.5 2006/01/13 20:41:59 acg +//Andy Goodrich: Changes to add port registration to the things that are +//checked when SC_NO_WRITE_CHECK is not defined. +// +//Revision 1.4 2006/01/13 18:47:20 acg +//Reversed sense of multiwriter signal check. It now defaults to ON unless the +//user defines SC_NO_WRITE_CHEK before inclusion of the file. +// +//Revision 1.3 2006/01/03 23:18:26 acg +//Changed copyright to include 2006. +// +//Revision 1.2 2005/12/20 21:58:18 acg +//Removed Makefile.in, changed the event() methods to use sc_simcontext::event_occurred. +// +//Revision 1.1.1.1 2005/12/19 23:16:43 acg +//First check in of SystemC 2.1 into its own archive. +// +//Revision 1.19 2005/09/15 23:01:51 acg +//Added std:: prefix to appropriate methods and types to get around +//issues with the Edison Front End. +// +//Revision 1.18 2005/06/10 22:43:55 acg +//Added CVS change log annotation. +// + +#endif + +// Taf! diff --git a/ext/systemc/src/sysc/communication/sc_signal_ifs.h b/ext/systemc/src/sysc/communication/sc_signal_ifs.h new file mode 100644 index 000000000..ad703aaa7 --- /dev/null +++ b/ext/systemc/src/sysc/communication/sc_signal_ifs.h @@ -0,0 +1,305 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_signal_ifs.h -- The sc_signal<T> interface classes. + + Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21 + + CHANGE LOG IS AT THE END OF THE FILE + *****************************************************************************/ + +#ifndef SC_SIGNAL_IFS_H +#define SC_SIGNAL_IFS_H + + +#include "sysc/communication/sc_interface.h" +#include "sysc/communication/sc_writer_policy.h" + + +namespace sc_dt +{ + class sc_logic; +} + +namespace sc_core { + +class sc_signal_bool_deval; +class sc_signal_logic_deval; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_signal_in_if<T> +// +// The sc_signal<T> input interface class. +// ---------------------------------------------------------------------------- + +template <class T> +class sc_signal_in_if +: virtual public sc_interface +{ +public: + + // get the value changed event + virtual const sc_event& value_changed_event() const = 0; + + + // read the current value + virtual const T& read() const = 0; + + // get a reference to the current value (for tracing) + virtual const T& get_data_ref() const = 0; + + + // was there a value changed event? + virtual bool event() const = 0; + +protected: + + // constructor + + sc_signal_in_if() + {} + +private: + + // disabled + sc_signal_in_if( const sc_signal_in_if<T>& ); + sc_signal_in_if<T>& operator = ( const sc_signal_in_if<T>& ); +}; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_signal_in_if<bool> +// +// Specialization of sc_signal_in_if<T> for type bool. +// ---------------------------------------------------------------------------- + +class sc_reset; + +template <> +class sc_signal_in_if<bool> +: virtual public sc_interface +{ + friend class sc_reset; +public: + + // get the value changed event + virtual const sc_event& value_changed_event() const = 0; + + // get the positive edge event + virtual const sc_event& posedge_event() const = 0; + + // get the negative edge event + virtual const sc_event& negedge_event() const = 0; + + + // read the current value + virtual const bool& read() const = 0; + + // get a reference to the current value (for tracing) + virtual const bool& get_data_ref() const = 0; + + + // was there a value changed event? + virtual bool event() const = 0; + + // was there a positive edge event? + virtual bool posedge() const = 0; + + // was there a negative edge event? + virtual bool negedge() const = 0; + +protected: + + // constructor + + sc_signal_in_if() + {} + +private: + + // disabled + sc_signal_in_if( const sc_signal_in_if<bool>& ); + sc_signal_in_if<bool>& operator = ( const sc_signal_in_if<bool>& ); + + // designate this object as a reset signal + virtual sc_reset* is_reset() const + { return NULL; } +}; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_signal_in_if<sc_dt::sc_logic> +// +// Specialization of sc_signal_in_if<T> for type sc_dt::sc_logic. +// ---------------------------------------------------------------------------- + +template <> +class sc_signal_in_if<sc_dt::sc_logic> +: virtual public sc_interface +{ +public: + + // get the value changed event + virtual const sc_event& value_changed_event() const = 0; + + // get the positive edge event + virtual const sc_event& posedge_event() const = 0; + + // get the negative edge event + virtual const sc_event& negedge_event() const = 0; + + + // read the current value + virtual const sc_dt::sc_logic& read() const = 0; + + // get a reference to the current value (for tracing) + virtual const sc_dt::sc_logic& get_data_ref() const = 0; + + + // was there a value changed event? + virtual bool event() const = 0; + + // was there a positive edge event? + virtual bool posedge() const = 0; + + // was there a negative edge event? + virtual bool negedge() const = 0; + + +protected: + + // constructor + + sc_signal_in_if() + {} + +private: + + // disabled + sc_signal_in_if( const sc_signal_in_if<sc_dt::sc_logic>& ); + sc_signal_in_if<sc_dt::sc_logic>& operator = ( + const sc_signal_in_if<sc_dt::sc_logic>& ); +}; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_signal_write_if<T> +// +// The standard output interface class. +// ---------------------------------------------------------------------------- +template< typename T > +class sc_signal_write_if : public virtual sc_interface +{ +public: + sc_signal_write_if() {} + // write the new value + virtual void write( const T& ) = 0; + virtual sc_writer_policy get_writer_policy() const + { return SC_DEFAULT_WRITER_POLICY; } +private: + // disabled + sc_signal_write_if( const sc_signal_write_if<T>& ); + sc_signal_write_if<T>& operator = ( const sc_signal_write_if<T>& ); +}; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_signal_inout_if<T> +// +// The sc_signal<T> input/output interface class. +// ---------------------------------------------------------------------------- + +template <class T> +class sc_signal_inout_if +: public sc_signal_in_if<T>, public sc_signal_write_if<T> +{ + +protected: + + // constructor + + sc_signal_inout_if() + {} + +private: + + // disabled + sc_signal_inout_if( const sc_signal_inout_if<T>& ); + sc_signal_inout_if<T>& operator = ( const sc_signal_inout_if<T>& ); +}; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_signal_out_if<T> +// +// The sc_signal<T> output interface class. +// ---------------------------------------------------------------------------- + +// sc_signal_out_if can also be read from, hence no difference with +// sc_signal_inout_if. + +#define sc_signal_out_if sc_signal_inout_if + +} // namespace sc_core + +//$Log: sc_signal_ifs.h,v $ +//Revision 1.4 2011/08/26 20:45:43 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +//Revision 1.3 2011/02/18 20:23:45 acg +// Andy Goodrich: Copyright update. +// +//Revision 1.2 2010/12/07 19:50:37 acg +// Andy Goodrich: addition of writer policies, courtesy of Philipp Hartmann. +// +//Revision 1.1.1.1 2006/12/15 20:20:04 acg +//SystemC 2.3 +// +//Revision 1.4 2006/08/29 23:35:00 acg +// Andy Goodrich: added bind_count() method to allow users to determine which +// ports are connected in before_end_of_elaboration(). +// +//Revision 1.3 2006/04/11 23:11:57 acg +// Andy Goodrich: Changes for reset support that only includes +// sc_cthread_process instances. +// +//Revision 1.2 2006/01/03 23:18:26 acg +//Changed copyright to include 2006. +// +//Revision 1.1.1.1 2005/12/19 23:16:43 acg +//First check in of SystemC 2.1 into its own archive. +// +//Revision 1.10 2005/09/15 23:01:51 acg +//Added std:: prefix to appropriate methods and types to get around +//issues with the Edison Front End. +// +//Revision 1.9 2005/06/29 18:12:12 acg +//Added $log. +// +//Revision 1.8 2005/06/10 22:43:55 acg +//Added CVS change log annotation. +// + +#endif + +// Taf! diff --git a/ext/systemc/src/sysc/communication/sc_signal_ports.cpp b/ext/systemc/src/sysc/communication/sc_signal_ports.cpp new file mode 100644 index 000000000..d3a182e54 --- /dev/null +++ b/ext/systemc/src/sysc/communication/sc_signal_ports.cpp @@ -0,0 +1,441 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_signal_ports.cpp -- The sc_signal<T> port classes. + + Original Author: Martin Janssen, Synopsys, Inc., 2001-08-20 + + CHANGE LOG IS AT THE END OF THE FILE + *****************************************************************************/ + +#include "sysc/communication/sc_signal_ports.h" +#include "sysc/datatypes/int/sc_signed.h" +#include "sysc/datatypes/int/sc_unsigned.h" +#include "sysc/datatypes/bit/sc_lv_base.h" +#include "sysc/utils/sc_utils_ids.h" + +namespace sc_core { + +// ---------------------------------------------------------------------------- +// CLASS : sc_in<bool> +// +// Specialization of sc_in<T> for type bool. +// ---------------------------------------------------------------------------- + +// called when elaboration is done + +void +sc_in<bool>::end_of_elaboration() +{ + if( m_traces != 0 ) { + for( int i = 0; i < (int)m_traces->size(); ++ i ) { + sc_trace_params* p = (*m_traces)[i]; + in_if_type* iface = DCAST<in_if_type*>( get_interface() ); + sc_trace( p->tf, iface->read(), p->name ); + } + remove_traces(); + } +} + +// called by sc_trace + +void +sc_in<bool>::add_trace_internal(sc_trace_file* tf_, + const std::string& name_) const +{ + if( tf_ != 0 ) { + if( m_traces == 0 ) { + m_traces = new sc_trace_params_vec; + } + m_traces->push_back( new sc_trace_params( tf_, name_ ) ); + } +} + +void +sc_in<bool>::add_trace(sc_trace_file* tf_, + const std::string& name_) const +{ + sc_deprecated_add_trace(); + add_trace_internal(tf_, name_); +} + +void +sc_in<bool>::remove_traces() const +{ + if( m_traces != 0 ) { + for( int i = m_traces->size() - 1; i >= 0; -- i ) { + delete (*m_traces)[i]; + } + delete m_traces; + m_traces = 0; + } +} + + +// called by pbind (for internal use only) + +int +sc_in<bool>::vbind( sc_interface& interface_ ) +{ + return sc_port_b<if_type>::vbind( interface_ ); +} + +int +sc_in<bool>::vbind( sc_port_base& parent_ ) +{ + in_port_type* in_parent = DCAST<in_port_type*>( &parent_ ); + if( in_parent != 0 ) { + sc_port_base::bind( *in_parent ); + return 0; + } + inout_port_type* inout_parent = DCAST<inout_port_type*>( &parent_ ); + if( inout_parent != 0 ) { + sc_port_base::bind( *inout_parent ); + return 0; + } + // type mismatch + return 2; +} + + +// ---------------------------------------------------------------------------- +// CLASS : sc_in<sc_logic> +// +// Specialization of sc_in<T> for type sc_logic. +// ---------------------------------------------------------------------------- + +// called when elaboration is done + +void +sc_in<sc_dt::sc_logic>::end_of_elaboration() +{ + if( m_traces != 0 ) { + for( int i = 0; i < (int)m_traces->size(); ++ i ) { + sc_trace_params* p = (*m_traces)[i]; + in_if_type* iface = DCAST<in_if_type*>( get_interface() ); + sc_trace( p->tf, iface->read(), p->name ); + } + remove_traces(); + } +} + + +// called by sc_trace + +void +sc_in<sc_dt::sc_logic>::add_trace_internal( sc_trace_file* tf_, + const std::string& name_ ) const +{ + if( tf_ != 0 ) { + if( m_traces == 0 ) { + m_traces = new sc_trace_params_vec; + } + m_traces->push_back( new sc_trace_params( tf_, name_ ) ); + } +} + +void +sc_in<sc_dt::sc_logic>::add_trace( sc_trace_file* tf_, + const std::string& name_ ) const +{ + sc_deprecated_add_trace(); + add_trace_internal(tf_, name_); +} + +void +sc_in<sc_dt::sc_logic>::remove_traces() const +{ + if( m_traces != 0 ) { + for( int i = m_traces->size() - 1; i >= 0; -- i ) { + delete (*m_traces)[i]; + } + delete m_traces; + m_traces = 0; + } +} + + +// called by pbind (for internal use only) + +int +sc_in<sc_dt::sc_logic>::vbind( sc_interface& interface_ ) +{ + return sc_port_b<if_type>::vbind( interface_ ); +} + +int +sc_in<sc_dt::sc_logic>::vbind( sc_port_base& parent_ ) +{ + in_port_type* in_parent = DCAST<in_port_type*>( &parent_ ); + if( in_parent != 0 ) { + sc_port_base::bind( *in_parent ); + return 0; + } + inout_port_type* inout_parent = DCAST<inout_port_type*>( &parent_ ); + if( inout_parent != 0 ) { + sc_port_base::bind( *inout_parent ); + return 0; + } + // type mismatch + return 2; +} + + +// ---------------------------------------------------------------------------- +// CLASS : sc_inout<bool> +// +// Specialization of sc_inout<T> for type bool. +// ---------------------------------------------------------------------------- + +// destructor + +sc_inout<bool>::~sc_inout() +{ + delete m_change_finder_p; + delete m_neg_finder_p; + delete m_pos_finder_p; + delete m_init_val; + remove_traces(); +} + + +// set initial value (can also be called when port is not bound yet) + +void +sc_inout<bool>::initialize( const data_type& value_ ) +{ + inout_if_type* iface = DCAST<inout_if_type*>( get_interface() ); + if( iface != 0 ) { + iface->write( value_ ); + } else { + if( m_init_val == 0 ) { + m_init_val = new data_type; + } + *m_init_val = value_; + } +} + + +// called when elaboration is done + +void +sc_inout<bool>::end_of_elaboration() +{ + if( m_init_val != 0 ) { + write( *m_init_val ); + delete m_init_val; + m_init_val = 0; + } + if( m_traces != 0 ) { + for( int i = 0; i < (int)m_traces->size(); ++ i ) { + sc_trace_params* p = (*m_traces)[i]; + in_if_type* iface = DCAST<in_if_type*>( get_interface() ); + sc_trace( p->tf, iface->read(), p->name ); + } + remove_traces(); + } +} + + +// called by sc_trace + +void +sc_inout<bool>::add_trace_internal( sc_trace_file* tf_, + const std::string& name_ ) const +{ + if( tf_ != 0 ) { + if( m_traces == 0 ) { + m_traces = new sc_trace_params_vec; + } + m_traces->push_back( new sc_trace_params( tf_, name_ ) ); + } +} + +void +sc_inout<bool>::add_trace( sc_trace_file* tf_, + const std::string& name_ ) const +{ + sc_deprecated_add_trace(); + add_trace_internal(tf_, name_); +} + +void +sc_inout<bool>::remove_traces() const +{ + if( m_traces != 0 ) { + for( int i = m_traces->size() - 1; i >= 0; -- i ) { + delete (*m_traces)[i]; + } + delete m_traces; + m_traces = 0; + } +} + + +// ---------------------------------------------------------------------------- +// CLASS : sc_inout<sc_dt::sc_logic> +// +// Specialization of sc_inout<T> for type sc_dt::sc_logic. +// ---------------------------------------------------------------------------- + +// destructor + +sc_inout<sc_dt::sc_logic>::~sc_inout() +{ + delete m_change_finder_p; + delete m_neg_finder_p; + delete m_pos_finder_p; + delete m_init_val; + remove_traces(); +} + + +// set initial value (can also be called when port is not bound yet) + +void +sc_inout<sc_dt::sc_logic>::initialize( const data_type& value_ ) +{ + inout_if_type* iface = DCAST<inout_if_type*>( get_interface() ); + if( iface != 0 ) { + iface->write( value_ ); + } else { + if( m_init_val == 0 ) { + m_init_val = new data_type; + } + *m_init_val = value_; + } +} + + +// called when elaboration is done + +void +sc_inout<sc_dt::sc_logic>::end_of_elaboration() +{ + if( m_init_val != 0 ) { + write( *m_init_val ); + delete m_init_val; + m_init_val = 0; + } + if( m_traces != 0 ) { + for( int i = 0; i < (int)m_traces->size(); ++ i ) { + sc_trace_params* p = (*m_traces)[i]; + in_if_type* iface = DCAST<in_if_type*>( get_interface() ); + sc_trace( p->tf, iface->read(), p->name ); + } + remove_traces(); + } +} + + +// called by sc_trace + +void +sc_inout<sc_dt::sc_logic>::add_trace_internal( sc_trace_file* tf_, + const std::string& name_ ) const +{ + if( tf_ != 0 ) { + if( m_traces == 0 ) { + m_traces = new sc_trace_params_vec; + } + m_traces->push_back( new sc_trace_params( tf_, name_ ) ); + } +} + + +void +sc_inout<sc_dt::sc_logic>::add_trace( sc_trace_file* tf_, + const std::string& name_ ) const +{ + sc_deprecated_add_trace(); + add_trace_internal(tf_, name_); +} + +void +sc_inout<sc_dt::sc_logic>::remove_traces() const +{ + if( m_traces != 0 ) { + for( int i = m_traces->size() - 1; i >= 0; -- i ) { + delete (*m_traces)[i]; + } + delete m_traces; + m_traces = 0; + } +} + +void sc_deprecated_add_trace() +{ + static bool warn_add_trace_deprecated=true; + if ( warn_add_trace_deprecated ) + { + warn_add_trace_deprecated=false; + SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, + "sc_signal<T>::addtrace() is deprecated"); + } +} +} // namespace sc_core + +// $Log: sc_signal_ports.cpp,v $ +// Revision 1.3 2011/08/26 20:45:43 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +// Revision 1.2 2011/02/18 20:23:45 acg +// Andy Goodrich: Copyright update. +// +// Revision 1.1.1.1 2006/12/15 20:20:04 acg +// SystemC 2.3 +// +// Revision 1.8 2006/05/08 17:52:47 acg +// Andy Goodrich: +// (1) added David Long's forward declarations for friend functions, +// methods, and operators to keep the Microsoft compiler happy. +// (2) Added delta_count() method to sc_prim_channel for use by +// sc_signal so that the friend declaration in sc_simcontext.h +// can be for a non-templated class (i.e., sc_prim_channel.) +// +// Revision 1.7 2006/04/18 18:01:26 acg +// Andy Goodrich: added an add_trace_internal() method to the various port +// classes so that sc_trace has something to call that won't emit an +// IEEE 1666 deprecation message. +// +// Revision 1.6 2006/02/02 23:42:37 acg +// Andy Goodrich: implemented a much better fix to the sc_event_finder +// proliferation problem. This new version allocates only a single event +// finder for each port for each type of event, e.g., pos(), neg(), and +// value_change(). The event finder persists as long as the port does, +// which is what the LRM dictates. Because only a single instance is +// allocated for each event type per port there is not a potential +// explosion of storage as was true in the 2.0.1/2.1 versions. +// +// Revision 1.5 2006/01/25 00:31:11 acg +// Andy Goodrich: Changed over to use a standard message id of +// SC_ID_IEEE_1666_DEPRECATION for all deprecation messages. +// +// Revision 1.4 2006/01/24 20:46:32 acg +// Andy Goodrich: changes to eliminate use of deprecated features. For instance, +// using notify(SC_ZERO_TIME) in place of notify_delayed(). +// +// Revision 1.3 2006/01/13 18:47:42 acg +// Added $Log command so that CVS comments are reproduced in the source. +// + +// Taf! diff --git a/ext/systemc/src/sysc/communication/sc_signal_ports.h b/ext/systemc/src/sysc/communication/sc_signal_ports.h new file mode 100644 index 000000000..22c83c583 --- /dev/null +++ b/ext/systemc/src/sysc/communication/sc_signal_ports.h @@ -0,0 +1,1931 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_signal_ports.h -- The sc_signal<T> port classes. + + Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21 + + CHANGE LOG APPEARS AT THE END OF THE FILE + *****************************************************************************/ + +#ifndef SC_SIGNAL_PORTS_H +#define SC_SIGNAL_PORTS_H + + +#include "sysc/communication/sc_event_finder.h" +#include "sysc/communication/sc_port.h" +#include "sysc/communication/sc_signal_ifs.h" +#include "sysc/datatypes/bit/sc_logic.h" +#include "sysc/tracing/sc_trace.h" + +#if ! defined( SC_DISABLE_VIRTUAL_BIND ) +# define SC_VIRTUAL_ virtual +#else +# define SC_VIRTUAL_ /* non-virtual */ +#endif + +namespace sc_core { + +// ---------------------------------------------------------------------------- +// STRUCT : sc_trace_params +// +// Struct for storing the trace file and object name of an sc_trace call. +// FOR INTERNAL USE ONLY! +// ---------------------------------------------------------------------------- + +extern void sc_deprecated_add_trace(); + +struct sc_trace_params +{ + sc_trace_file* tf; + std::string name; + + sc_trace_params( sc_trace_file* tf_, const std::string& name_ ) + : tf( tf_ ), name( name_ ) + {} +}; + + +typedef std::vector<sc_trace_params*> sc_trace_params_vec; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_in<T> +// +// The sc_signal<T> input port class. +// ---------------------------------------------------------------------------- + +template <class T> +class sc_in +: public sc_port<sc_signal_in_if<T>,1,SC_ONE_OR_MORE_BOUND> +{ +public: + + // typedefs + + typedef T data_type; + + typedef sc_signal_in_if<data_type> if_type; + typedef sc_port<if_type,1,SC_ONE_OR_MORE_BOUND> base_type; + typedef sc_in<data_type> this_type; + typedef typename base_type::port_type base_port_type; + + typedef if_type in_if_type; + typedef base_type in_port_type; + typedef sc_signal_inout_if<data_type> inout_if_type; + typedef sc_port<inout_if_type,1,SC_ONE_OR_MORE_BOUND> inout_port_type; + +public: + + // constructors + + sc_in() + : base_type(), m_traces( 0 ), + m_change_finder_p(0) + {} + + explicit sc_in( const char* name_ ) + : base_type( name_ ), m_traces( 0 ), + m_change_finder_p(0) + {} + + explicit sc_in( const in_if_type& interface_ ) + : base_type( CCAST<in_if_type&>( interface_ ) ), m_traces( 0 ), + m_change_finder_p(0) + {} + + sc_in( const char* name_, const in_if_type& interface_ ) + : base_type( name_, CCAST<in_if_type&>( interface_ ) ), m_traces( 0 ), + m_change_finder_p(0) + {} + + explicit sc_in( in_port_type& parent_ ) + : base_type( parent_ ), m_traces( 0 ), + m_change_finder_p(0) + {} + + sc_in( const char* name_, in_port_type& parent_ ) + : base_type( name_, parent_ ), m_traces( 0 ), + m_change_finder_p(0) + {} + + explicit sc_in( inout_port_type& parent_ ) + : base_type(), m_traces( 0 ), + m_change_finder_p(0) + { sc_port_base::bind( parent_ ); } + + sc_in( const char* name_, inout_port_type& parent_ ) + : base_type( name_ ), m_traces( 0 ), + m_change_finder_p(0) + { sc_port_base::bind( parent_ ); } + + sc_in( this_type& parent_ ) + : base_type( parent_ ), m_traces( 0 ), + m_change_finder_p(0) + {} + + sc_in( const char* name_, this_type& parent_ ) + : base_type( name_, parent_ ), m_traces( 0 ), + m_change_finder_p(0) + {} + + + // destructor + + virtual ~sc_in() + { + remove_traces(); + delete m_change_finder_p; + } + + + // bind to in interface + + SC_VIRTUAL_ void bind( const in_if_type& interface_ ) + { sc_port_base::bind( CCAST<in_if_type&>( interface_ ) ); } + + SC_VIRTUAL_ void bind( in_if_type& interface_ ) + { this->bind( CCAST<const in_if_type&>( interface_ ) ); } + + void operator () ( const in_if_type& interface_ ) + { this->bind( interface_ ); } + + + // bind to parent in port + + SC_VIRTUAL_ void bind( in_port_type& parent_ ) + { sc_port_base::bind( parent_ ); } + + void operator () ( in_port_type& parent_ ) + { this->bind( parent_ ); } + + + // bind to parent inout port + + SC_VIRTUAL_ void bind( inout_port_type& parent_ ) + { sc_port_base::bind( parent_ ); } + + void operator () ( inout_port_type& parent_ ) + { this->bind( parent_ ); } + + + // interface access shortcut methods + + // get the default event + + const sc_event& default_event() const + { return (*this)->default_event(); } + + + // get the value changed event + + const sc_event& value_changed_event() const + { return (*this)->value_changed_event(); } + + + // read the current value + + const data_type& read() const + { return (*this)->read(); } + + operator const data_type& () const + { return (*this)->read(); } + + + // was there a value changed event? + + bool event() const + { return (*this)->event(); } + + + // (other) event finder method(s) + + sc_event_finder& value_changed() const + { + if ( !m_change_finder_p ) + { + m_change_finder_p = new sc_event_finder_t<in_if_type>( + *this, &in_if_type::value_changed_event ); + } + return *m_change_finder_p; + } + + + // called when elaboration is done + /* WHEN DEFINING THIS METHOD IN A DERIVED CLASS, */ + /* MAKE SURE THAT THIS METHOD IS CALLED AS WELL. */ + + virtual void end_of_elaboration(); + + virtual const char* kind() const + { return "sc_in"; } + + + void add_trace( sc_trace_file*, const std::string& ) const; + + // called by sc_trace + void add_trace_internal( sc_trace_file*, const std::string& ) const; + +protected: + + void remove_traces() const; + + mutable sc_trace_params_vec* m_traces; + +protected: + + // called by pbind (for internal use only) + virtual int vbind( sc_interface& ); + virtual int vbind( sc_port_base& ); + + // implement virtual base_type port-binding function + // - avoids warnings on some compilers + // - should only be called, when using sc_port_b explicitly + // - errors are detected during elaboration + + SC_VIRTUAL_ void bind( base_port_type& parent_ ) + { sc_port_base::bind( parent_ ); } + + +private: + mutable sc_event_finder* m_change_finder_p; + +private: + + // disabled + sc_in( const this_type& ); + this_type& operator = ( const this_type& ); + +#ifdef __GNUC__ + // Needed to circumvent a problem in the g++-2.95.2 compiler: + // This unused variable forces the compiler to instantiate + // an object of T template so an implicit conversion from + // read() to a C++ intrinsic data type will work. + static data_type dummy; +#endif +}; + +template<typename T> +::std::ostream& operator << ( ::std::ostream& os, const sc_in<T>& a ) +{ + return os << a->read(); +} + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + + +// called when elaboration is done + +template <class T> +inline +void +sc_in<T>::end_of_elaboration() +{ + if( m_traces != 0 ) { + for( int i = 0; i < (int)m_traces->size(); ++ i ) { + sc_trace_params* p = (*m_traces)[i]; + in_if_type* iface = DCAST<in_if_type*>( this->get_interface() ); + sc_trace( p->tf, iface->read(), p->name ); + } + remove_traces(); + } +} + + +// called by sc_trace + +template <class T> +inline +void +sc_in<T>::add_trace_internal( sc_trace_file* tf_, const std::string& name_ ) +const +{ + if( tf_ != 0 ) { + if( m_traces == 0 ) { + m_traces = new sc_trace_params_vec; + } + m_traces->push_back( new sc_trace_params( tf_, name_ ) ); + } +} + +template <class T> +inline +void +sc_in<T>::add_trace( sc_trace_file* tf_, const std::string& name_ ) +const +{ + sc_deprecated_add_trace(); + add_trace_internal(tf_, name_); +} + +template <class T> +inline +void +sc_in<T>::remove_traces() const +{ + if( m_traces != 0 ) { + for( int i = (int)m_traces->size() - 1; i >= 0; -- i ) { + delete (*m_traces)[i]; + } + delete m_traces; + m_traces = 0; + } +} + + +// called by pbind (for internal use only) + +template <class T> +inline +int +sc_in<T>::vbind( sc_interface& interface_ ) +{ + return sc_port_b<if_type>::vbind( interface_ ); +} + +template <class T> +inline +int +sc_in<T>::vbind( sc_port_base& parent_ ) +{ + in_port_type* in_parent = DCAST<in_port_type*>( &parent_ ); + if( in_parent != 0 ) { + sc_port_base::bind( *in_parent ); + return 0; + } + inout_port_type* inout_parent = DCAST<inout_port_type*>( &parent_ ); + if( inout_parent != 0 ) { + sc_port_base::bind( *inout_parent ); + return 0; + } + // type mismatch + return 2; +} + + +// ---------------------------------------------------------------------------- +// CLASS : sc_in<bool> +// +// Specialization of sc_in<T> for type bool. +// ---------------------------------------------------------------------------- + +template <> +class sc_in<bool> : + public sc_port<sc_signal_in_if<bool>,1,SC_ONE_OR_MORE_BOUND> +{ +public: + + // typedefs + + typedef bool data_type; + + typedef sc_signal_in_if<data_type> if_type; + typedef sc_port<if_type,1,SC_ONE_OR_MORE_BOUND> base_type; + typedef sc_in<data_type> this_type; + typedef /* typename */ base_type::port_type base_port_type; + + typedef if_type in_if_type; + typedef base_type in_port_type; + typedef sc_signal_inout_if<data_type> inout_if_type; + typedef sc_port<inout_if_type,1,SC_ONE_OR_MORE_BOUND> inout_port_type; + +public: + + // constructors + + sc_in() + : base_type(), m_traces( 0 ), m_change_finder_p(0), + m_neg_finder_p(0), m_pos_finder_p(0) + {} + + explicit sc_in( const char* name_ ) + : base_type( name_ ), m_traces( 0 ), m_change_finder_p(0), + m_neg_finder_p(0), m_pos_finder_p(0) + {} + + explicit sc_in( const in_if_type& interface_ ) + : base_type( CCAST<in_if_type&>( interface_ ) ), m_traces( 0 ), + m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) + {} + + sc_in( const char* name_, const in_if_type& interface_ ) + : base_type( name_, CCAST<in_if_type&>( interface_ ) ), m_traces( 0 ), + m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) + {} + + explicit sc_in( in_port_type& parent_ ) + : base_type( parent_ ), m_traces( 0 ), + m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) + {} + + sc_in( const char* name_, in_port_type& parent_ ) + : base_type( name_, parent_ ), m_traces( 0 ), + m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) + {} + + explicit sc_in( inout_port_type& parent_ ) + : base_type(), m_traces( 0 ), + m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) + { sc_port_base::bind( parent_ ); } + + sc_in( const char* name_, inout_port_type& parent_ ) + : base_type( name_ ), m_traces( 0 ), + m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) + { sc_port_base::bind( parent_ ); } + + sc_in( this_type& parent_ ) + : base_type( parent_ ), m_traces( 0 ), + m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) + {} + +#if defined(TESTING) + sc_in( const this_type& parent_ ) + : base_type( *(in_if_type*)parent_.get_interface() ) , m_traces( 0 ), + m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) + {} +#endif + + sc_in( const char* name_, this_type& parent_ ) + : base_type( name_, parent_ ), m_traces( 0 ), + m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) + {} + + + // destructor + + virtual ~sc_in() + { + remove_traces(); + delete m_change_finder_p; + delete m_neg_finder_p; + delete m_pos_finder_p; + } + + + // bind to in interface + + SC_VIRTUAL_ void bind( const in_if_type& interface_ ) + { sc_port_base::bind( CCAST<in_if_type&>( interface_ ) ); } + + SC_VIRTUAL_ void bind( in_if_type& interface_ ) + { this->bind( CCAST<const in_if_type&>( interface_ ) ); } + + void operator () ( const in_if_type& interface_ ) + { this->bind( interface_ ); } + + + // bind to parent in port + + SC_VIRTUAL_ void bind( in_port_type& parent_ ) + { sc_port_base::bind( parent_ ); } + + void operator () ( in_port_type& parent_ ) + { this->bind( parent_ ); } + + + // bind to parent inout port + + SC_VIRTUAL_ void bind( inout_port_type& parent_ ) + { sc_port_base::bind( parent_ ); } + + void operator () ( inout_port_type& parent_ ) + { this->bind( parent_ ); } + + + // interface access shortcut methods + + // get the default event + + const sc_event& default_event() const + { return (*this)->default_event(); } + + + // get the value changed event + + const sc_event& value_changed_event() const + { return (*this)->value_changed_event(); } + + // get the positive edge event + + const sc_event& posedge_event() const + { return (*this)->posedge_event(); } + + // get the negative edge event + + const sc_event& negedge_event() const + { return (*this)->negedge_event(); } + + + // read the current value + + const data_type& read() const + { return (*this)->read(); } + + operator const data_type& () const + { return (*this)->read(); } + + + // use for positive edge sensitivity + + sc_event_finder& pos() const + { + if ( !m_pos_finder_p ) + { + m_pos_finder_p = new sc_event_finder_t<in_if_type>( + *this, &in_if_type::posedge_event ); + } + return *m_pos_finder_p; + } + + // use for negative edge sensitivity + + sc_event_finder& neg() const + { + if ( !m_neg_finder_p ) + { + m_neg_finder_p = new sc_event_finder_t<in_if_type>( + *this, &in_if_type::negedge_event ); + } + return *m_neg_finder_p; + } + + + // was there a value changed event? + + bool event() const + { return (*this)->event(); } + + // was there a positive edge event? + + bool posedge() const + { return (*this)->posedge(); } + + // was there a negative edge event? + + bool negedge() const + { return (*this)->negedge(); } + + // (other) event finder method(s) + + sc_event_finder& value_changed() const + { + if ( !m_change_finder_p ) + { + m_change_finder_p = new sc_event_finder_t<in_if_type>( + *this, &in_if_type::value_changed_event ); + } + return *m_change_finder_p; + } + + + // called when elaboration is done + /* WHEN DEFINING THIS METHOD IN A DERIVED CLASS, */ + /* MAKE SURE THAT THIS METHOD IS CALLED AS WELL. */ + + virtual void end_of_elaboration(); + + virtual const char* kind() const + { return "sc_in"; } + + + void add_trace( sc_trace_file*, const std::string& ) const; + + // called by sc_trace + void add_trace_internal( sc_trace_file*, const std::string& ) const; + +protected: + + void remove_traces() const; + + mutable sc_trace_params_vec* m_traces; + +protected: + + // called by pbind (for internal use only) + virtual int vbind( sc_interface& ); + virtual int vbind( sc_port_base& ); + + // implement virtual base_type port-binding function + // - avoids warnings on some compilers + // - should only be called, when using sc_port_b explicitly + // - errors are detected during elaboration + + SC_VIRTUAL_ void bind( base_port_type& parent_ ) + { sc_port_base::bind( parent_ ); } + +private: + mutable sc_event_finder* m_change_finder_p; + mutable sc_event_finder* m_neg_finder_p; + mutable sc_event_finder* m_pos_finder_p; + +private: + + // disabled +#if defined(TESTING) +#else + sc_in( const this_type& ); +#endif + this_type& operator = ( const this_type& ); + +#ifdef __GNUC__ + // Needed to circumvent a problem in the g++-2.95.2 compiler: + // This unused variable forces the compiler to instantiate + // an object of T template so an implicit conversion from + // read() to a C++ intrinsic data type will work. + static data_type dummy; +#endif +}; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_in<sc_dt::sc_logic> +// +// Specialization of sc_in<T> for type sc_dt::sc_logic. +// ---------------------------------------------------------------------------- + +template <> +class sc_in<sc_dt::sc_logic> +: public sc_port<sc_signal_in_if<sc_dt::sc_logic>,1,SC_ONE_OR_MORE_BOUND> +{ +public: + + // typedefs + + typedef sc_dt::sc_logic data_type; + + typedef sc_signal_in_if<data_type> if_type; + typedef sc_port<if_type,1,SC_ONE_OR_MORE_BOUND> base_type; + typedef sc_in<data_type> this_type; + typedef /* typename */ base_type::port_type base_port_type; + + typedef if_type in_if_type; + typedef base_type in_port_type; + typedef sc_signal_inout_if<data_type> inout_if_type; + typedef sc_port<inout_if_type,1,SC_ONE_OR_MORE_BOUND> inout_port_type; + +public: + + // constructors + + sc_in() + : base_type(), m_traces( 0 ), + m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) + {} + + explicit sc_in( const char* name_ ) + : base_type( name_ ), m_traces( 0 ), + m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) + {} + + explicit sc_in( const in_if_type& interface_ ) + : base_type( CCAST<in_if_type&>( interface_ ) ), m_traces( 0 ), + m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) + {} + + sc_in( const char* name_, const in_if_type& interface_ ) + : base_type( name_, CCAST<in_if_type&>( interface_ ) ), m_traces( 0 ), + m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) + {} + + explicit sc_in( in_port_type& parent_ ) + : base_type( parent_ ), m_traces( 0 ), + m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) + {} + + sc_in( const char* name_, in_port_type& parent_ ) + : base_type( name_, parent_ ), m_traces( 0 ), + m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) + {} + + explicit sc_in( inout_port_type& parent_ ) + : base_type(), m_traces( 0 ), + m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) + { sc_port_base::bind( parent_ ); } + + sc_in( const char* name_, inout_port_type& parent_ ) + : base_type( name_ ), m_traces( 0 ), + m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) + { sc_port_base::bind( parent_ ); } + + sc_in( this_type& parent_ ) + : base_type( parent_ ), m_traces( 0 ), + m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) + {} + + sc_in( const char* name_, this_type& parent_ ) + : base_type( name_, parent_ ), m_traces( 0 ), + m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) + {} + + + // destructor + + virtual ~sc_in() + { + remove_traces(); + delete m_change_finder_p; + delete m_neg_finder_p; + delete m_pos_finder_p; + } + + + // bind to in interface + + SC_VIRTUAL_ void bind( const in_if_type& interface_ ) + { sc_port_base::bind( CCAST<in_if_type&>( interface_ ) ); } + + SC_VIRTUAL_ void bind( in_if_type& interface_ ) + { this->bind( CCAST<const in_if_type&>( interface_ ) ); } + + void operator () ( const in_if_type& interface_ ) + { this->bind( interface_ ); } + + + // bind to parent in port + + SC_VIRTUAL_ void bind( in_port_type& parent_ ) + { sc_port_base::bind( parent_ ); } + + void operator () ( in_port_type& parent_ ) + { this->bind( parent_ ); } + + + // bind to parent inout port + + SC_VIRTUAL_ void bind( inout_port_type& parent_ ) + { sc_port_base::bind( parent_ ); } + + void operator () ( inout_port_type& parent_ ) + { this->bind( parent_ ); } + + + // interface access shortcut methods + + // get the default event + + const sc_event& default_event() const + { return (*this)->default_event(); } + + + // get the value changed event + + const sc_event& value_changed_event() const + { return (*this)->value_changed_event(); } + + // get the positive edge event + + const sc_event& posedge_event() const + { return (*this)->posedge_event(); } + + // get the negative edge event + + const sc_event& negedge_event() const + { return (*this)->negedge_event(); } + + + // read the current value + + const data_type& read() const + { return (*this)->read(); } + + operator const data_type& () const + { return (*this)->read(); } + + + // use for positive edge sensitivity + + sc_event_finder& pos() const + { + if ( !m_pos_finder_p ) + { + m_pos_finder_p = new sc_event_finder_t<in_if_type>( + *this, &in_if_type::posedge_event ); + } + return *m_pos_finder_p; + } + + // use for negative edge sensitivity + + sc_event_finder& neg() const + { + if ( !m_neg_finder_p ) + { + m_neg_finder_p = new sc_event_finder_t<in_if_type>( + *this, &in_if_type::negedge_event ); + } + return *m_neg_finder_p; + } + + + // was there a value changed event? + + bool event() const + { return (*this)->event(); } + + // was there a positive edge event? + + bool posedge() const + { return (*this)->posedge(); } + + // was there a negative edge event? + + bool negedge() const + { return (*this)->negedge(); } + + // (other) event finder method(s) + + sc_event_finder& value_changed() const + { + if ( !m_change_finder_p ) + { + m_change_finder_p = new sc_event_finder_t<in_if_type>( + *this, &in_if_type::value_changed_event ); + } + return *m_change_finder_p; + } + + + // called when elaboration is done + /* WHEN DEFINING THIS METHOD IN A DERIVED CLASS, */ + /* MAKE SURE THAT THIS METHOD IS CALLED AS WELL. */ + + virtual void end_of_elaboration(); + + virtual const char* kind() const + { return "sc_in"; } + + + void add_trace( sc_trace_file*, const std::string& ) const; + + // called by sc_trace + void add_trace_internal( sc_trace_file*, const std::string& ) const; + +protected: + + void remove_traces() const; + + mutable sc_trace_params_vec* m_traces; + +protected: + + // called by pbind (for internal use only) + virtual int vbind( sc_interface& ); + virtual int vbind( sc_port_base& ); + + // implement virtual base_type port-binding function + // - avoids warnings on some compilers + // - should only be called, when using sc_port_b explicitly + // - errors are detected during elaboration + + SC_VIRTUAL_ void bind( base_port_type& parent_ ) + { sc_port_base::bind( parent_ ); } + +private: + mutable sc_event_finder* m_change_finder_p; + mutable sc_event_finder* m_neg_finder_p; + mutable sc_event_finder* m_pos_finder_p; + +private: + + // disabled + sc_in( const this_type& ); + this_type& operator = ( const this_type& ); + +#ifdef __GNUC__ + // Needed to circumvent a problem in the g++-2.95.2 compiler: + // This unused variable forces the compiler to instantiate + // an object of T template so an implicit conversion from + // read() to a C++ intrinsic data type will work. + static data_type dummy; +#endif +}; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_inout<T> +// +// The sc_signal<T> input/output port class. +// ---------------------------------------------------------------------------- + +template <class T> +class sc_inout +: public sc_port<sc_signal_inout_if<T>,1,SC_ONE_OR_MORE_BOUND> +{ +public: + + // typedefs + + typedef T data_type; + + typedef sc_signal_inout_if<data_type> if_type; + typedef sc_port<if_type,1,SC_ONE_OR_MORE_BOUND> base_type; + typedef sc_inout<data_type> this_type; + + typedef sc_signal_in_if<data_type> in_if_type; + typedef sc_port<in_if_type,1,SC_ONE_OR_MORE_BOUND> in_port_type; + typedef if_type inout_if_type; + typedef base_type inout_port_type; + +public: + + // constructors + + sc_inout() + : base_type(), m_init_val( 0 ), m_traces( 0 ), + m_change_finder_p(0) + {} + + explicit sc_inout( const char* name_ ) + : base_type( name_ ), m_init_val( 0 ), m_traces( 0 ), + m_change_finder_p(0) + {} + + explicit sc_inout( inout_if_type& interface_ ) + : base_type( interface_ ), m_init_val( 0 ), m_traces( 0 ), + m_change_finder_p(0) + {} + + sc_inout( const char* name_, inout_if_type& interface_ ) + : base_type( name_, interface_ ), m_init_val( 0 ), m_traces( 0 ), + m_change_finder_p(0) + {} + + explicit sc_inout( inout_port_type& parent_ ) + : base_type( parent_ ), m_init_val( 0 ), m_traces( 0 ), + m_change_finder_p(0) + {} + + sc_inout( const char* name_, inout_port_type& parent_ ) + : base_type( name_, parent_ ), m_init_val( 0 ), m_traces( 0 ), + m_change_finder_p(0) + {} + + sc_inout( this_type& parent_ ) + : base_type( parent_ ), m_init_val( 0 ), m_traces( 0 ), + m_change_finder_p(0) + {} + + sc_inout( const char* name_, this_type& parent_ ) + : base_type( name_, parent_ ), m_init_val( 0 ), m_traces( 0 ), + m_change_finder_p(0) + {} + + + // destructor + + virtual ~sc_inout(); + + + // interface access shortcut methods + + // get the default event + + const sc_event& default_event() const + { return (*this)->default_event(); } + + + // get the value changed event + + const sc_event& value_changed_event() const + { return (*this)->value_changed_event(); } + + + // read the current value + + const data_type& read() const + { return (*this)->read(); } + + operator const data_type& () const + { return (*this)->read(); } + + + // was there a value changed event? + + bool event() const + { return (*this)->event(); } + + + // write the new value + + void write( const data_type& value_ ) + { (*this)->write( value_ ); } + + this_type& operator = ( const data_type& value_ ) + { (*this)->write( value_ ); return *this; } + + this_type& operator = ( const in_if_type& interface_ ) + { (*this)->write( interface_.read() ); return *this; } + + this_type& operator = ( const in_port_type& port_ ) + { (*this)->write( port_->read() ); return *this; } + + this_type& operator = ( const inout_port_type& port_ ) + { (*this)->write( port_->read() ); return *this; } + + this_type& operator = ( const this_type& port_ ) + { (*this)->write( port_->read() ); return *this; } + + + // set initial value (can also be called when port is not bound yet) + + void initialize( const data_type& value_ ); + + void initialize( const in_if_type& interface_ ) + { initialize( interface_.read() ); } + + + // called when elaboration is done + /* WHEN DEFINING THIS METHOD IN A DERIVED CLASS, */ + /* MAKE SURE THAT THIS METHOD IS CALLED AS WELL. */ + + virtual void end_of_elaboration(); + + + // (other) event finder method(s) + + sc_event_finder& value_changed() const + { + if ( !m_change_finder_p ) + { + m_change_finder_p = new sc_event_finder_t<in_if_type>( + *this, &in_if_type::value_changed_event ); + } + return *m_change_finder_p; + } + + virtual const char* kind() const + { return "sc_inout"; } + +protected: + + data_type* m_init_val; + +public: + + // called by sc_trace + void add_trace_internal( sc_trace_file*, const std::string& ) const; + + void add_trace( sc_trace_file*, const std::string& ) const; + +protected: + + void remove_traces() const; + + mutable sc_trace_params_vec* m_traces; + +private: + mutable sc_event_finder* m_change_finder_p; + +private: + + // disabled + sc_inout( const this_type& ); + +#ifdef __GNUC__ + // Needed to circumvent a problem in the g++-2.95.2 compiler: + // This unused variable forces the compiler to instantiate + // an object of T template so an implicit conversion from + // read() to a C++ intrinsic data type will work. + static data_type dummy; +#endif +}; + +template<typename T> +::std::ostream& operator << ( ::std::ostream& os, const sc_inout<T>& a ) +{ + return os << a->read(); +} + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + + +// destructor + +template <class T> +inline +sc_inout<T>::~sc_inout() +{ + delete m_change_finder_p; + delete m_init_val; + remove_traces(); +} + + +// set initial value (can also be called when port is not bound yet) + +template <class T> +inline +void +sc_inout<T>::initialize( const data_type& value_ ) +{ + inout_if_type* iface = DCAST<inout_if_type*>( this->get_interface() ); + if( iface != 0 ) { + iface->write( value_ ); + } else { + if( m_init_val == 0 ) { + m_init_val = new data_type; + } + *m_init_val = value_; + } +} + + +// called when elaboration is done + +template <class T> +inline +void +sc_inout<T>::end_of_elaboration() +{ + if( m_init_val != 0 ) { + write( *m_init_val ); + delete m_init_val; + m_init_val = 0; + } + if( m_traces != 0 ) { + for( int i = 0; i < (int)m_traces->size(); ++ i ) { + sc_trace_params* p = (*m_traces)[i]; + in_if_type* iface = DCAST<in_if_type*>( this->get_interface() ); + sc_trace( p->tf, iface->read(), p->name ); + } + remove_traces(); + } +} + + +// called by sc_trace + +template <class T> +inline +void +sc_inout<T>::add_trace_internal( sc_trace_file* tf_, const std::string& name_) +const +{ + if( tf_ != 0 ) { + if( m_traces == 0 ) { + m_traces = new sc_trace_params_vec; + } + m_traces->push_back( new sc_trace_params( tf_, name_ ) ); + } +} + +template <class T> +inline +void +sc_inout<T>::add_trace( sc_trace_file* tf_, const std::string& name_) const +{ + sc_deprecated_add_trace(); + add_trace_internal(tf_, name_); +} + +template <class T> +inline +void +sc_inout<T>::remove_traces() const +{ + if( m_traces != 0 ) { + for( int i = m_traces->size() - 1; i >= 0; -- i ) { + delete (*m_traces)[i]; + } + delete m_traces; + m_traces = 0; + } +} + + +// ---------------------------------------------------------------------------- +// CLASS : sc_inout<bool> +// +// Specialization of sc_inout<T> for type bool. +// ---------------------------------------------------------------------------- + +template <> +class sc_inout<bool> : + public sc_port<sc_signal_inout_if<bool>,1,SC_ONE_OR_MORE_BOUND> +{ +public: + + // typedefs + + typedef bool data_type; + + typedef sc_signal_inout_if<data_type> if_type; + typedef sc_port<if_type,1,SC_ONE_OR_MORE_BOUND> base_type; + typedef sc_inout<data_type> this_type; + + typedef sc_signal_in_if<data_type> in_if_type; + typedef sc_port<in_if_type,1,SC_ONE_OR_MORE_BOUND> in_port_type; + typedef if_type inout_if_type; + typedef base_type inout_port_type; + +public: + + // constructors + + sc_inout() + : base_type(), m_init_val( 0 ), m_traces( 0 ), + m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) + {} + + explicit sc_inout( const char* name_ ) + : base_type( name_ ), m_init_val( 0 ), m_traces( 0 ), + m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) + {} + + explicit sc_inout( inout_if_type& interface_ ) + : base_type( interface_ ), m_init_val( 0 ), m_traces( 0 ), + m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) + {} + + sc_inout( const char* name_, inout_if_type& interface_ ) + : base_type( name_, interface_ ), m_init_val( 0 ), m_traces( 0 ), + m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) + {} + + explicit sc_inout( inout_port_type& parent_ ) + : base_type( parent_ ), m_init_val( 0 ), m_traces( 0 ), + m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) + {} + + sc_inout( const char* name_, inout_port_type& parent_ ) + : base_type( name_, parent_ ), m_init_val( 0 ), m_traces( 0 ), + m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) + {} + + sc_inout( this_type& parent_ ) + : base_type( parent_ ), m_init_val( 0 ), m_traces( 0 ), + m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) + {} + + sc_inout( const char* name_, this_type& parent_ ) + : base_type( name_, parent_ ), m_init_val( 0 ), m_traces( 0 ), + m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) + {} + + + // destructor + + virtual ~sc_inout(); + + + // interface access shortcut methods + + // get the default event + + const sc_event& default_event() const + { return (*this)->default_event(); } + + + // get the value changed event + + const sc_event& value_changed_event() const + { return (*this)->value_changed_event(); } + + // get the positive edge event + + const sc_event& posedge_event() const + { return (*this)->posedge_event(); } + + // get the negative edge event + + const sc_event& negedge_event() const + { return (*this)->negedge_event(); } + + + // read the current value + + const data_type& read() const + { return (*this)->read(); } + + operator const data_type& () const + { return (*this)->read(); } + + + // use for positive edge sensitivity + + sc_event_finder& pos() const + { + if ( !m_pos_finder_p ) + { + m_pos_finder_p = new sc_event_finder_t<in_if_type>( + *this, &in_if_type::posedge_event ); + } + return *m_pos_finder_p; + } + + // use for negative edge sensitivity + + sc_event_finder& neg() const + { + if ( !m_neg_finder_p ) + { + m_neg_finder_p = new sc_event_finder_t<in_if_type>( + *this, &in_if_type::negedge_event ); + } + return *m_neg_finder_p; + } + + + // was there a value changed event? + + bool event() const + { return (*this)->event(); } + + // was there a positive edge event? + + bool posedge() const + { return (*this)->posedge(); } + + // was there a negative edge event? + + bool negedge() const + { return (*this)->negedge(); } + + // write the new value + + void write( const data_type& value_ ) + { (*this)->write( value_ ); } + + this_type& operator = ( const data_type& value_ ) + { (*this)->write( value_ ); return *this; } + + this_type& operator = ( const in_if_type& interface_ ) + { (*this)->write( interface_.read() ); return *this; } + + this_type& operator = ( const in_port_type& port_ ) + { (*this)->write( port_->read() ); return *this; } + + this_type& operator = ( const inout_port_type& port_ ) + { (*this)->write( port_->read() ); return *this; } + + this_type& operator = ( const this_type& port_ ) + { (*this)->write( port_->read() ); return *this; } + + + // set initial value (can also be called when port is not bound yet) + + void initialize( const data_type& value_ ); + + void initialize( const in_if_type& interface_ ) + { initialize( interface_.read() ); } + + + // called when elaboration is done + /* WHEN DEFINING THIS METHOD IN A DERIVED CLASS, */ + /* MAKE SURE THAT THIS METHOD IS CALLED AS WELL. */ + + virtual void end_of_elaboration(); + + + // (other) event finder method(s) + + sc_event_finder& value_changed() const + { + if ( !m_change_finder_p ) + { + m_change_finder_p = new sc_event_finder_t<in_if_type>( + *this, &in_if_type::value_changed_event ); + } + return *m_change_finder_p; + } + + virtual const char* kind() const + { return "sc_inout"; } + +protected: + + data_type* m_init_val; + +public: + + // called by sc_trace + void add_trace_internal( sc_trace_file*, const std::string& ) const; + + void add_trace( sc_trace_file*, const std::string& ) const; + +protected: + + void remove_traces() const; + + mutable sc_trace_params_vec* m_traces; + +private: + mutable sc_event_finder* m_change_finder_p; + mutable sc_event_finder* m_neg_finder_p; + mutable sc_event_finder* m_pos_finder_p; + +private: + + // disabled + sc_inout( const this_type& ); + +#ifdef __GNUC__ + // Needed to circumvent a problem in the g++-2.95.2 compiler: + // This unused variable forces the compiler to instantiate + // an object of T template so an implicit conversion from + // read() to a C++ intrinsic data type will work. + static data_type dummy; +#endif +}; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_inout<sc_dt::sc_logic> +// +// Specialization of sc_inout<T> for type sc_dt::sc_logic. +// ---------------------------------------------------------------------------- + +template <> +class sc_inout<sc_dt::sc_logic> +: public sc_port<sc_signal_inout_if<sc_dt::sc_logic>,1,SC_ONE_OR_MORE_BOUND> +{ +public: + + // typedefs + + typedef sc_dt::sc_logic data_type; + + typedef sc_signal_inout_if<data_type> if_type; + typedef sc_port<if_type,1,SC_ONE_OR_MORE_BOUND> base_type; + typedef sc_inout<data_type> this_type; + + typedef sc_signal_in_if<data_type> in_if_type; + typedef sc_port<in_if_type,1,SC_ONE_OR_MORE_BOUND> in_port_type; + typedef if_type inout_if_type; + typedef base_type inout_port_type; + +public: + + // constructors + + sc_inout() + : base_type(), m_init_val( 0 ), m_traces( 0 ), + m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) + {} + + explicit sc_inout( const char* name_ ) + : base_type( name_ ), m_init_val( 0 ), m_traces( 0 ), + m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) + {} + + explicit sc_inout( inout_if_type& interface_ ) + : base_type( interface_ ), m_init_val( 0 ), m_traces( 0 ), + m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) + {} + + sc_inout( const char* name_, inout_if_type& interface_ ) + : base_type( name_, interface_ ), m_init_val( 0 ), m_traces( 0 ), + m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) + {} + + explicit sc_inout( inout_port_type& parent_ ) + : base_type( parent_ ), m_init_val( 0 ), m_traces( 0 ), + m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) + {} + + sc_inout( const char* name_, inout_port_type& parent_ ) + : base_type( name_, parent_ ), m_init_val( 0 ), m_traces( 0 ), + m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) + {} + + sc_inout( this_type& parent_ ) + : base_type( parent_ ), m_init_val( 0 ), m_traces( 0 ), + m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) + {} + + sc_inout( const char* name_, this_type& parent_ ) + : base_type( name_, parent_ ), m_init_val( 0 ), m_traces( 0 ), + m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) + {} + + + // destructor + + virtual ~sc_inout(); + + + // interface access shortcut methods + + // get the default event + + const sc_event& default_event() const + { return (*this)->default_event(); } + + + // get the value changed event + + const sc_event& value_changed_event() const + { return (*this)->value_changed_event(); } + + // get the positive edge event + + const sc_event& posedge_event() const + { return (*this)->posedge_event(); } + + // get the negative edge event + + const sc_event& negedge_event() const + { return (*this)->negedge_event(); } + + + // read the current value + + const data_type& read() const + { return (*this)->read(); } + + operator const data_type& () const + { return (*this)->read(); } + + + // use for positive edge sensitivity + + sc_event_finder& pos() const + { + if ( !m_pos_finder_p ) + { + m_pos_finder_p = new sc_event_finder_t<in_if_type>( + *this, &in_if_type::posedge_event ); + } + return *m_pos_finder_p; + } + + // use for negative edge sensitivity + + sc_event_finder& neg() const + { + if ( !m_neg_finder_p ) + { + m_neg_finder_p = new sc_event_finder_t<in_if_type>( + *this, &in_if_type::negedge_event ); + } + return *m_neg_finder_p; + } + + + // was there a value changed event? + + bool event() const + { return (*this)->event(); } + + // was there a positive edge event? + + bool posedge() const + { return (*this)->posedge(); } + + // was there a negative edge event? + + bool negedge() const + { return (*this)->negedge(); } + + // write the new value + + void write( const data_type& value_ ) + { (*this)->write( value_ ); } + + this_type& operator = ( const data_type& value_ ) + { (*this)->write( value_ ); return *this; } + + this_type& operator = ( const in_if_type& interface_ ) + { (*this)->write( interface_.read() ); return *this; } + + this_type& operator = ( const in_port_type& port_ ) + { (*this)->write( port_->read() ); return *this; } + + this_type& operator = ( const inout_port_type& port_ ) + { (*this)->write( port_->read() ); return *this; } + + this_type& operator = ( const this_type& port_ ) + { (*this)->write( port_->read() ); return *this; } + + + // set initial value (can also be called when port is not bound yet) + + void initialize( const data_type& value_ ); + + void initialize( const in_if_type& interface_ ) + { initialize( interface_.read() ); } + + + // called when elaboration is done + /* WHEN DEFINING THIS METHOD IN A DERIVED CLASS, */ + /* MAKE SURE THAT THIS METHOD IS CALLED AS WELL. */ + + virtual void end_of_elaboration(); + + + // (other) event finder method(s) + + sc_event_finder& value_changed() const + { + if ( !m_change_finder_p ) + { + m_change_finder_p = new sc_event_finder_t<in_if_type>( + *this, &in_if_type::value_changed_event ); + } + return *m_change_finder_p; + } + + virtual const char* kind() const + { return "sc_inout"; } + +protected: + + data_type* m_init_val; + +public: + + // called by sc_trace + void add_trace_internal( sc_trace_file*, const std::string& ) const; + + void add_trace( sc_trace_file*, const std::string& ) const; + +protected: + + void remove_traces() const; + + mutable sc_trace_params_vec* m_traces; + +private: + mutable sc_event_finder* m_change_finder_p; + mutable sc_event_finder* m_neg_finder_p; + mutable sc_event_finder* m_pos_finder_p; + +private: + + // disabled + sc_inout( const this_type& ); + +#ifdef __GNUC__ + // Needed to circumvent a problem in the g++-2.95.2 compiler: + // This unused variable forces the compiler to instantiate + // an object of T template so an implicit conversion from + // read() to a C++ intrinsic data type will work. + static data_type dummy; +#endif +}; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_out<T> +// +// The sc_signal<T> output port class. +// ---------------------------------------------------------------------------- + +// sc_out can also read from its port, hence no difference with sc_inout. +// For debugging reasons, a class is provided instead of a define. + +template <class T> +class sc_out +: public sc_inout<T> +{ +public: + + // typedefs + + typedef T data_type; + + typedef sc_out<data_type> this_type; + typedef sc_inout<data_type> base_type; + + typedef typename base_type::in_if_type in_if_type; + typedef typename base_type::in_port_type in_port_type; + typedef typename base_type::inout_if_type inout_if_type; + typedef typename base_type::inout_port_type inout_port_type; + +public: + + // constructors + + sc_out() + : base_type() + {} + + explicit sc_out( const char* name_ ) + : base_type( name_ ) + {} + + explicit sc_out( inout_if_type& interface_ ) + : base_type( interface_ ) + {} + + sc_out( const char* name_, inout_if_type& interface_ ) + : base_type( name_, interface_ ) + {} + + explicit sc_out( inout_port_type& parent_ ) + : base_type( parent_ ) + {} + + sc_out( const char* name_, inout_port_type& parent_ ) + : base_type( name_, parent_ ) + {} + + sc_out( this_type& parent_ ) + : base_type( parent_ ) + {} + + sc_out( const char* name_, this_type& parent_ ) + : base_type( name_, parent_ ) + {} + + + // destructor (does nothing) + + virtual ~sc_out() + {} + + + // write the new value + + this_type& operator = ( const data_type& value_ ) + { (*this)->write( value_ ); return *this; } + + this_type& operator = ( const in_if_type& interface_ ) + { (*this)->write( interface_.read() ); return *this; } + + this_type& operator = ( const in_port_type& port_ ) + { (*this)->write( port_->read() ); return *this; } + + this_type& operator = ( const inout_port_type& port_ ) + { (*this)->write( port_->read() ); return *this; } + + this_type& operator = ( const this_type& port_ ) + { (*this)->write( port_->read() ); return *this; } + + virtual const char* kind() const + { return "sc_out"; } + +private: + + // disabled + sc_out( const this_type& ); +}; + + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + + +// ---------------------------------------------------------------------------- +// FUNCTION : sc_trace +// ---------------------------------------------------------------------------- + +template <class T> +inline +void +sc_trace(sc_trace_file* tf, const sc_in<T>& port, const std::string& name) +{ + const sc_signal_in_if<T>* iface = 0; + if (sc_get_curr_simcontext()->elaboration_done() ) + { + iface = DCAST<const sc_signal_in_if<T>*>( port.get_interface() ); + } + + if ( iface ) + sc_trace( tf, iface->read(), name ); + else + port.add_trace_internal( tf, name ); +} + +template <class T> +inline +void +sc_trace( sc_trace_file* tf, const sc_inout<T>& port, + const std::string& name ) +{ + const sc_signal_in_if<T>* iface = 0; + if (sc_get_curr_simcontext()->elaboration_done() ) + { + iface =DCAST<const sc_signal_in_if<T>*>( port.get_interface() ); + } + + if ( iface ) + sc_trace( tf, iface->read(), name ); + else + port.add_trace_internal( tf, name ); +} + +} // namespace sc_core + +#undef SC_VIRTUAL_ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: Jason Elbaum, Motorola, Inc., 2001-11-12 + Description of Modification: Added a static, private, otherwise + unused data member to the sc_in + and sc_inout classes to address + a bug in the GNU compiler *only*. + This works around a bug in g++ 2.95.2 + regarding implicit casting from a + templated class to a C++ intrinsic type. + + *****************************************************************************/ +//$Log: sc_signal_ports.h,v $ +//Revision 1.10 2011/08/29 18:04:32 acg +// Philipp A. Hartmann: miscellaneous clean ups. +// +//Revision 1.9 2011/08/26 20:45:43 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +//Revision 1.8 2011/08/07 19:08:01 acg +// Andy Goodrich: moved logs to end of file so line number synching works +// better between versions. +// +//Revision 1.7 2011/08/07 18:53:09 acg +// Philipp A. Hartmann: add virtual instances of the bind function for +// base classes to eliminate warning messages for clang platforms. +// +//Revision 1.6 2011/04/02 00:03:23 acg +// Andy Goodrich: catch the other bind()'s that I missed in Philipp's update. +// +//Revision 1.5 2011/04/01 22:33:31 acg +// Philipp A. Harmann: Use const interface signature to implement non-const +// interface signature for virtual bind(...). +// +//Revision 1.4 2011/03/30 16:46:10 acg +// Andy Goodrich: added a signature and removed a virtual specification +// to eliminate warnings with certain compilers. +// +//Revision 1.3 2011/02/18 20:23:45 acg +// Andy Goodrich: Copyright update. +// +//Revision 1.2 2011/01/20 16:52:15 acg +// Andy Goodrich: changes for IEEE 1666 2011. +// +//Revision 1.1.1.1 2006/12/15 20:20:04 acg +//SystemC 2.3 +// +//Revision 1.11 2006/04/18 23:36:50 acg +// Andy Goodrich: made add_trace_internal public until I can figure out +// how to do a friend specification for sc_trace in an environment where +// there are partial template and full template specifications for its +// arguments. +// +//Revision 1.10 2006/04/18 18:01:26 acg +// Andy Goodrich: added an add_trace_internal() method to the various port +// classes so that sc_trace has something to call that won't emit an +// IEEE 1666 deprecation message. +// +//Revision 1.9 2006/03/13 20:19:44 acg +// Andy Goodrich: changed sc_event instances into pointers to sc_event instances +// that are allocated as needed. This saves considerable storage for large +// numbers of signals, etc. +// +//Revision 1.8 2006/02/02 23:42:37 acg +// Andy Goodrich: implemented a much better fix to the sc_event_finder +// proliferation problem. This new version allocates only a single event +// finder for each port for each type of event, e.g., pos(), neg(), and +// value_change(). The event finder persists as long as the port does, +// which is what the LRM dictates. Because only a single instance is +// allocated for each event type per port there is not a potential +// explosion of storage as was true in the 2.0.1/2.1 versions. +// +//Revision 1.7 2006/02/02 21:38:12 acg +// Andy Goodrich: fix to the comment log. +// +//Revision 1.4 2006/01/24 20:46:32 acg +//Andy Goodrich: changes to eliminate use of deprecated features. For instance, +//using notify(SC_ZERO_TIME) in place of notify_delayed(). +// +//Revision 1.3 2006/01/13 18:47:42 acg +//Added $Log command so that CVS comments are reproduced in the source. +// +//Revision 1.2 2006/01/03 23:18:26 acg +//Changed copyright to include 2006. +// +//Revision 1.1.1.1 2005/12/19 23:16:43 acg +//First check in of SystemC 2.1 into its own archive. +// +//Revision 1.18 2005/09/15 23:01:52 acg +//Added std:: prefix to appropriate methods and types to get around +//issues with the Edison Front End. +// +//Revision 1.17 2005/06/10 22:43:55 acg +//Added CVS change log annotation. +// + +#endif + +// Taf! diff --git a/ext/systemc/src/sysc/communication/sc_signal_resolved.cpp b/ext/systemc/src/sysc/communication/sc_signal_resolved.cpp new file mode 100644 index 000000000..2b0aeca0b --- /dev/null +++ b/ext/systemc/src/sysc/communication/sc_signal_resolved.cpp @@ -0,0 +1,152 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_signal_resolved.cpp -- The resolved signal class. + + Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21 + + CHANGE LOG IS AT THE END OF THE FILE + *****************************************************************************/ + +#include "sysc/kernel/sc_simcontext.h" +#include "sysc/kernel/sc_process_handle.h" +#include "sysc/communication/sc_signal_resolved.h" + +namespace sc_core { + +// Note that we assume that two drivers driving the resolved signal to a 1 or +// 0 is O.K. This might not be true for all technologies, but is certainly +// true for CMOS, the predominant technology in use today. + +const sc_dt::sc_logic_value_t +sc_logic_resolution_tbl[4][4] = +{ // 0 1 Z X + { sc_dt::Log_0, sc_dt::Log_X, sc_dt::Log_0, sc_dt::Log_X }, // 0 + { sc_dt::Log_X, sc_dt::Log_1, sc_dt::Log_1, sc_dt::Log_X }, // 1 + { sc_dt::Log_0, sc_dt::Log_1, sc_dt::Log_Z, sc_dt::Log_X }, // Z + { sc_dt::Log_X, sc_dt::Log_X, sc_dt::Log_X, sc_dt::Log_X } // X +}; + + +// ---------------------------------------------------------------------------- +// FUNCTION : sc_logic_resolve +// +// Resolution function for sc_dt::sc_logic. +// ---------------------------------------------------------------------------- + +// resolves sc_dt::sc_logic values and returns the resolved value + +static void +sc_logic_resolve( sc_dt::sc_logic& result_, + const std::vector<sc_dt::sc_logic>& values_ ) +{ + int sz = values_.size(); + + assert( sz != 0 ); + + if( sz == 1 ) { + result_ = values_[0]; + return; + } + + sc_dt::sc_logic_value_t res = values_[0].value(); + for( int i = sz - 1; i > 0 && res != sc_dt::Log_X; -- i ) { + res = sc_logic_resolution_tbl[res][values_[i].value()]; + } + result_ = res; +} + + +// ---------------------------------------------------------------------------- +// CLASS : sc_signal_resolved +// +// The resolved signal class. +// ---------------------------------------------------------------------------- + +// write the new value + +void +sc_signal_resolved::write( const data_type& value_ ) +{ + sc_process_b* cur_proc = sc_get_current_process_b(); + + bool value_changed = false; + bool found = false; + + for( int i = m_proc_vec.size() - 1; i >= 0; -- i ) { + if( cur_proc == m_proc_vec[i] ) { + if( value_ != m_val_vec[i] ) { + m_val_vec[i] = value_; + value_changed = true; + } + found = true; + break; + } + } + + if( ! found ) { + m_proc_vec.push_back( cur_proc ); + m_val_vec.push_back( value_ ); + value_changed = true; + } + + if( value_changed ) { + request_update(); + } +} + + +void +sc_signal_resolved::update() +{ + sc_logic_resolve( m_new_val, m_val_vec ); + base_type::update(); +} + + +} // namespace sc_core + +// $Log: sc_signal_resolved.cpp,v $ +// Revision 1.5 2011/08/26 20:45:44 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +// Revision 1.4 2011/02/18 20:23:45 acg +// Andy Goodrich: Copyright update. +// +// Revision 1.3 2011/02/07 19:16:50 acg +// Andy Goodrich: changes for handling multiple writers. +// +// Revision 1.2 2011/01/20 16:52:15 acg +// Andy Goodrich: changes for IEEE 1666 2011. +// +// Revision 1.1.1.1 2006/12/15 20:20:04 acg +// SystemC 2.3 +// +// Revision 1.4 2006/03/21 00:00:27 acg +// Andy Goodrich: changed name of sc_get_current_process_base() to be +// sc_get_current_process_b() since its returning an sc_process_b instance. +// +// Revision 1.3 2006/01/13 18:47:42 acg +// Added $Log command so that CVS comments are reproduced in the source. +// + +// Taf! diff --git a/ext/systemc/src/sysc/communication/sc_signal_resolved.h b/ext/systemc/src/sysc/communication/sc_signal_resolved.h new file mode 100644 index 000000000..f5e8c714e --- /dev/null +++ b/ext/systemc/src/sysc/communication/sc_signal_resolved.h @@ -0,0 +1,153 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_signal_resolved.h -- The resolved signal class. + + Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21 + + CHANGE LOG IS AT THE END OF THE FILE + *****************************************************************************/ + + +#ifndef SC_SIGNAL_RESOLVED_H +#define SC_SIGNAL_RESOLVED_H + + +#include "sysc/communication/sc_signal.h" + +namespace sc_core { + +class sc_process_b; + +extern const sc_dt::sc_logic_value_t sc_logic_resolution_tbl[4][4]; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_signal_resolved +// +// The resolved signal class. +// ---------------------------------------------------------------------------- + +class sc_signal_resolved +: public sc_signal<sc_dt::sc_logic,SC_MANY_WRITERS> +{ +public: + + // typedefs + + typedef sc_signal_resolved this_type; + typedef sc_signal<sc_dt::sc_logic,SC_MANY_WRITERS> base_type; + typedef sc_dt::sc_logic data_type; + +public: + + // constructors + + sc_signal_resolved() : + base_type( sc_gen_unique_name( "signal_resolved" ) ), m_proc_vec(), + m_val_vec() + {} + + explicit sc_signal_resolved( const char* name_ ): + base_type( name_ ), m_proc_vec(), m_val_vec() + {} + + sc_signal_resolved( const char* name_, const data_type & initial_value_ ) + : base_type( name_, initial_value_ ) + , m_proc_vec() + , m_val_vec() + {} + + // interface methods + + virtual void register_port( sc_port_base&, const char* ) + {} + + + // write the new value + virtual void write( const data_type& ); + + + // other methods + + this_type& operator = ( const data_type& a ) + { write( a ); return *this; } + + this_type& operator = ( const this_type& a ) + { write( a.read() ); return *this; } + + virtual const char* kind() const + { return "sc_signal_resolved"; } + +protected: + + virtual void update(); + +protected: + + std::vector<sc_process_b*> m_proc_vec; // processes writing this signal + std::vector<data_type> m_val_vec; // new values written this signal + +private: + + // disabled + sc_signal_resolved( const this_type& ); +}; + +} // namespace sc_core + +//$Log: sc_signal_resolved.h,v $ +//Revision 1.6 2011/08/26 20:45:44 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +//Revision 1.5 2011/08/24 22:05:36 acg +// Torsten Maehne: initialization changes to remove warnings. +// +//Revision 1.4 2011/04/19 02:36:26 acg +// Philipp A. Hartmann: new aysnc_update and mutex support. +// +//Revision 1.3 2011/02/18 20:23:45 acg +// Andy Goodrich: Copyright update. +// +//Revision 1.2 2011/01/20 16:52:15 acg +// Andy Goodrich: changes for IEEE 1666 2011. +// +//Revision 1.1.1.1 2006/12/15 20:20:04 acg +//SystemC 2.3 +// +//Revision 1.2 2006/01/03 23:18:26 acg +//Changed copyright to include 2006. +// +//Revision 1.1.1.1 2005/12/19 23:16:43 acg +//First check in of SystemC 2.1 into its own archive. +// +//Revision 1.10 2005/09/15 23:01:52 acg +//Added std:: prefix to appropriate methods and types to get around +//issues with the Edison Front End. +// +//Revision 1.9 2005/06/10 22:43:55 acg +//Added CVS change log annotation. +// + +#endif + +// Taf! diff --git a/ext/systemc/src/sysc/communication/sc_signal_resolved_ports.cpp b/ext/systemc/src/sysc/communication/sc_signal_resolved_ports.cpp new file mode 100644 index 000000000..17da6396a --- /dev/null +++ b/ext/systemc/src/sysc/communication/sc_signal_resolved_ports.cpp @@ -0,0 +1,107 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_signal_resolved_ports.cpp -- The sc_signal_resolved port classes. + + Original Author: Martin Janssen, Synopsys, Inc., 2001-08-20 + + CHANGE LOG IS AT THE END OF THE FILE + *****************************************************************************/ + +#include <cstdio> + +#include "sysc/kernel/sc_simcontext.h" +#include "sysc/kernel/sc_process_handle.h" +#include "sysc/communication/sc_communication_ids.h" +#include "sysc/communication/sc_signal_resolved.h" +#include "sysc/communication/sc_signal_resolved_ports.h" + +namespace sc_core { + +// ---------------------------------------------------------------------------- +// CLASS : sc_in_resolved +// +// The sc_signal_resolved input port class. +// ---------------------------------------------------------------------------- + +// called when elaboration is done + +void +sc_in_resolved::end_of_elaboration() +{ + base_type::end_of_elaboration(); + // check if bound channel is a resolved signal + if( DCAST<sc_signal_resolved*>( get_interface() ) == 0 ) { + char msg[BUFSIZ]; + std::sprintf( msg, "%s (%s)", name(), kind() ); + SC_REPORT_ERROR( SC_ID_RESOLVED_PORT_NOT_BOUND_, msg ); + } +} + + +// ---------------------------------------------------------------------------- +// CLASS : sc_inout_resolved +// +// The sc_signal_resolved input/output port class. +// ---------------------------------------------------------------------------- + +// called when elaboration is done + +void +sc_inout_resolved::end_of_elaboration() +{ + base_type::end_of_elaboration(); + // check if bound channel is a resolved signal + if( DCAST<sc_signal_resolved*>( get_interface() ) == 0 ) { + char msg[BUFSIZ]; + std::sprintf( msg, "%s (%s)", name(), kind() ); + SC_REPORT_ERROR( SC_ID_RESOLVED_PORT_NOT_BOUND_, msg ); + } +} + + +// ---------------------------------------------------------------------------- +// CLASS : sc_out_resolved +// +// The sc_signal_resolved output port class. +// ---------------------------------------------------------------------------- + +} // namespace sc_core + +// $Log: sc_signal_resolved_ports.cpp,v $ +// Revision 1.4 2011/08/26 20:45:44 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +// Revision 1.3 2011/02/18 20:23:45 acg +// Andy Goodrich: Copyright update. +// +// Revision 1.2 2011/02/07 19:16:50 acg +// Andy Goodrich: changes for handling multiple writers. +// +// Revision 1.1.1.1 2006/12/15 20:20:04 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:47:42 acg +// Added $Log command so that CVS comments are reproduced in the source. +// + +// Taf! diff --git a/ext/systemc/src/sysc/communication/sc_signal_resolved_ports.h b/ext/systemc/src/sysc/communication/sc_signal_resolved_ports.h new file mode 100644 index 000000000..6b0d777d7 --- /dev/null +++ b/ext/systemc/src/sysc/communication/sc_signal_resolved_ports.h @@ -0,0 +1,349 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_signal_resolved_ports.h -- The sc_signal_resolved port classes. + + Original Author: Martin Janssen, Synopsys, Inc., 2001-08-20 + + CHANGE LOG IS AT THE END OF THE FILE + *****************************************************************************/ + +#ifndef SC_SIGNAL_RESOLVED_PORTS_H +#define SC_SIGNAL_RESOLVED_PORTS_H + + +#include "sysc/communication/sc_signal_ports.h" +#include "sysc/datatypes/bit/sc_logic.h" + +namespace sc_core { + +// ---------------------------------------------------------------------------- +// CLASS : sc_in_resolved +// +// The sc_signal_resolved input port class. +// ---------------------------------------------------------------------------- + +class sc_in_resolved + : public sc_in<sc_dt::sc_logic> +{ +public: + + // typedefs + + typedef sc_dt::sc_logic data_type; + + typedef sc_in_resolved this_type; + typedef sc_in<data_type> base_type; + + typedef base_type::in_if_type in_if_type; + typedef base_type::in_port_type in_port_type; + typedef base_type::inout_port_type inout_port_type; + +public: + + // constructors + + sc_in_resolved() + : base_type() + {} + + explicit sc_in_resolved( const char* name_ ) + : base_type( name_ ) + {} + + explicit sc_in_resolved( const in_if_type& interface_ ) + : base_type( interface_ ) + {} + + sc_in_resolved( const char* name_, const in_if_type& interface_ ) + : base_type( name_, interface_ ) + {} + + explicit sc_in_resolved( in_port_type& parent_ ) + : base_type( parent_ ) + {} + + sc_in_resolved( const char* name_, in_port_type& parent_ ) + : base_type( name_, parent_ ) + {} + + explicit sc_in_resolved( inout_port_type& parent_ ) + : base_type( parent_ ) + {} + + sc_in_resolved( const char* name_, inout_port_type& parent_ ) + : base_type( name_, parent_ ) + {} + + sc_in_resolved( this_type& parent_ ) + : base_type( parent_ ) + {} + + sc_in_resolved( const char* name_, this_type& parent_ ) + : base_type( name_, parent_ ) + {} + + + // destructor (does nothing) + + virtual ~sc_in_resolved() + {} + + + // called when elaboration is done + /* WHEN DEFINING THIS METHOD IN A DERIVED CLASS, */ + /* MAKE SURE THAT THIS METHOD IS CALLED AS WELL. */ + + virtual void end_of_elaboration(); + + virtual const char* kind() const + { return "sc_in_resolved"; } + +private: + + // disabled + sc_in_resolved( const this_type& ); + this_type& operator = ( const this_type& ); +}; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_inout_resolved +// +// The sc_signal_resolved input/output port class. +// ---------------------------------------------------------------------------- + +class sc_inout_resolved + : public sc_inout<sc_dt::sc_logic> +{ +public: + + // typedefs + + typedef sc_dt::sc_logic data_type; + + typedef sc_inout_resolved this_type; + typedef sc_inout<data_type> base_type; + + typedef base_type::in_if_type in_if_type; + typedef base_type::in_port_type in_port_type; + typedef base_type::inout_if_type inout_if_type; + typedef base_type::inout_port_type inout_port_type; + +public: + + // constructors + + sc_inout_resolved() + : base_type() + {} + + explicit sc_inout_resolved( const char* name_ ) + : base_type( name_ ) + {} + + explicit sc_inout_resolved( inout_if_type& interface_ ) + : base_type( interface_ ) + {} + + sc_inout_resolved( const char* name_, inout_if_type& interface_ ) + : base_type( name_, interface_ ) + {} + + explicit sc_inout_resolved( inout_port_type& parent_ ) + : base_type( parent_ ) + {} + + sc_inout_resolved( const char* name_, inout_port_type& parent_ ) + : base_type( name_, parent_ ) + {} + + sc_inout_resolved( this_type& parent_ ) + : base_type( parent_ ) + {} + + sc_inout_resolved( const char* name_, this_type& parent_ ) + : base_type( name_, parent_ ) + {} + + + // destructor (does nothing) + + virtual ~sc_inout_resolved() + {} + + + // write the new value + + this_type& operator = ( const data_type& value_ ) + { (*this)->write( value_ ); return *this; } + + this_type& operator = ( const in_if_type& interface_ ) + { (*this)->write( interface_.read() ); return *this; } + + this_type& operator = ( const in_port_type& port_ ) + { (*this)->write( port_->read() ); return *this; } + + this_type& operator = ( const inout_port_type& port_ ) + { (*this)->write( port_->read() ); return *this; } + + this_type& operator = ( const this_type& port_ ) + { (*this)->write( port_->read() ); return *this; } + + + // called when elaboration is done + /* WHEN DEFINING THIS METHOD IN A DERIVED CLASS, */ + /* MAKE SURE THAT THIS METHOD IS CALLED AS WELL. */ + + virtual void end_of_elaboration(); + + virtual const char* kind() const + { return "sc_inout_resolved"; } + +private: + + // disabled + sc_inout_resolved( const this_type& ); +}; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_out_resolved +// +// The sc_signal_resolved output port class. +// ---------------------------------------------------------------------------- + +// sc_out_resolved can also read from its port, hence no difference with +// sc_inout_resolved. For debugging reasons, a class is provided instead +// of a typedef. + +class sc_out_resolved + : public sc_inout_resolved +{ +public: + + // typedefs + + typedef sc_out_resolved this_type; + typedef sc_inout_resolved base_type; + + typedef base_type::data_type data_type; + + typedef base_type::in_if_type in_if_type; + typedef base_type::in_port_type in_port_type; + typedef base_type::inout_if_type inout_if_type; + typedef base_type::inout_port_type inout_port_type; + +public: + + // constructors + + sc_out_resolved() + : base_type() + {} + + explicit sc_out_resolved( const char* name_ ) + : base_type( name_ ) + {} + + explicit sc_out_resolved( inout_if_type& interface_ ) + : base_type( interface_ ) + {} + + sc_out_resolved( const char* name_, inout_if_type& interface_ ) + : base_type( name_, interface_ ) + {} + + explicit sc_out_resolved( inout_port_type& parent_ ) + : base_type( parent_ ) + {} + + sc_out_resolved( const char* name_, inout_port_type& parent_ ) + : base_type( name_, parent_ ) + {} + + sc_out_resolved( this_type& parent_ ) + : base_type( parent_ ) + {} + + sc_out_resolved( const char* name_, this_type& parent_ ) + : base_type( name_, parent_ ) + {} + + + // destructor (does nothing) + + virtual ~sc_out_resolved() + {} + + + // write the new value + + this_type& operator = ( const data_type& value_ ) + { (*this)->write( value_ ); return *this; } + + this_type& operator = ( const in_if_type& interface_ ) + { (*this)->write( interface_.read() ); return *this; } + + this_type& operator = ( const in_port_type& port_ ) + { (*this)->write( port_->read() ); return *this; } + + this_type& operator = ( const inout_port_type& port_ ) + { (*this)->write( port_->read() ); return *this; } + + this_type& operator = ( const this_type& port_ ) + { (*this)->write( port_->read() ); return *this; } + + virtual const char* kind() const + { return "sc_out_resolved"; } + +private: + + // disabled + sc_out_resolved( const this_type& ); +}; + +} // namespace sc_core + +//$Log: sc_signal_resolved_ports.h,v $ +//Revision 1.3 2011/08/26 20:45:44 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +//Revision 1.2 2011/02/18 20:23:45 acg +// Andy Goodrich: Copyright update. +// +//Revision 1.1.1.1 2006/12/15 20:20:04 acg +//SystemC 2.3 +// +//Revision 1.2 2006/01/03 23:18:26 acg +//Changed copyright to include 2006. +// +//Revision 1.1.1.1 2005/12/19 23:16:43 acg +//First check in of SystemC 2.1 into its own archive. +// +//Revision 1.9 2005/06/10 22:43:55 acg +//Added CVS change log annotation. +// + +#endif + +// Taf! diff --git a/ext/systemc/src/sysc/communication/sc_signal_rv.h b/ext/systemc/src/sysc/communication/sc_signal_rv.h new file mode 100644 index 000000000..0d870e78e --- /dev/null +++ b/ext/systemc/src/sysc/communication/sc_signal_rv.h @@ -0,0 +1,255 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_signal_rv.h -- The resolved vector signal class. + + Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21 + + CHANGE LOG IS AT THE END OF THE FILE + *****************************************************************************/ + +#ifndef SC_SIGNAL_RV_H +#define SC_SIGNAL_RV_H + +#include "sysc/communication/sc_signal.h" +#include "sysc/datatypes/bit/sc_lv.h" + +namespace sc_core { + +class sc_process_b; + + +// ---------------------------------------------------------------------------- +// CLASS sc_lv_resolve<W> +// +// Resolution function for sc_dt::sc_lv<W>. +// ---------------------------------------------------------------------------- + +extern const sc_dt::sc_logic_value_t sc_logic_resolution_tbl[4][4]; + + +template <int W> +class sc_lv_resolve +{ +public: + + // resolves sc_dt::sc_lv<W> values and returns the resolved value + static void resolve(sc_dt::sc_lv<W>&, const std::vector<sc_dt::sc_lv<W>*>&); +}; + + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + +// resolves sc_dt::sc_lv<W> values and returns the resolved value + +template <int W> +inline +void +sc_lv_resolve<W>::resolve( sc_dt::sc_lv<W>& result_, + const std::vector<sc_dt::sc_lv<W>*>& values_ ) +{ + int sz = values_.size(); + + assert( sz != 0 ); + + if( sz == 1 ) { + result_ = *values_[0]; + return; + } + + for( int j = result_.length() - 1; j >= 0; -- j ) { + sc_dt::sc_logic_value_t res = (*values_[0])[j].value(); + for( int i = sz - 1; i > 0 && res != 3; -- i ) { + res = sc_logic_resolution_tbl[res][(*values_[i])[j].value()]; + } + result_[j] = res; + } +} + + +// ---------------------------------------------------------------------------- +// CLASS : sc_signal_rv<W> +// +// The resolved vector signal class. +// ---------------------------------------------------------------------------- + +template <int W> +class sc_signal_rv +: public sc_signal<sc_dt::sc_lv<W>, SC_MANY_WRITERS> +{ +public: + + // typedefs + + typedef sc_signal_rv<W> this_type; + typedef sc_signal<sc_dt::sc_lv<W>, SC_MANY_WRITERS> base_type; + typedef sc_dt::sc_lv<W> data_type; + +public: + + // constructors + + sc_signal_rv() + : base_type( sc_gen_unique_name( "signal_rv" ) ) + {} + + explicit sc_signal_rv( const char* name_ ) + : base_type( name_ ) + {} + + + // destructor + virtual ~sc_signal_rv(); + + + // interface methods + + virtual void register_port( sc_port_base&, const char* ) + {} + + + // write the new value + virtual void write( const data_type& ); + + + // other methods + + this_type& operator = ( const data_type& a ) + { write( a ); return *this; } + + this_type& operator = ( const this_type& a ) + { write( a.read() ); return *this; } + + virtual const char* kind() const + { return "sc_signal_rv"; } + +protected: + + virtual void update(); + +protected: + + std::vector<sc_process_b*> m_proc_vec; // processes writing this signal + std::vector<data_type*> m_val_vec; // new values written this signal + +private: + + // disabled + sc_signal_rv( const this_type& ); +}; + + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + + +// destructor + +template <int W> +inline +sc_signal_rv<W>::~sc_signal_rv() +{ + for( int i = m_val_vec.size() - 1; i >= 0; -- i ) { + delete m_val_vec[i]; + } +} + + +// write the new value + +template <int W> +inline +void +sc_signal_rv<W>::write( const data_type& value_ ) +{ + sc_process_b* cur_proc = sc_get_current_process_b(); + + bool value_changed = false; + bool found = false; + + for( int i = m_proc_vec.size() - 1; i >= 0; -- i ) { + if( cur_proc == m_proc_vec[i] ) { + if( value_ != *m_val_vec[i] ) { + *m_val_vec[i] = value_; + value_changed = true; + } + found = true; + break; + } + } + + if( ! found ) { + m_proc_vec.push_back( cur_proc ); + m_val_vec.push_back( new data_type( value_ ) ); + value_changed = true; + } + + if( value_changed ) { + this->request_update(); + } +} + + +template <int W> +inline +void +sc_signal_rv<W>::update() +{ + sc_lv_resolve<W>::resolve( this->m_new_val, m_val_vec ); + base_type::update(); +} + +} // namespace sc_core + +//$Log: sc_signal_rv.h,v $ +//Revision 1.4 2011/08/26 20:45:44 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +//Revision 1.3 2011/04/19 02:36:26 acg +// Philipp A. Hartmann: new aysnc_update and mutex support. +// +//Revision 1.2 2011/02/18 20:23:45 acg +// Andy Goodrich: Copyright update. +// +//Revision 1.1.1.1 2006/12/15 20:20:04 acg +//SystemC 2.3 +// +//Revision 1.3 2006/03/21 00:00:27 acg +// Andy Goodrich: changed name of sc_get_current_process_base() to be +// sc_get_current_process_b() since its returning an sc_process_b instance. +// +//Revision 1.2 2006/01/03 23:18:26 acg +//Changed copyright to include 2006. +// +//Revision 1.1.1.1 2005/12/19 23:16:43 acg +//First check in of SystemC 2.1 into its own archive. +// +//Revision 1.10 2005/09/15 23:01:52 acg +//Added std:: prefix to appropriate methods and types to get around +//issues with the Edison Front End. +// +//Revision 1.9 2005/06/10 22:43:55 acg +//Added CVS change log annotation. +// + +#endif + +// Taf! diff --git a/ext/systemc/src/sysc/communication/sc_signal_rv_ports.h b/ext/systemc/src/sysc/communication/sc_signal_rv_ports.h new file mode 100644 index 000000000..ee6d17b25 --- /dev/null +++ b/ext/systemc/src/sysc/communication/sc_signal_rv_ports.h @@ -0,0 +1,401 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_signal_rv_ports.h -- The resolved vector signal ports. + + Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21 + + CHANGE LOG IS AT THE END OF THE FILE + *****************************************************************************/ + +#ifndef SC_SIGNAL_RV_PORTS_H +#define SC_SIGNAL_RV_PORTS_H + + +#include <cstdio> + +#include "sysc/communication/sc_communication_ids.h" +#include "sysc/communication/sc_signal_ports.h" +#include "sysc/communication/sc_signal_rv.h" +#include "sysc/datatypes/bit/sc_lv.h" + +namespace sc_core { + +// ---------------------------------------------------------------------------- +// CLASS : sc_in_rv<W> +// +// The sc_signal_rv<W> input port class. +// ---------------------------------------------------------------------------- + +template <int W> +class sc_in_rv + : public sc_in<sc_dt::sc_lv<W> > +{ +public: + + // typedefs + + typedef sc_dt::sc_lv<W> data_type; + + typedef sc_in_rv<W> this_type; + typedef sc_in<data_type> base_type; + + typedef typename base_type::in_if_type in_if_type; + typedef typename base_type::in_port_type in_port_type; + typedef typename base_type::inout_port_type inout_port_type; + +public: + + // constructors + + sc_in_rv() + : base_type() + {} + + explicit sc_in_rv( const char* name_ ) + : base_type( name_ ) + {} + + explicit sc_in_rv( const in_if_type& interface_ ) + : base_type( interface_ ) + {} + + sc_in_rv( const char* name_, const in_if_type& interface_ ) + : base_type( name_, interface_ ) + {} + + explicit sc_in_rv( in_port_type& parent_ ) + : base_type( parent_ ) + {} + + sc_in_rv( const char* name_, in_port_type& parent_ ) + : base_type( name_, parent_ ) + {} + + explicit sc_in_rv( inout_port_type& parent_ ) + : base_type( parent_ ) + {} + + sc_in_rv( const char* name_, inout_port_type& parent_ ) + : base_type( name_, parent_ ) + {} + + sc_in_rv( this_type& parent_ ) + : base_type( parent_ ) + {} + + sc_in_rv( const char* name_, this_type& parent_ ) + : base_type( name_, parent_ ) + {} + + + // destructor (does nothing) + + virtual ~sc_in_rv() + {} + + + // called when elaboration is done + /* WHEN DEFINING THIS METHOD IN A DERIVED CLASS, */ + /* MAKE SURE THAT THIS METHOD IS CALLED AS WELL. */ + + virtual void end_of_elaboration(); + + virtual const char* kind() const + { return "sc_in_rv"; } + +private: + + // disabled + sc_in_rv( const this_type& ); + this_type& operator = ( const this_type& ); +}; + + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + + +// called when elaboration is done + +template <int W> +void +sc_in_rv<W>::end_of_elaboration() +{ + base_type::end_of_elaboration(); + // check if bound channel is a resolved signal + if( DCAST<sc_signal_rv<W>*>( this->get_interface() ) == 0 ) { + char msg[BUFSIZ]; + std::sprintf( msg, "%s (%s)", this->name(), kind() ); + SC_REPORT_ERROR( SC_ID_RESOLVED_PORT_NOT_BOUND_, msg ); + } +} + + +// ---------------------------------------------------------------------------- +// CLASS : sc_inout_rv<W> +// +// The sc_signal_rv<W> input/output port class. +// ---------------------------------------------------------------------------- + +template <int W> +class sc_inout_rv + : public sc_inout<sc_dt::sc_lv<W> > +{ +public: + + // typedefs + + typedef sc_dt::sc_lv<W> data_type; + + typedef sc_inout_rv<W> this_type; + typedef sc_inout<data_type> base_type; + + typedef typename base_type::in_if_type in_if_type; + typedef typename base_type::in_port_type in_port_type; + typedef typename base_type::inout_if_type inout_if_type; + typedef typename base_type::inout_port_type inout_port_type; + +public: + + // constructors + + sc_inout_rv() + : base_type() + {} + + explicit sc_inout_rv( const char* name_ ) + : base_type( name_ ) + {} + + explicit sc_inout_rv( inout_if_type& interface_ ) + : base_type( interface_ ) + {} + + sc_inout_rv( const char* name_, inout_if_type& interface_ ) + : base_type( name_, interface_ ) + {} + + explicit sc_inout_rv( inout_port_type& parent_ ) + : base_type( parent_ ) + {} + + sc_inout_rv( const char* name_, inout_port_type& parent_ ) + : base_type( name_, parent_ ) + {} + + sc_inout_rv( this_type& parent_ ) + : base_type( parent_ ) + {} + + sc_inout_rv( const char* name_, this_type& parent_ ) + : base_type( name_, parent_ ) + {} + + + // destructor (does nothing) + + virtual ~sc_inout_rv() + {} + + + // write the new value + + this_type& operator = ( const data_type& value_ ) + { (*this)->write( value_ ); return *this; } + + this_type& operator = ( const in_if_type& interface_ ) + { (*this)->write( interface_.read() ); return *this; } + + this_type& operator = ( const in_port_type& port_ ) + { (*this)->write( port_->read() ); return *this; } + + this_type& operator = ( const inout_port_type& port_ ) + { (*this)->write( port_->read() ); return *this; } + + this_type& operator = ( const this_type& port_ ) + { (*this)->write( port_->read() ); return *this; } + + + // called when elaboration is done + /* WHEN DEFINING THIS METHOD IN A DERIVED CLASS, */ + /* MAKE SURE THAT THIS METHOD IS CALLED AS WELL. */ + + virtual void end_of_elaboration(); + + virtual const char* kind() const + { return "sc_inout_rv"; } + +private: + + // disabled + sc_inout_rv( const this_type& ); +}; + + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + + +// called when elaboration is done + +template <int W> +void +sc_inout_rv<W>::end_of_elaboration() +{ + base_type::end_of_elaboration(); + // check if bound channel is a resolved signal + if( DCAST<sc_signal_rv<W>*>( this->get_interface() ) == 0 ) { + char msg[BUFSIZ]; + std::sprintf( msg, "%s (%s)", this->name(), kind() ); + SC_REPORT_ERROR( SC_ID_RESOLVED_PORT_NOT_BOUND_, msg ); + } +} + + +// ---------------------------------------------------------------------------- +// CLASS : sc_out_rv<W> +// +// The sc_signal_rv<W> output port class. +// ---------------------------------------------------------------------------- + +// sc_out_rv can also read from its port, hence no difference with +// sc_inout_rv. For debugging reasons, a class is provided instead +// of a define. + +template <int W> +class sc_out_rv + : public sc_inout_rv<W> +{ +public: + + // typedefs + + typedef sc_out_rv<W> this_type; + typedef sc_inout_rv<W> base_type; + + typedef typename base_type::data_type data_type; + + typedef typename base_type::in_if_type in_if_type; + typedef typename base_type::in_port_type in_port_type; + typedef typename base_type::inout_if_type inout_if_type; + typedef typename base_type::inout_port_type inout_port_type; + +public: + + // constructors + + sc_out_rv() + : base_type() + {} + + explicit sc_out_rv( const char* name_ ) + : base_type( name_ ) + {} + + explicit sc_out_rv( inout_if_type& interface_ ) + : base_type( interface_ ) + {} + + sc_out_rv( const char* name_, inout_if_type& interface_ ) + : base_type( name_, interface_ ) + {} + + explicit sc_out_rv( inout_port_type& parent_ ) + : base_type( parent_ ) + {} + + sc_out_rv( const char* name_, inout_port_type& parent_ ) + : base_type( name_, parent_ ) + {} + + sc_out_rv( this_type& parent_ ) + : base_type( parent_ ) + {} + + sc_out_rv( const char* name_, this_type& parent_ ) + : base_type( name_, parent_ ) + {} + + + // destructor (does nothing) + + virtual ~sc_out_rv() + {} + + + // write the new value + + this_type& operator = ( const data_type& value_ ) + { (*this)->write( value_ ); return *this; } + + this_type& operator = ( const in_if_type& interface_ ) + { (*this)->write( interface_.read() ); return *this; } + + this_type& operator = ( const in_port_type& port_ ) + { (*this)->write( port_->read() ); return *this; } + + this_type& operator = ( const inout_port_type& port_ ) + { (*this)->write( port_->read() ); return *this; } + + this_type& operator = ( const this_type& port_ ) + { (*this)->write( port_->read() ); return *this; } + + virtual const char* kind() const + { return "sc_out_rv"; } + +private: + + // disabled + sc_out_rv( const this_type& ); +}; + + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + +} // namespace sc_core + +//$Log: sc_signal_rv_ports.h,v $ +//Revision 1.3 2011/08/26 20:45:44 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +//Revision 1.2 2011/02/18 20:23:45 acg +// Andy Goodrich: Copyright update. +// +//Revision 1.1.1.1 2006/12/15 20:20:04 acg +//SystemC 2.3 +// +//Revision 1.2 2006/01/03 23:18:27 acg +//Changed copyright to include 2006. +// +//Revision 1.1.1.1 2005/12/19 23:16:43 acg +//First check in of SystemC 2.1 into its own archive. +// +//Revision 1.11 2005/09/15 23:01:52 acg +//Added std:: prefix to appropriate methods and types to get around +//issues with the Edison Front End. +// +//Revision 1.10 2005/06/10 22:43:56 acg +//Added CVS change log annotation. +// + +#endif + +// Taf! diff --git a/ext/systemc/src/sysc/communication/sc_writer_policy.h b/ext/systemc/src/sysc/communication/sc_writer_policy.h new file mode 100644 index 000000000..93b80f861 --- /dev/null +++ b/ext/systemc/src/sysc/communication/sc_writer_policy.h @@ -0,0 +1,143 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_writer_policy.h -- The sc_signal<T> writer policy definition + + Original Author: Philipp A: Hartmann, OFFIS + + CHANGE LOG IS AT THE END OF THE FILE + *****************************************************************************/ + + +#ifndef SC_WRITER_POLICY_H_INCLUDED_ +#define SC_WRITER_POLICY_H_INCLUDED_ + +#if !defined(SC_DEFAULT_WRITER_POLICY) +# if defined(SC_NO_WRITE_CHECK) +# define SC_DEFAULT_WRITER_POLICY SC_UNCHECKED_WRITERS +# else +# define SC_DEFAULT_WRITER_POLICY SC_ONE_WRITER +# endif +#endif + +namespace sc_core { + +class sc_object; +class sc_port_base; +extern +void +sc_signal_invalid_writer( sc_object* target, sc_object* first_writer, + sc_object* second_writer, bool check_delta ); + +// SIGNAL WRITING POLICIES +// +// Note: if you add a new policy to the enum below you will need to add +// an additional overload of sc_reset::reset_signal_is() for the sc_signal<bool> +// instance. That will require changes to sysc/kernel/sc_reset.cpp and +// sysc/kernel/sc_reset.h + +enum sc_writer_policy +{ + SC_ONE_WRITER = 0, ///< unique writer (from a unique port) + SC_MANY_WRITERS = 1, ///< allow multiple writers (with different ports) + SC_UNCHECKED_WRITERS = 3 ///< even allow delta cycle conflicts (non-standard) +}; + +// signal forward declaration +template< typename T, sc_writer_policy POL = SC_DEFAULT_WRITER_POLICY > +class sc_signal; + +template< sc_writer_policy > +struct sc_writer_policy_check; + +struct sc_writer_policy_nocheck_write +{ + bool check_write( sc_object* /* target */, bool /* value_changed */ ) + { return true; } + void update(){} +}; + +struct sc_writer_policy_check_write +{ + bool check_write( sc_object* target, bool value_changed ); + void update(){} +protected: + sc_writer_policy_check_write( bool check_delta = false ) + : m_check_delta( check_delta ), m_writer_p(NULL) {} + const bool m_check_delta; + sc_object* m_writer_p; +}; + +struct sc_writer_policy_check_delta + : sc_writer_policy_check_write +{ + + sc_writer_policy_check_delta() + : sc_writer_policy_check_write(true) {} + + bool check_write( sc_object* target, bool value_changed ) + { + if( value_changed ) + return sc_writer_policy_check_write::check_write( target, true ); + return true; + } + + void update(){ m_writer_p = NULL; } +}; + +struct sc_writer_policy_nocheck_port +{ + bool check_port( sc_object*, sc_port_base*, bool ) + { return true; } +}; + +struct sc_writer_policy_check_port +{ + bool check_port( sc_object* target, sc_port_base* port, bool is_output ); + +protected: + sc_writer_policy_check_port() : m_output(0) {} + sc_port_base* m_output; +}; + +template<> +struct sc_writer_policy_check<SC_ONE_WRITER> + : sc_writer_policy_check_port + , sc_writer_policy_check_write +{}; + +template<> +struct sc_writer_policy_check<SC_MANY_WRITERS> + : sc_writer_policy_nocheck_port + , sc_writer_policy_check_delta +{}; + +template<> +struct sc_writer_policy_check<SC_UNCHECKED_WRITERS> + : sc_writer_policy_nocheck_port + , sc_writer_policy_nocheck_write +{}; + +} // namespace sc_core + +#endif + +// Taf! diff --git a/ext/systemc/src/sysc/datatypes/bit/sc_bit.cpp b/ext/systemc/src/sysc/datatypes/bit/sc_bit.cpp new file mode 100644 index 000000000..5401eaead --- /dev/null +++ b/ext/systemc/src/sysc/datatypes/bit/sc_bit.cpp @@ -0,0 +1,138 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_bit.cpp -- Bit class. + + Original Author: Gene Bushuyev, Synopsys, Inc. + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + + +// $Log: sc_bit.cpp,v $ +// Revision 1.1.1.1 2006/12/15 20:20:04 acg +// SystemC 2.3 +// +// Revision 1.6 2006/04/12 20:17:52 acg +// Andy Goodrich: enabled deprecation message for sc_bit. +// +// Revision 1.5 2006/01/25 00:31:15 acg +// Andy Goodrich: Changed over to use a standard message id of +// SC_ID_IEEE_1666_DEPRECATION for all deprecation messages. +// +// Revision 1.4 2006/01/24 20:50:55 acg +// Andy Goodrich: added warnings indicating that sc_bit is deprecated and that +// the C bool data type should be used in its place. +// +// Revision 1.3 2006/01/13 18:53:53 acg +// Andy Goodrich: added $Log command so that CVS comments are reproduced in +// the source. +// + +#include "sysc/datatypes/bit/sc_bit.h" +#include "sysc/datatypes/bit/sc_bit_ids.h" +#include "sysc/utils/sc_utils_ids.h" +#include "sysc/datatypes/bit/sc_logic.h" + +#include <cstdio> + + +namespace sc_dt +{ + +// ---------------------------------------------------------------------------- +// CLASS : sc_bit +// +// Bit class. +// Note: VSIA compatibility indicated. +// ---------------------------------------------------------------------------- + +// support methods + +void +sc_bit::invalid_value( char c ) +{ + char msg[BUFSIZ]; + std::sprintf( msg, "sc_bit( '%c' )", c ); + SC_REPORT_ERROR( sc_core::SC_ID_VALUE_NOT_VALID_, msg ); +} + +void +sc_bit::invalid_value( int i ) +{ + char msg[BUFSIZ]; + std::sprintf( msg, "sc_bit( %d )", i ); + SC_REPORT_ERROR( sc_core::SC_ID_VALUE_NOT_VALID_, msg ); +} + + +// constructors + +sc_bit::sc_bit( const sc_logic& a ) // non-VSIA + : m_val( a.to_bool() ) +{ + sc_deprecated_sc_bit(); +} + + +// assignment operators + +sc_bit& +sc_bit::operator = ( const sc_logic& b ) // non-VSIA +{ + return ( *this = sc_bit( b ) ); +} + + +// other methods + +void +sc_bit::scan( ::std::istream& is ) +{ + bool b; + is >> b; + *this = b; +} + +void sc_deprecated_sc_bit() +{ + static bool warn_sc_bit_deprecated=true; + if ( warn_sc_bit_deprecated ) + { + warn_sc_bit_deprecated=false; + SC_REPORT_INFO(sc_core::SC_ID_IEEE_1666_DEPRECATION_, + "sc_bit is deprecated, use bool instead"); + } +} + +} // namespace sc_dt + + +// Taf! diff --git a/ext/systemc/src/sysc/datatypes/bit/sc_bit.h b/ext/systemc/src/sysc/datatypes/bit/sc_bit.h new file mode 100644 index 000000000..2703971b6 --- /dev/null +++ b/ext/systemc/src/sysc/datatypes/bit/sc_bit.h @@ -0,0 +1,407 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_bit.h -- Bit class. + + Original Author: Stan Y. Liao, Synopsys, Inc. + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + +// $Log: sc_bit.h,v $ +// Revision 1.2 2011/08/07 18:54:19 acg +// Philipp A. Hartmann: remove friend function declarations that implement +// code, and clean up how bit and logic operators are defined in general. +// +// Revision 1.1.1.1 2006/12/15 20:20:04 acg +// SystemC 2.3 +// +// Revision 1.6 2006/05/08 17:49:59 acg +// Andy Goodrich: Added David Long's declarations for friend operators, +// functions, and methods, to keep the Microsoft compiler happy. +// +// Revision 1.5 2006/04/12 20:17:52 acg +// Andy Goodrich: enabled deprecation message for sc_bit. +// +// Revision 1.4 2006/01/24 20:50:55 acg +// Andy Goodrich: added warnings indicating that sc_bit is deprecated and that +// the C bool data type should be used in its place. +// +// Revision 1.3 2006/01/13 18:53:53 acg +// Andy Goodrich: added $Log command so that CVS comments are reproduced in +// the source. +// + +#ifndef SC_BIT_H +#define SC_BIT_H + + +#include "sysc/datatypes/int/sc_nbdefs.h" +#include "sysc/utils/sc_iostream.h" + + +namespace sc_dt +{ + +// classes defined in this module +class sc_bit; + +// forward class declarations +class sc_logic; + +extern void sc_deprecated_sc_bit(); + +// ---------------------------------------------------------------------------- +// CLASS : sc_bit +// +// Bit class. +// Note: VSIA compatibility indicated. +// ---------------------------------------------------------------------------- + +class sc_bit +{ + // support methods + + static void invalid_value( char ); + static void invalid_value( int ); + + static bool to_value( char c ) + { + if( c != '0' && c != '1' ) { + invalid_value( c ); + } + return ( c == '0' ? false : true ); + } + + static bool to_value( int i ) + { + if( i != 0 && i != 1 ) { + invalid_value( i ); + } + return ( i == 0 ? false : true ); + } + static bool to_value( bool b ) + { return b; } + +#define DEFN_TO_VALUE_T(tp) \ + static bool to_value( tp i ) \ + { return to_value( (int) i); } + + DEFN_TO_VALUE_T(unsigned) + DEFN_TO_VALUE_T(long) + DEFN_TO_VALUE_T(unsigned long) + DEFN_TO_VALUE_T(int64) + DEFN_TO_VALUE_T(uint64) + +#undef DEFN_TO_VALUE_T + +public: + + // constructors + // MANDATORY + + sc_bit() + : m_val( false ) + { + sc_deprecated_sc_bit(); + } + +#define DEFN_CTOR_T(tp) \ + explicit sc_bit( tp a ) \ + : m_val( to_value(a) ) \ + { sc_deprecated_sc_bit(); } + + DEFN_CTOR_T(bool) + DEFN_CTOR_T(char) + DEFN_CTOR_T(int) + DEFN_CTOR_T(unsigned) + DEFN_CTOR_T(long) + DEFN_CTOR_T(unsigned long) + DEFN_CTOR_T(int64) + DEFN_CTOR_T(uint64) + +#undef DEFN_CTOR_T + + explicit sc_bit( const sc_logic& a ); // non-VSIA + + + // copy constructor + // MANDATORY + + sc_bit( const sc_bit& a ) + : m_val( a.m_val ) + {} + + + // destructor + // MANDATORY + + ~sc_bit() + {} + + + // assignment operators + // MANDATORY + + sc_bit& operator = ( const sc_bit& b ) + { m_val = b.m_val; return *this; } + +#define DEFN_ASN_OP_T(op,tp) \ + sc_bit& operator op( tp b ) \ + { return ( *this op sc_bit( b ) ); } +#define DEFN_ASN_OP(op) \ + DEFN_ASN_OP_T(op,int) \ + DEFN_ASN_OP_T(op,bool) \ + DEFN_ASN_OP_T(op,char) + + DEFN_ASN_OP(=) + DEFN_ASN_OP_T(=,int64) + DEFN_ASN_OP_T(=,uint64) + DEFN_ASN_OP_T(=,long) + DEFN_ASN_OP_T(=,unsigned long) + + sc_bit& operator = ( const sc_logic& b ); // non-VSIA + + + // bitwise assignment operators + + sc_bit& operator &= ( const sc_bit& b ) + { m_val = ( m_val && b.m_val ); return *this; } + + sc_bit& operator |= ( const sc_bit& b ) + { m_val = ( m_val || b.m_val ); return *this; } + + sc_bit& operator ^= ( const sc_bit& b ) + { m_val = ( m_val != b.m_val ); return *this; } + + DEFN_ASN_OP(&=) + DEFN_ASN_OP(|=) + DEFN_ASN_OP(^=) + +#undef DEFN_ASN_OP_T +#undef DEFN_ASN_OP + + // conversions + // MANDATORY + + // implicit conversion to bool + + operator bool () const + { return m_val; } + + bool operator ! () const // non-VSIA + { return ! m_val; } + + + // explicit conversions + + bool to_bool() const // non-VSIA + { return m_val; } + + char to_char() const + { return ( m_val ? '1' : '0' ); } + + + // relational operators and functions + + // MANDATORY + + friend bool operator == ( const sc_bit& a, const sc_bit& b ); + friend bool operator != ( const sc_bit& a, const sc_bit& b ); + + // bitwise operators and functions + + // bitwise complement + + // MANDATORY + + friend const sc_bit operator ~ ( const sc_bit& a ); + + // RECOMMENDED + + sc_bit& b_not() + { m_val = ( ! m_val ); return *this; } + + // binary bit-wise operations + + friend const sc_bit operator | ( const sc_bit& a, const sc_bit& b ); + friend const sc_bit operator & ( const sc_bit& a, const sc_bit& b ); + friend const sc_bit operator ^ ( const sc_bit& a, const sc_bit& b ); + + // other methods + + void print( ::std::ostream& os = ::std::cout ) const + { os << to_bool(); } + + void scan( ::std::istream& = ::std::cin ); + +private: + bool m_val; +}; + +// ---------------------------------------------------------------------------- +// relational operators and functions + +#define DEFN_BIN_FUN_T(ret,fun,tp) \ + inline ret fun( const sc_bit& a, tp b ) \ + { return fun(a, sc_bit(b) ); } \ + inline ret fun( tp b, const sc_bit& a ) \ + { return fun( sc_bit(a), b ); } + +#define DEFN_BIN_FUN(ret,fun) \ + DEFN_BIN_FUN_T(ret,fun,bool) \ + DEFN_BIN_FUN_T(ret,fun,char) \ + DEFN_BIN_FUN_T(ret,fun,int) + +// MANDATORY + +inline bool operator == ( const sc_bit& a, const sc_bit& b ) + { return ( a.m_val == b.m_val ); } + +inline bool operator != ( const sc_bit& a, const sc_bit& b ) + { return ( a.m_val != b.m_val ); } + +DEFN_BIN_FUN(bool,operator==) +DEFN_BIN_FUN(bool,operator!=) + +// OPTIONAL + +inline bool equal( const sc_bit& a, const sc_bit& b ) + { return ( a == b ); } + +inline bool not_equal( const sc_bit& a, const sc_bit& b ) + { return ( a != b ); } + +DEFN_BIN_FUN(bool,equal) +DEFN_BIN_FUN(bool,not_equal) + +// ---------------------------------------------------------------------------- +// bitwise operators and functions + +// bitwise complement + + // MANDATORY + + inline const sc_bit operator ~ ( const sc_bit& a ) + { return sc_bit( ! a.m_val ); } + + + // OPTIONAL + + inline const sc_bit b_not( const sc_bit& a ) + { return ( ~ a ); } + + + // RECOMMENDED + + inline void b_not( sc_bit& r, const sc_bit& a ) + { r = ( ~ a ); } + + // binary bit-wise operations + + // MANDATORY + + inline const sc_bit operator & ( const sc_bit& a, const sc_bit& b ) + { return sc_bit( a.m_val && b.m_val ); } + + inline const sc_bit operator | ( const sc_bit& a, const sc_bit& b ) + { return sc_bit( a.m_val || b.m_val ); } + + inline const sc_bit operator ^ ( const sc_bit& a, const sc_bit& b ) + { return sc_bit( a.m_val != b.m_val ); } + + DEFN_BIN_FUN(const sc_bit,operator&) + DEFN_BIN_FUN(const sc_bit,operator|) + DEFN_BIN_FUN(const sc_bit,operator^) + + // OPTIONAL + + inline const sc_bit b_and ( const sc_bit& a, const sc_bit& b ) + { return a & b; } + + inline const sc_bit b_or ( const sc_bit& a, const sc_bit& b ) + { return a | b; } + + inline const sc_bit b_xor ( const sc_bit& a, const sc_bit& b ) + { return a ^ b; } + + DEFN_BIN_FUN(const sc_bit,b_and) + DEFN_BIN_FUN(const sc_bit,b_or) + DEFN_BIN_FUN(const sc_bit,b_xor) + + // RECOMMENDED + +#define DEFN_TRN_FUN_T(fun,tp) \ + inline void fun( sc_bit& r, const sc_bit& a, tp b ) \ + { r = fun( a, sc_bit(b) ); } \ + inline void fun( sc_bit& r, tp a, const sc_bit& b ) \ + { r = fun( sc_bit(a), b ); } + +#define DEFN_TRN_FUN(fun) \ + inline void fun( sc_bit& r, const sc_bit& a, const sc_bit& b ) \ + { r = fun( a , b ); } \ + DEFN_TRN_FUN_T(fun,int) \ + DEFN_TRN_FUN_T(fun,bool) \ + DEFN_TRN_FUN_T(fun,char) + + DEFN_TRN_FUN( b_and ) + DEFN_TRN_FUN( b_or ) + DEFN_TRN_FUN( b_xor ) + +#undef DEFN_BIN_FUN_T +#undef DEFN_BIN_FUN +#undef DEFN_TRN_FUN_T +#undef DEFN_TRN_FUN + + +// ---------------------------------------------------------------------------- + +inline +::std::ostream& +operator << ( ::std::ostream& os, const sc_bit& a ) +{ + a.print( os ); + return os; +} + +inline +::std::istream& +operator >> ( ::std::istream& is, sc_bit& a ) +{ + a.scan( is ); + return is; +} + +} // namespace sc_dt + + +#endif + +// Taf! diff --git a/ext/systemc/src/sysc/datatypes/bit/sc_bit_ids.h b/ext/systemc/src/sysc/datatypes/bit/sc_bit_ids.h new file mode 100644 index 000000000..0e77e9078 --- /dev/null +++ b/ext/systemc/src/sysc/datatypes/bit/sc_bit_ids.h @@ -0,0 +1,106 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_bit_ids.h -- Report ids for the datatypes/bit code. + + Original Author: Martin Janssen, Synopsys, Inc., 2002-01-17 + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + +// $Log: sc_bit_ids.h,v $ +// Revision 1.1.1.1 2006/12/15 20:20:04 acg +// SystemC 2.3 +// +// Revision 1.5 2006/01/25 00:31:15 acg +// Andy Goodrich: Changed over to use a standard message id of +// SC_ID_IEEE_1666_DEPRECATION for all deprecation messages. +// +// Revision 1.4 2006/01/24 20:50:55 acg +// Andy Goodrich: added warnings indicating that sc_bit is deprecated and that +// the C bool data type should be used in its place. +// +// Revision 1.3 2006/01/13 18:53:53 acg +// Andy Goodrich: added $Log command so that CVS comments are reproduced in +// the source. +// + +#ifndef SC_BIT_IDS_H +#define SC_BIT_IDS_H + + +#include "sysc/utils/sc_report.h" + + +// ---------------------------------------------------------------------------- +// Report ids (datatypes/bit) +// +// Report ids in the range of 200-299. +// ---------------------------------------------------------------------------- + +#ifndef SC_DEFINE_MESSAGE +#define SC_DEFINE_MESSAGE(id,unused1,unused2) \ + namespace sc_core { extern const char id[]; } +namespace sc_core { + extern const char SC_ID_REGISTER_ID_FAILED_[]; // in sc_report_handler.cpp +} +#endif + + +SC_DEFINE_MESSAGE( SC_ID_LENGTH_MISMATCH_, 200, + "length mismatch in bit/logic vector assignment" ) +SC_DEFINE_MESSAGE( SC_ID_INCOMPATIBLE_TYPES_, 201, + "incompatible types" ) +SC_DEFINE_MESSAGE( SC_ID_CANNOT_CONVERT_, 202, + "cannot perform conversion" ) +SC_DEFINE_MESSAGE( SC_ID_INCOMPATIBLE_VECTORS_, 203, + "incompatible vectors" ) +SC_DEFINE_MESSAGE( SC_ID_VALUE_NOT_VALID_, 204, + "value is not valid" ) +SC_DEFINE_MESSAGE( SC_ID_ZERO_LENGTH_, 205, + "zero length" ) +SC_DEFINE_MESSAGE( SC_ID_VECTOR_CONTAINS_LOGIC_VALUE_, 206, + "vector contains 4-value logic" ) +SC_DEFINE_MESSAGE( SC_ID_SC_BV_CANNOT_CONTAIN_X_AND_Z_, 207, + "sc_bv cannot contain values X and Z" ) +SC_DEFINE_MESSAGE( SC_ID_VECTOR_TOO_LONG_, 208, + "vector is too long: truncated" ) +SC_DEFINE_MESSAGE( SC_ID_VECTOR_TOO_SHORT_, 209, + "vector is too short: 0-padded" ) +SC_DEFINE_MESSAGE( SC_ID_WRONG_VALUE_, 210, + "wrong value" ) +SC_DEFINE_MESSAGE( SC_ID_LOGIC_Z_TO_BOOL_, 211, + "sc_logic value 'Z' cannot be converted to bool" ) +SC_DEFINE_MESSAGE( SC_ID_LOGIC_X_TO_BOOL_, 212, + "sc_logic value 'X' cannot be converted to bool" ) + +#endif + +// Taf! diff --git a/ext/systemc/src/sysc/datatypes/bit/sc_bit_proxies.h b/ext/systemc/src/sysc/datatypes/bit/sc_bit_proxies.h new file mode 100644 index 000000000..59d997181 --- /dev/null +++ b/ext/systemc/src/sysc/datatypes/bit/sc_bit_proxies.h @@ -0,0 +1,3884 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_bit_proxies.h -- Proxy classes for vector data types. + + Original Author: Gene Bushuyev, Synopsys, Inc. + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + +#ifndef SC_BIT_PROXIES_H +#define SC_BIT_PROXIES_H + + +#include "sysc/datatypes/bit/sc_bit_ids.h" +#include "sysc/datatypes/bit/sc_proxy.h" + + +namespace sc_dt +{ + +// classes defined in this module +template <class X> class sc_bitref_r; +template <class X> class sc_bitref; +template <class X> class sc_subref_r; +template <class X> class sc_subref; +template <class X, class Y> class sc_concref_r; +template <class X, class Y> class sc_concref; + + +// ---------------------------------------------------------------------------- +// CLASS TEMPLATE : sc_bitref_r<T> +// +// Proxy class for sc_proxy bit selection (r-value only). +// ---------------------------------------------------------------------------- + +template <class T> +class sc_bitref_r +{ + friend class sc_bv_base; + friend class sc_lv_base; + +public: + + // typedefs + + typedef typename T::traits_type traits_type; + typedef typename traits_type::bit_type bit_type; + + // constructor + + sc_bitref_r( const T& obj_, int index_ ) + : m_obj( CCAST<T&>( obj_ ) ), m_index( index_ ) + {} + + + // copy constructor + + sc_bitref_r( const sc_bitref_r<T>& a ) + : m_obj( a.m_obj ), m_index( a.m_index ) + {} + + // cloning + + sc_bitref_r<T>* clone() const + { return new sc_bitref_r<T>( *this ); } + + + // bitwise operators and functions + + // bitwise complement + + const bit_type operator ~ () const + { return bit_type( sc_logic::not_table[value()] ); } + + + // implicit conversion to bit_type + + operator const bit_type() const + { return bit_type( m_obj.get_bit( m_index ) ); } + + + // explicit conversions + + sc_logic_value_t value() const + { return m_obj.get_bit( m_index ); } + + + bool is_01() const + { return sc_logic( value() ).is_01(); } + + bool to_bool() const + { return sc_logic( value() ).to_bool(); } + + char to_char() const + { return sc_logic( value() ).to_char(); } + + + // common methods + + int length() const + { return 1; } + + int size() const + { return ( (length() - 1) / SC_DIGIT_SIZE + 1 ); } + + sc_logic_value_t get_bit( int n ) const; + + sc_digit get_word( int i ) const; + sc_digit get_cword( int i ) const; + + + // other methods + + void print( ::std::ostream& os = ::std::cout ) const + { os << to_char(); } + +protected: + + T& m_obj; + int m_index; + +private: + + // disabled + sc_bitref_r(); + sc_bitref_r<T>& operator = ( const sc_bitref_r<T>& ); +}; + + +// bitwise operators and functions + +// bitwise and + +template <class T1, class T2> +inline +const sc_logic +operator & ( const sc_bitref_r<T1>& a, const sc_bitref_r<T2>& b ); + + +// bitwise or + +template <class T1, class T2> +inline +const sc_logic +operator | ( const sc_bitref_r<T1>& a, const sc_bitref_r<T2>& b ); + + +// bitwise xor + +template <class T1, class T2> +inline +const sc_logic +operator ^ ( const sc_bitref_r<T1>& a, const sc_bitref_r<T2>& b ); + + +// relational operators and functions + +template <class T1, class T2> +inline +bool +operator == ( const sc_bitref_r<T1>& a, const sc_bitref_r<T2>& b ); + +template <class T1, class T2> +inline +bool +operator != ( const sc_bitref_r<T1>& a, const sc_bitref_r<T2>& b ); + + +// r-value concatenation operators and functions + +template <class T1, class T2> +inline +sc_concref_r<sc_bitref_r<T1>,sc_bitref_r<T2> > +operator , ( sc_bitref_r<T1>, sc_bitref_r<T2> ); + +template <class T1, class T2> +inline +sc_concref_r<sc_bitref_r<T1>,sc_subref_r<T2> > +operator , ( sc_bitref_r<T1>, sc_subref_r<T2> ); + +template <class T1, class T2, class T3> +inline +sc_concref_r<sc_bitref_r<T1>,sc_concref_r<T2,T3> > +operator , ( sc_bitref_r<T1>, sc_concref_r<T2,T3> ); + +template <class T1, class T2> +inline +sc_concref_r<sc_bitref_r<T1>,T2> +operator , ( sc_bitref_r<T1>, const sc_proxy<T2>& ); + +template <class T> +inline +sc_concref_r<sc_bitref_r<T>,sc_lv_base> +operator , ( sc_bitref_r<T>, const char* ); + +template <class T> +inline +sc_concref_r<sc_lv_base,sc_bitref_r<T> > +operator , ( const char*, sc_bitref_r<T> ); + +template <class T> +inline +sc_concref_r<sc_bitref_r<T>,sc_lv_base> +operator , ( sc_bitref_r<T>, const sc_logic& ); + +template <class T> +inline +sc_concref_r<sc_lv_base,sc_bitref_r<T> > +operator , ( const sc_logic&, sc_bitref_r<T> ); + +template <class T> +inline +sc_concref_r<sc_bitref_r<T>,sc_lv_base> +operator , ( sc_bitref_r<T>, bool ); + +template <class T> +inline +sc_concref_r<sc_lv_base,sc_bitref_r<T> > +operator , ( bool, sc_bitref_r<T> ); + + +template <class T1, class T2> +inline +sc_concref_r<sc_bitref_r<T1>,sc_bitref_r<T2> > +concat( sc_bitref_r<T1>, sc_bitref_r<T2> ); + +template <class T1, class T2> +inline +sc_concref_r<sc_bitref_r<T1>,sc_subref_r<T2> > +concat( sc_bitref_r<T1>, sc_subref_r<T2> ); + +template <class T1, class T2, class T3> +inline +sc_concref_r<sc_bitref_r<T1>,sc_concref_r<T2,T3> > +concat( sc_bitref_r<T1>, sc_concref_r<T2,T3> ); + +template <class T1, class T2> +inline +sc_concref_r<sc_bitref_r<T1>,T2> +concat( sc_bitref_r<T1>, const sc_proxy<T2>& ); + +template <class T> +inline +sc_concref_r<sc_bitref_r<T>,sc_lv_base> +concat( sc_bitref_r<T>, const char* ); + +template <class T> +inline +sc_concref_r<sc_lv_base,sc_bitref_r<T> > +concat( const char*, sc_bitref_r<T> ); + +template <class T> +inline +sc_concref_r<sc_bitref_r<T>,sc_lv_base> +concat( sc_bitref_r<T>, const sc_logic& ); + +template <class T> +inline +sc_concref_r<sc_lv_base,sc_bitref_r<T> > +concat( const sc_logic&, sc_bitref_r<T> ); + +template <class T> +inline +sc_concref_r<sc_bitref_r<T>,sc_lv_base> +concat( sc_bitref_r<T>, bool ); + +template <class T> +inline +sc_concref_r<sc_lv_base,sc_bitref_r<T> > +concat( bool, sc_bitref_r<T> ); + + +#ifdef SC_DT_MIXED_COMMA_OPERATORS + +template <class T1, class T2> +inline +sc_concref_r<sc_bitref_r<T1>,sc_bitref_r<T2> > +operator , ( sc_bitref_r<T1>, sc_bitref<T2> ); + +template <class T1, class T2> +inline +sc_concref_r<sc_bitref_r<T1>,sc_bitref_r<T2> > +operator , ( sc_bitref<T1>, sc_bitref_r<T2> ); + +template <class T1, class T2> +inline +sc_concref_r<sc_bitref_r<T1>,sc_subref_r<T2> > +operator , ( sc_bitref_r<T1>, sc_subref<T2> ); + +template <class T1, class T2> +inline +sc_concref_r<sc_bitref_r<T1>,sc_subref_r<T2> > +operator , ( sc_bitref<T1>, sc_subref_r<T2> ); + +template <class T1, class T2, class T3> +inline +sc_concref_r<sc_bitref_r<T1>,sc_concref_r<T2,T3> > +operator , ( sc_bitref_r<T1>, sc_concref<T2,T3> ); + +template <class T1, class T2, class T3> +inline +sc_concref_r<sc_bitref_r<T1>,sc_concref_r<T2,T3> > +operator , ( sc_bitref<T1>, sc_concref_r<T2,T3> ); + +template <class T1, class T2> +inline +sc_concref_r<sc_bitref_r<T1>,T2> +operator , ( sc_bitref<T1>, const sc_proxy<T2>& ); + +template <class T1, class T2> +inline +sc_concref_r<sc_bitref_r<T1>,T2> +operator , ( sc_bitref_r<T1>, sc_proxy<T2>& ); + +template <class T> +inline +sc_concref_r<sc_bitref_r<T>,sc_lv_base> +operator , ( sc_bitref<T>, const char* ); + +template <class T> +inline +sc_concref_r<sc_lv_base,sc_bitref_r<T> > +operator , ( const char*, sc_bitref<T> ); + +template <class T> +inline +sc_concref_r<sc_bitref_r<T>,sc_lv_base> +operator , ( sc_bitref<T>, const sc_logic& ); + +template <class T> +inline +sc_concref_r<sc_lv_base,sc_bitref_r<T> > +operator , ( const sc_logic&, sc_bitref<T> ); + +template <class T> +inline +sc_concref_r<sc_bitref_r<T>,sc_lv_base> +operator , ( sc_bitref<T>, bool ); + +template <class T> +inline +sc_concref_r<sc_lv_base,sc_bitref_r<T> > +operator , ( bool, sc_bitref<T> ); + + +template <class T1, class T2> +inline +sc_concref_r<sc_bitref_r<T1>,sc_bitref_r<T2> > +concat( sc_bitref_r<T1>, sc_bitref<T2> ); + +template <class T1, class T2> +inline +sc_concref_r<sc_bitref_r<T1>,sc_bitref_r<T2> > +concat( sc_bitref<T1>, sc_bitref_r<T2> ); + +template <class T1, class T2> +inline +sc_concref_r<sc_bitref_r<T1>,sc_subref_r<T2> > +concat( sc_bitref_r<T1>, sc_subref<T2> ); + +template <class T1, class T2> +inline +sc_concref_r<sc_bitref_r<T1>,sc_subref_r<T2> > +concat( sc_bitref<T1>, sc_subref_r<T2> ); + +template <class T1, class T2, class T3> +inline +sc_concref_r<sc_bitref_r<T1>,sc_concref_r<T2,T3> > +concat( sc_bitref_r<T1>, sc_concref<T2,T3> ); + +template <class T1, class T2, class T3> +inline +sc_concref_r<sc_bitref_r<T1>,sc_concref_r<T2,T3> > +concat( sc_bitref<T1>, sc_concref_r<T2,T3> ); + +template <class T1, class T2> +inline +sc_concref_r<sc_bitref_r<T1>,T2> +concat( sc_bitref<T1>, const sc_proxy<T2>& ); + +template <class T1, class T2> +inline +sc_concref_r<sc_bitref_r<T1>,T2> +concat( sc_bitref_r<T1>, sc_proxy<T2>& ); + +template <class T> +inline +sc_concref_r<sc_bitref_r<T>,sc_lv_base> +concat( sc_bitref<T>, const char* ); + +template <class T> +inline +sc_concref_r<sc_lv_base,sc_bitref_r<T> > +concat( const char*, sc_bitref<T> ); + +template <class T> +inline +sc_concref_r<sc_bitref_r<T>,sc_lv_base> +concat( sc_bitref<T>, const sc_logic& ); + +template <class T> +inline +sc_concref_r<sc_lv_base,sc_bitref_r<T> > +concat( const sc_logic&, sc_bitref<T> ); + +template <class T> +inline +sc_concref_r<sc_bitref_r<T>,sc_lv_base> +concat( sc_bitref<T>, bool ); + +template <class T> +inline +sc_concref_r<sc_lv_base,sc_bitref_r<T> > +concat( bool, sc_bitref<T> ); + +#endif + + +// ---------------------------------------------------------------------------- +// CLASS TEMPLATE : sc_bitref<X> +// +// Proxy class for sc_proxy bit selection (r-value and l-value). +// ---------------------------------------------------------------------------- + +template <class X> +class sc_bitref + : public sc_bitref_r<X> +{ + friend class sc_bv_base; + friend class sc_lv_base; + +public: + + // constructor + + sc_bitref( X& obj_, int index_ ) + : sc_bitref_r<X>( obj_, index_ ) + {} + + + // copy constructor + + sc_bitref( const sc_bitref<X>& a ) + : sc_bitref_r<X>( a ) + {} + + + // cloning + + sc_bitref<X>* clone() const + { return new sc_bitref<X>( *this ); } + + + // assignment operators + + sc_bitref<X>& operator = ( const sc_bitref_r<X>& a ); + sc_bitref<X>& operator = ( const sc_bitref<X>& a ); + + sc_bitref<X>& operator = ( const sc_logic& a ) + { this->m_obj.set_bit( this->m_index, a.value() ); return *this; } + + sc_bitref<X>& operator = ( sc_logic_value_t v ) + { *this = sc_logic( v ); return *this; } + + sc_bitref<X>& operator = ( bool a ) + { *this = sc_logic( a ); return *this; } + + sc_bitref<X>& operator = ( char a ) + { *this = sc_logic( a ); return *this; } + + sc_bitref<X>& operator = ( int a ) + { *this = sc_logic( a ); return *this; } + + sc_bitref<X>& operator = ( const sc_bit& a ) + { *this = sc_logic( a ); return *this; } + + + // bitwise assignment operators + + sc_bitref<X>& operator &= ( const sc_bitref_r<X>& a ); + sc_bitref<X>& operator &= ( const sc_logic& a ); + + sc_bitref<X>& operator &= ( sc_logic_value_t v ) + { *this &= sc_logic( v ); return *this; } + + sc_bitref<X>& operator &= ( bool a ) + { *this &= sc_logic( a ); return *this; } + + sc_bitref<X>& operator &= ( char a ) + { *this &= sc_logic( a ); return *this; } + + sc_bitref<X>& operator &= ( int a ) + { *this &= sc_logic( a ); return *this; } + + + sc_bitref<X>& operator |= ( const sc_bitref_r<X>& a ); + sc_bitref<X>& operator |= ( const sc_logic& a ); + + sc_bitref<X>& operator |= ( sc_logic_value_t v ) + { *this |= sc_logic( v ); return *this; } + + sc_bitref<X>& operator |= ( bool a ) + { *this |= sc_logic( a ); return *this; } + + sc_bitref<X>& operator |= ( char a ) + { *this |= sc_logic( a ); return *this; } + + sc_bitref<X>& operator |= ( int a ) + { *this |= sc_logic( a ); return *this; } + + + sc_bitref<X>& operator ^= ( const sc_bitref_r<X>& a ); + sc_bitref<X>& operator ^= ( const sc_logic& a ); + + sc_bitref<X>& operator ^= ( sc_logic_value_t v ) + { *this ^= sc_logic( v ); return *this; } + + sc_bitref<X>& operator ^= ( bool a ) + { *this ^= sc_logic( a ); return *this; } + + sc_bitref<X>& operator ^= ( char a ) + { *this ^= sc_logic( a ); return *this; } + + sc_bitref<X>& operator ^= ( int a ) + { *this ^= sc_logic( a ); return *this; } + + + // bitwise operators and functions + + // bitwise complement + + sc_bitref<X>& b_not(); + + + // common methods + + void set_bit( int n, sc_logic_value_t value ); + + void set_word( int i, sc_digit w ); + void set_cword( int i, sc_digit w ); + + void clean_tail() + { this->m_obj.clean_tail(); } + + + // other methods + + void scan( ::std::istream& is = ::std::cin ); + +private: + + // disabled + sc_bitref(); +}; + + +// l-value concatenation operators and functions + +template <class T1, class T2> +inline +sc_concref<sc_bitref<T1>,sc_bitref<T2> > +operator , ( sc_bitref<T1>, sc_bitref<T2> ); + +template <class T1, class T2> +inline +sc_concref<sc_bitref<T1>,sc_subref<T2> > +operator , ( sc_bitref<T1>, sc_subref<T2> ); + +template <class T1, class T2, class T3> +inline +sc_concref<sc_bitref<T1>,sc_concref<T2,T3> > +operator , ( sc_bitref<T1>, sc_concref<T2,T3> ); + +template <class T1, class T2> +inline +sc_concref<sc_bitref<T1>,T2> +operator , ( sc_bitref<T1>, sc_proxy<T2>& ); + + +template <class T1, class T2> +inline +sc_concref<sc_bitref<T1>,sc_bitref<T2> > +concat( sc_bitref<T1>, sc_bitref<T2> ); + +template <class T1, class T2> +inline +sc_concref<sc_bitref<T1>,sc_subref<T2> > +concat( sc_bitref<T1>, sc_subref<T2> ); + +template <class T1, class T2, class T3> +inline +sc_concref<sc_bitref<T1>,sc_concref<T2,T3> > +concat( sc_bitref<T1>, sc_concref<T2,T3> ); + +template <class T1, class T2> +inline +sc_concref<sc_bitref<T1>,T2> +concat( sc_bitref<T1>, sc_proxy<T2>& ); + + +template <class T> +::std::istream& +operator >> ( ::std::istream&, sc_bitref<T> ); + + +// ---------------------------------------------------------------------------- +// CLASS TEMPLATE : sc_subref_r<X> +// +// Proxy class for sc_proxy part selection (r-value only). +// ---------------------------------------------------------------------------- + +template <class X> +class sc_subref_r + : public sc_proxy<sc_subref_r<X> > +{ + void check_bounds(); + +public: + + // constructor + + sc_subref_r( const X& obj_, int hi_, int lo_ ) + : m_obj( CCAST<X&>( obj_ ) ), m_hi( hi_ ), m_lo( lo_ ), m_len( 0 ) + { check_bounds(); } + + + // copy constructor + + sc_subref_r( const sc_subref_r<X>& a ) + : m_obj( a.m_obj ), m_hi( a.m_hi ), m_lo( a.m_lo ), m_len( a.m_len ) + {} + + + // cloning + + sc_subref_r<X>* clone() const + { return new sc_subref_r<X>( *this ); } + + + // common methods + + int length() const + { return m_len; } + + int size() const + { return ( (length() - 1) / SC_DIGIT_SIZE + 1 ); } + + sc_logic_value_t get_bit( int n ) const; + void set_bit( int n, sc_logic_value_t value ); + + sc_digit get_word( int i )const; + void set_word( int i, sc_digit w ); + + sc_digit get_cword( int i ) const; + void set_cword( int i, sc_digit w ); + + void clean_tail() + { m_obj.clean_tail(); } + + + // other methods + + bool is_01() const; + + bool reversed() const + { return m_lo > m_hi; } + +protected: + + X& m_obj; + int m_hi; + int m_lo; + int m_len; + +private: + + // disabled + sc_subref_r(); + sc_subref_r<X>& operator = ( const sc_subref_r<X>& ); +}; + + +// r-value concatenation operators and functions + +template <class T1, class T2> +inline +sc_concref_r<sc_subref_r<T1>,sc_bitref_r<T2> > +operator , ( sc_subref_r<T1>, sc_bitref_r<T2> ); + +template <class T1, class T2> +inline +sc_concref_r<sc_subref_r<T1>,sc_subref_r<T2> > +operator , ( sc_subref_r<T1>, sc_subref_r<T2> ); + +template <class T1, class T2, class T3> +inline +sc_concref_r<sc_subref_r<T1>,sc_concref_r<T2,T3> > +operator , ( sc_subref_r<T1>, sc_concref_r<T2,T3> ); + +template <class T1, class T2> +inline +sc_concref_r<sc_subref_r<T1>,T2> +operator , ( sc_subref_r<T1>, const sc_proxy<T2>& ); + +template <class T> +inline +sc_concref_r<sc_subref_r<T>,sc_lv_base> +operator , ( sc_subref_r<T>, const char* ); + +template <class T> +inline +sc_concref_r<sc_lv_base,sc_subref_r<T> > +operator , ( const char*, sc_subref_r<T> ); + +template <class T> +inline +sc_concref_r<sc_subref_r<T>,sc_lv_base> +operator , ( sc_subref_r<T>, const sc_logic& ); + +template <class T> +inline +sc_concref_r<sc_lv_base,sc_subref_r<T> > +operator , ( const sc_logic&, sc_subref_r<T> ); + +template <class T> +inline +sc_concref_r<sc_subref_r<T>,sc_bv_base> +operator , ( sc_subref_r<T>, bool ); + +template <class T> +inline +sc_concref_r<sc_bv_base,sc_subref_r<T> > +operator , ( bool, sc_subref_r<T> ); + + +template <class T1, class T2> +inline +sc_concref_r<sc_subref_r<T1>,sc_bitref_r<T2> > +concat( sc_subref_r<T1>, sc_bitref_r<T2> ); + +template <class T1, class T2> +inline +sc_concref_r<sc_subref_r<T1>,sc_subref_r<T2> > +concat( sc_subref_r<T1>, sc_subref_r<T2> ); + +template <class T1, class T2, class T3> +inline +sc_concref_r<sc_subref_r<T1>,sc_concref_r<T2,T3> > +concat( sc_subref_r<T1>, sc_concref_r<T2,T3> ); + +template <class T1, class T2> +inline +sc_concref_r<sc_subref_r<T1>,T2> +concat( sc_subref_r<T1>, const sc_proxy<T2>& ); + +template <class T> +inline +sc_concref_r<sc_subref_r<T>,sc_lv_base> +concat( sc_subref_r<T>, const char* ); + +template <class T> +inline +sc_concref_r<sc_lv_base,sc_subref_r<T> > +concat( const char*, sc_subref_r<T> ); + +template <class T> +inline +sc_concref_r<sc_subref_r<T>,sc_lv_base> +concat( sc_subref_r<T>, const sc_logic& ); + +template <class T> +inline +sc_concref_r<sc_lv_base,sc_subref_r<T> > +concat( const sc_logic&, sc_subref_r<T> ); + +template <class T> +inline +sc_concref_r<sc_subref_r<T>,sc_bv_base> +concat( sc_subref_r<T>, bool ); + +template <class T> +inline +sc_concref_r<sc_bv_base,sc_subref_r<T> > +concat( bool, sc_subref_r<T> ); + + +#ifdef SC_DT_MIXED_COMMA_OPERATORS + +template <class T1, class T2> +inline +sc_concref_r<sc_subref_r<T1>,sc_bitref_r<T2> > +operator , ( sc_subref_r<T1>, sc_bitref<T2> ); + +template <class T1, class T2> +inline +sc_concref_r<sc_subref_r<T1>,sc_bitref_r<T2> > +operator , ( sc_subref<T1>, sc_bitref_r<T2> ); + +template <class T1, class T2> +inline +sc_concref_r<sc_subref_r<T1>,sc_subref_r<T2> > +operator , ( sc_subref_r<T1>, sc_subref<T2> ); + +template <class T1, class T2> +inline +sc_concref_r<sc_subref_r<T1>,sc_subref_r<T2> > +operator , ( sc_subref<T1>, sc_subref_r<T2> ); + +template <class T1, class T2, class T3> +inline +sc_concref_r<sc_subref_r<T1>,sc_concref_r<T2,T3> > +operator , ( sc_subref_r<T1>, sc_concref<T2,T3> ); + +template <class T1, class T2, class T3> +inline +sc_concref_r<sc_subref_r<T1>,sc_concref_r<T2,T3> > +operator , ( sc_subref<T1>, sc_concref_r<T2,T3> ); + +template <class T1, class T2> +inline +sc_concref_r<sc_subref_r<T1>,T2> +operator , ( sc_subref<T1>, const sc_proxy<T2>& ); + +template <class T1, class T2> +inline +sc_concref_r<sc_subref_r<T1>,T2> +operator , ( sc_subref_r<T1>, sc_proxy<T2>& ); + +template <class T> +inline +sc_concref_r<sc_subref_r<T>,sc_lv_base> +operator , ( sc_subref<T>, const char* ); + +template <class T> +inline +sc_concref_r<sc_lv_base,sc_subref_r<T> > +operator , ( const char*, sc_subref<T> ); + +template <class T> +inline +sc_concref_r<sc_subref_r<T>,sc_lv_base> +operator , ( sc_subref<T>, const sc_logic& ); + +template <class T> +inline +sc_concref_r<sc_lv_base,sc_subref_r<T> > +operator , ( const sc_logic&, sc_subref<T> ); + +template <class T> +inline +sc_concref_r<sc_subref_r<T>,sc_bv_base> +operator , ( sc_subref<T>, bool ); + +template <class T> +inline +sc_concref_r<sc_bv_base,sc_subref_r<T> > +operator , ( bool, sc_subref<T> ); + + +template <class T1, class T2> +inline +sc_concref_r<sc_subref_r<T1>,sc_bitref_r<T2> > +concat( sc_subref_r<T1>, sc_bitref<T2> ); + +template <class T1, class T2> +inline +sc_concref_r<sc_subref_r<T1>,sc_bitref_r<T2> > +concat( sc_subref<T1>, sc_bitref_r<T2> ); + +template <class T1, class T2> +inline +sc_concref_r<sc_subref_r<T1>,sc_subref_r<T2> > +concat( sc_subref_r<T1>, sc_subref<T2> ); + +template <class T1, class T2> +inline +sc_concref_r<sc_subref_r<T1>,sc_subref_r<T2> > +concat( sc_subref<T1>, sc_subref_r<T2> ); + +template <class T1, class T2, class T3> +inline +sc_concref_r<sc_subref_r<T1>,sc_concref_r<T2,T3> > +concat( sc_subref_r<T1>, sc_concref<T2,T3> ); + +template <class T1, class T2, class T3> +inline +sc_concref_r<sc_subref_r<T1>,sc_concref_r<T2,T3> > +concat( sc_subref<T1>, sc_concref_r<T2,T3> ); + +template <class T1, class T2> +inline +sc_concref_r<sc_subref_r<T1>,T2> +concat( sc_subref<T1>, const sc_proxy<T2>& ); + +template <class T1, class T2> +inline +sc_concref_r<sc_subref_r<T1>,T2> +concat( sc_subref_r<T1>, sc_proxy<T2>& ); + +template <class T> +inline +sc_concref_r<sc_subref_r<T>,sc_lv_base> +concat( sc_subref<T>, const char* ); + +template <class T> +inline +sc_concref_r<sc_lv_base,sc_subref_r<T> > +concat( const char*, sc_subref<T> ); + +template <class T> +inline +sc_concref_r<sc_subref_r<T>,sc_lv_base> +concat( sc_subref<T>, const sc_logic& ); + +template <class T> +inline +sc_concref_r<sc_lv_base,sc_subref_r<T> > +concat( const sc_logic&, sc_subref<T> ); + +template <class T> +inline +sc_concref_r<sc_subref_r<T>,sc_bv_base> +concat( sc_subref<T>, bool ); + +template <class T> +inline +sc_concref_r<sc_bv_base,sc_subref_r<T> > +concat( bool, sc_subref<T> ); + +#endif + + +// ---------------------------------------------------------------------------- +// CLASS TEMPLATE : sc_subref<X> +// +// Proxy class for sc_proxy part selection (r-value and l-value). +// ---------------------------------------------------------------------------- + +template <class X> +class sc_subref + : public sc_subref_r<X> +{ +public: + + // typedefs + + typedef sc_subref_r<X> base_type; + + + // constructor + + sc_subref( X& obj_, int hi_, int lo_ ) + : sc_subref_r<X>( obj_, hi_, lo_ ) + {} + + + // copy constructor + + sc_subref( const sc_subref<X>& a ) + : sc_subref_r<X>( a ) + {} + + + // cloning + + sc_subref<X>* clone() const + { return new sc_subref<X>( *this ); } + + + // assignment operators + + template <class Y> + sc_subref<X>& operator = ( const sc_proxy<Y>& a ) + { base_type::assign_( a ); return *this; } + + sc_subref<X>& operator = ( const sc_subref_r<X>& a ); + sc_subref<X>& operator = ( const sc_subref<X>& a ); + + sc_subref<X>& operator = ( const char* a ) + { base_type::assign_( a ); return *this; } + + sc_subref<X>& operator = ( const bool* a ) + { base_type::assign_( a ); return *this; } + + sc_subref<X>& operator = ( const sc_logic* a ) + { base_type::assign_( a ); return *this; } + + sc_subref<X>& operator = ( const sc_unsigned& a ) + { base_type::assign_( a ); return *this; } + + sc_subref<X>& operator = ( const sc_signed& a ) + { base_type::assign_( a ); return *this; } + + sc_subref<X>& operator = ( const sc_uint_base& a ) + { base_type::assign_( a ); return *this; } + + sc_subref<X>& operator = ( const sc_int_base& a ) + { base_type::assign_( a ); return *this; } + + sc_subref<X>& operator = ( unsigned long a ) + { base_type::assign_( a ); return *this; } + + sc_subref<X>& operator = ( long a ) + { base_type::assign_( a ); return *this; } + + sc_subref<X>& operator = ( unsigned int a ) + { base_type::assign_( a ); return *this; } + + sc_subref<X>& operator = ( int a ) + { base_type::assign_( a ); return *this; } + + sc_subref<X>& operator = ( uint64 a ) + { base_type::assign_( a ); return *this; } + + sc_subref<X>& operator = ( int64 a ) + { base_type::assign_( a ); return *this; } + + + // other methods + + void scan( ::std::istream& = ::std::cin ); + +private: + + // disabled + sc_subref(); +}; + + +// l-value concatenation operators and functions + +template <class T1, class T2> +inline +sc_concref<sc_subref<T1>,sc_bitref<T2> > +operator , ( sc_subref<T1>, sc_bitref<T2> ); + +template <class T1, class T2> +inline +sc_concref<sc_subref<T1>,sc_subref<T2> > +operator , ( sc_subref<T1>, sc_subref<T2> ); + +template <class T1, class T2, class T3> +inline +sc_concref<sc_subref<T1>,sc_concref<T2,T3> > +operator , ( sc_subref<T1>, sc_concref<T2,T3> ); + +template <class T1, class T2> +inline +sc_concref<sc_subref<T1>,T2> +operator , ( sc_subref<T1>, sc_proxy<T2>& ); + + +template <class T1, class T2> +inline +sc_concref<sc_subref<T1>,sc_bitref<T2> > +concat( sc_subref<T1>, sc_bitref<T2> ); + +template <class T1, class T2> +inline +sc_concref<sc_subref<T1>,sc_subref<T2> > +concat( sc_subref<T1>, sc_subref<T2> ); + +template <class T1, class T2, class T3> +inline +sc_concref<sc_subref<T1>,sc_concref<T2,T3> > +concat( sc_subref<T1>, sc_concref<T2,T3> ); + +template <class T1, class T2> +inline +sc_concref<sc_subref<T1>,T2> +concat( sc_subref<T1>, sc_proxy<T2>& ); + + +template <class T> +inline +::std::istream& +operator >> ( ::std::istream&, sc_subref<T> ); + + +// ---------------------------------------------------------------------------- +// CLASS TEMPLATE : sc_concref_r<X,Y> +// +// Proxy class for sc_proxy concatenation (r-value only). +// ---------------------------------------------------------------------------- + +template <class X, class Y> +class sc_concref_r + : public sc_proxy<sc_concref_r<X,Y> > +{ +public: + + // constructor + + sc_concref_r( const X& left_, const Y& right_, int delete_ = 0 ) + : m_left( CCAST<X&>( left_ ) ), m_right( CCAST<Y&>( right_ ) ), + m_delete( delete_ ), m_refs( *new int( 1 ) ) + {} + + + // copy constructor + + sc_concref_r( const sc_concref_r<X,Y>& a ) + : m_left( a.m_left ), m_right( a.m_right ), + m_delete( a.m_delete ), m_refs( a.m_refs ) + { ++ m_refs; } + + + // destructor + + virtual ~sc_concref_r(); + + + // cloning + + sc_concref_r<X,Y>* clone() const + { return new sc_concref_r<X,Y>( *this ); } + + + // common methods + + int length() const + { return ( m_left.length() + m_right.length() ); } + + int size() const + { return ( (length() - 1) / SC_DIGIT_SIZE + 1 ); } + + sc_logic_value_t get_bit( int n ) const; + void set_bit( int n, sc_logic_value_t value ); + + sc_digit get_word( int i ) const; + void set_word( int i, sc_digit w ); + + sc_digit get_cword( int i ) const; + void set_cword( int i, sc_digit w ); + + void clean_tail() + { m_left.clean_tail(); m_right.clean_tail(); } + + + // other methods + + bool is_01() const + { return ( m_left.is_01() && m_right.is_01() ); } + +protected: + + X& m_left; + Y& m_right; + mutable int m_delete; + int& m_refs; + +private: + + // disabled + sc_concref_r(); + sc_concref_r<X,Y>& operator = ( const sc_concref_r<X,Y>& ); +}; + + +// r-value concatenation operators and functions + +template <class T1, class T2, class T3> +inline +sc_concref_r<sc_concref_r<T1,T2>,sc_bitref_r<T3> > +operator , ( sc_concref_r<T1,T2>, sc_bitref_r<T3> ); + +template <class T1, class T2, class T3> +inline +sc_concref_r<sc_concref_r<T1,T2>,sc_subref_r<T3> > +operator , ( sc_concref_r<T1,T2>, sc_subref_r<T3> ); + +template <class T1, class T2, class T3, class T4> +inline +sc_concref_r<sc_concref_r<T1,T2>,sc_concref_r<T3,T4> > +operator , ( sc_concref_r<T1,T2>, sc_concref_r<T3,T4> ); + +template <class T1, class T2, class T3> +inline +sc_concref_r<sc_concref_r<T1,T2>,T3> +operator , ( sc_concref_r<T1,T2>, const sc_proxy<T3>& ); + +template <class T1, class T2> +inline +sc_concref_r<sc_concref_r<T1,T2>,sc_lv_base> +operator , ( sc_concref_r<T1,T2>, const char* ); + +template <class T1, class T2> +inline +sc_concref_r<sc_lv_base,sc_concref_r<T1,T2> > +operator , ( const char*, sc_concref_r<T1,T2> ); + +template <class T1, class T2> +inline +sc_concref_r<sc_concref_r<T1,T2>,sc_lv_base> +operator , ( sc_concref_r<T1,T2>, const sc_logic& ); + +template <class T1, class T2> +inline +sc_concref_r<sc_lv_base,sc_concref_r<T1,T2> > +operator , ( const sc_logic&, sc_concref_r<T1,T2> ); + +template <class T1, class T2> +inline +sc_concref_r<sc_concref_r<T1,T2>,sc_bv_base> +operator , ( sc_concref_r<T1,T2>, bool ); + +template <class T1, class T2> +inline +sc_concref_r<sc_bv_base,sc_concref_r<T1,T2> > +operator , ( bool, sc_concref_r<T1,T2> ); + + +template <class T1, class T2, class T3> +inline +sc_concref_r<sc_concref_r<T1,T2>,sc_bitref_r<T3> > +concat( sc_concref_r<T1,T2>, sc_bitref_r<T3> ); + +template <class T1, class T2, class T3> +inline +sc_concref_r<sc_concref_r<T1,T2>,sc_subref_r<T3> > +concat( sc_concref_r<T1,T2>, sc_subref_r<T3> ); + +template <class T1, class T2, class T3, class T4> +inline +sc_concref_r<sc_concref_r<T1,T2>,sc_concref_r<T3,T4> > +concat( sc_concref_r<T1,T2>, sc_concref_r<T3,T4> ); + +template <class T1, class T2, class T3> +inline +sc_concref_r<sc_concref_r<T1,T2>,T3> +concat( sc_concref_r<T1,T2>, const sc_proxy<T3>& ); + +template <class T1, class T2> +inline +sc_concref_r<sc_concref_r<T1,T2>,sc_lv_base> +concat( sc_concref_r<T1,T2>, const char* ); + +template <class T1, class T2> +inline +sc_concref_r<sc_lv_base,sc_concref_r<T1,T2> > +concat( const char*, sc_concref_r<T1,T2> ); + +template <class T1, class T2> +inline +sc_concref_r<sc_concref_r<T1,T2>,sc_lv_base> +concat( sc_concref_r<T1,T2>, const sc_logic& ); + +template <class T1, class T2> +inline +sc_concref_r<sc_lv_base,sc_concref_r<T1,T2> > +concat( const sc_logic&, sc_concref_r<T1,T2> ); + +template <class T1, class T2> +inline +sc_concref_r<sc_concref_r<T1,T2>,sc_bv_base> +concat( sc_concref_r<T1,T2>, bool ); + +template <class T1, class T2> +inline +sc_concref_r<sc_bv_base,sc_concref_r<T1,T2> > +concat( bool, sc_concref_r<T1,T2> ); + + +#ifdef SC_DT_MIXED_COMMA_OPERATORS + +template <class T1, class T2, class T3> +inline +sc_concref_r<sc_concref_r<T1,T2>,sc_bitref_r<T3> > +operator , ( sc_concref_r<T1,T2>, sc_bitref<T3> ); + +template <class T1, class T2, class T3> +inline +sc_concref_r<sc_concref_r<T1,T2>,sc_bitref_r<T3> > +operator , ( sc_concref<T1,T2>, sc_bitref_r<T3> ); + +template <class T1, class T2, class T3> +inline +sc_concref_r<sc_concref_r<T1,T2>,sc_subref_r<T3> > +operator , ( sc_concref_r<T1,T2>, sc_subref<T3> ); + +template <class T1, class T2, class T3> +inline +sc_concref_r<sc_concref_r<T1,T2>,sc_subref_r<T3> > +operator , ( sc_concref<T1,T2>, sc_subref_r<T3> ); + +template <class T1, class T2, class T3, class T4> +inline +sc_concref_r<sc_concref_r<T1,T2>,sc_concref_r<T3,T4> > +operator , ( sc_concref_r<T1,T2>, sc_concref<T3,T4> ); + +template <class T1, class T2, class T3, class T4> +inline +sc_concref_r<sc_concref_r<T1,T2>,sc_concref_r<T3,T4> > +operator , ( sc_concref<T1,T2>, sc_concref_r<T3,T4> ); + +template <class T1, class T2, class T3> +inline +sc_concref_r<sc_concref_r<T1,T2>,T3> +operator , ( sc_concref<T1,T2>, const sc_proxy<T3>& ); + +template <class T1, class T2, class T3> +inline +sc_concref_r<sc_concref_r<T1,T2>,T3> +operator , ( sc_concref_r<T1,T2>, sc_proxy<T3>& ); + +template <class T1, class T2> +inline +sc_concref_r<sc_concref_r<T1,T2>,sc_lv_base> +operator , ( sc_concref<T1,T2>, const char* ); + +template <class T1, class T2> +inline +sc_concref_r<sc_lv_base,sc_concref_r<T1,T2> > +operator , ( const char*, sc_concref<T1,T2> ); + +template <class T1, class T2> +inline +sc_concref_r<sc_concref_r<T1,T2>,sc_lv_base> +operator , ( sc_concref<T1,T2>, const sc_logic& ); + +template <class T1, class T2> +inline +sc_concref_r<sc_lv_base,sc_concref_r<T1,T2> > +operator , ( const sc_logic&, sc_concref<T1,T2> ); + +template <class T1, class T2> +inline +sc_concref_r<sc_concref_r<T1,T2>,sc_bv_base> +operator , ( sc_concref<T1,T2>, bool ); + +template <class T1, class T2> +inline +sc_concref_r<sc_bv_base,sc_concref_r<T1,T2> > +operator , ( bool, sc_concref<T1,T2> ); + + +template <class T1, class T2, class T3> +inline +sc_concref_r<sc_concref_r<T1,T2>,sc_bitref_r<T3> > +concat( sc_concref_r<T1,T2>, sc_bitref<T3> ); + +template <class T1, class T2, class T3> +inline +sc_concref_r<sc_concref_r<T1,T2>,sc_bitref_r<T3> > +concat( sc_concref<T1,T2>, sc_bitref_r<T3> ); + +template <class T1, class T2, class T3> +inline +sc_concref_r<sc_concref_r<T1,T2>,sc_subref_r<T3> > +concat( sc_concref_r<T1,T2>, sc_subref<T3> ); + +template <class T1, class T2, class T3> +inline +sc_concref_r<sc_concref_r<T1,T2>,sc_subref_r<T3> > +concat( sc_concref<T1,T2>, sc_subref_r<T3> ); + +template <class T1, class T2, class T3, class T4> +inline +sc_concref_r<sc_concref_r<T1,T2>,sc_concref_r<T3,T4> > +concat( sc_concref_r<T1,T2>, sc_concref<T3,T4> ); + +template <class T1, class T2, class T3, class T4> +inline +sc_concref_r<sc_concref_r<T1,T2>,sc_concref_r<T3,T4> > +concat( sc_concref<T1,T2>, sc_concref_r<T3,T4> ); + +template <class T1, class T2, class T3> +inline +sc_concref_r<sc_concref_r<T1,T2>,T3> +concat( sc_concref<T1,T2>, const sc_proxy<T3>& ); + +template <class T1, class T2, class T3> +inline +sc_concref_r<sc_concref_r<T1,T2>,T3> +concat( sc_concref_r<T1,T2>, sc_proxy<T3>& ); + +template <class T1, class T2> +inline +sc_concref_r<sc_concref_r<T1,T2>,sc_lv_base> +concat( sc_concref<T1,T2>, const char* ); + +template <class T1, class T2> +inline +sc_concref_r<sc_lv_base,sc_concref_r<T1,T2> > +concat( const char*, sc_concref<T1,T2> ); + +template <class T1, class T2> +inline +sc_concref_r<sc_concref_r<T1,T2>,sc_lv_base> +concat( sc_concref<T1,T2>, const sc_logic& ); + +template <class T1, class T2> +inline +sc_concref_r<sc_lv_base,sc_concref_r<T1,T2> > +concat( const sc_logic&, sc_concref<T1,T2> ); + +template <class T1, class T2> +inline +sc_concref_r<sc_concref_r<T1,T2>,sc_bv_base> +concat( sc_concref<T1,T2>, bool ); + +template <class T1, class T2> +inline +sc_concref_r<sc_bv_base,sc_concref_r<T1,T2> > +concat( bool, sc_concref<T1,T2> ); + +#endif + + +// ---------------------------------------------------------------------------- +// CLASS TEMPLATE : sc_concref<X,Y> +// +// Proxy class for sc_proxy concatenation (r-value and l-value). +// ---------------------------------------------------------------------------- + +template <class X, class Y> +class sc_concref + : public sc_concref_r<X,Y> +{ +public: + + // typedefs + + typedef sc_concref_r<X,Y> base_type; + + + // constructor + + sc_concref( X& left_, Y& right_, int delete_ = 0 ) + : sc_concref_r<X,Y>( left_, right_, delete_ ) + {} + + + // copy constructor + + sc_concref( const sc_concref<X,Y>& a ) + : sc_concref_r<X,Y>( a ) + {} + + + // cloning + + sc_concref<X,Y>* clone() const + { return new sc_concref<X,Y>( *this ); } + + + // assignment operators + + template <class Z> + sc_concref<X,Y>& operator = ( const sc_proxy<Z>& a ) + { base_type::assign_( a ); return *this; } + + sc_concref<X,Y>& operator = ( const sc_concref<X,Y>& a ) + { base_type::assign_( a ); return *this; } + + sc_concref<X,Y>& operator = ( const char* a ) + { base_type::assign_( a ); return *this; } + + sc_concref<X,Y>& operator = ( const bool* a ) + { base_type::assign_( a ); return *this; } + + sc_concref<X,Y>& operator = ( const sc_logic* a ) + { base_type::assign_( a ); return *this; } + + sc_concref<X,Y>& operator = ( const sc_unsigned& a ) + { base_type::assign_( a ); return *this; } + + sc_concref<X,Y>& operator = ( const sc_signed& a ) + { base_type::assign_( a ); return *this; } + + sc_concref<X,Y>& operator = ( const sc_uint_base& a ) + { base_type::assign_( a ); return *this; } + + sc_concref<X,Y>& operator = ( const sc_int_base& a ) + { base_type::assign_( a ); return *this; } + + sc_concref<X,Y>& operator = ( unsigned long a ) + { base_type::assign_( a ); return *this; } + + sc_concref<X,Y>& operator = ( long a ) + { base_type::assign_( a ); return *this; } + + sc_concref<X,Y>& operator = ( unsigned int a ) + { base_type::assign_( a ); return *this; } + + sc_concref<X,Y>& operator = ( int a ) + { base_type::assign_( a ); return *this; } + + sc_concref<X,Y>& operator = ( uint64 a ) + { base_type::assign_( a ); return *this; } + + sc_concref<X,Y>& operator = ( int64 a ) + { base_type::assign_( a ); return *this; } + + + // other methods + + void scan( ::std::istream& = ::std::cin ); + +private: + + // disabled + sc_concref(); +}; + + +// l-value concatenation operators and functions + +template <class T1, class T2, class T3> +inline +sc_concref<sc_concref<T1,T2>,sc_bitref<T3> > +operator , ( sc_concref<T1,T2>, sc_bitref<T3> ); + +template <class T1, class T2, class T3> +inline +sc_concref<sc_concref<T1,T2>,sc_subref<T3> > +operator , ( sc_concref<T1,T2>, sc_subref<T3> ); + +template <class T1, class T2, class T3, class T4> +inline +sc_concref<sc_concref<T1,T2>,sc_concref<T3,T4> > +operator , ( sc_concref<T1,T2>, sc_concref<T3,T4> ); + +template <class T1, class T2, class T3> +inline +sc_concref<sc_concref<T1,T2>,T3> +operator , ( sc_concref<T1,T2>, sc_proxy<T3>& ); + + +template <class T1, class T2, class T3> +inline +sc_concref<sc_concref<T1,T2>,sc_bitref<T3> > +concat( sc_concref<T1,T2>, sc_bitref<T3> ); + +template <class T1, class T2, class T3> +inline +sc_concref<sc_concref<T1,T2>,sc_subref<T3> > +concat( sc_concref<T1,T2>, sc_subref<T3> ); + +template <class T1, class T2, class T3, class T4> +inline +sc_concref<sc_concref<T1,T2>,sc_concref<T3,T4> > +concat( sc_concref<T1,T2>, sc_concref<T3,T4> ); + +template <class T1, class T2, class T3> +inline +sc_concref<sc_concref<T1,T2>,T3> +concat( sc_concref<T1,T2>, sc_proxy<T3>& ); + + +template <class T1, class T2> +inline +::std::istream& +operator >> ( ::std::istream&, sc_concref<T1,T2> ); + + +// ---------------------------------------------------------------------------- +// CLASS TEMPLATE : sc_proxy<T> +// +// Base class template for bit/logic vector classes. +// (Barton/Nackmann implementation) +// ---------------------------------------------------------------------------- + +// r-value concatenation operators and functions + +template <class T1, class T2> +inline +sc_concref_r<T1,sc_bitref_r<T2> > +operator , ( const sc_proxy<T1>&, sc_bitref_r<T2> ); + +template <class T1, class T2> +inline +sc_concref_r<T1,sc_subref_r<T2> > +operator , ( const sc_proxy<T1>&, sc_subref_r<T2> ); + +template <class T1, class T2, class T3> +inline +sc_concref_r<T1,sc_concref_r<T2,T3> > +operator , ( const sc_proxy<T1>&, sc_concref_r<T2,T3> ); + +template <class T1, class T2> +inline +sc_concref_r<T1,T2> +operator , ( const sc_proxy<T1>&, const sc_proxy<T2>& ); + +template <class T> +inline +sc_concref_r<T,sc_lv_base> +operator , ( const sc_proxy<T>&, const char* ); + +template <class T> +inline +sc_concref_r<sc_lv_base,T> +operator , ( const char*, const sc_proxy<T>& ); + +template <class T> +inline +sc_concref_r<T,sc_lv_base> +operator , ( const sc_proxy<T>&, const sc_logic& ); + +template <class T> +inline +sc_concref_r<sc_lv_base,T> +operator , ( const sc_logic&, const sc_proxy<T>& ); + +template <class T> +inline +sc_concref_r<T,sc_bv_base> +operator , ( const sc_proxy<T>&, bool ); + +template <class T> +inline +sc_concref_r<sc_bv_base,T> +operator , ( bool, const sc_proxy<T>& ); + + +template <class T1, class T2> +inline +sc_concref_r<T1,sc_bitref_r<T2> > +concat( const sc_proxy<T1>&, sc_bitref_r<T2> ); + +template <class T1, class T2> +inline +sc_concref_r<T1,sc_subref_r<T2> > +concat( const sc_proxy<T1>&, sc_subref_r<T2> ); + +template <class T1, class T2, class T3> +inline +sc_concref_r<T1,sc_concref_r<T2,T3> > +concat( const sc_proxy<T1>&, sc_concref_r<T2,T3> ); + +template <class T1, class T2> +inline +sc_concref_r<T1,T2> +concat( const sc_proxy<T1>&, const sc_proxy<T2>& ); + +template <class T> +inline +sc_concref_r<T,sc_lv_base> +concat( const sc_proxy<T>&, const char* ); + +template <class T> +inline +sc_concref_r<sc_lv_base,T> +concat( const char*, const sc_proxy<T>& ); + +template <class T> +inline +sc_concref_r<T,sc_lv_base> +concat( const sc_proxy<T>&, const sc_logic& ); + +template <class T> +inline +sc_concref_r<sc_lv_base,T> +concat( const sc_logic&, const sc_proxy<T>& ); + +template <class T> +inline +sc_concref_r<T,sc_bv_base> +concat( const sc_proxy<T>&, bool ); + +template <class T> +inline +sc_concref_r<sc_bv_base,T> +concat( bool, const sc_proxy<T>& ); + + +#ifdef SC_DT_MIXED_COMMA_OPERATORS + +template <class T1, class T2> +inline +sc_concref_r<T1,sc_bitref_r<T2> > +operator , ( const sc_proxy<T1>&, sc_bitref<T2> ); + +template <class T1, class T2> +inline +sc_concref_r<T1,sc_bitref_r<T2> > +operator , ( sc_proxy<T1>&, sc_bitref_r<T2> ); + +template <class T1, class T2> +inline +sc_concref_r<T1,sc_subref_r<T2> > +operator , ( const sc_proxy<T1>&, sc_subref<T2> ); + +template <class T1, class T2> +inline +sc_concref_r<T1,sc_subref_r<T2> > +operator , ( sc_proxy<T1>&, sc_subref_r<T2> ); + +template <class T1, class T2, class T3> +inline +sc_concref_r<T1,sc_concref_r<T2,T3> > +operator , ( const sc_proxy<T1>&, sc_concref<T2,T3> ); + +template <class T1, class T2, class T3> +inline +sc_concref_r<T1,sc_concref_r<T2,T3> > +operator , ( sc_proxy<T1>&, sc_concref_r<T2,T3> ); + +template <class T1, class T2> +inline +sc_concref_r<T1,T2> +operator , ( const sc_proxy<T1>&, sc_proxy<T2>& ); + +template <class T1, class T2> +inline +sc_concref_r<T1,T2> +operator , ( sc_proxy<T1>&, const sc_proxy<T2>& ); + +template <class T> +inline +sc_concref_r<T,sc_lv_base> +operator , ( sc_proxy<T>&, const char* ); + +template <class T> +inline +sc_concref_r<sc_lv_base,T> +operator , ( const char*, sc_proxy<T>& ); + +template <class T> +inline +sc_concref_r<T,sc_lv_base> +operator , ( sc_proxy<T>&, const sc_logic& ); + +template <class T> +inline +sc_concref_r<sc_lv_base,T> +operator , ( const sc_logic&, sc_proxy<T>& ); + +template <class T> +inline +sc_concref_r<T,sc_bv_base> +operator , ( sc_proxy<T>&, bool ); + +template <class T> +inline +sc_concref_r<sc_bv_base,T> +operator , ( bool, sc_proxy<T>& ); + + +template <class T1, class T2> +inline +sc_concref_r<T1,sc_bitref_r<T2> > +concat( const sc_proxy<T1>&, sc_bitref<T2> ); + +template <class T1, class T2> +inline +sc_concref_r<T1,sc_bitref_r<T2> > +concat( sc_proxy<T1>&, sc_bitref_r<T2> ); + +template <class T1, class T2> +inline +sc_concref_r<T1,sc_subref_r<T2> > +concat( const sc_proxy<T1>&, sc_subref<T2> ); + +template <class T1, class T2> +inline +sc_concref_r<T1,sc_subref_r<T2> > +concat( sc_proxy<T1>&, sc_subref_r<T2> ); + +template <class T1, class T2, class T3> +inline +sc_concref_r<T1,sc_concref_r<T2,T3> > +concat( const sc_proxy<T1>&, sc_concref<T2,T3> ); + +template <class T1, class T2, class T3> +inline +sc_concref_r<T1,sc_concref_r<T2,T3> > +concat( sc_proxy<T1>&, sc_concref_r<T2,T3> ); + +template <class T1, class T2> +inline +sc_concref_r<T1,T2> +concat( const sc_proxy<T1>&, sc_proxy<T2>& ); + +template <class T1, class T2> +inline +sc_concref_r<T1,T2> +concat( sc_proxy<T1>&, const sc_proxy<T2>& ); + +template <class T> +inline +sc_concref_r<T,sc_lv_base> +concat( sc_proxy<T>&, const char* ); + +template <class T> +inline +sc_concref_r<sc_lv_base,T> +concat( const char*, sc_proxy<T>& ); + +template <class T> +inline +sc_concref_r<T,sc_lv_base> +concat( sc_proxy<T>&, const sc_logic& ); + +template <class T> +inline +sc_concref_r<sc_lv_base,T> +concat( const sc_logic&, sc_proxy<T>& ); + +template <class T> +inline +sc_concref_r<T,sc_bv_base> +concat( sc_proxy<T>&, bool ); + +template <class T> +inline +sc_concref_r<sc_bv_base,T> +concat( bool, sc_proxy<T>& ); + +#endif + + +// l-value concatenation operators and functions + +template <class T1, class T2> +inline +sc_concref<T1,sc_bitref<T2> > +operator , ( sc_proxy<T1>&, sc_bitref<T2> ); + +template <class T1, class T2> +inline +sc_concref<T1,sc_subref<T2> > +operator , ( sc_proxy<T1>&, sc_subref<T2> ); + +template <class T1, class T2, class T3> +inline +sc_concref<T1,sc_concref<T2,T3> > +operator , ( sc_proxy<T1>&, sc_concref<T2,T3> ); + +template <class T1, class T2> +inline +sc_concref<T1,T2> +operator , ( sc_proxy<T1>&, sc_proxy<T2>& ); + + +template <class T1, class T2> +inline +sc_concref<T1,sc_bitref<T2> > +concat( sc_proxy<T1>&, sc_bitref<T2> ); + +template <class T1, class T2> +inline +sc_concref<T1,sc_subref<T2> > +concat( sc_proxy<T1>&, sc_subref<T2> ); + +template <class T1, class T2, class T3> +inline +sc_concref<T1,sc_concref<T2,T3> > +concat( sc_proxy<T1>&, sc_concref<T2,T3> ); + +template <class T1, class T2> +inline +sc_concref<T1,T2> +concat( sc_proxy<T1>&, sc_proxy<T2>& ); + + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + +// ---------------------------------------------------------------------------- +// CLASS TEMPLATE : sc_bitref_r<T> +// +// Proxy class for sc_proxy bit selection (r-value only). +// ---------------------------------------------------------------------------- + +// bitwise operators and functions + +// bitwise and + +template <class T1, class T2> +inline +const sc_logic +operator & ( const sc_bitref_r<T1>& a, const sc_bitref_r<T2>& b ) +{ + return sc_logic( sc_logic::and_table[a.value()][b.value()] ); +} + + +// bitwise or + +template <class T1, class T2> +inline +const sc_logic +operator | ( const sc_bitref_r<T1>& a, const sc_bitref_r<T2>& b ) +{ + return sc_logic( sc_logic::or_table[a.value()][b.value()] ); +} + + +// bitwise xor + +template <class T1, class T2> +inline +const sc_logic +operator ^ ( const sc_bitref_r<T1>& a, const sc_bitref_r<T2>& b ) +{ + return sc_logic( sc_logic::xor_table[a.value()][b.value()] ); +} + + +// relational operators and functions + +template <class T1, class T2> +inline +bool +operator == ( const sc_bitref_r<T1>& a, const sc_bitref_r<T2>& b ) +{ + return ( (int) a.value() == b.value() ); +} + +template <class T1, class T2> +inline +bool +operator != ( const sc_bitref_r<T1>& a, const sc_bitref_r<T2>& b ) +{ + return ( (int) a.value() != b.value() ); +} + + +// common methods + +template <class T> +inline +sc_logic_value_t +sc_bitref_r<T>::get_bit( int n ) const +{ + if( n == 0 ) { + return m_obj.get_bit( m_index ); + } else { + SC_REPORT_ERROR( sc_core::SC_ID_OUT_OF_BOUNDS_ , 0 ); + // never reached + return Log_0; + } +} + + +template <class T> +inline +sc_digit +sc_bitref_r<T>::get_word( int n ) const +{ + if( n == 0 ) { + return ( get_bit( n ) & SC_DIGIT_ONE ); + } else { + SC_REPORT_ERROR( sc_core::SC_ID_OUT_OF_BOUNDS_, 0 ); + // never reached + return 0; + } +} + +template <class T> +inline +sc_digit +sc_bitref_r<T>::get_cword( int n ) const +{ + if( n == 0 ) { + return ( (get_bit( n ) & SC_DIGIT_TWO) >> 1 ); + } else { + SC_REPORT_ERROR( sc_core::SC_ID_OUT_OF_BOUNDS_, 0 ); + // never reached + return 0; + } +} + + +// r-value concatenation operators and functions + +template <class T1, class T2> +inline +sc_concref_r<sc_bitref_r<T1>,sc_bitref_r<T2> > +operator , ( sc_bitref_r<T1> a, sc_bitref_r<T2> b ) +{ + return sc_concref_r<sc_bitref_r<T1>,sc_bitref_r<T2> >( + *a.clone(), *b.clone(), 3 ); +} + +template <class T1, class T2> +inline +sc_concref_r<sc_bitref_r<T1>,sc_subref_r<T2> > +operator , ( sc_bitref_r<T1> a, sc_subref_r<T2> b ) +{ + return sc_concref_r<sc_bitref_r<T1>,sc_subref_r<T2> >( + *a.clone(), *b.clone(), 3 ); +} + +template <class T1, class T2, class T3> +inline +sc_concref_r<sc_bitref_r<T1>,sc_concref_r<T2,T3> > +operator , ( sc_bitref_r<T1> a, sc_concref_r<T2,T3> b ) +{ + return sc_concref_r<sc_bitref_r<T1>,sc_concref_r<T2,T3> >( + *a.clone(), *b.clone(), 3 ); +} + +template <class T1, class T2> +inline +sc_concref_r<sc_bitref_r<T1>,T2> +operator , ( sc_bitref_r<T1> a, const sc_proxy<T2>& b ) +{ + return sc_concref_r<sc_bitref_r<T1>,T2>( + *a.clone(), b.back_cast(), 1 ); +} + + +template <class T1, class T2> +inline +sc_concref_r<sc_bitref_r<T1>,sc_bitref_r<T2> > +concat( sc_bitref_r<T1> a, sc_bitref_r<T2> b ) +{ + return sc_concref_r<sc_bitref_r<T1>,sc_bitref_r<T2> >( + *a.clone(), *b.clone(), 3 ); +} + +template <class T1, class T2> +inline +sc_concref_r<sc_bitref_r<T1>,sc_subref_r<T2> > +concat( sc_bitref_r<T1> a, sc_subref_r<T2> b ) +{ + return sc_concref_r<sc_bitref_r<T1>,sc_subref_r<T2> >( + *a.clone(), *b.clone(), 3 ); +} + +template <class T1, class T2, class T3> +inline +sc_concref_r<sc_bitref_r<T1>,sc_concref_r<T2,T3> > +concat( sc_bitref_r<T1> a, sc_concref_r<T2,T3> b ) +{ + return sc_concref_r<sc_bitref_r<T1>,sc_concref_r<T2,T3> >( + *a.clone(), *b.clone(), 3 ); +} + +template <class T1, class T2> +inline +sc_concref_r<sc_bitref_r<T1>,T2> +concat( sc_bitref_r<T1> a, const sc_proxy<T2>& b ) +{ + return sc_concref_r<sc_bitref_r<T1>,T2>( + *a.clone(), b.back_cast(), 1 ); +} + + +#ifdef SC_DT_MIXED_COMMA_OPERATORS + +template <class T1, class T2> +inline +sc_concref_r<sc_bitref_r<T1>,sc_bitref_r<T2> > +operator , ( sc_bitref_r<T1> a, sc_bitref<T2> b ) +{ + return sc_concref_r<sc_bitref_r<T1>,sc_bitref_r<T2> >( + *a.clone(), *b.clone(), 3 ); +} + +template <class T1, class T2> +inline +sc_concref_r<sc_bitref_r<T1>,sc_bitref_r<T2> > +operator , ( sc_bitref<T1> a, sc_bitref_r<T2> b ) +{ + return sc_concref_r<sc_bitref_r<T1>,sc_bitref_r<T2> >( + *a.clone(), *b.clone(), 3 ); +} + +template <class T1, class T2> +inline +sc_concref_r<sc_bitref_r<T1>,sc_subref_r<T2> > +operator , ( sc_bitref_r<T1> a, sc_subref<T2> b ) +{ + return sc_concref_r<sc_bitref_r<T1>,sc_subref_r<T2> >( + *a.clone(), *b.clone(), 3 ); +} + +template <class T1, class T2> +inline +sc_concref_r<sc_bitref_r<T1>,sc_subref_r<T2> > +operator , ( sc_bitref<T1> a, sc_subref_r<T2> b ) +{ + return sc_concref_r<sc_bitref_r<T1>,sc_subref_r<T2> >( + *a.clone(), *b.clone(), 3 ); +} + +template <class T1, class T2, class T3> +inline +sc_concref_r<sc_bitref_r<T1>,sc_concref_r<T2,T3> > +operator , ( sc_bitref_r<T1> a, sc_concref<T2,T3> b ) +{ + return sc_concref_r<sc_bitref_r<T1>,sc_concref_r<T2,T3> >( + *a.clone(), *b.clone(), 3 ); +} + +template <class T1, class T2, class T3> +inline +sc_concref_r<sc_bitref_r<T1>,sc_concref_r<T2,T3> > +operator , ( sc_bitref<T1> a, sc_concref_r<T2,T3> b ) +{ + return sc_concref_r<sc_bitref_r<T1>,sc_concref_r<T2,T3> >( + *a.clone(), *b.clone(), 3 ); +} + +template <class T1, class T2> +inline +sc_concref_r<sc_bitref_r<T1>,T2> +operator , ( sc_bitref<T1> a, const sc_proxy<T2>& b ) +{ + return sc_concref_r<sc_bitref_r<T1>,T2>( + *a.clone(), b.back_cast(), 1 ); +} + +template <class T1, class T2> +inline +sc_concref_r<sc_bitref_r<T1>,T2> +operator , ( sc_bitref_r<T1> a, sc_proxy<T2>& b ) +{ + return sc_concref_r<sc_bitref_r<T1>,T2>( + *a.clone(), b.back_cast(), 1 ); +} + + +template <class T1, class T2> +inline +sc_concref_r<sc_bitref_r<T1>,sc_bitref_r<T2> > +concat( sc_bitref_r<T1> a, sc_bitref<T2> b ) +{ + return sc_concref_r<sc_bitref_r<T1>,sc_bitref_r<T2> >( + *a.clone(), *b.clone(), 3 ); +} + +template <class T1, class T2> +inline +sc_concref_r<sc_bitref_r<T1>,sc_bitref_r<T2> > +concat( sc_bitref<T1> a, sc_bitref_r<T2> b ) +{ + return sc_concref_r<sc_bitref_r<T1>,sc_bitref_r<T2> >( + *a.clone(), *b.clone(), 3 ); +} + +template <class T1, class T2> +inline +sc_concref_r<sc_bitref_r<T1>,sc_subref_r<T2> > +concat( sc_bitref_r<T1> a, sc_subref<T2> b ) +{ + return sc_concref_r<sc_bitref_r<T1>,sc_subref_r<T2> >( + *a.clone(), *b.clone(), 3 ); +} + +template <class T1, class T2> +inline +sc_concref_r<sc_bitref_r<T1>,sc_subref_r<T2> > +concat( sc_bitref<T1> a, sc_subref_r<T2> b ) +{ + return sc_concref_r<sc_bitref_r<T1>,sc_subref_r<T2> >( + *a.clone(), *b.clone(), 3 ); +} + +template <class T1, class T2, class T3> +inline +sc_concref_r<sc_bitref_r<T1>,sc_concref_r<T2,T3> > +concat( sc_bitref_r<T1> a, sc_concref<T2,T3> b ) +{ + return sc_concref_r<sc_bitref_r<T1>,sc_concref_r<T2,T3> >( + *a.clone(), *b.clone(), 3 ); +} + +template <class T1, class T2, class T3> +inline +sc_concref_r<sc_bitref_r<T1>,sc_concref_r<T2,T3> > +concat( sc_bitref<T1> a, sc_concref_r<T2,T3> b ) +{ + return sc_concref_r<sc_bitref_r<T1>,sc_concref_r<T2,T3> >( + *a.clone(), *b.clone(), 3 ); +} + +template <class T1, class T2> +inline +sc_concref_r<sc_bitref_r<T1>,T2> +concat( sc_bitref<T1> a, const sc_proxy<T2>& b ) +{ + return sc_concref_r<sc_bitref_r<T1>,T2>( + *a.clone(), b.back_cast(), 1 ); +} + +template <class T1, class T2> +inline +sc_concref_r<sc_bitref_r<T1>,T2> +concat( sc_bitref_r<T1> a, sc_proxy<T2>& b ) +{ + return sc_concref_r<sc_bitref_r<T1>,T2>( + *a.clone(), b.back_cast(), 1 ); +} + +#endif + + +// ---------------------------------------------------------------------------- +// CLASS TEMPLATE : sc_bitref<X> +// +// Proxy class for sc_proxy bit selection (r-value and l-value). +// ---------------------------------------------------------------------------- + +// assignment operators + +template <class X> +inline +sc_bitref<X>& +sc_bitref<X>::operator = ( const sc_bitref_r<X>& a ) +{ + this->m_obj.set_bit( this->m_index, a.value() ); + return *this; +} + +template <class X> +inline +sc_bitref<X>& +sc_bitref<X>::operator = ( const sc_bitref<X>& a ) +{ + if( &a != this ) { + this->m_obj.set_bit( this->m_index, a.value() ); + } + return *this; +} + + +// bitwise assignment operators + +template <class X> +inline +sc_bitref<X>& +sc_bitref<X>::operator &= ( const sc_bitref_r<X>& a ) +{ + if( &a != this ) { + this->m_obj.set_bit( this->m_index, + sc_logic::and_table[this->value()][a.value()] ); + } + return *this; +} + +template <class X> +inline +sc_bitref<X>& +sc_bitref<X>::operator &= ( const sc_logic& a ) +{ + this->m_obj.set_bit( this->m_index, + sc_logic::and_table[this->value()][a.value()] ); + return *this; +} + + +template <class X> +inline +sc_bitref<X>& +sc_bitref<X>::operator |= ( const sc_bitref_r<X>& a ) +{ + if( &a != this ) { + this->m_obj.set_bit( this->m_index, + sc_logic::or_table[this->value()][a.value()] ); + } + return *this; +} + +template <class X> +inline +sc_bitref<X>& +sc_bitref<X>::operator |= ( const sc_logic& a ) +{ + this->m_obj.set_bit( this->m_index, + sc_logic::or_table[this->value()][a.value()] ); + return *this; +} + + +template <class X> +inline +sc_bitref<X>& +sc_bitref<X>::operator ^= ( const sc_bitref_r<X>& a ) +{ + if( &a != this ) { + this->m_obj.set_bit( this->m_index, + sc_logic::xor_table[this->value()][a.value()] ); + } + return *this; +} + +template <class X> +inline +sc_bitref<X>& +sc_bitref<X>::operator ^= ( const sc_logic& a ) +{ + this->m_obj.set_bit( this->m_index, + sc_logic::xor_table[this->value()][a.value()] ); + return *this; +} + + +// bitwise operators and functions + +// bitwise complement + +template <class X> +inline +sc_bitref<X>& +sc_bitref<X>::b_not() +{ + this->m_obj.set_bit( this->m_index, + sc_logic::not_table[this->value()] ); + return *this; +} + + +// common methods + +template <class X> +inline +void +sc_bitref<X>::set_bit( int n, sc_logic_value_t value ) +{ + if( n == 0 ) { + this->m_obj.set_bit( this->m_index, value ); + } else { + SC_REPORT_ERROR( sc_core::SC_ID_OUT_OF_BOUNDS_, 0 ); + } +} + +template <class X> +inline +void +sc_bitref<X>::set_word( int n, sc_digit w ) +{ + unsigned int bi = this->m_index % (8*sizeof(sc_digit)); + sc_digit temp; + unsigned int wi = this->m_index / (8*sizeof(sc_digit)); + if( n == 0 ) { + temp = this->m_obj.get_word(wi); + temp = (temp & ~(1 << bi)) | ((w&1) << bi); + this->m_obj.set_word(wi, temp); + } else { + SC_REPORT_ERROR( sc_core::SC_ID_OUT_OF_BOUNDS_, 0 ); + } + +} + +template <class X> +inline +void +sc_bitref<X>::set_cword( int n, sc_digit w ) +{ + unsigned int bi = this->m_index % (8*sizeof(sc_digit)); + sc_digit temp; + unsigned int wi = this->m_index / (8*sizeof(sc_digit)); + if( n == 0 ) { + temp = this->m_obj.get_cword(wi); + temp = (temp & ~(1 << bi)) | ((w&1) << bi); + this->m_obj.set_cword(wi, temp); + } else { + SC_REPORT_ERROR( sc_core::SC_ID_OUT_OF_BOUNDS_, 0 ); + } +} + +// other methods + +template <class X> +inline +void +sc_bitref<X>::scan( ::std::istream& is ) +{ + char c; + is >> c; + *this = c; +} + + +// l-value concatenation operators and functions + +template <class T1, class T2> +inline +sc_concref<sc_bitref<T1>,sc_bitref<T2> > +operator , ( sc_bitref<T1> a, sc_bitref<T2> b ) +{ + return sc_concref<sc_bitref<T1>,sc_bitref<T2> >( + *a.clone(), *b.clone(), 3 ); +} + +template <class T1, class T2> +inline +sc_concref<sc_bitref<T1>,sc_subref<T2> > +operator , ( sc_bitref<T1> a, sc_subref<T2> b ) +{ + return sc_concref<sc_bitref<T1>,sc_subref<T2> >( + *a.clone(), *b.clone(), 3 ); +} + +template <class T1, class T2, class T3> +inline +sc_concref<sc_bitref<T1>,sc_concref<T2,T3> > +operator , ( sc_bitref<T1> a, sc_concref<T2,T3> b ) +{ + return sc_concref<sc_bitref<T1>,sc_concref<T2,T3> >( + *a.clone(), *b.clone(), 3 ); +} + +template <class T1, class T2> +inline +sc_concref<sc_bitref<T1>,T2> +operator , ( sc_bitref<T1> a, sc_proxy<T2>& b ) +{ + return sc_concref<sc_bitref<T1>,T2>( + *a.clone(), b.back_cast(), 1 ); +} + + +template <class T1, class T2> +inline +sc_concref<sc_bitref<T1>,sc_bitref<T2> > +concat( sc_bitref<T1> a, sc_bitref<T2> b ) +{ + return sc_concref<sc_bitref<T1>,sc_bitref<T2> >( + *a.clone(), *b.clone(), 3 ); +} + +template <class T1, class T2> +inline +sc_concref<sc_bitref<T1>,sc_subref<T2> > +concat( sc_bitref<T1> a, sc_subref<T2> b ) +{ + return sc_concref<sc_bitref<T1>,sc_subref<T2> >( + *a.clone(), *b.clone(), 3 ); +} + +template <class T1, class T2, class T3> +inline +sc_concref<sc_bitref<T1>,sc_concref<T2,T3> > +concat( sc_bitref<T1> a, sc_concref<T2,T3> b ) +{ + return sc_concref<sc_bitref<T1>,sc_concref<T2,T3> >( + *a.clone(), *b.clone(), 3 ); +} + +template <class T1, class T2> +inline +sc_concref<sc_bitref<T1>,T2> +concat( sc_bitref<T1> a, sc_proxy<T2>& b ) +{ + return sc_concref<sc_bitref<T1>,T2>( + *a.clone(), b.back_cast(), 1 ); +} + + +template <class X> +inline +::std::istream& +operator >> ( ::std::istream& is, sc_bitref<X> a ) +{ + a.scan( is ); + return is; +} + + +// ---------------------------------------------------------------------------- +// CLASS TEMPLATE : sc_subref_r<X> +// +// Proxy class for sc_proxy part selection (r-value only). +// ---------------------------------------------------------------------------- + +template <class X> +inline +void +sc_subref_r<X>::check_bounds() +{ + int len = m_obj.length(); + if( m_hi < 0 || m_hi >= len || m_lo < 0 || m_lo >= len ) { + SC_REPORT_ERROR( sc_core::SC_ID_OUT_OF_BOUNDS_, 0 ); + } + if( reversed() ) { + m_len = m_lo - m_hi + 1; + } else { + m_len = m_hi - m_lo + 1; + } +} + + +// common methods + +template <class X> +inline +sc_logic_value_t +sc_subref_r<X>::get_bit( int n ) const +{ + if( reversed() ) { + return m_obj.get_bit( m_lo - n ); + } else { + return m_obj.get_bit( m_lo + n ); + } +} + +template <class X> +inline +void +sc_subref_r<X>::set_bit( int n, sc_logic_value_t value ) +{ + if( reversed() ) { + m_obj.set_bit( m_lo - n, value ); + } else { + m_obj.set_bit( m_lo + n, value ); + } +} + + +template <class X> +inline +sc_digit +sc_subref_r<X>::get_word( int i ) const +{ + int n1 = 0; + int n2 = 0; + sc_digit result = 0; + int k = 0; + if( reversed() ) { + n1 = m_lo - i * SC_DIGIT_SIZE; + n2 = sc_max( n1 - SC_DIGIT_SIZE, m_hi - 1 ); + for( int n = n1; n > n2; n -- ) { + result |= (m_obj[n].value() & SC_DIGIT_ONE) << k ++; + } + } else { + n1 = m_lo + i * SC_DIGIT_SIZE; + n2 = sc_min( n1 + SC_DIGIT_SIZE, m_hi + 1 ); + for( int n = n1; n < n2; n ++ ) { + result |= (m_obj[n].value() & SC_DIGIT_ONE) << k ++; + } + } + return result; +} + +template <class X> +inline +void +sc_subref_r<X>::set_word( int i, sc_digit w ) +{ + int n1 = 0; + int n2 = 0; + int k = 0; + if( reversed() ) { + n1 = m_lo - i * SC_DIGIT_SIZE; + n2 = sc_max( n1 - SC_DIGIT_SIZE, m_hi - 1 ); + for( int n = n1; n > n2; n -- ) { + m_obj.set_bit( n, sc_logic_value_t( + ( (w >> k ++) & SC_DIGIT_ONE ) | + ( m_obj[n].value() & SC_DIGIT_TWO ) ) ); + } + } else { + n1 = m_lo + i * SC_DIGIT_SIZE; + n2 = sc_min( n1 + SC_DIGIT_SIZE, m_hi + 1 ); + for( int n = n1; n < n2; n ++ ) { + m_obj.set_bit( n, sc_logic_value_t( + ( (w >> k ++) & SC_DIGIT_ONE ) | + ( m_obj[n].value() & SC_DIGIT_TWO ) ) ); + } + } +} + + +template <class X> +inline +sc_digit +sc_subref_r<X>::get_cword( int i ) const +{ + int n1 = 0; + int n2 = 0; + sc_digit result = 0; + int k = 0; + if( reversed() ) { + n1 = m_lo - i * SC_DIGIT_SIZE; + n2 = sc_max( n1 - SC_DIGIT_SIZE, m_hi - 1 ); + for( int n = n1; n > n2; n -- ) { + result |= ((m_obj[n].value() & SC_DIGIT_TWO) >> 1) << k ++; + } + } else { + n1 = m_lo + i * SC_DIGIT_SIZE; + n2 = sc_min( n1 + SC_DIGIT_SIZE, m_hi + 1 ); + for( int n = n1; n < n2; n ++ ) { + result |= ((m_obj[n].value() & SC_DIGIT_TWO) >> 1) << k ++; + } + } + return result; +} + +template <class X> +inline +void +sc_subref_r<X>::set_cword( int i, sc_digit w ) +{ + int n1 = 0; + int n2 = 0; + int k = 0; + if( reversed() ) { + n1 = m_lo - i * SC_DIGIT_SIZE; + n2 = sc_max( n1 - SC_DIGIT_SIZE, m_hi - 1 ); + for( int n = n1; n > n2; n -- ) { + m_obj.set_bit( n, sc_logic_value_t( + ( ((w >> k ++) & SC_DIGIT_ONE) << 1 ) | + ( m_obj[n].value() & SC_DIGIT_ONE ) ) ); + } + } else { + n1 = m_lo + i * SC_DIGIT_SIZE; + n2 = sc_min( n1 + SC_DIGIT_SIZE, m_hi + 1 ); + for( int n = n1; n < n2; n ++ ) { + m_obj.set_bit( n, sc_logic_value_t( + ( ((w >> k ++) & SC_DIGIT_ONE) << 1 ) | + ( m_obj[n].value() & SC_DIGIT_ONE ) ) ); + } + } +} + + +// other methods + +template <class X> +inline +bool +sc_subref_r<X>::is_01() const +{ + int sz = size(); + for( int i = 0; i < sz; ++ i ) { + if( get_cword( i ) != SC_DIGIT_ZERO ) { + return false; + } + } + return true; +} + + +// r-value concatenation operators and functions + +template <class T1, class T2> +inline +sc_concref_r<sc_subref_r<T1>,sc_bitref_r<T2> > +operator , ( sc_subref_r<T1> a, sc_bitref_r<T2> b ) +{ + return sc_concref_r<sc_subref_r<T1>,sc_bitref_r<T2> >( + *a.clone(), *b.clone(), 3 ); +} + +template <class T1, class T2> +inline +sc_concref_r<sc_subref_r<T1>,sc_subref_r<T2> > +operator , ( sc_subref_r<T1> a, sc_subref_r<T2> b ) +{ + return sc_concref_r<sc_subref_r<T1>,sc_subref_r<T2> >( + *a.clone(), *b.clone(), 3 ); +} + +template <class T1, class T2, class T3> +inline +sc_concref_r<sc_subref_r<T1>,sc_concref_r<T2,T3> > +operator , ( sc_subref_r<T1> a, sc_concref_r<T2,T3> b ) +{ + return sc_concref_r<sc_subref_r<T1>,sc_concref_r<T2,T3> >( + *a.clone(), *b.clone(), 3 ); +} + +template <class T1, class T2> +inline +sc_concref_r<sc_subref_r<T1>,T2> +operator , ( sc_subref_r<T1> a, const sc_proxy<T2>& b ) +{ + return sc_concref_r<sc_subref_r<T1>,T2>( + *a.clone(), b.back_cast(), 1 ); +} + + +template <class T1, class T2> +inline +sc_concref_r<sc_subref_r<T1>,sc_bitref_r<T2> > +concat( sc_subref_r<T1> a, sc_bitref_r<T2> b ) +{ + return sc_concref_r<sc_subref_r<T1>,sc_bitref_r<T2> >( + *a.clone(), *b.clone(), 3 ); +} + +template <class T1, class T2> +inline +sc_concref_r<sc_subref_r<T1>,sc_subref_r<T2> > +concat( sc_subref_r<T1> a, sc_subref_r<T2> b ) +{ + return sc_concref_r<sc_subref_r<T1>,sc_subref_r<T2> >( + *a.clone(), *b.clone(), 3 ); +} + +template <class T1, class T2, class T3> +inline +sc_concref_r<sc_subref_r<T1>,sc_concref_r<T2,T3> > +concat( sc_subref_r<T1> a, sc_concref_r<T2,T3> b ) +{ + return sc_concref_r<sc_subref_r<T1>,sc_concref_r<T2,T3> >( + *a.clone(), *b.clone(), 3 ); +} + +template <class T1, class T2> +inline +sc_concref_r<sc_subref_r<T1>,T2> +concat( sc_subref_r<T1> a, const sc_proxy<T2>& b ) +{ + return sc_concref_r<sc_subref_r<T1>,T2>( + *a.clone(), b.back_cast(), 1 ); +} + + +#ifdef SC_DT_MIXED_COMMA_OPERATORS + +template <class T1, class T2> +inline +sc_concref_r<sc_subref_r<T1>,sc_bitref_r<T2> > +operator , ( sc_subref_r<T1> a, sc_bitref<T2> b ) +{ + return sc_concref_r<sc_subref_r<T1>,sc_bitref_r<T2> >( + *a.clone(), *b.clone(), 3 ); +} + +template <class T1, class T2> +inline +sc_concref_r<sc_subref_r<T1>,sc_bitref_r<T2> > +operator , ( sc_subref<T1> a, sc_bitref_r<T2> b ) +{ + return sc_concref_r<sc_subref_r<T1>,sc_bitref_r<T2> >( + *a.clone(), *b.clone(), 3 ); +} + +template <class T1, class T2> +inline +sc_concref_r<sc_subref_r<T1>,sc_subref_r<T2> > +operator , ( sc_subref_r<T1> a, sc_subref<T2> b ) +{ + return sc_concref_r<sc_subref_r<T1>,sc_subref_r<T2> >( + *a.clone(), *b.clone(), 3 ); +} + +template <class T1, class T2> +inline +sc_concref_r<sc_subref_r<T1>,sc_subref_r<T2> > +operator , ( sc_subref<T1> a, sc_subref_r<T2> b ) +{ + return sc_concref_r<sc_subref_r<T1>,sc_subref_r<T2> >( + *a.clone(), *b.clone(), 3 ); +} + +template <class T1, class T2, class T3> +inline +sc_concref_r<sc_subref_r<T1>,sc_concref_r<T2,T3> > +operator , ( sc_subref_r<T1> a, sc_concref<T2,T3> b ) +{ + return sc_concref_r<sc_subref_r<T1>,sc_concref_r<T2,T3> >( + *a.clone(), *b.clone(), 3 ); +} + +template <class T1, class T2, class T3> +inline +sc_concref_r<sc_subref_r<T1>,sc_concref_r<T2,T3> > +operator , ( sc_subref<T1> a, sc_concref_r<T2,T3> b ) +{ + return sc_concref_r<sc_subref_r<T1>,sc_concref_r<T2,T3> >( + *a.clone(), *b.clone(), 3 ); +} + +template <class T1, class T2> +inline +sc_concref_r<sc_subref_r<T1>,T2> +operator , ( sc_subref<T1> a, const sc_proxy<T2>& b ) +{ + return sc_concref_r<sc_subref_r<T1>,T2>( + *a.clone(), b.back_cast(), 1 ); +} + +template <class T1, class T2> +inline +sc_concref_r<sc_subref_r<T1>,T2> +operator , ( sc_subref_r<T1> a, sc_proxy<T2>& b ) +{ + return sc_concref_r<sc_subref_r<T1>,T2>( + *a.clone(), b.back_cast(), 1 ); +} + + +template <class T1, class T2> +inline +sc_concref_r<sc_subref_r<T1>,sc_bitref_r<T2> > +concat( sc_subref_r<T1> a, sc_bitref<T2> b ) +{ + return sc_concref_r<sc_subref_r<T1>,sc_bitref_r<T2> >( + *a.clone(), *b.clone(), 3 ); +} + +template <class T1, class T2> +inline +sc_concref_r<sc_subref_r<T1>,sc_bitref_r<T2> > +concat( sc_subref<T1> a, sc_bitref_r<T2> b ) +{ + return sc_concref_r<sc_subref_r<T1>,sc_bitref_r<T2> >( + *a.clone(), *b.clone(), 3 ); +} + +template <class T1, class T2> +inline +sc_concref_r<sc_subref_r<T1>,sc_subref_r<T2> > +concat( sc_subref_r<T1> a, sc_subref<T2> b ) +{ + return sc_concref_r<sc_subref_r<T1>,sc_subref_r<T2> >( + *a.clone(), *b.clone(), 3 ); +} + +template <class T1, class T2> +inline +sc_concref_r<sc_subref_r<T1>,sc_subref_r<T2> > +concat( sc_subref<T1> a, sc_subref_r<T2> b ) +{ + return sc_concref_r<sc_subref_r<T1>,sc_subref_r<T2> >( + *a.clone(), *b.clone(), 3 ); +} + +template <class T1, class T2, class T3> +inline +sc_concref_r<sc_subref_r<T1>,sc_concref_r<T2,T3> > +concat( sc_subref_r<T1> a, sc_concref<T2,T3> b ) +{ + return sc_concref_r<sc_subref_r<T1>,sc_concref_r<T2,T3> >( + *a.clone(), *b.clone(), 3 ); +} + +template <class T1, class T2, class T3> +inline +sc_concref_r<sc_subref_r<T1>,sc_concref_r<T2,T3> > +concat( sc_subref<T1> a, sc_concref_r<T2,T3> b ) +{ + return sc_concref_r<sc_subref_r<T1>,sc_concref_r<T2,T3> >( + *a.clone(), *b.clone(), 3 ); +} + +template <class T1, class T2> +inline +sc_concref_r<sc_subref_r<T1>,T2> +concat( sc_subref<T1> a, const sc_proxy<T2>& b ) +{ + return sc_concref_r<sc_subref_r<T1>,T2>( + *a.clone(), b.back_cast(), 1 ); +} + +template <class T1, class T2> +inline +sc_concref_r<sc_subref_r<T1>,T2> +concat( sc_subref_r<T1> a, sc_proxy<T2>& b ) +{ + return sc_concref_r<sc_subref_r<T1>,T2>( + *a.clone(), b.back_cast(), 1 ); +} + +#endif + + +// ---------------------------------------------------------------------------- +// CLASS TEMPLATE : sc_subref<X> +// +// Proxy class for sc_proxy part selection (r-value and l-value). +// ---------------------------------------------------------------------------- + +// assignment operators + +// sc_subref<X>::operator = ( const sc_subref_r<X>& ) in sc_lv_base.h +// sc_subref<X>::operator = ( const sc_subref<X>& ) in sc_lv_base.h + + +// other methods + +template <class T> +inline +void +sc_subref<T>::scan( ::std::istream& is ) +{ + std::string s; + is >> s; + *this = s.c_str(); +} + + +// l-value concatenation operators and functions + +template <class T1, class T2> +inline +sc_concref<sc_subref<T1>,sc_bitref<T2> > +operator , ( sc_subref<T1> a, sc_bitref<T2> b ) +{ + return sc_concref<sc_subref<T1>,sc_bitref<T2> >( + *a.clone(), *b.clone(), 3 ); +} + +template <class T1, class T2> +inline +sc_concref<sc_subref<T1>,sc_subref<T2> > +operator , ( sc_subref<T1> a, sc_subref<T2> b ) +{ + return sc_concref<sc_subref<T1>,sc_subref<T2> >( + *a.clone(), *b.clone(), 3 ); +} + +template <class T1, class T2, class T3> +inline +sc_concref<sc_subref<T1>,sc_concref<T2,T3> > +operator , ( sc_subref<T1> a, sc_concref<T2,T3> b ) +{ + return sc_concref<sc_subref<T1>,sc_concref<T2,T3> >( + *a.clone(), *b.clone(), 3 ); +} + +template <class T1, class T2> +inline +sc_concref<sc_subref<T1>,T2> +operator , ( sc_subref<T1> a, sc_proxy<T2>& b ) +{ + return sc_concref<sc_subref<T1>,T2>( + *a.clone(), b.back_cast(), 1 ); +} + + +template <class T1, class T2> +inline +sc_concref<sc_subref<T1>,sc_bitref<T2> > +concat( sc_subref<T1> a, sc_bitref<T2> b ) +{ + return sc_concref<sc_subref<T1>,sc_bitref<T2> >( + *a.clone(), *b.clone(), 3 ); +} + +template <class T1, class T2> +inline +sc_concref<sc_subref<T1>,sc_subref<T2> > +concat( sc_subref<T1> a, sc_subref<T2> b ) +{ + return sc_concref<sc_subref<T1>,sc_subref<T2> >( + *a.clone(), *b.clone(), 3 ); +} + +template <class T1, class T2, class T3> +inline +sc_concref<sc_subref<T1>,sc_concref<T2,T3> > +concat( sc_subref<T1> a, sc_concref<T2,T3> b ) +{ + return sc_concref<sc_subref<T1>,sc_concref<T2,T3> >( + *a.clone(), *b.clone(), 3 ); +} + +template <class T1, class T2> +inline +sc_concref<sc_subref<T1>,T2> +concat( sc_subref<T1> a, sc_proxy<T2>& b ) +{ + return sc_concref<sc_subref<T1>,T2>( + *a.clone(), b.back_cast(), 1 ); +} + + +template <class X> +inline +::std::istream& +operator >> ( ::std::istream& is, sc_subref<X> a ) +{ + a.scan( is ); + return is; +} + + +// ---------------------------------------------------------------------------- +// CLASS TEMPLATE : sc_concref_r<X,Y> +// +// Proxy class for sc_proxy concatenation (r-value only). +// ---------------------------------------------------------------------------- + +// destructor + +template <class X, class Y> +inline +sc_concref_r<X,Y>::~sc_concref_r() +{ + if( -- m_refs == 0 ) { + delete &m_refs; + if( m_delete == 0 ) { + return; + } + if( m_delete & 1 ) { + delete &m_left; + } + if( m_delete & 2 ) { + delete &m_right; + } + } +} + + +// common methods + +template <class X, class Y> +inline +sc_logic_value_t +sc_concref_r<X,Y>::get_bit( int n ) const +{ + int r_len = m_right.length(); + if( n < r_len ) { + return m_right.get_bit( n ); + } else if( n < r_len + m_left.length() ) { + return m_left.get_bit( n - r_len ); + } else { + SC_REPORT_ERROR( sc_core::SC_ID_OUT_OF_BOUNDS_, 0 ); + // never reached + return Log_0; + } +} + +template <class X, class Y> +inline +void +sc_concref_r<X,Y>::set_bit( int n, sc_logic_value_t v ) +{ + int r_len = m_right.length(); + if( n < r_len ) { + m_right.set_bit( n, v ); + } else if( n < r_len + m_left.length() ) { + m_left.set_bit( n - r_len, v ); + } else { + SC_REPORT_ERROR( sc_core::SC_ID_OUT_OF_BOUNDS_, 0 ); + } +} + + +template <class X, class Y> +inline +sc_digit +sc_concref_r<X,Y>::get_word( int i ) const +{ + if( i < 0 || i >= size() ) { + SC_REPORT_ERROR( sc_core::SC_ID_OUT_OF_BOUNDS_, 0 ); + } + // 0 <= i < size() + Y& r = m_right; + int r_len = r.length(); + int border = r_len / SC_DIGIT_SIZE; + if( i < border ) { + return r.get_word( i ); + } + // border <= i < size() + X& l = m_left; + int shift = r_len % SC_DIGIT_SIZE; + int j = i - border; + if( shift == 0 ) { + return l.get_word( j ); + } + // border <= i < size() && shift != 0 + int nshift = SC_DIGIT_SIZE - shift; + if( i == border ) { + sc_digit rl_mask = ~SC_DIGIT_ZERO >> nshift; + return ( (r.get_word( i ) & rl_mask) | (l.get_word( 0 ) << shift) ); + } + // border < i < size() && shift != 0 + if ( j < l.size() ) + return ( (l.get_word( j - 1 ) >> nshift) | (l.get_word( j ) << shift) ); + else + return (l.get_word( j - 1 ) >> nshift); +} + +template <class X, class Y> +inline +void +sc_concref_r<X,Y>::set_word( int i, sc_digit w ) +{ + if( i < 0 || i >= size() ) { + SC_REPORT_ERROR( sc_core::SC_ID_OUT_OF_BOUNDS_, 0 ); + } + // 0 <= i < size() + Y& r = m_right; + int r_len = r.length(); + int border = r_len / SC_DIGIT_SIZE; + if( i < border ) { + r.set_word( i, w ); + return; + } + // border <= i < size() + X& l = m_left; + int shift = r_len % SC_DIGIT_SIZE; + int j = i - border; + if( shift == 0 ) { + l.set_word( j, w ); + return; + } + // border <= i < size() && shift != 0 + int nshift = SC_DIGIT_SIZE - shift; + sc_digit lh_mask = ~SC_DIGIT_ZERO << nshift; + if( i == border ) { + sc_digit rl_mask = ~SC_DIGIT_ZERO >> nshift; + r.set_word( i, w & rl_mask ); + l.set_word( 0, (l.get_word( 0 ) & lh_mask) | (w >> shift) ); + return; + } + // border < i < size() && shift != 0 + sc_digit ll_mask = ~SC_DIGIT_ZERO >> shift; + l.set_word( j - 1, (l.get_word( j - 1 ) & ll_mask) | (w << nshift) ); + if ( j < l.size() ) + l.set_word( j, (l.get_word( j ) & lh_mask) | (w >> shift) ); +} + + +template <class X, class Y> +inline +sc_digit +sc_concref_r<X,Y>::get_cword( int i ) const +{ + if( i < 0 || i >= size() ) { + SC_REPORT_ERROR( sc_core::SC_ID_OUT_OF_BOUNDS_, 0 ); + } + // 0 <= i < size() + Y& r = m_right; + int r_len = r.length(); + int border = r_len / SC_DIGIT_SIZE; + if( i < border ) { + return r.get_cword( i ); + } + // border <= i < size() + X& l = m_left; + int shift = r_len % SC_DIGIT_SIZE; + int j = i - border; + if( shift == 0 ) { + return l.get_cword( j ); + } + // border <= i < size() && shift != 0 + int nshift = SC_DIGIT_SIZE - shift; + if( i == border ) { + sc_digit rl_mask = ~SC_DIGIT_ZERO >> nshift; + return ( (r.get_cword( i ) & rl_mask) | (l.get_cword( 0 ) << shift) ); + } + // border < i < size() && shift != 0 + if ( j < l.size() ) + return ( (l.get_cword(j - 1) >> nshift) | (l.get_cword(j) << shift) ); + else + return (l.get_cword( j - 1 ) >> nshift); +} + +template <class X, class Y> +inline +void +sc_concref_r<X,Y>::set_cword( int i, sc_digit w ) +{ + if( i < 0 || i >= size() ) { + SC_REPORT_ERROR( sc_core::SC_ID_OUT_OF_BOUNDS_, 0 ); + } + // 0 <= i < size() + Y& r = m_right; + int r_len = r.length(); + int border = r_len / SC_DIGIT_SIZE; + if( i < border ) { + r.set_cword( i, w ); + return; + } + // border <= i < size() + X& l = m_left; + int shift = r_len % SC_DIGIT_SIZE; + int j = i - border; + if( shift == 0 ) { + l.set_cword( j, w ); + return; + } + // border <= i < size() && shift != 0 + int nshift = SC_DIGIT_SIZE - shift; + sc_digit lh_mask = ~SC_DIGIT_ZERO << nshift; + if( i == border ) { + sc_digit rl_mask = ~SC_DIGIT_ZERO >> nshift; + r.set_cword( i, w & rl_mask ); + l.set_cword( 0, (l.get_cword( 0 ) & lh_mask) | (w >> shift) ); + return; + } + // border < i < size() && shift != 0 + sc_digit ll_mask = ~SC_DIGIT_ZERO >> shift; + l.set_cword( j - 1, (l.get_cword( j - 1 ) & ll_mask) | (w << nshift) ); + if ( j < l.size() ) + l.set_cword( j, (l.get_cword( j ) & lh_mask) | (w >> shift) ); +} + + +// r-value concatenation operators and functions + +template <class T1, class T2, class T3> +inline +sc_concref_r<sc_concref_r<T1,T2>,sc_bitref_r<T3> > +operator , ( sc_concref_r<T1,T2> a, sc_bitref_r<T3> b ) +{ + return sc_concref_r<sc_concref_r<T1,T2>,sc_bitref_r<T3> >( + *a.clone(), *b.clone(), 3 ); +} + +template <class T1, class T2, class T3> +inline +sc_concref_r<sc_concref_r<T1,T2>,sc_subref_r<T3> > +operator , ( sc_concref_r<T1,T2> a, sc_subref_r<T3> b ) +{ + return sc_concref_r<sc_concref_r<T1,T2>,sc_subref_r<T3> >( + *a.clone(), *b.clone(), 3 ); +} + +template <class T1, class T2, class T3, class T4> +inline +sc_concref_r<sc_concref_r<T1,T2>,sc_concref_r<T3,T4> > +operator , ( sc_concref_r<T1,T2> a, sc_concref_r<T3,T4> b ) +{ + return sc_concref_r<sc_concref_r<T1,T2>,sc_concref_r<T3,T4> >( + *a.clone(), *b.clone(), 3 ); +} + +template <class T1, class T2, class T3> +inline +sc_concref_r<sc_concref_r<T1,T2>,T3> +operator , ( sc_concref_r<T1,T2> a, const sc_proxy<T3>& b ) +{ + return sc_concref_r<sc_concref_r<T1,T2>,T3>( + *a.clone(), b.back_cast(), 1 ); +} + + +template <class T1, class T2, class T3> +inline +sc_concref_r<sc_concref_r<T1,T2>,sc_bitref_r<T3> > +concat( sc_concref_r<T1,T2> a, sc_bitref_r<T3> b ) +{ + return sc_concref_r<sc_concref_r<T1,T2>,sc_bitref_r<T3> >( + *a.clone(), *b.clone(), 3 ); +} + +template <class T1, class T2, class T3> +inline +sc_concref_r<sc_concref_r<T1,T2>,sc_subref_r<T3> > +concat( sc_concref_r<T1,T2> a, sc_subref_r<T3> b ) +{ + return sc_concref_r<sc_concref_r<T1,T2>,sc_subref_r<T3> >( + *a.clone(), *b.clone(), 3 ); +} + +template <class T1, class T2, class T3, class T4> +inline +sc_concref_r<sc_concref_r<T1,T2>,sc_concref_r<T3,T4> > +concat( sc_concref_r<T1,T2> a, sc_concref_r<T3,T4> b ) +{ + return sc_concref_r<sc_concref_r<T1,T2>,sc_concref_r<T3,T4> >( + *a.clone(), *b.clone(), 3 ); +} + +template <class T1, class T2, class T3> +inline +sc_concref_r<sc_concref_r<T1,T2>,T3> +concat( sc_concref_r<T1,T2> a, const sc_proxy<T3>& b ) +{ + return sc_concref_r<sc_concref_r<T1,T2>,T3>( + *a.clone(), b.back_cast(), 1 ); +} + + +#ifdef SC_DT_MIXED_COMMA_OPERATORS + +template <class T1, class T2, class T3> +inline +sc_concref_r<sc_concref_r<T1,T2>,sc_bitref_r<T3> > +operator , ( sc_concref_r<T1,T2> a, sc_bitref<T3> b ) +{ + return sc_concref_r<sc_concref_r<T1,T2>,sc_bitref_r<T3> >( + *a.clone(), *b.clone(), 3 ); +} + +template <class T1, class T2, class T3> +inline +sc_concref_r<sc_concref_r<T1,T2>,sc_bitref_r<T3> > +operator , ( sc_concref<T1,T2> a, sc_bitref_r<T3> b ) +{ + return sc_concref_r<sc_concref_r<T1,T2>,sc_bitref_r<T3> >( + *a.clone(), *b.clone(), 3 ); +} + +template <class T1, class T2, class T3> +inline +sc_concref_r<sc_concref_r<T1,T2>,sc_subref_r<T3> > +operator , ( sc_concref_r<T1,T2> a, sc_subref<T3> b ) +{ + return sc_concref_r<sc_concref_r<T1,T2>,sc_subref_r<T3> >( + *a.clone(), *b.clone(), 3 ); +} + +template <class T1, class T2, class T3> +inline +sc_concref_r<sc_concref_r<T1,T2>,sc_subref_r<T3> > +operator , ( sc_concref<T1,T2> a, sc_subref_r<T3> b ) +{ + return sc_concref_r<sc_concref_r<T1,T2>,sc_subref_r<T3> >( + *a.clone(), *b.clone(), 3 ); +} + +template <class T1, class T2, class T3, class T4> +inline +sc_concref_r<sc_concref_r<T1,T2>,sc_concref_r<T3,T4> > +operator , ( sc_concref_r<T1,T2> a, sc_concref<T3,T4> b ) +{ + return sc_concref_r<sc_concref_r<T1,T2>,sc_concref_r<T3,T4> >( + *a.clone(), *b.clone(), 3 ); +} + +template <class T1, class T2, class T3, class T4> +inline +sc_concref_r<sc_concref_r<T1,T2>,sc_concref_r<T3,T4> > +operator , ( sc_concref<T1,T2> a, sc_concref_r<T3,T4> b ) +{ + return sc_concref_r<sc_concref_r<T1,T2>,sc_concref_r<T3,T4> >( + *a.clone(), *b.clone(), 3 ); +} + +template <class T1, class T2, class T3> +inline +sc_concref_r<sc_concref_r<T1,T2>,T3> +operator , ( sc_concref<T1,T2> a, const sc_proxy<T3>& b ) +{ + return sc_concref_r<sc_concref_r<T1,T2>,T3>( + *a.clone(), b.back_cast(), 1 ); +} + +template <class T1, class T2, class T3> +inline +sc_concref_r<sc_concref_r<T1,T2>,T3> +operator , ( sc_concref_r<T1,T2> a, sc_proxy<T3>& b ) +{ + return sc_concref_r<sc_concref_r<T1,T2>,T3>( + *a.clone(), b.back_cast(), 1 ); +} + + +template <class T1, class T2, class T3> +inline +sc_concref_r<sc_concref_r<T1,T2>,sc_bitref_r<T3> > +concat( sc_concref_r<T1,T2> a, sc_bitref<T3> b ) +{ + return sc_concref_r<sc_concref_r<T1,T2>,sc_bitref_r<T3> >( + *a.clone(), *b.clone(), 3 ); +} + +template <class T1, class T2, class T3> +inline +sc_concref_r<sc_concref_r<T1,T2>,sc_bitref_r<T3> > +concat( sc_concref<T1,T2> a, sc_bitref_r<T3> b ) +{ + return sc_concref_r<sc_concref_r<T1,T2>,sc_bitref_r<T3> >( + *a.clone(), *b.clone(), 3 ); +} + +template <class T1, class T2, class T3> +inline +sc_concref_r<sc_concref_r<T1,T2>,sc_subref_r<T3> > +concat( sc_concref_r<T1,T2> a, sc_subref<T3> b ) +{ + return sc_concref_r<sc_concref_r<T1,T2>,sc_subref_r<T3> >( + *a.clone(), *b.clone(), 3 ); +} + +template <class T1, class T2, class T3> +inline +sc_concref_r<sc_concref_r<T1,T2>,sc_subref_r<T3> > +concat( sc_concref<T1,T2> a, sc_subref_r<T3> b ) +{ + return sc_concref_r<sc_concref_r<T1,T2>,sc_subref_r<T3> >( + *a.clone(), *b.clone(), 3 ); +} + +template <class T1, class T2, class T3, class T4> +inline +sc_concref_r<sc_concref_r<T1,T2>,sc_concref_r<T3,T4> > +concat( sc_concref_r<T1,T2> a, sc_concref<T3,T4> b ) +{ + return sc_concref_r<sc_concref_r<T1,T2>,sc_concref_r<T3,T4> >( + *a.clone(), *b.clone(), 3 ); +} + +template <class T1, class T2, class T3, class T4> +inline +sc_concref_r<sc_concref_r<T1,T2>,sc_concref_r<T3,T4> > +concat( sc_concref<T1,T2> a, sc_concref_r<T3,T4> b ) +{ + return sc_concref_r<sc_concref_r<T1,T2>,sc_concref_r<T3,T4> >( + *a.clone(), *b.clone(), 3 ); +} + +template <class T1, class T2, class T3> +inline +sc_concref_r<sc_concref_r<T1,T2>,T3> +concat( sc_concref<T1,T2> a, const sc_proxy<T3>& b ) +{ + return sc_concref_r<sc_concref_r<T1,T2>,T3>( + *a.clone(), b.back_cast(), 1 ); +} + +template <class T1, class T2, class T3> +inline +sc_concref_r<sc_concref_r<T1,T2>,T3> +concat( sc_concref_r<T1,T2> a, sc_proxy<T3>& b ) +{ + return sc_concref_r<sc_concref_r<T1,T2>,T3>( + *a.clone(), b.back_cast(), 1 ); +} + +#endif + + +// ---------------------------------------------------------------------------- +// CLASS TEMPLATE : sc_concref<X,Y> +// +// Proxy class for sc_proxy concatenation (r-value and l-value). +// ---------------------------------------------------------------------------- + +// other methods + +template <class T1, class T2> +inline +void +sc_concref<T1,T2>::scan( ::std::istream& is ) +{ + std::string s; + is >> s; + *this = s.c_str(); +} + + +// l-value concatenation operators and functions + +template <class T1, class T2, class T3> +inline +sc_concref<sc_concref<T1,T2>,sc_bitref<T3> > +operator , ( sc_concref<T1,T2> a, sc_bitref<T3> b ) +{ + return sc_concref<sc_concref<T1,T2>,sc_bitref<T3> >( + *a.clone(), *b.clone(), 3 ); +} + +template <class T1, class T2, class T3> +inline +sc_concref<sc_concref<T1,T2>,sc_subref<T3> > +operator , ( sc_concref<T1,T2> a, sc_subref<T3> b ) +{ + return sc_concref<sc_concref<T1,T2>,sc_subref<T3> >( + *a.clone(), *b.clone(), 3 ); +} + +template <class T1, class T2, class T3, class T4> +inline +sc_concref<sc_concref<T1,T2>,sc_concref<T3,T4> > +operator , ( sc_concref<T1,T2> a, sc_concref<T3,T4> b ) +{ + return sc_concref<sc_concref<T1,T2>,sc_concref<T3,T4> >( + *a.clone(), *b.clone(), 3 ); +} + +template <class T1, class T2, class T3> +inline +sc_concref<sc_concref<T1,T2>,T3> +operator , ( sc_concref<T1,T2> a, sc_proxy<T3>& b ) +{ + return sc_concref<sc_concref<T1,T2>,T3>( + *a.clone(), b.back_cast(), 1 ); +} + + +template <class T1, class T2, class T3> +inline +sc_concref<sc_concref<T1,T2>,sc_bitref<T3> > +concat( sc_concref<T1,T2> a, sc_bitref<T3> b ) +{ + return sc_concref<sc_concref<T1,T2>,sc_bitref<T3> >( + *a.clone(), *b.clone(), 3 ); +} + +template <class T1, class T2, class T3> +inline +sc_concref<sc_concref<T1,T2>,sc_subref<T3> > +concat( sc_concref<T1,T2> a, sc_subref<T3> b ) +{ + return sc_concref<sc_concref<T1,T2>,sc_subref<T3> >( + *a.clone(), *b.clone(), 3 ); +} + +template <class T1, class T2, class T3, class T4> +inline +sc_concref<sc_concref<T1,T2>,sc_concref<T3,T4> > +concat( sc_concref<T1,T2> a, sc_concref<T3,T4> b ) +{ + return sc_concref<sc_concref<T1,T2>,sc_concref<T3,T4> >( + *a.clone(), *b.clone(), 3 ); +} + +template <class T1, class T2, class T3> +inline +sc_concref<sc_concref<T1,T2>,T3> +concat( sc_concref<T1,T2> a, sc_proxy<T3>& b ) +{ + return sc_concref<sc_concref<T1,T2>,T3>( + *a.clone(), b.back_cast(), 1 ); +} + + +template <class X, class Y> +inline +::std::istream& +operator >> ( ::std::istream& is, sc_concref<X,Y> a ) +{ + a.scan( is ); + return is; +} + + +// ---------------------------------------------------------------------------- +// CLASS TEMPLATE : sc_proxy<T> +// +// Base class template for bit/logic vector classes. +// (Barton/Nackmann implementation) +// ---------------------------------------------------------------------------- + +// r-value concatenation operators and functions + +template <class T1, class T2> +inline +sc_concref_r<T1,sc_bitref_r<T2> > +operator , ( const sc_proxy<T1>& a, sc_bitref_r<T2> b ) +{ + return sc_concref_r<T1,sc_bitref_r<T2> >( + a.back_cast(), *b.clone(), 2 ); +} + +template <class T1, class T2> +inline +sc_concref_r<T1,sc_subref_r<T2> > +operator , ( const sc_proxy<T1>& a, sc_subref_r<T2> b ) +{ + return sc_concref_r<T1,sc_subref_r<T2> >( + a.back_cast(), *b.clone(), 2 ); +} + +template <class T1, class T2, class T3> +inline +sc_concref_r<T1,sc_concref_r<T2,T3> > +operator , ( const sc_proxy<T1>& a, sc_concref_r<T2,T3> b ) +{ + return sc_concref_r<T1,sc_concref_r<T2,T3> >( + a.back_cast(), *b.clone(), 2 ); +} + +template <class T1, class T2> +inline +sc_concref_r<T1,T2> +operator , ( const sc_proxy<T1>& a, const sc_proxy<T2>& b ) +{ + return sc_concref_r<T1,T2>( + a.back_cast(), b.back_cast() ); +} + + +template <class T1, class T2> +inline +sc_concref_r<T1,sc_bitref_r<T2> > +concat( const sc_proxy<T1>& a, sc_bitref_r<T2> b ) +{ + return sc_concref_r<T1,sc_bitref_r<T2> >( + a.back_cast(), *b.clone(), 2 ); +} + +template <class T1, class T2> +inline +sc_concref_r<T1,sc_subref_r<T2> > +concat( const sc_proxy<T1>& a, sc_subref_r<T2> b ) +{ + return sc_concref_r<T1,sc_subref_r<T2> >( + a.back_cast(), *b.clone(), 2 ); +} + +template <class T1, class T2, class T3> +inline +sc_concref_r<T1,sc_concref_r<T2,T3> > +concat( const sc_proxy<T1>& a, sc_concref_r<T2,T3> b ) +{ + return sc_concref_r<T1,sc_concref_r<T2,T3> >( + a.back_cast(), *b.clone(), 2 ); +} + +template <class T1, class T2> +inline +sc_concref_r<T1,T2> +concat( const sc_proxy<T1>& a, const sc_proxy<T2>& b ) +{ + return sc_concref_r<T1,T2>( + a.back_cast(), b.back_cast() ); +} + + +#ifdef SC_DT_MIXED_COMMA_OPERATORS + +template <class T1, class T2> +inline +sc_concref_r<T1,sc_bitref_r<T2> > +operator , ( const sc_proxy<T1>& a, sc_bitref<T2> b ) +{ + return sc_concref_r<T1,sc_bitref_r<T2> >( + a.back_cast(), *b.clone(), 2 ); +} + +template <class T1, class T2> +inline +sc_concref_r<T1,sc_bitref_r<T2> > +operator , ( sc_proxy<T1>& a, sc_bitref_r<T2> b ) +{ + return sc_concref_r<T1,sc_bitref_r<T2> >( + a.back_cast(), *b.clone(), 2 ); +} + +template <class T1, class T2> +inline +sc_concref_r<T1,sc_subref_r<T2> > +operator , ( const sc_proxy<T1>& a, sc_subref<T2> b ) +{ + return sc_concref_r<T1,sc_subref_r<T2> >( + a.back_cast(), *b.clone(), 2 ); +} + +template <class T1, class T2> +inline +sc_concref_r<T1,sc_subref_r<T2> > +operator , ( sc_proxy<T1>& a, sc_subref_r<T2> b ) +{ + return sc_concref_r<T1,sc_subref_r<T2> >( + a.back_cast(), *b.clone(), 2 ); +} + +template <class T1, class T2, class T3> +inline +sc_concref_r<T1,sc_concref_r<T2,T3> > +operator , ( const sc_proxy<T1>& a, sc_concref<T2,T3> b ) +{ + return sc_concref_r<T1,sc_concref_r<T2,T3> >( + a.back_cast(), *b.clone(), 2 ); +} + +template <class T1, class T2, class T3> +inline +sc_concref_r<T1,sc_concref_r<T2,T3> > +operator , ( sc_proxy<T1>& a, sc_concref_r<T2,T3> b ) +{ + return sc_concref_r<T1,sc_concref_r<T2,T3> >( + a.back_cast(), *b.clone(), 2 ); +} + +template <class T1, class T2> +inline +sc_concref_r<T1,T2> +operator , ( const sc_proxy<T1>& a, sc_proxy<T2>& b ) +{ + return sc_concref_r<T1,T2>( + a.back_cast(), b.back_cast() ); +} + +template <class T1, class T2> +inline +sc_concref_r<T1,T2> +operator , ( sc_proxy<T1>& a, const sc_proxy<T2>& b ) +{ + return sc_concref_r<T1,T2>( + a.back_cast(), b.back_cast() ); +} + + +template <class T1, class T2> +inline +sc_concref_r<T1,sc_bitref_r<T2> > +concat( const sc_proxy<T1>& a, sc_bitref<T2> b ) +{ + return sc_concref_r<T1,sc_bitref_r<T2> >( + a.back_cast(), *b.clone(), 2 ); +} + +template <class T1, class T2> +inline +sc_concref_r<T1,sc_bitref_r<T2> > +concat( sc_proxy<T1>& a, sc_bitref_r<T2> b ) +{ + return sc_concref_r<T1,sc_bitref_r<T2> >( + a.back_cast(), *b.clone(), 2 ); +} + +template <class T1, class T2> +inline +sc_concref_r<T1,sc_subref_r<T2> > +concat( const sc_proxy<T1>& a, sc_subref<T2> b ) +{ + return sc_concref_r<T1,sc_subref_r<T2> >( + a.back_cast(), *b.clone(), 2 ); +} + +template <class T1, class T2> +inline +sc_concref_r<T1,sc_subref_r<T2> > +concat( sc_proxy<T1>& a, sc_subref_r<T2> b ) +{ + return sc_concref_r<T1,sc_subref_r<T2> >( + a.back_cast(), *b.clone(), 2 ); +} + +template <class T1, class T2, class T3> +inline +sc_concref_r<T1,sc_concref_r<T2,T3> > +concat( const sc_proxy<T1>& a, sc_concref<T2,T3> b ) +{ + return sc_concref_r<T1,sc_concref_r<T2,T3> >( + a.back_cast(), *b.clone(), 2 ); +} + +template <class T1, class T2, class T3> +inline +sc_concref_r<T1,sc_concref_r<T2,T3> > +concat( sc_proxy<T1>& a, sc_concref_r<T2,T3> b ) +{ + return sc_concref_r<T1,sc_concref_r<T2,T3> >( + a.back_cast(), *b.clone(), 2 ); +} + +template <class T1, class T2> +inline +sc_concref_r<T1,T2> +concat( const sc_proxy<T1>& a, sc_proxy<T2>& b ) +{ + return sc_concref_r<T1,T2>( + a.back_cast(), b.back_cast() ); +} + +template <class T1, class T2> +inline +sc_concref_r<T1,T2> +concat( sc_proxy<T1>& a, const sc_proxy<T2>& b ) +{ + return sc_concref_r<T1,T2>( + a.back_cast(), b.back_cast() ); +} + +#endif + + +// l-value concatenation operators and functions + +template <class T1, class T2> +inline +sc_concref<T1,sc_bitref<T2> > +operator , ( sc_proxy<T1>& a, sc_bitref<T2> b ) +{ + return sc_concref<T1,sc_bitref<T2> >( + a.back_cast(), *b.clone(), 2 ); +} + +template <class T1, class T2> +inline +sc_concref<T1,sc_subref<T2> > +operator , ( sc_proxy<T1>& a, sc_subref<T2> b ) +{ + return sc_concref<T1,sc_subref<T2> >( + a.back_cast(), *b.clone(), 2 ); +} + +template <class T1, class T2, class T3> +inline +sc_concref<T1,sc_concref<T2,T3> > +operator , ( sc_proxy<T1>& a, sc_concref<T2,T3> b ) +{ + return sc_concref<T1,sc_concref<T2,T3> >( + a.back_cast(), *b.clone(), 2 ); +} + +template <class T1, class T2> +inline +sc_concref<T1,T2> +operator , ( sc_proxy<T1>& a, sc_proxy<T2>& b ) +{ + return sc_concref<T1,T2>( + a.back_cast(), b.back_cast() ); +} + + +template <class T1, class T2> +inline +sc_concref<T1,sc_bitref<T2> > +concat( sc_proxy<T1>& a, sc_bitref<T2> b ) +{ + return sc_concref<T1,sc_bitref<T2> >( + a.back_cast(), *b.clone(), 2 ); +} + +template <class T1, class T2> +inline +sc_concref<T1,sc_subref<T2> > +concat( sc_proxy<T1>& a, sc_subref<T2> b ) +{ + return sc_concref<T1,sc_subref<T2> >( + a.back_cast(), *b.clone(), 2 ); +} + +template <class T1, class T2, class T3> +inline +sc_concref<T1,sc_concref<T2,T3> > +concat( sc_proxy<T1>& a, sc_concref<T2,T3> b ) +{ + return sc_concref<T1,sc_concref<T2,T3> >( + a.back_cast(), *b.clone(), 2 ); +} + +template <class T1, class T2> +inline +sc_concref<T1,T2> +concat( sc_proxy<T1>& a, sc_proxy<T2>& b ) +{ + return sc_concref<T1,T2>( + a.back_cast(), b.back_cast() ); +} + +} // namespace sc_dt + +// $Log: sc_bit_proxies.h,v $ +// Revision 1.10 2011/09/05 21:19:53 acg +// Philipp A. Hartmann: added parentheses to expressions to eliminate +// compiler warnings. +// +// Revision 1.9 2011/09/01 15:03:42 acg +// Philipp A. Hartmann: add parentheses to eliminate compiler warnings. +// +// Revision 1.8 2011/08/29 18:04:32 acg +// Philipp A. Hartmann: miscellaneous clean ups. +// +// Revision 1.7 2011/08/24 22:05:40 acg +// Torsten Maehne: initialization changes to remove warnings. +// +// Revision 1.6 2010/02/22 14:25:43 acg +// Andy Goodrich: removed 'mutable' directive from references, since it +// is not a legal C++ construct. +// +// Revision 1.5 2009/02/28 00:26:14 acg +// Andy Goodrich: bug fixes. +// +// Revision 1.4 2007/03/14 17:48:37 acg +// Andy Goodrich: fixed bug. +// +// Revision 1.3 2007/01/18 19:29:18 acg +// Andy Goodrich: fixed bug in concatenations of bit selects on sc_lv and +// sc_bv types. The offending code was in sc_bitref<X>::set_word and +// sc_bitref<X>::get_word. These methods were not writing the bit they +// represented, but rather writing an entire word whose index was the +// index of the bit they represented. This not only did not write the +// correct bit, but clobbered a word that might not even be in the +// variable the reference was for. +// +// Revision 1.2 2007/01/17 22:45:08 acg +// Andy Goodrich: fixed sc_bitref<X>::set_bit(). +// +// Revision 1.1.1.1 2006/12/15 20:31:36 acg +// SystemC 2.2 +// +// Revision 1.3 2006/01/13 18:53:53 acg +// Andy Goodrich: added $Log command so that CVS comments are reproduced in +// the source. +// + + +#endif diff --git a/ext/systemc/src/sysc/datatypes/bit/sc_bv.h b/ext/systemc/src/sysc/datatypes/bit/sc_bv.h new file mode 100644 index 000000000..de4221c7f --- /dev/null +++ b/ext/systemc/src/sysc/datatypes/bit/sc_bv.h @@ -0,0 +1,201 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_bv.h -- Arbitrary size bit vector class. + + Original Author: Gene Bushuyev, Synopsys, Inc. + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + +// $Log: sc_bv.h,v $ +// Revision 1.1.1.1 2006/12/15 20:20:04 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:53:53 acg +// Andy Goodrich: added $Log command so that CVS comments are reproduced in +// the source. +// + +#ifndef SC_BV_H +#define SC_BV_H + + +#include "sysc/datatypes/bit/sc_bv_base.h" + + +namespace sc_dt +{ + +// classes defined in this module +template <int W> class sc_bv; + + +// ---------------------------------------------------------------------------- +// CLASS TEMPLATE : sc_bv<W> +// +// Arbitrary size bit vector class. +// ---------------------------------------------------------------------------- + +template <int W> +class sc_bv + : public sc_bv_base +{ +public: + + // constructors + + sc_bv() + :sc_bv_base( W ) + {} + + explicit sc_bv( bool init_value ) + : sc_bv_base( init_value, W ) + {} + + explicit sc_bv( char init_value ) + : sc_bv_base( (init_value != '0'), W ) + {} + + sc_bv( const char* a ) + : sc_bv_base( W ) + { sc_bv_base::operator = ( a ); } + + sc_bv( const bool* a ) + : sc_bv_base( W ) + { sc_bv_base::operator = ( a ); } + + sc_bv( const sc_logic* a ) + : sc_bv_base( W ) + { sc_bv_base::operator = ( a ); } + + sc_bv( const sc_unsigned& a ) + : sc_bv_base( W ) + { sc_bv_base::operator = ( a ); } + + sc_bv( const sc_signed& a ) + : sc_bv_base( W ) + { sc_bv_base::operator = ( a ); } + + sc_bv( const sc_uint_base& a ) + : sc_bv_base( W ) + { sc_bv_base::operator = ( a ); } + + sc_bv( const sc_int_base& a ) + : sc_bv_base( W ) + { sc_bv_base::operator = ( a ); } + + sc_bv( unsigned long a ) + : sc_bv_base( W ) + { sc_bv_base::operator = ( a ); } + + sc_bv( long a ) + : sc_bv_base( W ) + { sc_bv_base::operator = ( a ); } + + sc_bv( unsigned int a ) + : sc_bv_base( W ) + { sc_bv_base::operator = ( a ); } + + sc_bv( int a ) + : sc_bv_base( W ) + { sc_bv_base::operator = ( a ); } + + sc_bv( uint64 a ) + : sc_bv_base( W ) + { sc_bv_base::operator = ( a ); } + + sc_bv( int64 a ) + : sc_bv_base( W ) + { sc_bv_base::operator = ( a ); } + + template <class X> + sc_bv( const sc_proxy<X>& a ) + : sc_bv_base( W ) + { sc_bv_base::operator = ( a ); } + + sc_bv( const sc_bv<W>& a ) + : sc_bv_base( a ) + {} + + + // assignment operators + + template <class X> + sc_bv<W>& operator = ( const sc_proxy<X>& a ) + { sc_bv_base::operator = ( a ); return *this; } + + sc_bv<W>& operator = ( const sc_bv<W>& a ) + { sc_bv_base::operator = ( a ); return *this; } + + sc_bv<W>& operator = ( const char* a ) + { sc_bv_base::operator = ( a ); return *this; } + + sc_bv<W>& operator = ( const bool* a ) + { sc_bv_base::operator = ( a ); return *this; } + + sc_bv<W>& operator = ( const sc_logic* a ) + { sc_bv_base::operator = ( a ); return *this; } + + sc_bv<W>& operator = ( const sc_unsigned& a ) + { sc_bv_base::operator = ( a ); return *this; } + + sc_bv<W>& operator = ( const sc_signed& a ) + { sc_bv_base::operator = ( a ); return *this; } + + sc_bv<W>& operator = ( const sc_uint_base& a ) + { sc_bv_base::operator = ( a ); return *this; } + + sc_bv<W>& operator = ( const sc_int_base& a ) + { sc_bv_base::operator = ( a ); return *this; } + + sc_bv<W>& operator = ( unsigned long a ) + { sc_bv_base::operator = ( a ); return *this; } + + sc_bv<W>& operator = ( long a ) + { sc_bv_base::operator = ( a ); return *this; } + + sc_bv<W>& operator = ( unsigned int a ) + { sc_bv_base::operator = ( a ); return *this; } + + sc_bv<W>& operator = ( int a ) + { sc_bv_base::operator = ( a ); return *this; } + + sc_bv<W>& operator = ( uint64 a ) + { sc_bv_base::operator = ( a ); return *this; } + + sc_bv<W>& operator = ( int64 a ) + { sc_bv_base::operator = ( a ); return *this; } +}; + +} // namespace sc_dt + + +#endif diff --git a/ext/systemc/src/sysc/datatypes/bit/sc_bv_base.cpp b/ext/systemc/src/sysc/datatypes/bit/sc_bv_base.cpp new file mode 100644 index 000000000..b6ffaa32b --- /dev/null +++ b/ext/systemc/src/sysc/datatypes/bit/sc_bv_base.cpp @@ -0,0 +1,388 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_bv_base.cpp -- Arbitrary size bit vector class. + + Original Author: Gene Bushuyev, Synopsys, Inc. + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + + +// $Log: sc_bv_base.cpp,v $ +// Revision 1.2 2011/08/24 22:05:40 acg +// Torsten Maehne: initialization changes to remove warnings. +// +// Revision 1.1.1.1 2006/12/15 20:20:04 acg +// SystemC 2.3 +// +// Revision 1.4 2006/04/11 23:12:26 acg +// Andy Goodrich: Fixed bug in parsing of extended string constants like +// 0bus1110011. +// +// Revision 1.3 2006/01/13 18:53:53 acg +// Andy Goodrich: added $Log command so that CVS comments are reproduced in +// the source. +// + +#include <string.h> + +#include "sysc/datatypes/bit/sc_bit_ids.h" +#include "sysc/datatypes/bit/sc_bv_base.h" +#include "sysc/datatypes/fx/sc_fix.h" +#include "sysc/datatypes/fx/sc_ufix.h" + + +namespace sc_dt +{ + +// ---------------------------------------------------------------------------- +// CLASS : sc_bv_base +// +// Arbitrary size bit vector base class. +// ---------------------------------------------------------------------------- + +void +sc_bv_base::init( int length_, bool init_value ) +{ + // check the length + if( length_ <= 0 ) { + SC_REPORT_ERROR( sc_core::SC_ID_ZERO_LENGTH_, 0 ); + } + // allocate memory for the data and control words + m_len = length_; + m_size = (m_len - 1) / SC_DIGIT_SIZE + 1; + m_data = new sc_digit[m_size]; + // initialize the bits to 'init_value' + sc_digit dw = init_value ? ~SC_DIGIT_ZERO : SC_DIGIT_ZERO; + int sz = m_size; + for( int i = 0; i < sz; ++ i ) { + m_data[i] = dw; + } + clean_tail(); +} + + +void +sc_bv_base::assign_from_string( const std::string& s ) +{ + // s must have been converted to bin + int len = m_len; + int s_len = s.length() - 1; + int min_len = sc_min( len, s_len ); + int i = 0; + for( ; i < min_len; ++ i ) { + char c = s[s_len - i - 1]; + if( c != '0' && c != '1' ) { + SC_REPORT_ERROR( sc_core::SC_ID_CANNOT_CONVERT_, + "string can contain only '0' and '1' characters" ); + } + set_bit( i, sc_logic_value_t( c - '0' ) ); + } + // if formatted, fill the rest with sign(s), otherwise fill with zeros + sc_logic_value_t fill = (s[s_len] == 'F' ? sc_logic_value_t( s[0] - '0' ) + : sc_logic_value_t( 0 )); + for( ; i < len; ++ i ) { + set_bit( i, fill ); + } +} + + +// constructors + +sc_bv_base::sc_bv_base( const char* a ) + : m_len( 0 ), m_size( 0 ), m_data( 0 ) +{ + std::string s = convert_to_bin( a ); + init( s.length() - 1 ); + assign_from_string( s ); +} + +sc_bv_base::sc_bv_base( const char* a, int length_ ) + : m_len( 0 ), m_size( 0 ), m_data( 0 ) +{ + init( length_ ); + assign_from_string( convert_to_bin( a ) ); +} + +sc_bv_base::sc_bv_base( const sc_bv_base& a ) + : sc_proxy<sc_bv_base>(), + m_len( a.m_len ), + m_size( a.m_size ), + m_data( new sc_digit[m_size] ) +{ + // copy the bits + int sz = m_size; + for( int i = 0; i < sz; ++ i ) { + m_data[i] = a.m_data[i]; + } +} + + +// assignment operators + +sc_bv_base& +sc_bv_base::operator = ( const char* a ) +{ + assign_from_string( convert_to_bin( a ) ); + return *this; +} + + +#if 0 + +// bitwise complement + +sc_bv_base& +sc_bv_base::b_not() +{ + int sz = m_size; + for( int i = 0; i < sz; ++ i ) { + m_data[i] = ~m_data[i]; + } + clean_tail(); + return *this; +} + + +// bitwise left shift + +sc_bv_base& +sc_bv_base::operator <<= ( int n ) +{ + if( n < 0 ) { + char msg[BUFSIZ]; + std::sprintf( msg, + "left shift operation is only allowed with positive " + "shift values, shift value = %d", n ); + SC_REPORT_ERROR( sc_core::SC_ID_OUT_OF_BOUNDS_, msg ); + } + int sz = m_size; + if( n >= m_len ) { + for( int i = 0; i < sz; ++ i ) { + m_data[i] = SC_DIGIT_ZERO; + } + // clean_tail(); + return *this; + } + int wn = n / SC_DIGIT_SIZE; + int bn = n % SC_DIGIT_SIZE; + if( wn != 0 ) { + // shift words + int i = sz - 1; + for( ; i >= wn; -- i ) { + m_data[i] = m_data[i - wn]; + } + for( ; i >= 0; -- i ) { + m_data[i] = SC_DIGIT_ZERO; + } + } + if( bn != 0 ) { + // shift bits + for( int i = sz - 1; i >= 1; -- i ) { + m_data[i] <<= bn; + m_data[i] |= m_data[i - 1] >> (SC_DIGIT_SIZE - bn); + } + m_data[0] <<= bn; + } + clean_tail(); + return *this; +} + + +// bitwise right shift + +sc_bv_base& +sc_bv_base::operator >>= ( int n ) +{ + if( n < 0 ) { + char msg[BUFSIZ]; + std::sprintf( msg, + "right shift operation is only allowed with positive " + "shift values, shift value = %d", n ); + SC_REPORT_ERROR( sc_core::SC_ID_OUT_OF_BOUNDS_, msg ); + } + int sz = m_size; + if( n >= m_len ) { + for( int i = 0; i < sz; ++ i ) { + m_data[i] = SC_DIGIT_ZERO; + } + // clean_tail(); + return *this; + } + int wn = n / SC_DIGIT_SIZE; + int bn = n % SC_DIGIT_SIZE; + if( wn != 0 ) { + // shift words + int i = 0; + for( ; i < (sz - wn); ++ i ) { + m_data[i] = m_data[i + wn]; + } + for( ; i < sz; ++ i ) { + m_data[i] = SC_DIGIT_ZERO; + } + } + if( bn != 0 ) { + // shift bits + for( int i = 0; i < (sz - 1); ++ i ) { + m_data[i] >>= bn; + m_data[i] |= m_data[i + 1] << (SC_DIGIT_SIZE - bn); + } + m_data[sz - 1] >>= bn; + } + clean_tail(); + return *this; +} + + +// bitwise left rotate + +sc_bv_base& +sc_bv_base::lrotate( int n ) +{ + if( n < 0 ) { + char msg[BUFSIZ]; + std::sprintf( msg, + "left rotate operation is only allowed with positive " + "rotate values, rotate value = %d", n ); + SC_REPORT_ERROR( sc_core::SC_ID_OUT_OF_BOUNDS_, msg ); + } + int len = m_len; + n %= len; + *this = (*this << n) | (*this >> (len - n)); + return *this; +} + + +// bitwise right rotate + +sc_bv_base& +sc_bv_base::rrotate( int n ) +{ + if( n < 0 ) { + char msg[BUFSIZ]; + std::sprintf( msg, + "right rotate operation is only allowed with positive " + "rotate values, rotate value = %d", n ); + SC_REPORT_ERROR( sc_core::SC_ID_OUT_OF_BOUNDS_, msg ); + } + int len = m_len; + n %= len; + *this = (*this >> n) | (*this << (len - n)); + return *this; +} + +#endif + + +// ---------------------------------------------------------------------------- + +// convert formatted string to binary string + +const std::string +convert_to_bin( const char* s ) +{ + // Beware: logic character strings cannot start with '0x' or '0X', + // because this is seen as a hexadecimal encoding prefix! + + if( s == 0 ) { + SC_REPORT_ERROR(sc_core::SC_ID_CANNOT_CONVERT_, + "character string is zero" ); + } + if( *s == 0 ) { + SC_REPORT_ERROR(sc_core::SC_ID_CANNOT_CONVERT_, + "character string is empty"); + } + + int n = strlen( s ); + int i = 0; + if( s[0] == '-' || s[0] == '+' ) { + ++ i; + } + if( n > (i + 2) && s[i] == '0' ) + { + if (s[i+1] == 'b' || s[i+1] == 'B' ) + { + if ( s[i+2] == '0' || s[i+2] == '1' ) + { + std::string str( &s[2] ); + str += "F"; + return str; + } + } + if ( s[i+1] == 'b' || s[i+1] == 'B' || + s[i+1] == 'c' || s[i+1] == 'C' || + s[i+1] == 'd' || s[i+1] == 'D' || + s[i+1] == 'o' || s[i+1] == 'O' || + s[i+1] == 'x' || s[i+1] == 'X') + { + try { + // worst case length = n * 4 + sc_fix a( s, n * 4, n * 4, SC_TRN, SC_WRAP, 0, SC_ON ); + std::string str = a.to_bin(); + str += "F"; // mark the string as formatted + // get rid of prefix (0b) and redundant leading bits + const char* p = str.c_str() + 2; + while( p[1] && p[0] == p[1] ) { + ++ p; + } + return std::string( p ); + } catch( sc_core::sc_report ) { + char msg[BUFSIZ]; + std::sprintf( msg, "character string '%s' is not valid", s ); + SC_REPORT_ERROR( sc_core::SC_ID_CANNOT_CONVERT_, msg ); + // never reached + return std::string(); + } + } + + } + + // bin by default + + std::string str( s ); + str += "U"; // mark the string as unformatted + return str; +} + +// convert binary string to formatted string + +const std::string +convert_to_fmt( const std::string& s, sc_numrep numrep, bool w_prefix ) +{ + int n = s.length(); + std::string str("0bus"); + // str += "0bus"; + str += s; + sc_ufix a( str.c_str(), n, n, SC_TRN, SC_WRAP, 0, SC_ON ); + return a.to_string( numrep, w_prefix ); +} + +} // namespace sc_dt diff --git a/ext/systemc/src/sysc/datatypes/bit/sc_bv_base.h b/ext/systemc/src/sysc/datatypes/bit/sc_bv_base.h new file mode 100644 index 000000000..279001da5 --- /dev/null +++ b/ext/systemc/src/sysc/datatypes/bit/sc_bv_base.h @@ -0,0 +1,339 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_bv_base.h -- Arbitrary size bit vector class. + + Original Author: Gene Bushuyev, Synopsys, Inc. + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + +// $Log: sc_bv_base.h,v $ +// Revision 1.3 2011/08/26 22:32:00 acg +// Torsten Maehne: added parentheses to make opearator ordering more obvious. +// +// Revision 1.2 2011/08/15 16:43:24 acg +// Torsten Maehne: changes to remove unused argument warnings. +// +// Revision 1.1.1.1 2006/12/15 20:20:04 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:53:53 acg +// Andy Goodrich: added $Log command so that CVS comments are reproduced in +// the source. +// + +#ifndef SC_BV_BASE_H +#define SC_BV_BASE_H + + +#include "sysc/datatypes/bit/sc_bit_ids.h" +#include "sysc/datatypes/bit/sc_bit_proxies.h" +#include "sysc/datatypes/bit/sc_proxy.h" +#include "sysc/datatypes/int/sc_length_param.h" + + +namespace sc_dt +{ + +// classes defined in this module +class sc_bv_base; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_bv_base +// +// Arbitrary size bit vector base class. +// ---------------------------------------------------------------------------- + +class sc_bv_base + : public sc_proxy<sc_bv_base> +{ + friend class sc_lv_base; + + + void init( int length_, bool init_value = false ); + + void assign_from_string( const std::string& ); + +public: + + // typedefs + + typedef sc_proxy<sc_bv_base> base_type; + + + // constructors + + explicit sc_bv_base( int length_ = sc_length_param().len() ) + : m_len( 0 ), m_size( 0 ), m_data( 0 ) + { init( length_ ); } + + explicit sc_bv_base( bool a, + int length_ = sc_length_param().len() ) + : m_len( 0 ), m_size( 0 ), m_data( 0 ) + { init( length_, a ); } + + sc_bv_base( const char* a ); + + sc_bv_base( const char* a, int length_ ); + + template <class X> + sc_bv_base( const sc_proxy<X>& a ) + : m_len( 0 ), m_size( 0 ), m_data( 0 ) + { init( a.back_cast().length() ); base_type::assign_( a ); } + + sc_bv_base( const sc_bv_base& a ); + +#ifdef SC_DT_DEPRECATED + + explicit sc_bv_base( const sc_unsigned& a ) + : m_len( 0 ), m_size( 0 ), m_data( 0 ) + { init( a.length() ); base_type::assign_( a ); } + + explicit sc_bv_base( const sc_signed& a ) + : m_len( 0 ), m_size( 0 ), m_data( 0 ) + { init( a.length() ); base_type::assign_( a ); } + + explicit sc_bv_base( const sc_uint_base& a) + : m_len( 0 ), m_size( 0 ), m_data( 0 ) + { init( a.length() ); base_type::assign_( a ); } + + explicit sc_bv_base( const sc_int_base& a) + : m_len( 0 ), m_size( 0 ), m_data( 0 ) + { init( a.length() ); base_type::assign_( a ); } + +#endif + + + // destructor + + virtual ~sc_bv_base() + { delete [] m_data; } + + + // assignment operators + + template <class X> + sc_bv_base& operator = ( const sc_proxy<X>& a ) + { assign_p_( *this, a ); return *this; } + + sc_bv_base& operator = ( const sc_bv_base& a ) + { assign_p_( *this, a ); return *this; } + + sc_bv_base& operator = ( const char* a ); + + sc_bv_base& operator = ( const bool* a ) + { base_type::assign_( a ); return *this; } + + sc_bv_base& operator = ( const sc_logic* a ) + { base_type::assign_( a ); return *this; } + + sc_bv_base& operator = ( const sc_unsigned& a ) + { base_type::assign_( a ); return *this; } + + sc_bv_base& operator = ( const sc_signed& a ) + { base_type::assign_( a ); return *this; } + + sc_bv_base& operator = ( const sc_uint_base& a ) + { base_type::assign_( a ); return *this; } + + sc_bv_base& operator = ( const sc_int_base& a ) + { base_type::assign_( a ); return *this; } + + sc_bv_base& operator = ( unsigned long a ) + { base_type::assign_( a ); return *this; } + + sc_bv_base& operator = ( long a ) + { base_type::assign_( a ); return *this; } + + sc_bv_base& operator = ( unsigned int a ) + { base_type::assign_( a ); return *this; } + + sc_bv_base& operator = ( int a ) + { base_type::assign_( a ); return *this; } + + sc_bv_base& operator = ( uint64 a ) + { base_type::assign_( a ); return *this; } + + sc_bv_base& operator = ( int64 a ) + { base_type::assign_( a ); return *this; } + + +#if 0 + + // bitwise complement + + sc_bv_base& b_not(); + + const sc_bv_base operator ~ () const + { sc_bv_base a( *this ); return a.b_not(); } + + + // bitwise left shift + + sc_bv_base& operator <<= ( int n ); + + const sc_bv_base operator << ( int n ) const + { sc_bv_base a( *this ); return ( a <<= n ); } + + + // bitwise right shift + + sc_bv_base& operator >>= ( int n ); + + const sc_bv_base operator >> ( int n ) const + { sc_bv_base a( *this ); return ( a >>= n ); } + + + // bitwise left rotate + + sc_bv_base& lrotate( int n ); + + + // bitwise right rotate + + sc_bv_base& rrotate( int n ); + +#endif + + + // common methods + + int length() const + { return m_len; } + + int size() const + { return m_size; } + + sc_logic_value_t get_bit( int i ) const; + void set_bit( int i, sc_logic_value_t value ); + + sc_digit get_word( int i ) const + { return m_data[i]; } + + void set_word( int i, sc_digit w ) + { m_data[i] = w; } + + sc_digit get_cword( int /*i*/ ) const + { return SC_DIGIT_ZERO; } + + void set_cword( int i, sc_digit w ); + + void clean_tail(); + + + // other methods + + bool is_01() const + { return true; } + +protected: + + int m_len; // length in bits + int m_size; // size of data array + sc_digit* m_data; // data array +}; + + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + +#if 0 + +// bitwise left rotate + +inline +const sc_bv_base +lrotate( const sc_bv_base& x, int n ) +{ + sc_bv_base a( x ); + return a.lrotate( n ); +} + + +// bitwise right rotate + +inline +const sc_bv_base +rrotate( const sc_bv_base& x, int n ) +{ + sc_bv_base a( x ); + return a.rrotate( n ); +} + +#endif + + +// common methods + +inline +sc_logic_value_t +sc_bv_base::get_bit( int i ) const +{ + int wi = i / SC_DIGIT_SIZE; + int bi = i % SC_DIGIT_SIZE; + return sc_logic_value_t( (m_data[wi] >> bi) & SC_DIGIT_ONE ); +} + +inline +void +sc_bv_base::set_bit( int i, sc_logic_value_t value ) +{ + int wi = i / SC_DIGIT_SIZE; + int bi = i % SC_DIGIT_SIZE; + sc_digit mask = SC_DIGIT_ONE << bi; + m_data[wi] |= mask; // set bit to 1 + m_data[wi] &= value << bi | ~mask; +} + + +inline +void +sc_bv_base::set_cword( int /*i*/, sc_digit w ) +{ + if( w ) { + SC_REPORT_WARNING( sc_core::SC_ID_SC_BV_CANNOT_CONTAIN_X_AND_Z_, 0 ); + } +} + + +inline +void +sc_bv_base::clean_tail() +{ + int wi = m_size - 1; + int bi = m_len % SC_DIGIT_SIZE; + if ( bi != 0 ) m_data[wi] &= ~SC_DIGIT_ZERO >> (SC_DIGIT_SIZE - bi); +} + +} // namespace sc_dt + + +#endif diff --git a/ext/systemc/src/sysc/datatypes/bit/sc_logic.cpp b/ext/systemc/src/sysc/datatypes/bit/sc_logic.cpp new file mode 100644 index 000000000..15525f5c5 --- /dev/null +++ b/ext/systemc/src/sysc/datatypes/bit/sc_logic.cpp @@ -0,0 +1,175 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_logic.cpp -- C++ implementation of logic type. Behaves + pretty much the same way as HDLs logic type. + + Original Author: Stan Y. Liao, Synopsys, Inc. + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + + +// $Log: sc_logic.cpp,v $ +// Revision 1.1.1.1 2006/12/15 20:20:04 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:53:53 acg +// Andy Goodrich: added $Log command so that CVS comments are reproduced in +// the source. +// + +#include "sysc/datatypes/bit/sc_bit_ids.h" +#include "sysc/datatypes/bit/sc_logic.h" + + +namespace sc_dt +{ + +// ---------------------------------------------------------------------------- +// CLASS : sc_logic +// +// Four-valued logic type. +// ---------------------------------------------------------------------------- + +// support methods + +void +sc_logic::invalid_value( sc_logic_value_t v ) +{ + char msg[BUFSIZ]; + std::sprintf( msg, "sc_logic( %d )", v ); + SC_REPORT_ERROR( sc_core::SC_ID_VALUE_NOT_VALID_, msg ); +} + +void +sc_logic::invalid_value( char c ) +{ + char msg[BUFSIZ]; + std::sprintf( msg, "sc_logic( '%c' )", c ); + SC_REPORT_ERROR( sc_core::SC_ID_VALUE_NOT_VALID_, msg ); +} + +void +sc_logic::invalid_value( int i ) +{ + char msg[BUFSIZ]; + std::sprintf( msg, "sc_logic( %d )", i ); + SC_REPORT_ERROR( sc_core::SC_ID_VALUE_NOT_VALID_, msg ); +} + + +void +sc_logic::invalid_01() const +{ + if( (int) m_val == Log_Z ) { + SC_REPORT_WARNING( sc_core::SC_ID_LOGIC_Z_TO_BOOL_, 0 ); + } else { + SC_REPORT_WARNING( sc_core::SC_ID_LOGIC_X_TO_BOOL_, 0 ); + } +} + + +// conversion tables + +const sc_logic_value_t sc_logic::char_to_logic[128] = +{ + Log_0, Log_1, Log_Z, Log_X, Log_X, Log_X, Log_X, Log_X, + Log_X, Log_X, Log_X, Log_X, Log_X, Log_X, Log_X, Log_X, + Log_X, Log_X, Log_X, Log_X, Log_X, Log_X, Log_X, Log_X, + Log_X, Log_X, Log_X, Log_X, Log_X, Log_X, Log_X, Log_X, + Log_X, Log_X, Log_X, Log_X, Log_X, Log_X, Log_X, Log_X, + Log_X, Log_X, Log_X, Log_X, Log_X, Log_X, Log_X, Log_X, + Log_0, Log_1, Log_X, Log_X, Log_X, Log_X, Log_X, Log_X, + Log_X, Log_X, Log_X, Log_X, Log_X, Log_X, Log_X, Log_X, + Log_X, Log_X, Log_X, Log_X, Log_X, Log_X, Log_X, Log_X, + Log_X, Log_X, Log_X, Log_X, Log_X, Log_X, Log_X, Log_X, + Log_X, Log_X, Log_X, Log_X, Log_X, Log_X, Log_X, Log_X, + Log_X, Log_X, Log_Z, Log_X, Log_X, Log_X, Log_X, Log_X, + Log_X, Log_X, Log_X, Log_X, Log_X, Log_X, Log_X, Log_X, + Log_X, Log_X, Log_X, Log_X, Log_X, Log_X, Log_X, Log_X, + Log_X, Log_X, Log_X, Log_X, Log_X, Log_X, Log_X, Log_X, + Log_X, Log_X, Log_Z, Log_X, Log_X, Log_X, Log_X, Log_X +}; + +const char sc_logic::logic_to_char[4] = { '0', '1', 'Z', 'X' }; + +const sc_logic_value_t sc_logic::and_table[4][4] = +{ + { Log_0, Log_0, Log_0, Log_0 }, + { Log_0, Log_1, Log_X, Log_X }, + { Log_0, Log_X, Log_X, Log_X }, + { Log_0, Log_X, Log_X, Log_X } +}; + +const sc_logic_value_t sc_logic::or_table[4][4] = +{ + { Log_0, Log_1, Log_X, Log_X }, + { Log_1, Log_1, Log_1, Log_1 }, + { Log_X, Log_1, Log_X, Log_X }, + { Log_X, Log_1, Log_X, Log_X } +}; + +const sc_logic_value_t sc_logic::xor_table[4][4] = +{ + { Log_0, Log_1, Log_X, Log_X }, + { Log_1, Log_0, Log_X, Log_X }, + { Log_X, Log_X, Log_X, Log_X }, + { Log_X, Log_X, Log_X, Log_X } +}; + +const sc_logic_value_t sc_logic::not_table[4] = + { Log_1, Log_0, Log_X, Log_X }; + + +// other methods + +void +sc_logic::scan( ::std::istream& is ) +{ + char c; + is >> c; + *this = c; +} + + +// #ifdef SC_DT_DEPRECATED +const sc_logic sc_logic_0( Log_0 ); +const sc_logic sc_logic_1( Log_1 ); +const sc_logic sc_logic_Z( Log_Z ); +const sc_logic sc_logic_X( Log_X ); +// #endif + +const sc_logic SC_LOGIC_0( Log_0 ); +const sc_logic SC_LOGIC_1( Log_1 ); +const sc_logic SC_LOGIC_Z( Log_Z ); +const sc_logic SC_LOGIC_X( Log_X ); + +} // namespace sc_dt diff --git a/ext/systemc/src/sysc/datatypes/bit/sc_logic.h b/ext/systemc/src/sysc/datatypes/bit/sc_logic.h new file mode 100644 index 000000000..6008e3e2e --- /dev/null +++ b/ext/systemc/src/sysc/datatypes/bit/sc_logic.h @@ -0,0 +1,384 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_logic.h -- C++ implementation of logic type. Behaves + pretty much the same way as HDLs except with 4 values. + + Original Author: Stan Y. Liao, Synopsys, Inc. + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + +// $Log: sc_logic.h,v $ +// Revision 1.3 2011/08/07 18:54:19 acg +// Philipp A. Hartmann: remove friend function declarations that implement +// code, and clean up how bit and logic operators are defined in general. +// +// Revision 1.2 2011/01/25 20:50:37 acg +// Andy Goodrich: changes for IEEE 1666 2011. +// +// Revision 1.1.1.1 2006/12/15 20:20:04 acg +// SystemC 2.3 +// +// Revision 1.5 2006/12/02 21:00:57 acg +// Andy Goodrich: fixes for concatenation support. +// +// Revision 1.4 2006/05/08 17:49:59 acg +// Andy Goodrich: Added David Long's declarations for friend operators, +// functions, and methods, to keep the Microsoft compiler happy. +// +// Revision 1.3 2006/01/13 18:53:53 acg +// Andy Goodrich: added $Log command so that CVS comments are reproduced in +// the source. +// + +#ifndef SC_LOGIC_H +#define SC_LOGIC_H + + +#include <cstdio> + +#include "sysc/utils/sc_iostream.h" +#include "sysc/kernel/sc_macros.h" +#include "sysc/utils/sc_mempool.h" +#include "sysc/datatypes/bit/sc_bit.h" + + +namespace sc_dt +{ + +// classes defined in this module +class sc_logic; + + +// ---------------------------------------------------------------------------- +// ENUM : sc_logic_value_t +// +// Enumeration of values for sc_logic. +// ---------------------------------------------------------------------------- + +enum sc_logic_value_t +{ + Log_0 = 0, + Log_1, + Log_Z, + Log_X +}; + +// ---------------------------------------------------------------------------- +// CLASS : sc_logic +// +// Four-valued logic type. +// ---------------------------------------------------------------------------- + +class sc_logic +{ +private: + + // support methods + + static void invalid_value( sc_logic_value_t ); + static void invalid_value( char ); + static void invalid_value( int ); + + static sc_logic_value_t to_value( sc_logic_value_t v ) + { + if( v < Log_0 || v > Log_X ) { + invalid_value( v ); + } + return v; + } + + static sc_logic_value_t to_value( bool b ) + { return ( b ? Log_1 : Log_0 ); } + + static sc_logic_value_t to_value( char c ) + { + sc_logic_value_t v; + unsigned int index = (int)c; + if ( index > 127 ) + { + invalid_value(c); + v = Log_X; + } + else + { + v = char_to_logic[index]; + if( v < Log_0 || v > Log_X ) { + invalid_value( c ); + } + } + return v; + } + + static sc_logic_value_t to_value( int i ) + { + if( i < 0 || i > 3 ) { + invalid_value( i ); + } + return sc_logic_value_t( i ); + } + + + void invalid_01() const; + +public: + + // conversion tables + + static const sc_logic_value_t char_to_logic[128]; + static const char logic_to_char[4]; + static const sc_logic_value_t and_table[4][4]; + static const sc_logic_value_t or_table[4][4]; + static const sc_logic_value_t xor_table[4][4]; + static const sc_logic_value_t not_table[4]; + + + // constructors + + sc_logic() + : m_val( Log_X ) + {} + + sc_logic( const sc_logic& a ) + : m_val( a.m_val ) + {} + + sc_logic( sc_logic_value_t v ) + : m_val( to_value( v ) ) + {} + + explicit sc_logic( bool a ) + : m_val( to_value( a ) ) + {} + + explicit sc_logic( char a ) + : m_val( to_value( a ) ) + {} + + explicit sc_logic( int a ) + : m_val( to_value( a ) ) + {} + + explicit sc_logic( const sc_bit& a ) + : m_val( to_value( a.to_bool() ) ) + {} + + + // destructor + + ~sc_logic() + {} + + + // (bitwise) assignment operators + +#define DEFN_ASN_OP_T(op,tp) \ + sc_logic& operator op ( tp v ) \ + { *this op sc_logic( v ); return *this; } + +#define DEFN_ASN_OP(op) \ + DEFN_ASN_OP_T(op, sc_logic_value_t) \ + DEFN_ASN_OP_T(op, bool) \ + DEFN_ASN_OP_T(op, char) \ + DEFN_ASN_OP_T(op, int ) \ + DEFN_ASN_OP_T(op, const sc_bit& ) + + sc_logic& operator = ( const sc_logic& a ) + { m_val = a.m_val; return *this; } + + sc_logic& operator &= ( const sc_logic& b ) + { m_val = and_table[m_val][b.m_val]; return *this; } + + sc_logic& operator |= ( const sc_logic& b ) + { m_val = or_table[m_val][b.m_val]; return *this; } + + sc_logic& operator ^= ( const sc_logic& b ) + { m_val = xor_table[m_val][b.m_val]; return *this; } + + DEFN_ASN_OP(=) + DEFN_ASN_OP(&=) + DEFN_ASN_OP(|=) + DEFN_ASN_OP(^=) + +#undef DEFN_ASN_OP_T +#undef DEFN_ASN_OP + + + // bitwise operators and functions + + + friend const sc_logic operator & ( const sc_logic&, const sc_logic& ); + friend const sc_logic operator | ( const sc_logic&, const sc_logic& ); + friend const sc_logic operator ^ ( const sc_logic&, const sc_logic& ); + + // relational operators + + friend bool operator == ( const sc_logic&, const sc_logic& ); + friend bool operator != ( const sc_logic&, const sc_logic& ); + + // bitwise complement + + const sc_logic operator ~ () const + { return sc_logic( not_table[m_val] ); } + + sc_logic& b_not() + { m_val = not_table[m_val]; return *this; } + + + // explicit conversions + + sc_logic_value_t value() const + { return m_val; } + + + bool is_01() const + { return ( (int) m_val == Log_0 || (int) m_val == Log_1 ); } + + bool to_bool() const + { if( ! is_01() ) { invalid_01(); } return ( (int) m_val != Log_0 ); } + + char to_char() const + { return logic_to_char[m_val]; } + + + // other methods + + void print( ::std::ostream& os = ::std::cout ) const + { os << to_char(); } + + void scan( ::std::istream& is = ::std::cin ); + + + // memory (de)allocation + + static void* operator new( std::size_t, void* p ) // placement new + { return p; } + + static void* operator new( std::size_t sz ) + { return sc_core::sc_mempool::allocate( sz ); } + + static void operator delete( void* p, std::size_t sz ) + { sc_core::sc_mempool::release( p, sz ); } + + static void* operator new [] ( std::size_t sz ) + { return sc_core::sc_mempool::allocate( sz ); } + + static void operator delete [] ( void* p, std::size_t sz ) + { sc_core::sc_mempool::release( p, sz ); } + +private: + + sc_logic_value_t m_val; + +private: + + // disabled + explicit sc_logic( const char* ); + sc_logic& operator = ( const char* ); +}; + +// ---------------------------------------------------------------------------- + +// bitwise operators + +inline const sc_logic operator & ( const sc_logic& a, const sc_logic& b ) + { return sc_logic( sc_logic::and_table[a.m_val][b.m_val] ); } + +inline const sc_logic operator | ( const sc_logic& a, const sc_logic& b ) + { return sc_logic( sc_logic::or_table[a.m_val][b.m_val] ); } + +inline const sc_logic operator ^ ( const sc_logic& a, const sc_logic& b ) + { return sc_logic( sc_logic::xor_table[a.m_val][b.m_val] ); } + +#define DEFN_BIN_OP_T(ret,op,tp) \ + inline ret operator op ( const sc_logic& a, tp b ) \ + { return ( a op sc_logic( b ) ); } \ + inline ret operator op ( tp a, const sc_logic& b ) \ + { return ( sc_logic( a ) op b ); } + +#define DEFN_BIN_OP(ret,op) \ + DEFN_BIN_OP_T(ret,op,sc_logic_value_t) \ + DEFN_BIN_OP_T(ret,op,bool) \ + DEFN_BIN_OP_T(ret,op,char) \ + DEFN_BIN_OP_T(ret,op,int) + +DEFN_BIN_OP(const sc_logic,&) +DEFN_BIN_OP(const sc_logic,|) +DEFN_BIN_OP(const sc_logic,^) + +// relational operators and functions + +inline bool operator == ( const sc_logic& a, const sc_logic& b ) + { return ( (int) a.m_val == b.m_val ); } + +inline bool operator != ( const sc_logic& a, const sc_logic& b ) + { return ( (int) a.m_val != b.m_val ); } + +DEFN_BIN_OP(bool,==) +DEFN_BIN_OP(bool,!=) + +#undef DEFN_BIN_OP_T +#undef DEFN_BIN_OP + +// ---------------------------------------------------------------------------- + +inline +::std::ostream& +operator << ( ::std::ostream& os, const sc_logic& a ) +{ + a.print( os ); + return os; +} + +inline +::std::istream& +operator >> ( ::std::istream& is, sc_logic& a ) +{ + a.scan( is ); + return is; +} + + +extern const sc_logic SC_LOGIC_0; +extern const sc_logic SC_LOGIC_1; +extern const sc_logic SC_LOGIC_Z; +extern const sc_logic SC_LOGIC_X; + +// #ifdef SC_DT_DEPRECATED +extern const sc_logic sc_logic_0; +extern const sc_logic sc_logic_1; +extern const sc_logic sc_logic_Z; +extern const sc_logic sc_logic_X; +// #endif + +} // namespace sc_dt + +#endif diff --git a/ext/systemc/src/sysc/datatypes/bit/sc_lv.h b/ext/systemc/src/sysc/datatypes/bit/sc_lv.h new file mode 100644 index 000000000..8eae23b73 --- /dev/null +++ b/ext/systemc/src/sysc/datatypes/bit/sc_lv.h @@ -0,0 +1,205 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_lv.h -- Arbitrary size logic vector class. + + Original Author: Gene Bushuyev, Synopsys, Inc. + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + +// $Log: sc_lv.h,v $ +// Revision 1.1.1.1 2006/12/15 20:20:04 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:53:53 acg +// Andy Goodrich: added $Log command so that CVS comments are reproduced in +// the source. +// + +#ifndef SC_LV_H +#define SC_LV_H + + +#include "sysc/datatypes/bit/sc_lv_base.h" + + +namespace sc_dt +{ + +// classes defined in this module +template <int W> class sc_lv; + + +// ---------------------------------------------------------------------------- +// CLASS TEMPLATE : sc_lv<W> +// +// Arbitrary size logic vector class. +// ---------------------------------------------------------------------------- + +template <int W> +class sc_lv + : public sc_lv_base +{ +public: + + // constructors + + sc_lv() + : sc_lv_base( W ) + {} + + explicit sc_lv( const sc_logic& init_value ) + : sc_lv_base( init_value, W ) + {} + + explicit sc_lv( bool init_value ) + : sc_lv_base( sc_logic( init_value ), W ) + {} + + explicit sc_lv( char init_value ) + : sc_lv_base( sc_logic( init_value ), W ) + {} + + sc_lv( const char* a ) + : sc_lv_base( W ) + { sc_lv_base::operator = ( a ); } + + sc_lv( const bool* a ) + : sc_lv_base( W ) + { sc_lv_base::operator = ( a ); } + + sc_lv( const sc_logic* a ) + : sc_lv_base( W ) + { sc_lv_base::operator = ( a ); } + + sc_lv( const sc_unsigned& a ) + : sc_lv_base( W ) + { sc_lv_base::operator = ( a ); } + + sc_lv( const sc_signed& a ) + : sc_lv_base( W ) + { sc_lv_base::operator = ( a ); } + + sc_lv( const sc_uint_base& a ) + : sc_lv_base( W ) + { sc_lv_base::operator = ( a ); } + + sc_lv( const sc_int_base& a ) + : sc_lv_base( W ) + { sc_lv_base::operator = ( a ); } + + sc_lv( unsigned long a ) + : sc_lv_base( W ) + { sc_lv_base::operator = ( a ); } + + sc_lv( long a ) + : sc_lv_base( W ) + { sc_lv_base::operator = ( a ); } + + sc_lv( unsigned int a ) + : sc_lv_base( W ) + { sc_lv_base::operator = ( a ); } + + sc_lv( int a ) + : sc_lv_base( W ) + { sc_lv_base::operator = ( a ); } + + sc_lv( uint64 a ) + : sc_lv_base( W ) + { sc_lv_base::operator = ( a ); } + + sc_lv( int64 a ) + : sc_lv_base( W ) + { sc_lv_base::operator = ( a ); } + + template <class X> + sc_lv( const sc_proxy<X>& a ) + : sc_lv_base( W ) + { sc_lv_base::operator = ( a ); } + + sc_lv( const sc_lv<W>& a ) + : sc_lv_base( a ) + {} + + + // assignment operators + + template <class X> + sc_lv<W>& operator = ( const sc_proxy<X>& a ) + { sc_lv_base::operator = ( a ); return *this; } + + sc_lv<W>& operator = ( const sc_lv<W>& a ) + { sc_lv_base::operator = ( a ); return *this; } + + sc_lv<W>& operator = ( const char* a ) + { sc_lv_base::operator = ( a ); return *this; } + + sc_lv<W>& operator = ( const bool* a ) + { sc_lv_base::operator = ( a ); return *this; } + + sc_lv<W>& operator = ( const sc_logic* a ) + { sc_lv_base::operator = ( a ); return *this; } + + sc_lv<W>& operator = ( const sc_unsigned& a ) + { sc_lv_base::operator = ( a ); return *this; } + + sc_lv<W>& operator = ( const sc_signed& a ) + { sc_lv_base::operator = ( a ); return *this; } + + sc_lv<W>& operator = ( const sc_uint_base& a ) + { sc_lv_base::operator = ( a ); return *this; } + + sc_lv<W>& operator = ( const sc_int_base& a ) + { sc_lv_base::operator = ( a ); return *this; } + + sc_lv<W>& operator = ( unsigned long a ) + { sc_lv_base::operator = ( a ); return *this; } + + sc_lv<W>& operator = ( long a ) + { sc_lv_base::operator = ( a ); return *this; } + + sc_lv<W>& operator = ( unsigned int a ) + { sc_lv_base::operator = ( a ); return *this; } + + sc_lv<W>& operator = ( int a ) + { sc_lv_base::operator = ( a ); return *this; } + + sc_lv<W>& operator = ( uint64 a ) + { sc_lv_base::operator = ( a ); return *this; } + + sc_lv<W>& operator = ( int64 a ) + { sc_lv_base::operator = ( a ); return *this; } +}; + +} // namespace sc_dt + + +#endif diff --git a/ext/systemc/src/sysc/datatypes/bit/sc_lv_base.cpp b/ext/systemc/src/sysc/datatypes/bit/sc_lv_base.cpp new file mode 100644 index 000000000..617d74d03 --- /dev/null +++ b/ext/systemc/src/sysc/datatypes/bit/sc_lv_base.cpp @@ -0,0 +1,173 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_lv_base.cpp -- Arbitrary size logic vector class. + + Original Author: Gene Bushuyev, Synopsys, Inc. + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + + +// $Log: sc_lv_base.cpp,v $ +// Revision 1.2 2011/08/24 22:05:40 acg +// Torsten Maehne: initialization changes to remove warnings. +// +// Revision 1.1.1.1 2006/12/15 20:20:04 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:53:53 acg +// Andy Goodrich: added $Log command so that CVS comments are reproduced in +// the source. +// + +#include "sysc/datatypes/bit/sc_bit_ids.h" +#include "sysc/datatypes/bit/sc_lv_base.h" + + +namespace sc_dt +{ + +// ---------------------------------------------------------------------------- +// CLASS : sc_lv_base +// +// Arbitrary size logic vector base class. +// ---------------------------------------------------------------------------- + +static const sc_digit data_array[] = + { SC_DIGIT_ZERO, ~SC_DIGIT_ZERO, SC_DIGIT_ZERO, ~SC_DIGIT_ZERO }; + +static const sc_digit ctrl_array[] = + { SC_DIGIT_ZERO, SC_DIGIT_ZERO, ~SC_DIGIT_ZERO, ~SC_DIGIT_ZERO }; + + +void +sc_lv_base::init( int length_, const sc_logic& init_value ) +{ + // check the length + if( length_ <= 0 ) { + SC_REPORT_ERROR( sc_core::SC_ID_ZERO_LENGTH_, 0 ); + } + // allocate memory for the data and control words + m_len = length_; + m_size = (m_len - 1) / SC_DIGIT_SIZE + 1; + m_data = new sc_digit[m_size * 2]; + m_ctrl = m_data + m_size; + // initialize the bits to 'init_value' + sc_digit dw = data_array[init_value.value()]; + sc_digit cw = ctrl_array[init_value.value()]; + int sz = m_size; + for( int i = 0; i < sz; ++ i ) { + m_data[i] = dw; + m_ctrl[i] = cw; + } + clean_tail(); +} + + +void +sc_lv_base::assign_from_string( const std::string& s ) +{ + // s must have been converted to bin + int len = m_len; + int s_len = s.length() - 1; + int min_len = sc_min( len, s_len ); + int i = 0; + for( ; i < min_len; ++ i ) { + char c = s[s_len - i - 1]; + set_bit( i, sc_logic::char_to_logic[(int)c] ); + } + // if formatted, fill the rest with sign(s), otherwise fill with zeros + sc_logic_value_t fill = (s[s_len] == 'F' ? sc_logic_value_t( s[0] - '0' ) + : sc_logic_value_t( 0 )); + for( ; i < len; ++ i ) { + set_bit( i, fill ); + } +} + + +// constructors + +sc_lv_base::sc_lv_base( const char* a ) + : m_len( 0 ), m_size( 0 ), m_data( 0 ), m_ctrl( 0 ) +{ + std::string s = convert_to_bin( a ); + init( s.length() - 1 ); + assign_from_string( s ); +} + +sc_lv_base::sc_lv_base( const char* a, int length_ ) + : m_len( 0 ), m_size( 0 ), m_data( 0 ), m_ctrl( 0 ) +{ + init( length_ ); + assign_from_string( convert_to_bin( a ) ); +} + +sc_lv_base::sc_lv_base( const sc_lv_base& a ) + : sc_proxy<sc_lv_base>(), + m_len( a.m_len ), + m_size( a.m_size ), + m_data( new sc_digit[m_size * 2] ), + m_ctrl( m_data + m_size ) +{ + // copy the bits + int sz = m_size; + for( int i = 0; i < sz; ++ i ) { + m_data[i] = a.m_data[i]; + m_ctrl[i] = a.m_ctrl[i]; + } +} + + +// assignment operators + +sc_lv_base& +sc_lv_base::operator = ( const char* a ) +{ + assign_from_string( convert_to_bin( a ) ); + return *this; +} + + +// returns true if logic vector contains only 0's and 1's + +bool +sc_lv_base::is_01() const +{ + int sz = m_size; + for( int i = 0; i < sz; ++ i ) { + if( m_ctrl[i] != 0 ) { + return false; + } + } + return true; +} + +} // namespace sc_dt diff --git a/ext/systemc/src/sysc/datatypes/bit/sc_lv_base.h b/ext/systemc/src/sysc/datatypes/bit/sc_lv_base.h new file mode 100644 index 000000000..313afa56e --- /dev/null +++ b/ext/systemc/src/sysc/datatypes/bit/sc_lv_base.h @@ -0,0 +1,1827 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_lv_base.h -- Arbitrary size logic vector class. + + Original Author: Gene Bushuyev, Synopsys, Inc. + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + Andy Goodrich, Forte Design Systems + Fixed bug in clean_tail for sizes that are modulo 32, which caused + zeroing of values. + + *****************************************************************************/ + +// $Log: sc_lv_base.h,v $ +// Revision 1.4 2011/08/26 22:32:00 acg +// Torsten Maehne: added parentheses to make opearator ordering more obvious. +// +// Revision 1.3 2010/01/27 19:41:29 acg +// Andy Goodrich: fix 8 instances of sc_concref constructor invocations +// that failed to indicate that their arguments should be freed when the +// object was freed. +// +// Revision 1.2 2009/02/28 00:26:14 acg +// Andy Goodrich: bug fixes. +// +// Revision 1.2 2007/03/14 17:47:49 acg +// Andy Goodrich: Formatting. +// +// Revision 1.1.1.1 2006/12/15 20:31:36 acg +// SystemC 2.2 +// +// Revision 1.3 2006/01/13 18:53:53 acg +// Andy Goodrich: added $Log command so that CVS comments are reproduced in +// the source. +// + +#ifndef SC_LV_BASE_H +#define SC_LV_BASE_H + + +#include "sysc/datatypes/bit/sc_bit_ids.h" +#include "sysc/datatypes/bit/sc_bv_base.h" +#include "sysc/datatypes/bit/sc_logic.h" +#include "sysc/datatypes/int/sc_length_param.h" + + +namespace sc_dt +{ + +// classes defined in this module +class sc_lv_base; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_lv_base +// +// Arbitrary size logic vector base class. +// ---------------------------------------------------------------------------- + +class sc_lv_base + : public sc_proxy<sc_lv_base> +{ + friend class sc_bv_base; + + + void init( int length_, const sc_logic& init_value = SC_LOGIC_X ); + + void assign_from_string( const std::string& ); + +public: + + // typedefs + + typedef sc_proxy<sc_lv_base> base_type; + + + // constructors + + explicit sc_lv_base( int length_ = sc_length_param().len() ) + : m_len( 0 ), m_size( 0 ), m_data( 0 ), m_ctrl( 0 ) + { init( length_ ); } + + explicit sc_lv_base( const sc_logic& a, + int length_ = sc_length_param().len() ) + : m_len( 0 ), m_size( 0 ), m_data( 0 ), m_ctrl( 0 ) + { init( length_, a ); } + + sc_lv_base( const char* a ); + + sc_lv_base( const char* a, int length_ ); + + template <class X> + sc_lv_base( const sc_proxy<X>& a ) + : m_len( 0 ), m_size( 0 ), m_data( 0 ), m_ctrl( 0 ) + { init( a.back_cast().length() ); base_type::assign_( a ); } + + sc_lv_base( const sc_lv_base& a ); + +#ifdef SC_DT_DEPRECATED + + explicit sc_lv_base( const sc_unsigned& a ) + : m_len( 0 ), m_size( 0 ), m_data( 0 ), m_ctrl( 0 ) + { init( a.length() ); base_type::assign_( a ); } + + explicit sc_lv_base( const sc_signed& a ) + : m_len( 0 ), m_size( 0 ), m_data( 0 ), m_ctrl( 0 ) + { init( a.length() ); base_type::assign_( a ); } + + explicit sc_lv_base( const sc_uint_base& a ) + : m_len( 0 ), m_size( 0 ), m_data( 0 ), m_ctrl( 0 ) + { init( a.length() ); base_type::assign_( a ); } + + explicit sc_lv_base( const sc_int_base& a ) + : m_len( 0 ), m_size( 0 ), m_data( 0 ), m_ctrl( 0 ) + { init( a.length() ); base_type::assign_( a ); } + +#endif + + + // destructor + + virtual ~sc_lv_base() + { delete [] m_data; } + + + // assignment operators + + template <class X> + sc_lv_base& operator = ( const sc_proxy<X>& a ) + { assign_p_( *this, a ); return *this; } + + sc_lv_base& operator = ( const sc_lv_base& a ) + { assign_p_( *this, a ); return *this; } + + sc_lv_base& operator = ( const char* a ); + + sc_lv_base& operator = ( const bool* a ) + { base_type::assign_( a ); return *this; } + + sc_lv_base& operator = ( const sc_logic* a ) + { base_type::assign_( a ); return *this; } + + sc_lv_base& operator = ( const sc_unsigned& a ) + { base_type::assign_( a ); return *this; } + + sc_lv_base& operator = ( const sc_signed& a ) + { base_type::assign_( a ); return *this; } + + sc_lv_base& operator = ( const sc_uint_base& a ) + { base_type::assign_( a ); return *this; } + + sc_lv_base& operator = ( const sc_int_base& a ) + { base_type::assign_( a ); return *this; } + + sc_lv_base& operator = ( unsigned long a ) + { base_type::assign_( a ); return *this; } + + sc_lv_base& operator = ( long a ) + { base_type::assign_( a ); return *this; } + + sc_lv_base& operator = ( unsigned int a ) + { base_type::assign_( a ); return *this; } + + sc_lv_base& operator = ( int a ) + { base_type::assign_( a ); return *this; } + + sc_lv_base& operator = ( uint64 a ) + { base_type::assign_( a ); return *this; } + + sc_lv_base& operator = ( int64 a ) + { base_type::assign_( a ); return *this; } + + +#if 0 + + // bitwise complement + + sc_lv_base& b_not() + { return sc_proxy<sc_lv_base>::b_not(); } + + const sc_lv_base operator ~ () const + { sc_lv_base a( *this ); return a.b_not(); } + + + // bitwise left shift + + sc_lv_base& operator <<= ( int n ) + { return sc_proxy<sc_lv_base>::operator <<= ( n ); } + + const sc_lv_base operator << ( int n ) const + { sc_lv_base a( *this ); return ( a <<= n ); } + + + // bitwise right shift + + sc_lv_base& operator >>= ( int n ) + { return sc_proxy<sc_lv_base>::operator >>= ( n ); } + + const sc_lv_base operator >> ( int n ) const + { sc_lv_base a( *this ); return ( a >>= n ); } + + + // bitwise left rotate + + sc_lv_base& lrotate( int n ) + { return sc_proxy<sc_lv_base>::lrotate( n ); } + + + // bitwise right rotate + + sc_lv_base& rrotate( int n ) + { return sc_proxy<sc_lv_base>::rrotate( n ); } + +#endif + + + // common methods + + int length() const + { return m_len; } + + int size() const + { return m_size; } + + sc_logic_value_t get_bit( int i ) const; + void set_bit( int i, sc_logic_value_t value ); + + sc_digit get_word( int wi ) const + { return m_data[wi]; } + + // note the test for out of range access here. this is necessary + // because of the hair-brained way concatenations are set up. + // an extend_sign on a concatenation uses the whole length of + // the concatenation to determine how many words to set. + void set_word( int wi, sc_digit w ) + { assert ( wi < m_size ); m_data[wi] = w; } + + + sc_digit get_cword( int wi ) const + { return m_ctrl[wi]; } + + void set_cword( int wi, sc_digit w ) + { assert ( wi < m_size ); m_ctrl[wi] = w; } + + void clean_tail(); + + + // other methods + + bool is_01() const; + +protected: + + int m_len; // length in bits + int m_size; // size of the data array + sc_digit* m_data; // data array + sc_digit* m_ctrl; // dito (control part) +}; + + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + +#if 0 + +// bitwise left rotate + +inline +const sc_lv_base +lrotate( const sc_lv_base& x, int n ) +{ + sc_lv_base a( x ); + return a.lrotate( n ); +} + + +// bitwise right rotate + +inline +const sc_lv_base +rrotate( const sc_lv_base& x, int n ) +{ + sc_lv_base a( x ); + return a.rrotate( n ); +} + +#endif + + +inline +sc_logic_value_t +sc_lv_base::get_bit( int i ) const +{ + int wi = i / SC_DIGIT_SIZE; + int bi = i % SC_DIGIT_SIZE; + return sc_logic_value_t( ((m_data[wi] >> bi) & SC_DIGIT_ONE) | + (((m_ctrl[wi] >> bi) << 1) & SC_DIGIT_TWO) ); +} + +inline +void +sc_lv_base::set_bit( int i, sc_logic_value_t value ) +{ + int wi = i / SC_DIGIT_SIZE; // word index + int bi = i % SC_DIGIT_SIZE; // bit index + sc_digit mask = SC_DIGIT_ONE << bi; + m_data[wi] |= mask; // set bit to 1 + m_ctrl[wi] |= mask; // set bit to 1 + m_data[wi] &= value << bi | ~mask; + m_ctrl[wi] &= value >> 1 << bi | ~mask; +} + + +inline +void +sc_lv_base::clean_tail() +{ + int wi = m_size - 1; + int bi = m_len % SC_DIGIT_SIZE; + sc_digit mask = ~SC_DIGIT_ZERO >> (SC_DIGIT_SIZE - bi); + if ( mask ) + { + m_data[wi] &= mask; + m_ctrl[wi] &= mask; + } +} + + +// ---------------------------------------------------------------------------- +// CLASS TEMPLATE : sc_proxy +// +// Base class template for bit/logic vector classes. +// (Barton/Nackmann implementation) +// ---------------------------------------------------------------------------- + +// bitwise operators and functions + +// bitwise complement + +template <class X> +inline +const sc_lv_base +sc_proxy<X>::operator ~ () const +{ + sc_lv_base a( back_cast() ); + return a.b_not(); +} + + +// bitwise and + +template <class X, class Y> +inline +X& +operator &= ( sc_proxy<X>& px, const sc_proxy<Y>& py ) +{ + X& x = px.back_cast(); + sc_lv_base a( x.length() ); + a = py.back_cast(); + return b_and_assign_( x, a ); +} + + +#define DEFN_BITWISE_AND_ASN_OP_T(tp) \ +template <class X> \ +inline \ +X& \ +sc_proxy<X>::operator &= ( tp b ) \ +{ \ + X& x = back_cast(); \ + sc_lv_base a( x.length() ); \ + a = b; \ + return b_and_assign_( x, a ); \ +} + +DEFN_BITWISE_AND_ASN_OP_T(const char*) +DEFN_BITWISE_AND_ASN_OP_T(const bool*) +DEFN_BITWISE_AND_ASN_OP_T(const sc_logic*) +DEFN_BITWISE_AND_ASN_OP_T(const sc_unsigned&) +DEFN_BITWISE_AND_ASN_OP_T(const sc_signed&) +DEFN_BITWISE_AND_ASN_OP_T(unsigned long) +DEFN_BITWISE_AND_ASN_OP_T(long) +DEFN_BITWISE_AND_ASN_OP_T(uint64) +DEFN_BITWISE_AND_ASN_OP_T(int64) + +#undef DEFN_BITWISE_AND_ASN_OP_T + + +template <class X, class Y> +inline +const sc_lv_base +operator & ( const sc_proxy<X>& px, const sc_proxy<Y>& py ) +{ + sc_lv_base a( px.back_cast() ); + return ( a &= py.back_cast() ); +} + + +#define DEFN_BITWISE_AND_OP_T_A(tp) \ +template <class X> \ +inline \ +const sc_lv_base \ +sc_proxy<X>::operator & ( tp b ) const \ +{ \ + sc_lv_base a( back_cast() ); \ + return ( a &= b ); \ +} + +DEFN_BITWISE_AND_OP_T_A(const char*) +DEFN_BITWISE_AND_OP_T_A(const bool*) +DEFN_BITWISE_AND_OP_T_A(const sc_logic*) +DEFN_BITWISE_AND_OP_T_A(const sc_unsigned&) +DEFN_BITWISE_AND_OP_T_A(const sc_signed&) +DEFN_BITWISE_AND_OP_T_A(const sc_uint_base&) +DEFN_BITWISE_AND_OP_T_A(const sc_int_base&) +DEFN_BITWISE_AND_OP_T_A(unsigned long) +DEFN_BITWISE_AND_OP_T_A(long) +DEFN_BITWISE_AND_OP_T_A(unsigned int) +DEFN_BITWISE_AND_OP_T_A(int) +DEFN_BITWISE_AND_OP_T_A(uint64) +DEFN_BITWISE_AND_OP_T_A(int64) + +#undef DEFN_BITWISE_AND_OP_T_A + + +#define DEFN_BITWISE_AND_OP_T_B(tp) \ +template <class X> \ +inline \ +const sc_lv_base \ +operator & ( tp b, const sc_proxy<X>& px ) \ +{ \ + return ( px & b ); \ +} + +DEFN_BITWISE_AND_OP_T_B(const char*) +DEFN_BITWISE_AND_OP_T_B(const bool*) +DEFN_BITWISE_AND_OP_T_B(const sc_logic*) +DEFN_BITWISE_AND_OP_T_B(const sc_unsigned&) +DEFN_BITWISE_AND_OP_T_B(const sc_signed&) +DEFN_BITWISE_AND_OP_T_B(const sc_uint_base&) +DEFN_BITWISE_AND_OP_T_B(const sc_int_base&) +DEFN_BITWISE_AND_OP_T_B(unsigned long) +DEFN_BITWISE_AND_OP_T_B(long) +DEFN_BITWISE_AND_OP_T_B(unsigned int) +DEFN_BITWISE_AND_OP_T_B(int) +DEFN_BITWISE_AND_OP_T_B(uint64) +DEFN_BITWISE_AND_OP_T_B(int64) + +#undef DEFN_BITWISE_AND_OP_T_B + + +// bitwise or + +template <class X, class Y> +inline +X& +operator |= ( sc_proxy<X>& px, const sc_proxy<Y>& py ) +{ + X& x = px.back_cast(); + sc_lv_base a( x.length() ); + a = py.back_cast(); + return b_or_assign_( x, a ); +} + + +#define DEFN_BITWISE_OR_ASN_OP_T(tp) \ +template <class X> \ +inline \ +X& \ +sc_proxy<X>::operator |= ( tp b ) \ +{ \ + X& x = back_cast(); \ + sc_lv_base a( x.length() ); \ + a = b; \ + return b_or_assign_( x, a ); \ +} + +DEFN_BITWISE_OR_ASN_OP_T(const char*) +DEFN_BITWISE_OR_ASN_OP_T(const bool*) +DEFN_BITWISE_OR_ASN_OP_T(const sc_logic*) +DEFN_BITWISE_OR_ASN_OP_T(const sc_unsigned&) +DEFN_BITWISE_OR_ASN_OP_T(const sc_signed&) +DEFN_BITWISE_OR_ASN_OP_T(unsigned long) +DEFN_BITWISE_OR_ASN_OP_T(long) +DEFN_BITWISE_OR_ASN_OP_T(uint64) +DEFN_BITWISE_OR_ASN_OP_T(int64) + +#undef DEFN_BITWISE_OR_ASN_OP_T + + +template <class X, class Y> +inline +const sc_lv_base +operator | ( const sc_proxy<X>& px, const sc_proxy<Y>& py ) +{ + sc_lv_base a( px.back_cast() ); + return ( a |= py.back_cast() ); +} + + +#define DEFN_BITWISE_OR_OP_T_A(tp) \ +template <class X> \ +inline \ +const sc_lv_base \ +sc_proxy<X>::operator | ( tp b ) const \ +{ \ + sc_lv_base a( back_cast() ); \ + return ( a |= b ); \ +} + +DEFN_BITWISE_OR_OP_T_A(const char*) +DEFN_BITWISE_OR_OP_T_A(const bool*) +DEFN_BITWISE_OR_OP_T_A(const sc_logic*) +DEFN_BITWISE_OR_OP_T_A(const sc_unsigned&) +DEFN_BITWISE_OR_OP_T_A(const sc_signed&) +DEFN_BITWISE_OR_OP_T_A(const sc_uint_base&) +DEFN_BITWISE_OR_OP_T_A(const sc_int_base&) +DEFN_BITWISE_OR_OP_T_A(unsigned long) +DEFN_BITWISE_OR_OP_T_A(long) +DEFN_BITWISE_OR_OP_T_A(unsigned int) +DEFN_BITWISE_OR_OP_T_A(int) +DEFN_BITWISE_OR_OP_T_A(uint64) +DEFN_BITWISE_OR_OP_T_A(int64) + +#undef DEFN_BITWISE_OR_OP_T_A + + +#define DEFN_BITWISE_OR_OP_T_B(tp) \ +template <class X> \ +inline \ +const sc_lv_base \ +operator | ( tp b, const sc_proxy<X>& px ) \ +{ \ + return ( px | b ); \ +} + +DEFN_BITWISE_OR_OP_T_B(const char*) +DEFN_BITWISE_OR_OP_T_B(const bool*) +DEFN_BITWISE_OR_OP_T_B(const sc_logic*) +DEFN_BITWISE_OR_OP_T_B(const sc_unsigned&) +DEFN_BITWISE_OR_OP_T_B(const sc_signed&) +DEFN_BITWISE_OR_OP_T_B(const sc_uint_base&) +DEFN_BITWISE_OR_OP_T_B(const sc_int_base&) +DEFN_BITWISE_OR_OP_T_B(unsigned long) +DEFN_BITWISE_OR_OP_T_B(long) +DEFN_BITWISE_OR_OP_T_B(unsigned int) +DEFN_BITWISE_OR_OP_T_B(int) +DEFN_BITWISE_OR_OP_T_B(uint64) +DEFN_BITWISE_OR_OP_T_B(int64) + +#undef DEFN_BITWISE_OR_OP_T_B + + +// bitwise xor + +template <class X, class Y> +inline +X& +operator ^= ( sc_proxy<X>& px, const sc_proxy<Y>& py ) +{ + X& x = px.back_cast(); + sc_lv_base a( x.length() ); + a = py.back_cast(); + return b_xor_assign_( x, a ); +} + + +#define DEFN_BITWISE_XOR_ASN_OP_T(tp) \ +template <class X> \ +inline \ +X& \ +sc_proxy<X>::operator ^= ( tp b ) \ +{ \ + X& x = back_cast(); \ + sc_lv_base a( x.length() ); \ + a = b; \ + return b_xor_assign_( x, a ); \ +} + +DEFN_BITWISE_XOR_ASN_OP_T(const char*) +DEFN_BITWISE_XOR_ASN_OP_T(const bool*) +DEFN_BITWISE_XOR_ASN_OP_T(const sc_logic*) +DEFN_BITWISE_XOR_ASN_OP_T(const sc_unsigned&) +DEFN_BITWISE_XOR_ASN_OP_T(const sc_signed&) +DEFN_BITWISE_XOR_ASN_OP_T(unsigned long) +DEFN_BITWISE_XOR_ASN_OP_T(long) +DEFN_BITWISE_XOR_ASN_OP_T(uint64) +DEFN_BITWISE_XOR_ASN_OP_T(int64) + +#undef DEFN_BITWISE_XOR_ASN_OP_T + + +template <class X, class Y> +inline +const sc_lv_base +operator ^ ( const sc_proxy<X>& px, const sc_proxy<Y>& py ) +{ + sc_lv_base a( px.back_cast() ); + return ( a ^= py.back_cast() ); +} + + +#define DEFN_BITWISE_XOR_OP_T_A(tp) \ +template <class X> \ +inline \ +const sc_lv_base \ +sc_proxy<X>::operator ^ ( tp b ) const \ +{ \ + sc_lv_base a( back_cast() ); \ + return ( a ^= b ); \ +} + +DEFN_BITWISE_XOR_OP_T_A(const char*) +DEFN_BITWISE_XOR_OP_T_A(const bool*) +DEFN_BITWISE_XOR_OP_T_A(const sc_logic*) +DEFN_BITWISE_XOR_OP_T_A(const sc_unsigned&) +DEFN_BITWISE_XOR_OP_T_A(const sc_signed&) +DEFN_BITWISE_XOR_OP_T_A(const sc_uint_base&) +DEFN_BITWISE_XOR_OP_T_A(const sc_int_base&) +DEFN_BITWISE_XOR_OP_T_A(unsigned long) +DEFN_BITWISE_XOR_OP_T_A(long) +DEFN_BITWISE_XOR_OP_T_A(unsigned int) +DEFN_BITWISE_XOR_OP_T_A(int) +DEFN_BITWISE_XOR_OP_T_A(uint64) +DEFN_BITWISE_XOR_OP_T_A(int64) + +#undef DEFN_BITWISE_XOR_OP_T_A + + +#define DEFN_BITWISE_XOR_OP_T_B(tp) \ +template <class X> \ +inline \ +const sc_lv_base \ +operator ^ ( tp b, const sc_proxy<X>& px ) \ +{ \ + return ( px ^ b ); \ +} + +DEFN_BITWISE_XOR_OP_T_B(const char*) +DEFN_BITWISE_XOR_OP_T_B(const bool*) +DEFN_BITWISE_XOR_OP_T_B(const sc_logic*) +DEFN_BITWISE_XOR_OP_T_B(const sc_unsigned&) +DEFN_BITWISE_XOR_OP_T_B(const sc_signed&) +DEFN_BITWISE_XOR_OP_T_B(const sc_uint_base&) +DEFN_BITWISE_XOR_OP_T_B(const sc_int_base&) +DEFN_BITWISE_XOR_OP_T_B(unsigned long) +DEFN_BITWISE_XOR_OP_T_B(long) +DEFN_BITWISE_XOR_OP_T_B(unsigned int) +DEFN_BITWISE_XOR_OP_T_B(int) +DEFN_BITWISE_XOR_OP_T_B(uint64) +DEFN_BITWISE_XOR_OP_T_B(int64) + +#undef DEFN_BITWISE_XOR_OP_T_B + + +// bitwise left shift + +template <class X> +inline +const sc_lv_base +sc_proxy<X>::operator << ( int n ) const +{ + sc_lv_base a( back_cast().length()+n ); + a = back_cast(); + return ( a <<= n ); +} + + +// bitwise right shift + +template <class X> +inline +const sc_lv_base +sc_proxy<X>::operator >> ( int n ) const +{ + sc_lv_base a( back_cast() ); + return ( a >>= n ); +} + + +// bitwise left rotate + +template <class X> +inline +X& +sc_proxy<X>::lrotate( int n ) +{ + X& x = back_cast(); + if( n < 0 ) { + char msg[BUFSIZ]; + std::sprintf( msg, + "left rotate operation is only allowed with positive " + "rotate values, rotate value = %d", n ); + SC_REPORT_ERROR( sc_core::SC_ID_OUT_OF_BOUNDS_, msg ); + } + int len = x.length(); + n %= len; + // x = (x << n) | (x >> (len - n)); + sc_lv_base a( x << n ); + sc_lv_base b( x >> (len - n) ); + int sz = x.size(); + for( int i = 0; i < sz; ++ i ) { + x.set_word( i, a.get_word( i ) | b.get_word( i ) ); + x.set_cword( i, a.get_cword( i ) | b.get_cword( i ) ); + } + x.clean_tail(); + return x; +} + +template <class X> +inline +const sc_lv_base +lrotate( const sc_proxy<X>& x, int n ) +{ + sc_lv_base a( x.back_cast() ); + return a.lrotate( n ); +} + + +// bitwise right rotate + +template <class X> +inline +X& +sc_proxy<X>::rrotate( int n ) +{ + X& x = back_cast(); + if( n < 0 ) { + char msg[BUFSIZ]; + std::sprintf( msg, + "right rotate operation is only allowed with positive " + "rotate values, rotate value = %d", n ); + SC_REPORT_ERROR( sc_core::SC_ID_OUT_OF_BOUNDS_, msg ); + } + int len = x.length(); + n %= len; + // x = (x >> n) | (x << (len - n)); + sc_lv_base a( x >> n ); + sc_lv_base b( x << (len - n) ); + int sz = x.size(); + for( int i = 0; i < sz; ++ i ) { + x.set_word( i, a.get_word( i ) | b.get_word( i ) ); + x.set_cword( i, a.get_cword( i ) | b.get_cword( i ) ); + } + x.clean_tail(); + return x; +} + +template <class X> +inline +const sc_lv_base +rrotate( const sc_proxy<X>& x, int n ) +{ + sc_lv_base a( x.back_cast() ); + return a.rrotate( n ); +} + + +// bitwise reverse + +template <class X> +inline +const sc_lv_base +reverse( const sc_proxy<X>& x ) +{ + sc_lv_base a( x.back_cast() ); + return a.reverse(); +} + + +// relational operators + +template <class X, class Y> +inline +bool +operator == ( const sc_proxy<X>& px, const sc_proxy<Y>& py ) +{ + const X& x = px.back_cast(); + const Y& y = py.back_cast(); + int x_len = x.length(); + int y_len = y.length(); + if( x_len != y_len ) { + return false; + } + int sz = x.size(); + for( int i = 0; i < sz; ++ i ) { + if( x.get_word( i ) != y.get_word( i ) || + x.get_cword( i ) != y.get_cword( i ) ) { + return false; + } + } + return true; +} + + +#define DEFN_REL_OP_T(tp) \ +template <class X> \ +inline \ +bool \ +sc_proxy<X>::operator == ( tp b ) const \ +{ \ + const X& x = back_cast(); \ + sc_lv_base y( x.length() ); \ + y = b; \ + return ( x == y ); \ +} + +DEFN_REL_OP_T(const char*) +DEFN_REL_OP_T(const bool*) +DEFN_REL_OP_T(const sc_logic*) +DEFN_REL_OP_T(const sc_unsigned&) +DEFN_REL_OP_T(const sc_signed&) +DEFN_REL_OP_T(const sc_uint_base&) +DEFN_REL_OP_T(const sc_int_base&) +DEFN_REL_OP_T(unsigned long) +DEFN_REL_OP_T(long) +DEFN_REL_OP_T(unsigned int) +DEFN_REL_OP_T(int) +DEFN_REL_OP_T(uint64) +DEFN_REL_OP_T(int64) + +#undef DEFN_REL_OP_T + + +// ---------------------------------------------------------------------------- +// CLASS TEMPLATE : sc_bitref_r<X> +// +// Proxy class for sc_proxy bit selection (r-value only). +// ---------------------------------------------------------------------------- + +// r-value concatenation operators and functions + +template <class T> +inline +sc_concref_r<sc_bitref_r<T>,sc_lv_base> +operator , ( sc_bitref_r<T> a, const char* b ) +{ + return sc_concref_r<sc_bitref_r<T>,sc_lv_base>( + *a.clone(), *new sc_lv_base( b ), 3 ); +} + +template <class T> +inline +sc_concref_r<sc_lv_base,sc_bitref_r<T> > +operator , ( const char* a, sc_bitref_r<T> b ) +{ + return sc_concref_r<sc_lv_base,sc_bitref_r<T> >( + *new sc_lv_base( a ), *b.clone(), 3 ); +} + +template <class T> +inline +sc_concref_r<sc_bitref_r<T>,sc_lv_base> +operator , ( sc_bitref_r<T> a, const sc_logic& b ) +{ + return sc_concref_r<sc_bitref_r<T>,sc_lv_base>( + *a.clone(), *new sc_lv_base( b, 1 ), 3 ); +} + +template <class T> +inline +sc_concref_r<sc_lv_base,sc_bitref_r<T> > +operator , ( const sc_logic& a, sc_bitref_r<T> b ) +{ + return sc_concref_r<sc_lv_base,sc_bitref_r<T> >( + *new sc_lv_base( a, 1 ), *b.clone(), 3 ); +} + +template <class T> +inline +sc_concref_r<sc_bitref_r<T>,sc_bv_base> +operator , ( sc_bitref_r<T> a, bool b ) +{ + return sc_concref_r<sc_bitref_r<T>,sc_bv_base> + ( *a.clone(), *new sc_bv_base( b, 1 ), 3 ); +} + +template <class T> +inline +sc_concref_r<sc_bv_base,sc_bitref_r<T> > +operator , ( bool a, sc_bitref_r<T> b ) +{ + return sc_concref_r<sc_bv_base,sc_bitref_r<T> > + ( *new sc_bv_base( a, 1 ), *b.clone(), 3 ); +} + + +template <class T> +inline +sc_concref_r<sc_bitref_r<T>,sc_lv_base> +concat( sc_bitref_r<T> a, const char* b ) +{ + return sc_concref_r<sc_bitref_r<T>,sc_lv_base>( + *a.clone(), *new sc_lv_base( b ), 3 ); +} + +template <class T> +inline +sc_concref_r<sc_lv_base,sc_bitref_r<T> > +concat( const char* a, sc_bitref_r<T> b ) +{ + return sc_concref_r<sc_lv_base,sc_bitref_r<T> >( + *new sc_lv_base( a ), *b.clone(), 3 ); +} + +template <class T> +inline +sc_concref_r<sc_bitref_r<T>,sc_lv_base> +concat( sc_bitref_r<T> a, const sc_logic& b ) +{ + return sc_concref_r<sc_bitref_r<T>,sc_lv_base>( + *a.clone(), *new sc_lv_base( b, 1 ), 3 ); +} + +template <class T> +inline +sc_concref_r<sc_lv_base,sc_bitref_r<T> > +concat( const sc_logic& a, sc_bitref_r<T> b ) +{ + return sc_concref_r<sc_lv_base,sc_bitref_r<T> >( + *new sc_lv_base( a, 1 ), *b.clone(), 3 ); +} + +template <class T> +inline +sc_concref_r<sc_bitref_r<T>,sc_bv_base> +concat( sc_bitref_r<T> a, bool b ) +{ + return sc_concref_r<sc_bitref_r<T>,sc_bv_base> + ( *a.clone(), *new sc_bv_base( b, 1 ), 3 ); +} + +template <class T> +inline +sc_concref_r<sc_bv_base,sc_bitref_r<T> > +concat( bool a, sc_bitref_r<T> b ) +{ + return sc_concref_r<sc_bv_base,sc_bitref_r<T> > + ( *new sc_bv_base( a, 1 ), *b.clone(), 3 ); +} + + +#ifdef SC_DT_MIXED_COMMA_OPERATORS + +template <class T> +inline +sc_concref_r<sc_bitref_r<T>,sc_lv_base> +operator , ( sc_bitref<T> a, const char* b ) +{ + return sc_concref_r<sc_bitref_r<T>,sc_lv_base>( + *a.clone(), *new sc_lv_base( b ), 3 ); +} + +template <class T> +inline +sc_concref_r<sc_lv_base,sc_bitref_r<T> > +operator , ( const char* a, sc_bitref<T> b ) +{ + return sc_concref_r<sc_lv_base,sc_bitref_r<T> >( + *new sc_lv_base( a ), *b.clone(), 3 ); +} + +template <class T> +inline +sc_concref_r<sc_bitref_r<T>,sc_lv_base> +operator , ( sc_bitref<T> a, const sc_logic& b ) +{ + return sc_concref_r<sc_bitref_r<T>,sc_lv_base>( + *a.clone(), *new sc_lv_base( b, 1 ), 3 ); +} + +template <class T> +inline +sc_concref_r<sc_lv_base,sc_bitref_r<T> > +operator , ( const sc_logic& a, sc_bitref<T> b ) +{ + return sc_concref_r<sc_lv_base,sc_bitref_r<T> >( + *new sc_lv_base( a, 1 ), *b.clone(), 3 ); +} + +template <class T> +inline +sc_concref_r<sc_bitref_r<T>,sc_bv_base> +operator , ( sc_bitref<T> a, bool b ) +{ + return sc_concref_r<sc_bitref_r<T>,sc_bv_base> + ( *a.clone(), *new sc_bv_base( b, 1 ), 3 ); +} + +template <class T> +inline +sc_concref_r<sc_bv_base,sc_bitref_r<T> > +operator , ( bool a, sc_bitref<T> b ) +{ + return sc_concref_r<sc_bv_base,sc_bitref_r<T> > + ( *new sc_bv_base( a, 1 ), *b.clone(), 3 ); +} + + +template <class T> +inline +sc_concref_r<sc_bitref_r<T>,sc_lv_base> +concat( sc_bitref<T> a, const char* b ) +{ + return sc_concref_r<sc_bitref_r<T>,sc_lv_base>( + *a.clone(), *new sc_lv_base( b ), 3 ); +} + +template <class T> +inline +sc_concref_r<sc_lv_base,sc_bitref_r<T> > +concat( const char* a, sc_bitref<T> b ) +{ + return sc_concref_r<sc_lv_base,sc_bitref_r<T> >( + *new sc_lv_base( a ), *b.clone(), 3 ); +} + +template <class T> +inline +sc_concref_r<sc_bitref_r<T>,sc_lv_base> +concat( sc_bitref<T> a, const sc_logic& b ) +{ + return sc_concref_r<sc_bitref_r<T>,sc_lv_base>( + *a.clone(), *new sc_lv_base( b, 1 ), 3 ); +} + +template <class T> +inline +sc_concref_r<sc_lv_base,sc_bitref_r<T> > +concat( const sc_logic& a, sc_bitref<T> b ) +{ + return sc_concref_r<sc_lv_base,sc_bitref_r<T> >( + *new sc_lv_base( a, 1 ), *b.clone(), 3 ); +} + +template <class T> +inline +sc_concref_r<sc_bitref_r<T>,sc_bv_base> +concat( sc_bitref<T> a, bool b ) +{ + return sc_concref_r<sc_bitref_r<T>,sc_bv_base> + ( *a.clone(), *new sc_bv_base( b, 1 ), 3 ); +} + +template <class T> +inline +sc_concref_r<sc_bv_base,sc_bitref_r<T> > +concat( bool a, sc_bitref<T> b ) +{ + return sc_concref_r<sc_bv_base,sc_bitref_r<T> > + ( *new sc_bv_base( a, 1 ), *b.clone(), 3 ); +} + +#endif + + +// ---------------------------------------------------------------------------- +// CLASS TEMPLATE : sc_subref_r<X> +// +// Proxy class for sc_proxy part selection (r-value only). +// ---------------------------------------------------------------------------- + +// r-value concatenation operators and functions + +template <class T> +inline +sc_concref_r<sc_subref_r<T>,sc_lv_base> +operator , ( sc_subref_r<T> a, const char* b ) +{ + return sc_concref_r<sc_subref_r<T>,sc_lv_base>( + *a.clone(), *new sc_lv_base( b ), 3 ); +} + +template <class T> +inline +sc_concref_r<sc_lv_base,sc_subref_r<T> > +operator , ( const char* a, sc_subref_r<T> b ) +{ + return sc_concref_r<sc_lv_base,sc_subref_r<T> >( + *new sc_lv_base( a ), *b.clone(), 3 ); +} + +template <class T> +inline +sc_concref_r<sc_subref_r<T>,sc_lv_base> +operator , ( sc_subref_r<T> a, const sc_logic& b ) +{ + return sc_concref_r<sc_subref_r<T>,sc_lv_base>( + *a.clone(), *new sc_lv_base( b, 1 ), 3 ); +} + +template <class T> +inline +sc_concref_r<sc_lv_base,sc_subref_r<T> > +operator , ( const sc_logic& a, sc_subref_r<T> b ) +{ + return sc_concref_r<sc_lv_base,sc_subref_r<T> >( + *new sc_lv_base( a, 1 ), *b.clone(), 3 ); +} + +template <class T> +inline +sc_concref_r<sc_subref_r<T>,sc_bv_base> +operator , ( sc_subref_r<T> a, bool b ) +{ + return sc_concref_r<sc_subref_r<T>,sc_bv_base> + ( *a.clone(), *new sc_bv_base( b, 1 ), 3 ); +} + +template <class T> +inline +sc_concref_r<sc_bv_base,sc_subref_r<T> > +operator , ( bool a, sc_subref_r<T> b ) +{ + return sc_concref_r<sc_bv_base,sc_subref_r<T> > + ( *new sc_bv_base( a, 1 ), *b.clone(), 3 ); +} + + +template <class T> +inline +sc_concref_r<sc_subref_r<T>,sc_lv_base> +concat( sc_subref_r<T> a, const char* b ) +{ + return sc_concref_r<sc_subref_r<T>,sc_lv_base>( + *a.clone(), *new sc_lv_base( b ), 3 ); +} + +template <class T> +inline +sc_concref_r<sc_lv_base,sc_subref_r<T> > +concat( const char* a, sc_subref_r<T> b ) +{ + return sc_concref_r<sc_lv_base,sc_subref_r<T> >( + *new sc_lv_base( a ), *b.clone(), 3 ); +} + +template <class T> +inline +sc_concref_r<sc_subref_r<T>,sc_lv_base> +concat( sc_subref_r<T> a, const sc_logic& b ) +{ + return sc_concref_r<sc_subref_r<T>,sc_lv_base>( + *a.clone(), *new sc_lv_base( b, 1 ), 3 ); +} + +template <class T> +inline +sc_concref_r<sc_lv_base,sc_subref_r<T> > +concat( const sc_logic& a, sc_subref_r<T> b ) +{ + return sc_concref_r<sc_lv_base,sc_subref_r<T> >( + *new sc_lv_base( a, 1 ), *b.clone(), 3 ); +} + +template <class T> +inline +sc_concref_r<sc_subref_r<T>,sc_bv_base> +concat( sc_subref_r<T> a, bool b ) +{ + return sc_concref_r<sc_subref_r<T>,sc_bv_base> + ( *a.clone(), *new sc_bv_base( b, 1 ), 3 ); +} + +template <class T> +inline +sc_concref_r<sc_bv_base,sc_subref_r<T> > +concat( bool a, sc_subref_r<T> b ) +{ + return sc_concref_r<sc_bv_base,sc_subref_r<T> > + ( *new sc_bv_base( a, 1 ), *b.clone(), 3 ); +} + + +#ifdef SC_DT_MIXED_COMMA_OPERATORS + +template <class T> +inline +sc_concref_r<sc_subref_r<T>,sc_lv_base> +operator , ( sc_subref<T> a, const char* b ) +{ + return sc_concref_r<sc_subref_r<T>,sc_lv_base>( + *a.clone(), *new sc_lv_base( b ), 3 ); +} + +template <class T> +inline +sc_concref_r<sc_lv_base,sc_subref_r<T> > +operator , ( const char* a, sc_subref<T> b ) +{ + return sc_concref_r<sc_lv_base,sc_subref_r<T> >( + *new sc_lv_base( a ), *b.clone(), 3 ); +} + +template <class T> +inline +sc_concref_r<sc_subref_r<T>,sc_lv_base> +operator , ( sc_subref<T> a, const sc_logic& b ) +{ + return sc_concref_r<sc_subref_r<T>,sc_lv_base>( + *a.clone(), *new sc_lv_base( b, 1 ), 3 ); +} + +template <class T> +inline +sc_concref_r<sc_lv_base,sc_subref_r<T> > +operator , ( const sc_logic& a, sc_subref<T> b ) +{ + return sc_concref_r<sc_lv_base,sc_subref_r<T> >( + *new sc_lv_base( a, 1 ), *b.clone(), 3 ); +} + +template <class T> +inline +sc_concref_r<sc_subref_r<T>,sc_bv_base> +operator , ( sc_subref<T> a, bool b ) +{ + return sc_concref_r<sc_subref_r<T>,sc_bv_base> + ( *a.clone(), *new sc_bv_base( b, 1 ), 3 ); +} + +template <class T> +inline +sc_concref_r<sc_bv_base,sc_subref_r<T> > +operator , ( bool a, sc_subref<T> b ) +{ + return sc_concref_r<sc_bv_base,sc_subref_r<T> > + ( *new sc_bv_base( a, 1 ), *b.clone(), 3 ); +} + + +template <class T> +inline +sc_concref_r<sc_subref_r<T>,sc_lv_base> +concat( sc_subref<T> a, const char* b ) +{ + return sc_concref_r<sc_subref_r<T>,sc_lv_base>( + *a.clone(), *new sc_lv_base( b ), 3 ); +} + +template <class T> +inline +sc_concref_r<sc_lv_base,sc_subref_r<T> > +concat( const char* a, sc_subref<T> b ) +{ + return sc_concref_r<sc_lv_base,sc_subref_r<T> >( + *new sc_lv_base( a ), *b.clone(), 3 ); +} + +template <class T> +inline +sc_concref_r<sc_subref_r<T>,sc_lv_base> +concat( sc_subref<T> a, const sc_logic& b ) +{ + return sc_concref_r<sc_subref_r<T>,sc_lv_base>( + *a.clone(), *new sc_lv_base( b, 1 ), 3 ); +} + +template <class T> +inline +sc_concref_r<sc_lv_base,sc_subref_r<T> > +concat( const sc_logic& a, sc_subref<T> b ) +{ + return sc_concref_r<sc_lv_base,sc_subref_r<T> >( + *new sc_lv_base( a, 1 ), *b.clone(), 3 ); +} + +template <class T> +inline +sc_concref_r<sc_subref_r<T>,sc_bv_base> +concat( sc_subref<T> a, bool b ) +{ + return sc_concref_r<sc_subref_r<T>,sc_bv_base> + ( *a.clone(), *new sc_bv_base( b, 1 ), 3 ); +} + +template <class T> +inline +sc_concref_r<sc_bv_base,sc_subref_r<T> > +concat( bool a, sc_subref<T> b ) +{ + return sc_concref_r<sc_bv_base,sc_subref_r<T> > + ( *new sc_bv_base( a, 1 ), *b.clone(), 3 ); +} + +#endif + + +// ---------------------------------------------------------------------------- +// CLASS TEMPLATE : sc_subref<X> +// +// Proxy class for sc_proxy part selection (r-value and l-value). +// ---------------------------------------------------------------------------- + +template <class X> +inline +sc_subref<X>& +sc_subref<X>::operator = ( const sc_subref_r<X>& b ) +{ + sc_lv_base t( b ); // (partial) self assignment protection + int len = sc_min( this->length(), t.length() ); + if( ! this->reversed() ) { + for( int i = len - 1; i >= 0; -- i ) { + this->m_obj.set_bit( this->m_lo + i, t[i].value() ); + } + } else { + for( int i = len - 1; i >= 0; -- i ) { + this->m_obj.set_bit( this->m_lo - i, t[i].value() ); + } + } + return *this; +} + +template <class X> +inline +sc_subref<X>& +sc_subref<X>::operator = ( const sc_subref<X>& b ) +{ + sc_lv_base t( b ); // (partial) self assignment protection + int len = sc_min( this->length(), t.length() ); + if( ! this->reversed() ) { + for( int i = len - 1; i >= 0; -- i ) { + this->m_obj.set_bit( this->m_lo + i, t[i].value() ); + } + } else { + for( int i = len - 1; i >= 0; -- i ) { + this->m_obj.set_bit( this->m_lo - i, t[i].value() ); + } + } + return *this; +} + + +// ---------------------------------------------------------------------------- +// CLASS TEMPLATE : sc_concref_r<X,Y> +// +// Proxy class for sc_proxy concatenation (r-value only). +// ---------------------------------------------------------------------------- + +// r-value concatenation operators and functions + +template <class T1, class T2> +inline +sc_concref_r<sc_concref_r<T1,T2>,sc_lv_base> +operator , ( sc_concref_r<T1,T2> a, const char* b ) +{ + return sc_concref_r<sc_concref_r<T1,T2>,sc_lv_base>( + *a.clone(), *new sc_lv_base( b ), 3 ); +} + +template <class T1, class T2> +inline +sc_concref_r<sc_lv_base,sc_concref_r<T1,T2> > +operator , ( const char* a, sc_concref_r<T1,T2> b ) +{ + return sc_concref_r<sc_lv_base,sc_concref_r<T1,T2> >( + *new sc_lv_base( a ), *b.clone(), 3 ); +} + +template <class T1, class T2> +inline +sc_concref_r<sc_concref_r<T1,T2>,sc_lv_base> +operator , ( sc_concref_r<T1,T2> a, const sc_logic& b ) +{ + return sc_concref_r<sc_concref_r<T1,T2>,sc_lv_base>( + *a.clone(), *new sc_lv_base( b, 1 ), 3 ); +} + +template <class T1, class T2> +inline +sc_concref_r<sc_lv_base,sc_concref_r<T1,T2> > +operator , ( const sc_logic& a, sc_concref_r<T1,T2> b ) +{ + return sc_concref_r<sc_lv_base,sc_concref_r<T1,T2> >( + *new sc_lv_base( a, 1 ), *b.clone(), 3 ); +} + +template <class T1, class T2> +inline +sc_concref_r<sc_concref_r<T1,T2>,sc_bv_base> +operator , ( sc_concref_r<T1,T2> a, bool b ) +{ + return sc_concref_r<sc_concref_r<T1,T2>,sc_bv_base> + ( *a.clone(), *new sc_bv_base( b, 1 ), 3 ); +} + +template <class T1, class T2> +inline +sc_concref_r<sc_bv_base,sc_concref_r<T1,T2> > +operator , ( bool a, sc_concref_r<T1,T2> b ) +{ + return sc_concref_r<sc_bv_base,sc_concref_r<T1,T2> > + ( *new sc_bv_base( a, 1 ), *b.clone(), 3 ); +} + + +template <class T1, class T2> +inline +sc_concref_r<sc_concref_r<T1,T2>,sc_lv_base> +concat( sc_concref_r<T1,T2> a, const char* b ) +{ + return sc_concref_r<sc_concref_r<T1,T2>,sc_lv_base> + ( *a.clone(), *new sc_lv_base( b ), 3 ); +} + +template <class T1, class T2> +inline +sc_concref_r<sc_lv_base,sc_concref_r<T1,T2> > +concat( const char* a, sc_concref_r<T1,T2> b ) +{ + return sc_concref_r<sc_lv_base,sc_concref_r<T1,T2> > + ( *new sc_lv_base( a ), *b.clone(), 3 ); +} + +template <class T1, class T2> +inline +sc_concref_r<sc_concref_r<T1,T2>,sc_lv_base> +concat( sc_concref_r<T1,T2> a, const sc_logic& b ) +{ + return sc_concref_r<sc_concref_r<T1,T2>,sc_lv_base> + ( *a.clone(), *new sc_lv_base( b, 1 ), 3 ); +} + +template <class T1, class T2> +inline +sc_concref_r<sc_lv_base,sc_concref_r<T1,T2> > +concat( const sc_logic& a, sc_concref_r<T1,T2> b ) +{ + return sc_concref_r<sc_lv_base,sc_concref_r<T1,T2> > + ( *new sc_lv_base( a, 1 ), *b.clone(), 3 ); +} + +template <class T1, class T2> +inline +sc_concref_r<sc_concref_r<T1,T2>,sc_bv_base> +concat( sc_concref_r<T1,T2> a, bool b ) +{ + return sc_concref_r<sc_concref_r<T1,T2>,sc_bv_base> + ( *a.clone(), *new sc_bv_base( b, 1 ), 3 ); +} + +template <class T1, class T2> +inline +sc_concref_r<sc_bv_base,sc_concref_r<T1,T2> > +concat( bool a, sc_concref_r<T1,T2> b ) +{ + return sc_concref_r<sc_bv_base,sc_concref_r<T1,T2> > + ( *new sc_bv_base( a, 1 ), *b.clone(), 3 ); +} + + +#ifdef SC_DT_MIXED_COMMA_OPERATORS + +template <class T1, class T2> +inline +sc_concref_r<sc_concref_r<T1,T2>,sc_lv_base> +operator , ( sc_concref<T1,T2> a, const char* b ) +{ + return sc_concref_r<sc_concref_r<T1,T2>,sc_lv_base> + ( *a.clone(), *new sc_lv_base( b ), 3 ); +} + +template <class T1, class T2> +inline +sc_concref_r<sc_lv_base,sc_concref_r<T1,T2> > +operator , ( const char* a, sc_concref<T1,T2> b ) +{ + return sc_concref_r<sc_lv_base,sc_concref_r<T1,T2> > + ( *new sc_lv_base( a ), *b.clone(), 3 ); +} + +template <class T1, class T2> +inline +sc_concref_r<sc_concref_r<T1,T2>,sc_lv_base> +operator , ( sc_concref<T1,T2> a, const sc_logic& b ) +{ + return sc_concref_r<sc_concref_r<T1,T2>,sc_lv_base> + ( *a.clone(), *new sc_lv_base( b, 1 ), 3 ); +} + +template <class T1, class T2> +inline +sc_concref_r<sc_lv_base,sc_concref_r<T1,T2> > +operator , ( const sc_logic& a, sc_concref<T1,T2> b ) +{ + return sc_concref_r<sc_lv_base,sc_concref_r<T1,T2> > + ( *new sc_lv_base( a, 1 ), *b.clone(), 3 ); +} + +template <class T1, class T2> +inline +sc_concref_r<sc_concref_r<T1,T2>,sc_bv_base> +operator , ( sc_concref<T1,T2> a, bool b ) +{ + return sc_concref_r<sc_concref_r<T1,T2>,sc_bv_base> + ( *a.clone(), *new sc_bv_base( b, 1 ), 3 ); +} + +template <class T1, class T2> +inline +sc_concref_r<sc_bv_base,sc_concref_r<T1,T2> > +operator , ( bool a, sc_concref<T1,T2> b ) +{ + return sc_concref_r<sc_bv_base,sc_concref_r<T1,T2> > + ( *new sc_bv_base( a, 1 ), *b.clone(), 3 ); +} + + +template <class T1, class T2> +inline +sc_concref_r<sc_concref_r<T1,T2>,sc_lv_base> +concat( sc_concref<T1,T2> a, const char* b ) +{ + return sc_concref_r<sc_concref_r<T1,T2>,sc_lv_base> + ( *a.clone(), *new sc_lv_base( b ), 3 ); +} + +template <class T1, class T2> +inline +sc_concref_r<sc_lv_base,sc_concref_r<T1,T2> > +concat( const char* a, sc_concref<T1,T2> b ) +{ + return sc_concref_r<sc_lv_base,sc_concref_r<T1,T2> > + ( *new sc_lv_base( a ), *b.clone(), 3 ); +} + +template <class T1, class T2> +inline +sc_concref_r<sc_concref_r<T1,T2>,sc_lv_base> +concat( sc_concref<T1,T2> a, const sc_logic& b ) +{ + return sc_concref_r<sc_concref_r<T1,T2>,sc_lv_base> + ( *a.clone(), *new sc_lv_base( b, 1 ), 3 ); +} + +template <class T1, class T2> +inline +sc_concref_r<sc_lv_base,sc_concref_r<T1,T2> > +concat( const sc_logic& a, sc_concref<T1,T2> b ) +{ + return sc_concref_r<sc_lv_base,sc_concref_r<T1,T2> > + ( *new sc_lv_base( a, 1 ), *b.clone(), 3 ); +} + +template <class T1, class T2> +inline +sc_concref_r<sc_concref_r<T1,T2>,sc_bv_base> +concat( sc_concref<T1,T2> a, bool b ) +{ + return sc_concref_r<sc_concref_r<T1,T2>,sc_bv_base> + ( *a.clone(), *new sc_bv_base( b, 1 ), 3 ); +} + +template <class T1, class T2> +inline +sc_concref_r<sc_bv_base,sc_concref_r<T1,T2> > +concat( bool a, sc_concref<T1,T2> b ) +{ + return sc_concref_r<sc_bv_base,sc_concref_r<T1,T2> > + ( *new sc_bv_base( a, 1 ), *b.clone(), 3 ); +} + +#endif + + +// ---------------------------------------------------------------------------- +// CLASS TEMPLATE : sc_proxy<T> +// +// Base class template for bit/logic vector classes. +// (Barton/Nackmann implementation) +// ---------------------------------------------------------------------------- + +// r-value concatenation operators and functions + +template <class T> +inline +sc_concref_r<T,sc_lv_base> +operator , ( const sc_proxy<T>& a, const char* b ) +{ + return sc_concref_r<T,sc_lv_base> + ( a.back_cast(), *new sc_lv_base( b ), 2 ); +} + +template <class T> +inline +sc_concref_r<sc_lv_base,T> +operator , ( const char* a, const sc_proxy<T>& b ) +{ + return sc_concref_r<sc_lv_base,T> + ( *new sc_lv_base( a ), b.back_cast(), 1 ); +} + +template <class T> +inline +sc_concref_r<T,sc_lv_base> +operator , ( const sc_proxy<T>& a, const sc_logic& b ) +{ + return sc_concref_r<T,sc_lv_base> + ( a.back_cast(), *new sc_lv_base( b, 1 ), 2 ); +} + +template <class T> +inline +sc_concref_r<sc_lv_base,T> +operator , ( const sc_logic& a, const sc_proxy<T>& b ) +{ + return sc_concref_r<sc_lv_base,T> + ( *new sc_lv_base( a, 1 ), b.back_cast(), 1 ); +} + +template <class T> +inline +sc_concref_r<T,sc_bv_base> +operator , ( const sc_proxy<T>& a, bool b ) +{ + return sc_concref_r<T,sc_bv_base> + ( a.back_cast(), *new sc_bv_base( b, 1 ), 2 ); +} + +template <class T> +inline +sc_concref_r<sc_bv_base,T> +operator , ( bool a, const sc_proxy<T>& b ) +{ + return sc_concref_r<sc_bv_base,T> + ( *new sc_bv_base( a, 1 ), b.back_cast(), 1 ); +} + + +template <class T> +inline +sc_concref_r<T,sc_lv_base> +concat( const sc_proxy<T>& a, const char* b ) +{ + return sc_concref_r<T,sc_lv_base> + ( a.back_cast(), *new sc_lv_base( b ), 2 ); +} + +template <class T> +inline +sc_concref_r<sc_lv_base,T> +concat( const char* a, const sc_proxy<T>& b ) +{ + return sc_concref_r<sc_lv_base,T> + ( *new sc_lv_base( a ), b.back_cast(), 1 ); +} + +template <class T> +inline +sc_concref_r<T,sc_lv_base> +concat( const sc_proxy<T>& a, const sc_logic& b ) +{ + return sc_concref_r<T,sc_lv_base> + ( a.back_cast(), *new sc_lv_base( b, 1 ), 2 ); +} + +template <class T> +inline +sc_concref_r<sc_lv_base,T> +concat( const sc_logic& a, const sc_proxy<T>& b ) +{ + return sc_concref_r<sc_lv_base,T> + ( *new sc_lv_base( a, 1 ), b.back_cast(), 1 ); +} + +template <class T> +inline +sc_concref_r<T,sc_bv_base> +concat( const sc_proxy<T>& a, bool b ) +{ + return sc_concref_r<T,sc_bv_base> + ( a.back_cast(), *new sc_bv_base( b, 1 ), 2 ); +} + +template <class T> +inline +sc_concref_r<sc_bv_base,T> +concat( bool a, const sc_proxy<T>& b ) +{ + return sc_concref_r<sc_bv_base,T> + ( *new sc_bv_base( a, 1 ), b.back_cast(), 1 ); +} + + +#ifdef SC_DT_MIXED_COMMA_OPERATORS + +template <class T> +inline +sc_concref_r<T,sc_lv_base> +operator , ( sc_proxy<T>& a, const char* b ) +{ + return sc_concref_r<T,sc_lv_base> + ( a.back_cast(), *new sc_lv_base( b ), 2 ); +} + +template <class T> +inline +sc_concref_r<sc_lv_base,T> +operator , ( const char* a, sc_proxy<T>& b ) +{ + return sc_concref_r<sc_lv_base,T> + ( *new sc_lv_base( a ), b.back_cast(), 1 ); +} + +template <class T> +inline +sc_concref_r<T,sc_lv_base> +operator , ( sc_proxy<T>& a, const sc_logic& b ) +{ + return sc_concref_r<T,sc_lv_base> + ( a.back_cast(), *new sc_lv_base( b, 1 ), 2 ); +} + +template <class T> +inline +sc_concref_r<sc_lv_base,T> +operator , ( const sc_logic& a, sc_proxy<T>& b ) +{ + return sc_concref_r<sc_lv_base,T> + ( *new sc_lv_base( a, 1 ), b.back_cast(), 1 ); +} + +template <class T> +inline +sc_concref_r<T,sc_bv_base> +operator , ( sc_proxy<T>& a, bool b ) +{ + return sc_concref_r<T,sc_bv_base> + ( a.back_cast(), *new sc_bv_base( b, 1 ), 2 ); +} + +template <class T> +inline +sc_concref_r<sc_bv_base,T> +operator , ( bool a, sc_proxy<T>& b ) +{ + return sc_concref_r<sc_bv_base,T> + ( *new sc_bv_base( a, 1 ), b.back_cast(), 1 ); +} + + +template <class T> +inline +sc_concref_r<T,sc_lv_base> +concat( sc_proxy<T>& a, const char* b ) +{ + return sc_concref_r<T,sc_lv_base> + ( a.back_cast(), *new sc_lv_base( b ), 2 ); +} + +template <class T> +inline +sc_concref_r<sc_lv_base,T> +concat( const char* a, sc_proxy<T>& b ) +{ + return sc_concref_r<sc_lv_base,T> + ( *new sc_lv_base( a ), b.back_cast(), 1 ); +} + +template <class T> +inline +sc_concref_r<T,sc_lv_base> +concat( sc_proxy<T>& a, const sc_logic& b ) +{ + return sc_concref_r<T,sc_lv_base> + ( a.back_cast(), *new sc_lv_base( b, 1 ), 2 ); +} + +template <class T> +inline +sc_concref_r<sc_lv_base,T> +concat( const sc_logic& a, sc_proxy<T>& b ) +{ + return sc_concref_r<sc_lv_base,T> + ( *new sc_lv_base( a, 1 ), b.back_cast(), 1 ); +} + +template <class T> +inline +sc_concref_r<T,sc_bv_base> +concat( sc_proxy<T>& a, bool b ) +{ + return sc_concref_r<T,sc_bv_base> + ( a.back_cast(), *new sc_bv_base( b, 1 ), 2 ); +} + +template <class T> +inline +sc_concref_r<sc_bv_base,T> +concat( bool a, sc_proxy<T>& b ) +{ + return sc_concref_r<sc_bv_base,T> + ( *new sc_bv_base( a, 1 ), b.back_cast(), 1 ); +} + +#endif + +} // namespace sc_dt + + +#endif diff --git a/ext/systemc/src/sysc/datatypes/bit/sc_proxy.h b/ext/systemc/src/sysc/datatypes/bit/sc_proxy.h new file mode 100644 index 000000000..7c67b447d --- /dev/null +++ b/ext/systemc/src/sysc/datatypes/bit/sc_proxy.h @@ -0,0 +1,1609 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_proxy.h -- Proxy base class for vector data types. + + This class is created for several purposes: + 1) hiding operators from the global namespace that would be + otherwise found by Koenig lookup + 2) avoiding repeating the same operations in every class + including proxies that could also be achieved by common + base class, but this method allows + 3) improve performance by using non-virtual functions + + Original Author: Gene Bushuyev, Synopsys, Inc. + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + +// $Log: sc_proxy.h,v $ +// Revision 1.3 2010/12/07 20:09:07 acg +// Andy Goodrich: Fix for returning enough data +// +// Revision 1.2 2009/02/28 00:26:14 acg +// Andy Goodrich: bug fixes. +// +// Revision 1.1.1.1 2006/12/15 20:31:36 acg +// SystemC 2.2 +// +// Revision 1.3 2006/01/13 18:53:53 acg +// Andy Goodrich: added $Log command so that CVS comments are reproduced in +// the source. +// + +#ifndef SC_PROXY_H +#define SC_PROXY_H + + +#include "sysc/kernel/sc_cmnhdr.h" +#include "sysc/utils/sc_iostream.h" +#include "sysc/datatypes/int/sc_signed.h" +#include "sysc/datatypes/int/sc_unsigned.h" +#include "sysc/datatypes/int/sc_int_base.h" +#include "sysc/datatypes/int/sc_uint_base.h" +#include "sysc/datatypes/bit/sc_bit.h" +#include "sysc/datatypes/bit/sc_bit_ids.h" +#include "sysc/datatypes/bit/sc_logic.h" +#include "sysc/kernel/sc_macros.h" + + +namespace sc_dt +{ + +// classes defined in this module +template <class X> class sc_proxy; + +// forward class declarations +class sc_bv_base; +class sc_lv_base; +template <class X> class sc_bitref_r; +template <class X> class sc_bitref; +template <class X> class sc_subref_r; +template <class X> class sc_subref; +template <class X, class Y> class sc_concref_r; +template <class X, class Y> class sc_concref; + + +const int SC_DIGIT_SIZE = BITS_PER_BYTE * sizeof( sc_digit ); + +const sc_digit SC_DIGIT_ZERO = (sc_digit)0; +const sc_digit SC_DIGIT_ONE = (sc_digit)1; +const sc_digit SC_DIGIT_TWO = (sc_digit)2; + + +// assignment functions; forward declarations + +template <class X, class Y> +inline +void +assign_p_( sc_proxy<X>& px, const sc_proxy<Y>& py ); + +// Vector types that are not derived from sc_proxy must have a length() +// function and an operator []. + +template <class X, class T> +inline +void +assign_v_( sc_proxy<X>& px, const T& a ); + + +// other functions; forward declarations + +const std::string convert_to_bin( const char* s ); +const std::string convert_to_fmt( const std::string& s, sc_numrep numrep, bool ); + +// ---------------------------------------------------------------------------- +// CLASS TEMPLATE : sc_proxy_traits +// +// Template traits helper to select the correct bit/value/vector_types for +// sc_proxy-based vector classes. +// +// All types derived from/based on a bit-vector contain typedef to a plain bool, +// all others point to the sc_logic_value_t/sc_logic/sc_lv_base types. +// ---------------------------------------------------------------------------- + +template<typename X> struct sc_proxy_traits; + +template<> struct sc_proxy_traits<sc_bv_base> +{ + typedef sc_proxy_traits<sc_bv_base> traits_type; + typedef bool value_type; + typedef bool bit_type; + typedef sc_bv_base vector_type; + typedef traits_type type; +}; + +template<> struct sc_proxy_traits<sc_lv_base> +{ + typedef sc_proxy_traits<sc_lv_base> traits_type; + typedef sc_logic_value_t value_type; + typedef sc_logic bit_type; + typedef sc_lv_base vector_type; + typedef traits_type type; +}; + + +template<typename X> struct sc_proxy_traits<sc_bitref_r<X> > + : sc_proxy_traits<X> {}; + +template<typename X> struct sc_proxy_traits<sc_bitref<X> > + : sc_proxy_traits<X> {}; + + +template<typename X> struct sc_proxy_traits<sc_subref_r<X> > + : sc_proxy_traits<X> {}; + +template<typename X> struct sc_proxy_traits<sc_subref<X> > + : sc_proxy_traits<X> {}; + + +template<typename X> struct sc_proxy_traits<sc_proxy<X> > + : sc_proxy_traits<X> {}; + + +template< typename X, typename Y > struct sc_mixed_proxy_traits_helper + : sc_proxy_traits<sc_lv_base> {}; // logic vector by default + +template<typename X> struct sc_mixed_proxy_traits_helper<X,X> + : X {}; + + +template<typename X, typename Y> struct sc_proxy_traits< sc_concref_r<X,Y> > + : sc_mixed_proxy_traits_helper< typename X::traits_type::type + , typename Y::traits_type::type > +{}; + +template<typename X, typename Y> struct sc_proxy_traits<sc_concref<X,Y> > + : sc_mixed_proxy_traits_helper< typename X::traits_type::type + , typename Y::traits_type::type > +{}; + + +// ---------------------------------------------------------------------------- +// CLASS TEMPLATE : sc_proxy +// +// Base class template for bit/logic vector classes. +// (Barton/Nackmann implementation) +// ---------------------------------------------------------------------------- + +template <class X> +class sc_proxy // #### : public sc_value_base +{ +public: + typedef typename sc_proxy_traits<X>::type traits_type; + typedef typename traits_type::bit_type bit_type; + + // virtual destructor + + virtual ~sc_proxy() {} + + + // casts + + X& back_cast() + { return SCAST<X&>( *this ); } + + const X& back_cast() const + { return SCAST<const X&>( *this ); } + + + // assignment operators + + template <class Y> + X& assign_( const sc_proxy<Y>& a ) + { assign_p_( *this, a ); return back_cast(); } + + X& assign_( const char* a ); + X& assign_( const bool* a ); + X& assign_( const sc_logic* a ); + + X& assign_( const sc_unsigned& a ) + { assign_v_( *this, a ); return back_cast(); } + + X& assign_( const sc_signed& a ) + { assign_v_( *this, a ); return back_cast(); } + + X& assign_( const sc_uint_base& a ) + { return assign_( (uint64) a ); } + + X& assign_( const sc_int_base& a ) + { return assign_( (int64) a ); } + + X& assign_( unsigned int a ); + X& assign_( int a ); + + X& assign_( unsigned long a ); + + X& assign_( long a ); + + X& assign_( uint64 a ); + X& assign_( int64 a ); + + + // bitwise operators and functions + + // bitwise complement + + X& b_not(); + + const sc_lv_base operator ~ () const; + + + // bitwise and + + X& operator &= ( const char* b ); + X& operator &= ( const bool* b ); + X& operator &= ( const sc_logic* b ); + X& operator &= ( const sc_unsigned& b ); + X& operator &= ( const sc_signed& b ); + + X& operator &= ( const sc_uint_base& b ) + { return operator &= ( (uint64) b ); } + + X& operator &= ( const sc_int_base& b ) + { return operator &= ( (int64) b ); } + + X& operator &= ( unsigned long b ); + X& operator &= ( long b ); + + X& operator &= ( unsigned int b ) + { return operator &= ( (unsigned long) b ); } + + X& operator &= ( int b ) + { return operator &= ( (long) b ); } + + X& operator &= ( uint64 b ); + X& operator &= ( int64 b ); + + + const sc_lv_base operator & ( const char* b ) const; + const sc_lv_base operator & ( const bool* b ) const; + const sc_lv_base operator & ( const sc_logic* b ) const; + const sc_lv_base operator & ( const sc_unsigned& b ) const; + const sc_lv_base operator & ( const sc_signed& b ) const; + const sc_lv_base operator & ( const sc_uint_base& b ) const; + const sc_lv_base operator & ( const sc_int_base& b ) const; + const sc_lv_base operator & ( unsigned long b ) const; + const sc_lv_base operator & ( long b ) const; + const sc_lv_base operator & ( unsigned int b ) const; + const sc_lv_base operator & ( int b ) const; + const sc_lv_base operator & ( uint64 b ) const; + const sc_lv_base operator & ( int64 b ) const; + + + // bitwise or + + X& operator |= ( const char* b ); + X& operator |= ( const bool* b ); + X& operator |= ( const sc_logic* b ); + X& operator |= ( const sc_unsigned& b ); + X& operator |= ( const sc_signed& b ); + + X& operator |= ( const sc_uint_base& b ) + { return operator |= ( (uint64) b ); } + + X& operator |= ( const sc_int_base& b ) + { return operator |= ( (int64) b ); } + + X& operator |= ( unsigned long b ); + X& operator |= ( long b ); + + X& operator |= ( unsigned int b ) + { return operator |= ( (unsigned long) b ); } + + X& operator |= ( int b ) + { return operator |= ( (long) b ); } + + X& operator |= ( uint64 b ); + X& operator |= ( int64 b ); + + + const sc_lv_base operator | ( const char* b ) const; + const sc_lv_base operator | ( const bool* b ) const; + const sc_lv_base operator | ( const sc_logic* b ) const; + const sc_lv_base operator | ( const sc_unsigned& b ) const; + const sc_lv_base operator | ( const sc_signed& b ) const; + const sc_lv_base operator | ( const sc_uint_base& b ) const; + const sc_lv_base operator | ( const sc_int_base& b ) const; + const sc_lv_base operator | ( unsigned long b ) const; + const sc_lv_base operator | ( long b ) const; + const sc_lv_base operator | ( unsigned int b ) const; + const sc_lv_base operator | ( int b ) const; + const sc_lv_base operator | ( uint64 b ) const; + const sc_lv_base operator | ( int64 b ) const; + + + // bitwise xor + + X& operator ^= ( const char* b ); + X& operator ^= ( const bool* b ); + X& operator ^= ( const sc_logic* b ); + X& operator ^= ( const sc_unsigned& b ); + X& operator ^= ( const sc_signed& b ); + + X& operator ^= ( const sc_uint_base& b ) + { return operator ^= ( (uint64) b ); } + + X& operator ^= ( const sc_int_base& b ) + { return operator ^= ( (int64) b ); } + + X& operator ^= ( unsigned long b ); + X& operator ^= ( long b ); + + X& operator ^= ( unsigned int b ) + { return operator ^= ( (unsigned long) b ); } + + X& operator ^= ( int b ) + { return operator ^= ( (long) b ); } + + X& operator ^= ( uint64 b ); + X& operator ^= ( int64 b ); + + + const sc_lv_base operator ^ ( const char* b ) const; + const sc_lv_base operator ^ ( const bool* b ) const; + const sc_lv_base operator ^ ( const sc_logic* b ) const; + const sc_lv_base operator ^ ( const sc_unsigned& b ) const; + const sc_lv_base operator ^ ( const sc_signed& b ) const; + const sc_lv_base operator ^ ( const sc_uint_base& b ) const; + const sc_lv_base operator ^ ( const sc_int_base& b ) const; + const sc_lv_base operator ^ ( unsigned long b ) const; + const sc_lv_base operator ^ ( long b ) const; + const sc_lv_base operator ^ ( unsigned int b ) const; + const sc_lv_base operator ^ ( int b ) const; + const sc_lv_base operator ^ ( uint64 b ) const; + const sc_lv_base operator ^ ( int64 b ) const; + + + // bitwise left shift + + X& operator <<= ( int n ); + + const sc_lv_base operator << ( int n ) const; + + + // bitwise right shift + + X& operator >>= ( int n ); + + const sc_lv_base operator >> ( int n ) const; + + + // bitwise left rotate + + X& lrotate( int n ); + + + // bitwise right rotate + + X& rrotate( int n ); + + + // bitwise reverse + + X& reverse(); + + + // bit selection + + sc_bitref<X> operator [] ( int i ) + { return sc_bitref<X>( back_cast(), i ); } + + sc_bitref_r<X> operator [] ( int i ) const + { return sc_bitref_r<X>( back_cast(), i ); } + + sc_bitref<X> bit( int i ) + { return sc_bitref<X>( back_cast(), i ); } + + sc_bitref_r<X> bit( int i ) const + { return sc_bitref_r<X>( back_cast(), i ); } + + + // part selection + + sc_subref<X> operator () ( int hi, int lo ) + { return sc_subref<X>( back_cast(), hi, lo ); } + + sc_subref_r<X> operator () ( int hi, int lo ) const + { return sc_subref_r<X>( back_cast(), hi, lo ); } + + sc_subref<X> range( int hi, int lo ) + { return sc_subref<X>( back_cast(), hi, lo ); } + + sc_subref_r<X> range( int hi, int lo ) const + { return sc_subref_r<X>( back_cast(), hi, lo ); } + + + // reduce functions + + sc_logic_value_t and_reduce() const; + + sc_logic_value_t nand_reduce() const + { return sc_logic::not_table[and_reduce()]; } + + sc_logic_value_t or_reduce() const; + + sc_logic_value_t nor_reduce() const + { return sc_logic::not_table[or_reduce()]; } + + sc_logic_value_t xor_reduce() const; + + sc_logic_value_t xnor_reduce() const + { return sc_logic::not_table[xor_reduce()]; } + + + // relational operators + + bool operator == ( const char* b ) const; + bool operator == ( const bool* b ) const; + bool operator == ( const sc_logic* b ) const; + bool operator == ( const sc_unsigned& b ) const; + bool operator == ( const sc_signed& b ) const; + bool operator == ( const sc_uint_base& b ) const; + bool operator == ( const sc_int_base& b ) const; + bool operator == ( unsigned long b ) const; + bool operator == ( long b ) const; + bool operator == ( unsigned int b ) const; + bool operator == ( int b ) const; + bool operator == ( uint64 b ) const; + bool operator == ( int64 b ) const; + + + // explicit conversions to character string + + const std::string to_string() const; + const std::string to_string( sc_numrep ) const; + const std::string to_string( sc_numrep, bool ) const; + + + // explicit conversions + + inline int64 to_int64() const + { return to_anything_signed(); } + inline uint64 to_uint64() const; + int to_int() const + { return (int)to_anything_signed(); } + + unsigned int to_uint() const + { return (unsigned int)to_anything_unsigned(); } + + long to_long() const + { return (long)to_anything_signed(); } + + unsigned long to_ulong() const + { return (unsigned long)to_anything_unsigned(); } + +#ifdef SC_DT_DEPRECATED + + int to_signed() const + { return to_int(); } + + sc_digit to_unsigned() const + { return to_uint(); } + +#endif + + + // other methods + + void print( ::std::ostream& os = ::std::cout ) const + { + // the test below will force printing in binary if decimal is + // specified. + if ( sc_io_base(os, SC_DEC) == SC_DEC ) + os << to_string(); + else + os << to_string(sc_io_base(os,SC_BIN),sc_io_show_base(os)); + } + + void scan( ::std::istream& is = ::std::cin ); + +protected: + + void check_bounds( int n ) const; // check if bit n accessible + void check_wbounds( int n ) const; // check if word n accessible + + sc_digit to_anything_unsigned() const; + int64 to_anything_signed() const; +}; + + +// ---------------------------------------------------------------------------- + +// bitwise operators and functions + +// bitwise and + +template <class X, class Y> +inline +X& +operator &= ( sc_proxy<X>& px, const sc_proxy<Y>& py ); + + +template <class X, class Y> +inline +const sc_lv_base +operator & ( const sc_proxy<X>& px, const sc_proxy<Y>& py ); + + +#define DECL_BITWISE_AND_OP_T(tp) \ +template <class X> \ +inline \ +const sc_lv_base \ +operator & ( tp b, const sc_proxy<X>& px ); + +DECL_BITWISE_AND_OP_T(const char*) +DECL_BITWISE_AND_OP_T(const bool*) +DECL_BITWISE_AND_OP_T(const sc_logic*) +DECL_BITWISE_AND_OP_T(const sc_unsigned&) +DECL_BITWISE_AND_OP_T(const sc_signed&) +DECL_BITWISE_AND_OP_T(const sc_uint_base&) +DECL_BITWISE_AND_OP_T(const sc_int_base&) +DECL_BITWISE_AND_OP_T(unsigned long) +DECL_BITWISE_AND_OP_T(long) +DECL_BITWISE_AND_OP_T(unsigned int) +DECL_BITWISE_AND_OP_T(int) +DECL_BITWISE_AND_OP_T(uint64) +DECL_BITWISE_AND_OP_T(int64) + +#undef DECL_BITWISE_AND_OP_T + + +// bitwise or + +template <class X, class Y> +inline +X& +operator |= ( sc_proxy<X>& px, const sc_proxy<Y>& py ); + + +template <class X, class Y> +inline +const sc_lv_base +operator | ( const sc_proxy<X>& px, const sc_proxy<Y>& py ); + + +#define DECL_BITWISE_OR_OP_T(tp) \ +template <class X> \ +inline \ +const sc_lv_base \ +operator | ( tp a, const sc_proxy<X>& px ); + +DECL_BITWISE_OR_OP_T(const char*) +DECL_BITWISE_OR_OP_T(const bool*) +DECL_BITWISE_OR_OP_T(const sc_logic*) +DECL_BITWISE_OR_OP_T(const sc_unsigned&) +DECL_BITWISE_OR_OP_T(const sc_signed&) +DECL_BITWISE_OR_OP_T(const sc_uint_base&) +DECL_BITWISE_OR_OP_T(const sc_int_base&) +DECL_BITWISE_OR_OP_T(unsigned long) +DECL_BITWISE_OR_OP_T(long) +DECL_BITWISE_OR_OP_T(unsigned int) +DECL_BITWISE_OR_OP_T(int) +DECL_BITWISE_OR_OP_T(uint64) +DECL_BITWISE_OR_OP_T(int64) + +#undef DECL_BITWISE_OR_OP_T + + +// bitwise xor + +template <class X, class Y> +inline +X& +operator ^= ( sc_proxy<X>& px, const sc_proxy<Y>& py ); + + +template <class X, class Y> +inline +const sc_lv_base +operator ^ ( const sc_proxy<X>& px, const sc_proxy<Y>& py ); + + +#define DECL_BITWISE_XOR_OP_T(tp) \ +template <class X> \ +inline \ +const sc_lv_base \ +operator ^ ( tp a, const sc_proxy<X>& px ); + +DECL_BITWISE_XOR_OP_T(const char*) +DECL_BITWISE_XOR_OP_T(const bool*) +DECL_BITWISE_XOR_OP_T(const sc_logic*) +DECL_BITWISE_XOR_OP_T(const sc_unsigned&) +DECL_BITWISE_XOR_OP_T(const sc_signed&) +DECL_BITWISE_XOR_OP_T(const sc_uint_base&) +DECL_BITWISE_XOR_OP_T(const sc_int_base&) +DECL_BITWISE_XOR_OP_T(unsigned long) +DECL_BITWISE_XOR_OP_T(long) +DECL_BITWISE_XOR_OP_T(unsigned int) +DECL_BITWISE_XOR_OP_T(int) +DECL_BITWISE_XOR_OP_T(uint64) +DECL_BITWISE_XOR_OP_T(int64) + +#undef DECL_BITWISE_XOR_OP_T + + +// relational operators + +template <class X, class Y> +inline +bool +operator == ( const sc_proxy<X>& px, const sc_proxy<Y>& py ); + +template <class X, class Y> +inline +bool +operator != ( const sc_proxy<X>& px, const sc_proxy<Y>& py ); + + +#define DECL_REL_OP_T(tp) \ +template <class X> \ +inline \ +bool \ +operator == ( tp b, const sc_proxy<X>& px ); \ + \ +template <class X> \ +inline \ +bool \ +operator != ( const sc_proxy<X>& px, tp b ); \ + \ +template <class X> \ +inline \ +bool \ +operator != ( tp b, const sc_proxy<X>& px ); + +DECL_REL_OP_T(const char*) +DECL_REL_OP_T(const bool*) +DECL_REL_OP_T(const sc_logic*) +DECL_REL_OP_T(const sc_unsigned&) +DECL_REL_OP_T(const sc_signed&) +DECL_REL_OP_T(const sc_uint_base&) +DECL_REL_OP_T(const sc_int_base&) +DECL_REL_OP_T(unsigned long) +DECL_REL_OP_T(long) +DECL_REL_OP_T(unsigned int) +DECL_REL_OP_T(int) +DECL_REL_OP_T(uint64) +DECL_REL_OP_T(int64) + +#undef DECL_REL_OP_T + + +// l-value concatenation + +// Due to the fact that temporary objects cannot be passed to non-const +// references, we have to enumerate, use call by value, and use dynamic +// memory allocation (and deallocation). + + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + +template <class X> +inline +void +get_words_( const X& x, int wi, sc_digit& x_dw, sc_digit& x_cw ) +{ + x_dw = x.get_word( wi ); + x_cw = x.get_cword( wi ); +} + +template <class X> +inline +void +set_words_( X& x, int wi, sc_digit x_dw, sc_digit x_cw ) +{ + x.set_word( wi, x_dw ); + x.set_cword( wi, x_cw ); +} + +template <class X> +inline +void +extend_sign_w_( X& x, int wi, bool sign ) +{ + int sz = x.size(); + unsigned int sgn = (sign ? ~SC_DIGIT_ZERO : SC_DIGIT_ZERO); + for( int i = wi; i < sz; ++ i ) { + set_words_( x, i, sgn, SC_DIGIT_ZERO ); + } +} + + +// assignment functions + +template <class X, class Y> +inline +void +assign_p_( sc_proxy<X>& px, const sc_proxy<Y>& py ) +{ + if( (void*) &px != (void*) &py ) { + X& x = px.back_cast(); + const Y& y = py.back_cast(); + int sz = x.size(); + int min_sz = sc_min( sz, y.size() ); + int i = 0; + for( ; i < min_sz; ++ i ) { + set_words_( x, i, y.get_word( i ), y.get_cword( i ) ); + } + // extend with zeros + extend_sign_w_( x, i, false ); + x.clean_tail(); + } +} + +// Vector types that are not derived from sc_proxy, sc_int_base, +// sc_uint_base, sc_signed, or sc_unsigned, must have a length() +// function and an operator []. The vector argument type must support +// accessing bits that are beyond the msb. The vector argument type +// decides what to do there (e.g. sign extension or zero padding). + +template <class X, class T> +inline +void +assign_v_( sc_proxy<X>& px, const T& a ) +{ + X& x = px.back_cast(); + int i; + int len_x = x.length(); + int len_a = a.length(); + if ( len_a > len_x ) len_a = len_x; + for( i = 0 ; i < len_a; ++ i ) { + x.set_bit( i, sc_logic_value_t( (bool) a[i] ) ); + } + for( ; i < len_x; ++ i ) { + x.set_bit( i, sc_logic_value_t( false ) ); + } +} + +template <class X> +inline +void +assign_v_( sc_proxy<X>& px, const sc_int_base& a ) +{ + X& x = px.back_cast(); + int i; + bool sign = a < 0; + int len_x = x.length(); + int len_a = a.length(); + if ( len_a > len_x ) len_a = len_x; + for( i = 0 ; i < len_a; ++ i ) { + x.set_bit( i, sc_logic_value_t( (bool) a[i] ) ); + } + for( ; i < len_x; ++ i ) { + x.set_bit( i, sc_logic_value_t( sign ) ); + } +} + +template <class X> +inline +void +assign_v_( sc_proxy<X>& px, const sc_signed& a ) +{ + X& x = px.back_cast(); + int i; + bool sign = a < 0; + int len_x = x.length(); + int len_a = a.length(); + if ( len_a > len_x ) len_a = len_x; + for( i = 0 ; i < len_a; ++ i ) { + x.set_bit( i, sc_logic_value_t( (bool) a[i] ) ); + } + for( ; i < len_x; ++ i ) { + x.set_bit( i, sc_logic_value_t( sign ) ); + } +} + +template <class X> +inline +void +assign_v_( sc_proxy<X>& px, const sc_uint_base& a ) +{ + X& x = px.back_cast(); + int i; + int len_x = x.length(); + int len_a = a.length(); + if ( len_a > len_x ) len_a = len_x; + for( i = 0 ; i < len_a; ++ i ) { + x.set_bit( i, sc_logic_value_t( (bool) a[i] ) ); + } + for( ; i < len_x; ++ i ) { + x.set_bit( i, sc_logic_value_t( false ) ); + } +} + +template <class X> +inline +void +assign_v_( sc_proxy<X>& px, const sc_unsigned& a ) +{ + X& x = px.back_cast(); + int i; + int len_x = x.length(); + int len_a = a.length(); + if ( len_a > len_x ) len_a = len_x; + for( i = 0 ; i < len_a; ++ i ) { + x.set_bit( i, sc_logic_value_t( (bool) a[i] ) ); + } + for( ; i < len_x; ++ i ) { + x.set_bit( i, sc_logic_value_t( false ) ); + } +} + + +// assignment operators + +template <class X> +inline +X& +sc_proxy<X>::assign_( const char* a ) +{ + X& x = back_cast(); + std::string s = convert_to_bin( a ); + int len = x.length(); + int s_len = s.length() - 1; + int min_len = sc_min( len, s_len ); + int i = 0; + for( ; i < min_len; ++ i ) { + char c = s[s_len - i - 1]; + x.set_bit( i, sc_logic::char_to_logic[(int)c] ); + } + // if formatted, fill the rest with sign(s), otherwise fill with zeros + sc_logic_value_t fill = (s[s_len] == 'F' ? sc_logic_value_t( s[0] - '0' ) + : sc_logic_value_t( 0 )); + for( ; i < len; ++ i ) { + x.set_bit( i, fill ); + } + return x; +} + +template <class X> +inline +X& +sc_proxy<X>::assign_( const bool* a ) +{ + // the length of 'a' must be larger than or equal to the length of 'this' + X& x = back_cast(); + int len = x.length(); + for( int i = 0; i < len; ++ i ) { + x.set_bit( i, sc_logic_value_t( a[i] ) ); + } + return x; +} + +template <class X> +inline +X& +sc_proxy<X>::assign_( const sc_logic* a ) +{ + // the length of 'a' must be larger than or equal to the length of 'this' + X& x = back_cast(); + int len = x.length(); + for( int i = 0; i < len; ++ i ) { + x.set_bit( i, a[i].value() ); + } + return x; +} + +template <class X> +inline +X& +sc_proxy<X>::assign_( unsigned int a ) +{ + X& x = back_cast(); + set_words_( x, 0, (sc_digit)a, SC_DIGIT_ZERO ); + // extend with zeros + extend_sign_w_( x, 1, false ); + x.clean_tail(); + return x; +} + +template <class X> +inline +X& +sc_proxy<X>::assign_( int a ) +{ + X& x = back_cast(); + set_words_( x, 0, (sc_digit) a, SC_DIGIT_ZERO ); + // extend with sign(a) + extend_sign_w_( x, 1, (a < 0) ); + x.clean_tail(); + return x; +} + +#if defined(SC_LONG_64) + template <class X> + inline + X& + sc_proxy<X>::assign_( unsigned long a ) + { + X& x = back_cast(); + set_words_( x, 0, ((sc_digit) a & ~SC_DIGIT_ZERO), SC_DIGIT_ZERO ); + if( x.size() > 1 ) { + set_words_( x, 1, + ((sc_digit) (a >> SC_DIGIT_SIZE) & ~SC_DIGIT_ZERO), + SC_DIGIT_ZERO ); + // extend with zeros + extend_sign_w_( x, 2, false ); + } + x.clean_tail(); + return x; + } + + template <class X> + inline + X& + sc_proxy<X>::assign_( long a ) + { + X& x = back_cast(); + set_words_( x, 0, ((sc_digit) a & ~SC_DIGIT_ZERO), SC_DIGIT_ZERO ); + if( x.size() > 1 ) { + set_words_( x, 1, + ((sc_digit) ((uint64) a >> SC_DIGIT_SIZE) & ~SC_DIGIT_ZERO), + SC_DIGIT_ZERO ); + // extend with sign(a) + extend_sign_w_( x, 2, (a < 0) ); + } + x.clean_tail(); + return x; + } + +#else + template <class X> + inline + X& + sc_proxy<X>::assign_( unsigned long a ) + { + X& x = back_cast(); + set_words_( x, 0, (sc_digit)a, SC_DIGIT_ZERO ); + // extend with zeros + extend_sign_w_( x, 1, false ); + x.clean_tail(); + return x; + } + + template <class X> + inline + X& + sc_proxy<X>::assign_( long a ) + { + X& x = back_cast(); + set_words_( x, 0, (sc_digit) a, SC_DIGIT_ZERO ); + // extend with sign(a) + extend_sign_w_( x, 1, (a < 0) ); + x.clean_tail(); + return x; + } +#endif +template <class X> +inline +X& +sc_proxy<X>::assign_( uint64 a ) +{ + X& x = back_cast(); + set_words_( x, 0, ((sc_digit) a & ~SC_DIGIT_ZERO), SC_DIGIT_ZERO ); + if( x.size() > 1 ) { + set_words_( x, 1, + ((sc_digit) (a >> SC_DIGIT_SIZE) & ~SC_DIGIT_ZERO), + SC_DIGIT_ZERO ); + // extend with zeros + extend_sign_w_( x, 2, false ); + } + x.clean_tail(); + return x; +} + +template <class X> +inline +X& +sc_proxy<X>::assign_( int64 a ) +{ + X& x = back_cast(); + set_words_( x, 0, ((sc_digit) a & ~SC_DIGIT_ZERO), SC_DIGIT_ZERO ); + if( x.size() > 1 ) { + set_words_( x, 1, + ((sc_digit) ((uint64) a >> SC_DIGIT_SIZE) & ~SC_DIGIT_ZERO), + SC_DIGIT_ZERO ); + // extend with sign(a) + extend_sign_w_( x, 2, (a < 0) ); + } + x.clean_tail(); + return x; +} + + +// bitwise operators and functions + +// bitwise complement + +template <class X> +inline +X& +sc_proxy<X>::b_not() +{ + X& x = back_cast(); + int sz = x.size(); + for( int i = 0; i < sz; ++ i ) { + sc_digit x_dw, x_cw; + get_words_( x, i, x_dw, x_cw ); + x.set_word( i, x_cw | ~x_dw ); + } + x.clean_tail(); + return x; +} + + +// bitwise and + +template <class X, class Y> +inline +X& +b_and_assign_( sc_proxy<X>& px, const sc_proxy<Y>& py ) +{ + X& x = px.back_cast(); + const Y& y = py.back_cast(); + assert( x.length() == y.length() ); + int sz = x.size(); + for( int i = 0; i < sz; ++ i ) { + sc_digit x_dw, x_cw, y_dw, y_cw; + get_words_( x, i, x_dw, x_cw ); + get_words_( y, i, y_dw, y_cw ); + sc_digit cw = (x_dw & y_cw) | (x_cw & y_dw) | (x_cw & y_cw); + sc_digit dw = cw | (x_dw & y_dw); + set_words_( x, i, dw, cw ); + } + // tail cleaning not needed + return x; +} + + +// bitwise or + +template <class X, class Y> +inline +X& +b_or_assign_( sc_proxy<X>& px, const sc_proxy<Y>& py ) +{ + X& x = px.back_cast(); + const Y& y = py.back_cast(); + assert( x.length() == y.length() ); + int sz = x.size(); + for( int i = 0; i < sz; ++ i ) { + sc_digit x_dw, x_cw, y_dw, y_cw; + get_words_( x, i, x_dw, x_cw ); + get_words_( y, i, y_dw, y_cw ); + sc_digit cw = (x_cw & y_cw) | (x_cw & ~y_dw) | (~x_dw & y_cw); + sc_digit dw = cw | x_dw | y_dw; + set_words_( x, i, dw, cw ); + } + // tail cleaning not needed + return x; +} + + +// bitwise xor + +template <class X, class Y> +inline +X& +b_xor_assign_( sc_proxy<X>& a, const sc_proxy<Y>& b ) +{ + X& x = a.back_cast(); + const Y& y = b.back_cast(); + assert( x.length() == y.length() ); + int sz = x.size(); + for( int i = 0; i < sz; ++ i ) { + sc_digit x_dw, x_cw, y_dw, y_cw; + get_words_( x, i, x_dw, x_cw ); + get_words_( y, i, y_dw, y_cw ); + sc_digit cw = x_cw | y_cw; + sc_digit dw = cw | (x_dw ^ y_dw); + set_words_( x, i, dw, cw ); + } + // tail cleaning not needed + return x; +} + + +// bitwise left shift + +template <class X> +inline +X& +sc_proxy<X>::operator <<= ( int n ) +{ + X& x = back_cast(); + if( n < 0 ) { + char msg[BUFSIZ]; + std::sprintf( msg, + "left shift operation is only allowed with positive " + "shift values, shift value = %d", n ); + SC_REPORT_ERROR( sc_core::SC_ID_OUT_OF_BOUNDS_, msg ); + } + if( n >= x.length() ) { + extend_sign_w_( x, 0, false ); + // no tail cleaning needed + return x; + } + int sz = x.size(); + int wn = n / SC_DIGIT_SIZE; + int bn = n % SC_DIGIT_SIZE; + if( wn != 0 ) { + // shift words + int i = sz - 1; + for( ; i >= wn; -- i ) { + set_words_( x, i, x.get_word( i - wn ), x.get_cword( i - wn ) ); + } + for( ; i >= 0; -- i ) { + set_words_( x, i, SC_DIGIT_ZERO, SC_DIGIT_ZERO ); + } + } + if( bn != 0 ) { + // shift bits + for( int i = sz - 1; i >= 1; -- i ) { + sc_digit x_dw, x_cw; + get_words_( x, i, x_dw, x_cw ); + x_dw <<= bn; + x_dw |= x.get_word( i - 1 ) >> (SC_DIGIT_SIZE - bn); + x_cw <<= bn; + x_cw |= x.get_cword( i - 1 ) >> (SC_DIGIT_SIZE - bn); + set_words_( x, i, x_dw, x_cw ); + } + sc_digit x_dw, x_cw; + get_words_( x, 0, x_dw, x_cw ); + x_dw <<= bn; + x_cw <<= bn; + set_words_( x, 0, x_dw, x_cw ); + } + x.clean_tail(); + return x; +} + + +// bitwise right shift + + +template <class X> +inline +X& +sc_proxy<X>::operator >>= ( int n ) +{ + X& x = back_cast(); + if( n < 0 ) { + char msg[BUFSIZ]; + std::sprintf( msg, + "right shift operation is only allowed with positive " + "shift values, shift value = %d", n ); + SC_REPORT_ERROR( sc_core::SC_ID_OUT_OF_BOUNDS_, msg ); + } + if( n >= x.length() ) { + extend_sign_w_( x, 0, false ); + // no tail cleaning needed + return x; + } + int sz = x.size(); + int wn = n / SC_DIGIT_SIZE; + int bn = n % SC_DIGIT_SIZE; + if( wn != 0 ) { + // shift words + int i = 0; + for( ; i < (sz - wn); ++ i ) { + set_words_( x, i, x.get_word( i + wn ), x.get_cword( i + wn ) ); + } + for( ; i < sz; ++ i ) { + set_words_( x, i, SC_DIGIT_ZERO, SC_DIGIT_ZERO ); + } + } + if( bn != 0 ) { + // shift bits + for( int i = 0; i < (sz - 1); ++ i ) { + sc_digit x_dw, x_cw; + get_words_( x, i, x_dw, x_cw ); + x_dw >>= bn; + x_dw |= x.get_word( i + 1 ) << (SC_DIGIT_SIZE - bn); + x_cw >>= bn; + x_cw |= x.get_cword( i + 1 ) << (SC_DIGIT_SIZE - bn); + set_words_( x, i, x_dw, x_cw ); + } + sc_digit x_dw, x_cw; + get_words_( x, sz - 1, x_dw, x_cw ); + x_dw >>= bn; + x_cw >>= bn; + set_words_( x, sz - 1, x_dw, x_cw ); + } + x.clean_tail(); + return x; +} + + +// bitwise left rotate + +template <class X> +inline +const sc_lv_base +lrotate( const sc_proxy<X>& x, int n ); + + +// bitwise right rotate + +template <class X> +inline +const sc_lv_base +rrotate( const sc_proxy<X>& x, int n ); + + +// bitwise reverse + +template <class X> +inline +X& +sc_proxy<X>::reverse() +{ + X& x = back_cast(); + int len = x.length(); + int half_len = len / 2; + for( int i = 0, j = len - 1; i < half_len; ++ i, --j ) { + sc_logic_value_t t = x.get_bit( i ); + x.set_bit( i, x.get_bit( j ) ); + x.set_bit( j, t ); + } + return x; +} + +template <class X> +inline +const sc_lv_base +reverse( const sc_proxy<X>& a ); + + +// reduce functions + +template <class X> +inline +sc_logic_value_t +sc_proxy<X>::and_reduce() const +{ + const X& x = back_cast(); + sc_logic_value_t result = sc_logic_value_t( 1 ); + int len = x.length(); + for( int i = 0; i < len; ++ i ) { + result = sc_logic::and_table[result][x.get_bit( i )]; + } + return result; +} + +template <class X> +inline +sc_logic_value_t +sc_proxy<X>::or_reduce() const +{ + const X& x = back_cast(); + sc_logic_value_t result = sc_logic_value_t( 0 ); + int len = x.length(); + for( int i = 0; i < len; ++ i ) { + result = sc_logic::or_table[result][x.get_bit( i )]; + } + return result; +} + +template <class X> +inline +sc_logic_value_t +sc_proxy<X>::xor_reduce() const +{ + const X& x = back_cast(); + sc_logic_value_t result = sc_logic_value_t( 0 ); + int len = x.length(); + for( int i = 0; i < len; ++ i ) { + result = sc_logic::xor_table[result][x.get_bit( i )]; + } + return result; +} + + +// relational operators + +template <class X, class Y> +inline +bool +operator != ( const sc_proxy<X>& px, const sc_proxy<Y>& py ) +{ + return !( px == py ); +} + + +#define DEFN_REL_OP_T(tp) \ +template <class X> \ +inline \ +bool \ +operator == ( tp b, const sc_proxy<X>& px ) \ +{ \ + return ( px == b ); \ +} \ + \ +template <class X> \ +inline \ +bool \ +operator != ( const sc_proxy<X>& px, tp b ) \ +{ \ + return !( px == b ); \ +} \ + \ +template <class X> \ +inline \ +bool \ +operator != ( tp b, const sc_proxy<X>& px ) \ +{ \ + return !( px == b ); \ +} + +DEFN_REL_OP_T(const char*) +DEFN_REL_OP_T(const bool*) +DEFN_REL_OP_T(const sc_logic*) +DEFN_REL_OP_T(const sc_unsigned&) +DEFN_REL_OP_T(const sc_signed&) +DEFN_REL_OP_T(const sc_uint_base&) +DEFN_REL_OP_T(const sc_int_base&) +DEFN_REL_OP_T(unsigned long) +DEFN_REL_OP_T(long) +DEFN_REL_OP_T(unsigned int) +DEFN_REL_OP_T(int) +DEFN_REL_OP_T(uint64) +DEFN_REL_OP_T(int64) + +#undef DEFN_REL_OP_T + + +// explicit conversions to character string + +template <class X> +inline +const std::string +sc_proxy<X>::to_string() const +{ + const X& x = back_cast(); + int len = x.length(); + std::string s; // ( len + 1 ); + for( int i = 0; i < len; ++ i ) { + s += sc_logic::logic_to_char[x.get_bit( len - i - 1 )]; + } + return s; +} + +template <class X> +inline +const std::string +sc_proxy<X>::to_string( sc_numrep numrep ) const +{ + return convert_to_fmt( to_string(), numrep, true ); +} + +template <class X> +inline +const std::string +sc_proxy<X>::to_string( sc_numrep numrep, bool w_prefix ) const +{ + return convert_to_fmt( to_string(), numrep, w_prefix ); +} + + +// other methods + +template <class X> +inline +void +sc_proxy<X>::scan( ::std::istream& is ) +{ + std::string s; + is >> s; + back_cast() = s.c_str(); +} + + +template <class X> +inline +void +sc_proxy<X>::check_bounds( int n ) const // check if bit n accessible +{ + if( n < 0 || n >= back_cast().length() ) { + SC_REPORT_ERROR( sc_core::SC_ID_OUT_OF_BOUNDS_, 0 ); + } +} + +template <class X> +inline +void +sc_proxy<X>::check_wbounds( int n ) const // check if word n accessible +{ + if( n < 0 || n >= back_cast().size() ) { + SC_REPORT_ERROR( sc_core::SC_ID_OUT_OF_BOUNDS_, 0 ); + } +} + + +template <class X> +inline +sc_digit +sc_proxy<X>::to_anything_unsigned() const +{ + // only 0 word is returned + // can't convert logic values other than 0 and 1 + const X& x = back_cast(); + int len = x.length(); + if( x.get_cword( 0 ) != SC_DIGIT_ZERO ) { + SC_REPORT_WARNING( sc_core::SC_ID_VECTOR_CONTAINS_LOGIC_VALUE_, 0 ); + } + sc_digit w = x.get_word( 0 ); + if( len >= SC_DIGIT_SIZE ) { + return w; + } + return ( w & (~SC_DIGIT_ZERO >> (SC_DIGIT_SIZE - len)) ); +} + +template <class X> +inline +uint64 +sc_proxy<X>::to_uint64() const +{ + // words 1 and 0 returned. + // can't convert logic values other than 0 and 1 + const X& x = back_cast(); + int len = x.length(); + if( x.get_cword( 0 ) != SC_DIGIT_ZERO ) { + SC_REPORT_WARNING( sc_core::SC_ID_VECTOR_CONTAINS_LOGIC_VALUE_, 0 ); + } + uint64 w = x.get_word( 0 ); + if( len > SC_DIGIT_SIZE ) + { + if( x.get_cword( 1 ) != SC_DIGIT_ZERO ) { + SC_REPORT_WARNING( sc_core::SC_ID_VECTOR_CONTAINS_LOGIC_VALUE_, 0 ); + } + uint64 w1 = x.get_word( 1 ); + w = w | (w1 << SC_DIGIT_SIZE); + return w; + } + else if( len == SC_DIGIT_SIZE ) + { + return w; + } + else + { + return ( w & (~SC_DIGIT_ZERO >> (SC_DIGIT_SIZE - len)) ); + } +} + +template <class X> +inline +int64 +sc_proxy<X>::to_anything_signed() const +{ + const X& x = back_cast(); + int len = x.length(); + int64 w = 0; + + if( len > SC_DIGIT_SIZE ) + { + if( x.get_cword( 1 ) != SC_DIGIT_ZERO ) + SC_REPORT_WARNING( sc_core::SC_ID_VECTOR_CONTAINS_LOGIC_VALUE_, 0 ); + w = x.get_word(1); + } + if( x.get_cword( 0 ) != SC_DIGIT_ZERO ) + SC_REPORT_WARNING( sc_core::SC_ID_VECTOR_CONTAINS_LOGIC_VALUE_, 0 ); + w = (w << SC_DIGIT_SIZE) | x.get_word( 0 ); + if( len >= 64 ) { + return w; + } + + uint64 zero = 0; + sc_logic_value_t sgn = x.get_bit( len - 1 ); + if( sgn == 0 ) { + return (int64)( w & (~zero >> (64 - len)) ); + } else { + return (int64)( w | (~zero << len) ); + } +} + + +// ---------------------------------------------------------------------------- + +// functional notation for the reduce methods + +template <class X> +inline +sc_logic_value_t +and_reduce( const sc_proxy<X>& a ) +{ + return a.and_reduce(); +} + +template <class X> +inline +sc_logic_value_t +nand_reduce( const sc_proxy<X>& a ) +{ + return a.nand_reduce(); +} + +template <class X> +inline +sc_logic_value_t +or_reduce( const sc_proxy<X>& a ) +{ + return a.or_reduce(); +} + +template <class X> +inline +sc_logic_value_t +nor_reduce( const sc_proxy<X>& a ) +{ + return a.nor_reduce(); +} + +template <class X> +inline +sc_logic_value_t +xor_reduce( const sc_proxy<X>& a ) +{ + return a.xor_reduce(); +} + +template <class X> +inline +sc_logic_value_t +xnor_reduce( const sc_proxy<X>& a ) +{ + return a.xnor_reduce(); +} + + +// ---------------------------------------------------------------------------- + +template <class X> +inline +::std::ostream& +operator << ( ::std::ostream& os, const sc_proxy<X>& a ) +{ + a.print( os ); + return os; +} + +template <class X> +inline +::std::istream& +operator >> ( ::std::istream& is, sc_proxy<X>& a ) +{ + a.scan( is ); + return is; +} + +} // namespace sc_dt + + +#endif diff --git a/ext/systemc/src/sysc/datatypes/fx/fx.h b/ext/systemc/src/sysc/datatypes/fx/fx.h new file mode 100644 index 000000000..9c35014fa --- /dev/null +++ b/ext/systemc/src/sysc/datatypes/fx/fx.h @@ -0,0 +1,61 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + fx.h - Master include file for the fixed-point types. + + Original Author: Martin Janssen, Synopsys, Inc. + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + +// $Log: fx.h,v $ +// Revision 1.1.1.1 2006/12/15 20:20:04 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:53:57 acg +// Andy Goodrich: added $Log command so that CVS comments are reproduced in +// the source. +// + +#ifndef FX_H +#define FX_H + + +#include "sysc/datatypes/fx/sc_fixed.h" +#include "sysc/datatypes/fx/sc_fxcast_switch.h" +#include "sysc/datatypes/fx/sc_fxtype_params.h" +#include "sysc/datatypes/fx/sc_ufixed.h" + +#include "sysc/datatypes/fx/scfx_other_defs.h" + + +#endif + +// Taf! diff --git a/ext/systemc/src/sysc/datatypes/fx/sc_context.h b/ext/systemc/src/sysc/datatypes/fx/sc_context.h new file mode 100644 index 000000000..1e313a486 --- /dev/null +++ b/ext/systemc/src/sysc/datatypes/fx/sc_context.h @@ -0,0 +1,316 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_context.h - + + Original Author: Martin Janssen, Synopsys, Inc. + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + +// $Log: sc_context.h,v $ +// Revision 1.2 2011/08/24 22:05:43 acg +// Torsten Maehne: initialization changes to remove warnings. +// +// Revision 1.1.1.1 2006/12/15 20:20:04 acg +// SystemC 2.3 +// +// Revision 1.5 2006/05/26 20:36:52 acg +// Andy Goodrich: added a using for sc_core::default_ptr_hash_fn to keep HP +// aCC happy. +// +// Revision 1.4 2006/03/21 00:00:31 acg +// Andy Goodrich: changed name of sc_get_current_process_base() to be +// sc_get_current_process_b() since its returning an sc_process_b instance. +// +// Revision 1.3 2006/01/13 18:53:57 acg +// Andy Goodrich: added $Log command so that CVS comments are reproduced in +// the source. +// + +#ifndef SC_CONTEXT_H +#define SC_CONTEXT_H + + +#include "sysc/datatypes/fx/sc_fx_ids.h" +#include "sysc/kernel/sc_simcontext.h" +#include "sysc/utils/sc_hash.h" + + +namespace sc_core { + class sc_process_b; +} + +using sc_core::default_ptr_hash_fn; // To keep HP aCC happy. + +namespace sc_dt +{ + +// classes defined in this module +class sc_without_context; +template <class T> class sc_global; +template <class T> class sc_context; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_without_context +// +// Empty class that is used for its type only. +// ---------------------------------------------------------------------------- + +class sc_without_context {}; + + +// ---------------------------------------------------------------------------- +// TEMPLATE CLASS : sc_global +// +// Template global variable class; singleton; co-routine safe. +// ---------------------------------------------------------------------------- + +template <class T> +class sc_global +{ + + sc_global(); + + void update(); + +public: + + static sc_global<T>* instance(); + + const T*& value_ptr(); + +private: + static sc_global<T>* m_instance; + + sc_core::sc_phash<void*,const T*> m_map; + void* m_proc; // context (current process or NULL) + const T* m_value_ptr; + +}; + + +// ---------------------------------------------------------------------------- +// ENUM : sc_context_begin +// +// Enumeration of context begin options. +// ---------------------------------------------------------------------------- + +enum sc_context_begin +{ + SC_NOW, + SC_LATER +}; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_context +// +// Template context class; co-routine safe. +// ---------------------------------------------------------------------------- + +template <class T> +class sc_context +{ + // disabled + sc_context( const sc_context<T>& ); + void* operator new( std::size_t ); + +public: + + explicit sc_context( const T&, sc_context_begin = SC_NOW ); + ~sc_context(); + + void begin(); + void end(); + + static const T& default_value(); + const T& value() const; + +private: + + const T m_value; + const T*& m_def_value_ptr; + const T* m_old_value_ptr; +}; + + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + +// ---------------------------------------------------------------------------- +// TEMPLATE CLASS : sc_global +// +// Template global variable class; singleton; co-routine safe. +// ---------------------------------------------------------------------------- + +template <class T> +sc_global<T>* sc_global<T>::m_instance = 0; + +template <class T> +inline +sc_global<T>::sc_global() + : m_map() + // use &m_instance as unique "non-process" key (NULL denotes 'sc_main' context) + , m_proc( &m_instance ) + , m_value_ptr( 0 ) +{} + + +template <class T> +inline +void +sc_global<T>::update() +{ + void* p = sc_core::sc_get_current_process_b(); + if( p != m_proc ) + { + const T* vp = m_map[p]; + if( vp == 0 ) + { + vp = new T( sc_without_context() ); + m_map.insert( p, vp ); + } + m_proc = p; + m_value_ptr = vp; + } +} + + +template <class T> +inline +sc_global<T>* +sc_global<T>::instance() +{ + if( m_instance == 0 ) + { + m_instance = new sc_global<T>; + } + return m_instance; +} + + +template <class T> +inline +const T*& +sc_global<T>::value_ptr() +{ + update(); + return m_value_ptr; +} + + +// ---------------------------------------------------------------------------- +// CLASS : sc_context +// +// Template context class; co-routine safe. +// ---------------------------------------------------------------------------- + +template <class T> +inline +sc_context<T>::sc_context( const T& value_, sc_context_begin begin ) +: m_value( value_ ), + m_def_value_ptr( sc_global<T>::instance()->value_ptr() ), + m_old_value_ptr( 0 ) +{ + if( begin == SC_NOW ) + { + m_old_value_ptr = m_def_value_ptr; + m_def_value_ptr = &m_value; + } +} + +template <class T> +inline +sc_context<T>::~sc_context() +{ + if( m_old_value_ptr != 0 ) + { + m_def_value_ptr = m_old_value_ptr; + m_old_value_ptr = 0; + } +} + + +template <class T> +inline +void +sc_context<T>::begin() +{ + if( m_old_value_ptr == 0 ) + { + m_old_value_ptr = m_def_value_ptr; + m_def_value_ptr = &m_value; + } + else + { + SC_REPORT_ERROR( sc_core::SC_ID_CONTEXT_BEGIN_FAILED_, 0 ); + } +} + +template <class T> +inline +void +sc_context<T>::end() +{ + if( m_old_value_ptr != 0 ) + { + m_def_value_ptr = m_old_value_ptr; + m_old_value_ptr = 0; + } + else + { + SC_REPORT_ERROR( sc_core::SC_ID_CONTEXT_END_FAILED_, 0 ); + } +} + + +template <class T> +inline +const T& +sc_context<T>::default_value() +{ + return *sc_global<T>::instance()->value_ptr(); +} + +template <class T> +inline +const T& +sc_context<T>::value() const +{ + return m_value; +} + +} // namespace sc_dt + + +#endif + +// Taf! diff --git a/ext/systemc/src/sysc/datatypes/fx/sc_fix.h b/ext/systemc/src/sysc/datatypes/fx/sc_fix.h new file mode 100644 index 000000000..80df65a2c --- /dev/null +++ b/ext/systemc/src/sysc/datatypes/fx/sc_fix.h @@ -0,0 +1,1938 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_fix.h - + + Original Author: Martin Janssen, Synopsys, Inc. + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + +// $Log: sc_fix.h,v $ +// Revision 1.2 2011/01/19 18:57:40 acg +// Andy Goodrich: changes for IEEE_1666_2011. +// +// Revision 1.1.1.1 2006/12/15 20:20:04 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:53:57 acg +// Andy Goodrich: added $Log command so that CVS comments are reproduced in +// the source. +// + +#ifndef SC_FIX_H +#define SC_FIX_H + + +#include "sysc/datatypes/fx/sc_fxnum.h" + + +namespace sc_dt +{ + +// classes defined in this module +class sc_fix; +class sc_fix_fast; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_fix +// +// "Unconstrained" signed fixed-point class; arbitrary precision. +// ---------------------------------------------------------------------------- + +class sc_fix : public sc_fxnum +{ + +public: + + // constructors + + explicit sc_fix( sc_fxnum_observer* = 0 ); + sc_fix( int, int, + sc_fxnum_observer* = 0 ); + sc_fix( sc_q_mode, sc_o_mode, + sc_fxnum_observer* = 0 ); + sc_fix( sc_q_mode, sc_o_mode, int, + sc_fxnum_observer* = 0 ); + sc_fix( int, int, sc_q_mode, sc_o_mode, + sc_fxnum_observer* = 0 ); + sc_fix( int, int, sc_q_mode, sc_o_mode, int, + sc_fxnum_observer* = 0 ); + explicit sc_fix( const sc_fxcast_switch&, + sc_fxnum_observer* = 0 ); + sc_fix( int, int, + const sc_fxcast_switch&, + sc_fxnum_observer* = 0 ); + sc_fix( sc_q_mode, sc_o_mode, + const sc_fxcast_switch&, + sc_fxnum_observer* = 0 ); + sc_fix( sc_q_mode, sc_o_mode, int, + const sc_fxcast_switch&, + sc_fxnum_observer* = 0 ); + sc_fix( int, int, sc_q_mode, sc_o_mode, + const sc_fxcast_switch&, + sc_fxnum_observer* = 0 ); + sc_fix( int, int, sc_q_mode, sc_o_mode, int, + const sc_fxcast_switch&, + sc_fxnum_observer* = 0 ); + explicit sc_fix( const sc_fxtype_params&, + sc_fxnum_observer* = 0 ); + sc_fix( const sc_fxtype_params&, + const sc_fxcast_switch&, + sc_fxnum_observer* = 0 ); + +#define DECL_CTORS_T(tp) \ + sc_fix( tp, \ + int, int, \ + sc_fxnum_observer* = 0 ); \ + sc_fix( tp, \ + sc_q_mode, sc_o_mode, \ + sc_fxnum_observer* = 0 ); \ + sc_fix( tp, \ + sc_q_mode, sc_o_mode, int, \ + sc_fxnum_observer* = 0 ); \ + sc_fix( tp, \ + int, int, sc_q_mode, sc_o_mode, \ + sc_fxnum_observer* = 0 ); \ + sc_fix( tp, \ + int, int, sc_q_mode, sc_o_mode, int, \ + sc_fxnum_observer* = 0 ); \ + sc_fix( tp, \ + const sc_fxcast_switch&, \ + sc_fxnum_observer* = 0 ); \ + sc_fix( tp, \ + int, int, \ + const sc_fxcast_switch&, \ + sc_fxnum_observer* = 0 ); \ + sc_fix( tp, \ + sc_q_mode, sc_o_mode, \ + const sc_fxcast_switch&, \ + sc_fxnum_observer* = 0 ); \ + sc_fix( tp, \ + sc_q_mode, sc_o_mode, int, \ + const sc_fxcast_switch&, \ + sc_fxnum_observer* = 0 ); \ + sc_fix( tp, \ + int, int, sc_q_mode, sc_o_mode, \ + const sc_fxcast_switch&, \ + sc_fxnum_observer* = 0 ); \ + sc_fix( tp, \ + int, int, sc_q_mode, sc_o_mode, int, \ + const sc_fxcast_switch&, \ + sc_fxnum_observer* = 0 ); \ + sc_fix( tp, \ + const sc_fxtype_params&, \ + sc_fxnum_observer* = 0 ); \ + sc_fix( tp, \ + const sc_fxtype_params&, \ + const sc_fxcast_switch&, \ + sc_fxnum_observer* = 0 ); + +#define DECL_CTORS_T_A(tp) \ + sc_fix( tp, \ + sc_fxnum_observer* = 0 ); \ + DECL_CTORS_T(tp) + +#define DECL_CTORS_T_B(tp) \ + explicit sc_fix( tp, \ + sc_fxnum_observer* = 0 ); \ + DECL_CTORS_T(tp) + + DECL_CTORS_T_A(int) + DECL_CTORS_T_A(unsigned int) + DECL_CTORS_T_A(long) + DECL_CTORS_T_A(unsigned long) + DECL_CTORS_T_A(float) + DECL_CTORS_T_A(double) + DECL_CTORS_T_A(const char*) + DECL_CTORS_T_A(const sc_fxval&) + DECL_CTORS_T_A(const sc_fxval_fast&) + DECL_CTORS_T_A(const sc_fxnum&) + DECL_CTORS_T_A(const sc_fxnum_fast&) +#ifndef SC_FX_EXCLUDE_OTHER + DECL_CTORS_T_B(int64) + DECL_CTORS_T_B(uint64) + DECL_CTORS_T_B(const sc_int_base&) + DECL_CTORS_T_B(const sc_uint_base&) + DECL_CTORS_T_B(const sc_signed&) + DECL_CTORS_T_B(const sc_unsigned&) +#endif + +#undef DECL_CTORS_T +#undef DECL_CTORS_T_A +#undef DECL_CTORS_T_B + + // copy constructor + + sc_fix( const sc_fix& ); + + + // unary bitwise operators + + const sc_fix operator ~ () const; + + + // unary bitwise functions + + friend void b_not( sc_fix&, const sc_fix& ); + + + // binary bitwise operators + + friend const sc_fix operator & ( const sc_fix&, const sc_fix& ); + friend const sc_fix operator & ( const sc_fix&, const sc_fix_fast& ); + friend const sc_fix operator & ( const sc_fix_fast&, const sc_fix& ); + friend const sc_fix operator | ( const sc_fix&, const sc_fix& ); + friend const sc_fix operator | ( const sc_fix&, const sc_fix_fast& ); + friend const sc_fix operator | ( const sc_fix_fast&, const sc_fix& ); + friend const sc_fix operator ^ ( const sc_fix&, const sc_fix& ); + friend const sc_fix operator ^ ( const sc_fix&, const sc_fix_fast& ); + friend const sc_fix operator ^ ( const sc_fix_fast&, const sc_fix& ); + + + // binary bitwise functions + + friend void b_and( sc_fix&, const sc_fix&, const sc_fix& ); + friend void b_and( sc_fix&, const sc_fix&, const sc_fix_fast& ); + friend void b_and( sc_fix&, const sc_fix_fast&, const sc_fix& ); + friend void b_or ( sc_fix&, const sc_fix&, const sc_fix& ); + friend void b_or ( sc_fix&, const sc_fix&, const sc_fix_fast& ); + friend void b_or ( sc_fix&, const sc_fix_fast&, const sc_fix& ); + friend void b_xor( sc_fix&, const sc_fix&, const sc_fix& ); + friend void b_xor( sc_fix&, const sc_fix&, const sc_fix_fast& ); + friend void b_xor( sc_fix&, const sc_fix_fast&, const sc_fix& ); + + + // assignment operators + + sc_fix& operator = ( const sc_fix& ); + +#define DECL_ASN_OP_T(op,tp) \ + sc_fix& operator op ( tp ); + +#ifndef SC_FX_EXCLUDE_OTHER +#define DECL_ASN_OP_OTHER(op) \ + DECL_ASN_OP_T(op,int64) \ + DECL_ASN_OP_T(op,uint64) \ + DECL_ASN_OP_T(op,const sc_int_base&) \ + DECL_ASN_OP_T(op,const sc_uint_base&) \ + DECL_ASN_OP_T(op,const sc_signed&) \ + DECL_ASN_OP_T(op,const sc_unsigned&) +#else +#define DECL_ASN_OP_OTHER(op) +#endif + +#define DECL_ASN_OP(op) \ + DECL_ASN_OP_T(op,int) \ + DECL_ASN_OP_T(op,unsigned int) \ + DECL_ASN_OP_T(op,long) \ + DECL_ASN_OP_T(op,unsigned long) \ + DECL_ASN_OP_T(op,float) \ + DECL_ASN_OP_T(op,double) \ + DECL_ASN_OP_T(op,const char*) \ + DECL_ASN_OP_T(op,const sc_fxval&) \ + DECL_ASN_OP_T(op,const sc_fxval_fast&) \ + DECL_ASN_OP_T(op,const sc_fxnum&) \ + DECL_ASN_OP_T(op,const sc_fxnum_fast&) \ + DECL_ASN_OP_OTHER(op) + + DECL_ASN_OP(=) + + DECL_ASN_OP(*=) + DECL_ASN_OP(/=) + DECL_ASN_OP(+=) + DECL_ASN_OP(-=) + + DECL_ASN_OP_T(<<=,int) + DECL_ASN_OP_T(>>=,int) + + DECL_ASN_OP_T(&=,const sc_fix&) + DECL_ASN_OP_T(&=,const sc_fix_fast&) + DECL_ASN_OP_T(|=,const sc_fix&) + DECL_ASN_OP_T(|=,const sc_fix_fast&) + DECL_ASN_OP_T(^=,const sc_fix&) + DECL_ASN_OP_T(^=,const sc_fix_fast&) + +#undef DECL_ASN_OP_T +#undef DECL_ASN_OP_OTHER +#undef DECL_ASN_OP + + + // auto-increment and auto-decrement + + const sc_fxval operator ++ ( int ); + const sc_fxval operator -- ( int ); + + sc_fix& operator ++ (); + sc_fix& operator -- (); + +}; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_fix_fast +// +// "Unconstrained" signed fixed-point class; limited precision. +// ---------------------------------------------------------------------------- + +class sc_fix_fast : public sc_fxnum_fast +{ + +public: + + // constructors + + explicit sc_fix_fast( sc_fxnum_fast_observer* = 0 ); + sc_fix_fast( int, int, + sc_fxnum_fast_observer* = 0 ); + sc_fix_fast( sc_q_mode, sc_o_mode, + sc_fxnum_fast_observer* = 0 ); + sc_fix_fast( sc_q_mode, sc_o_mode, int, + sc_fxnum_fast_observer* = 0 ); + sc_fix_fast( int, int, sc_q_mode, sc_o_mode, + sc_fxnum_fast_observer* = 0 ); + sc_fix_fast( int, int, sc_q_mode, sc_o_mode, int, + sc_fxnum_fast_observer* = 0 ); + explicit sc_fix_fast( const sc_fxcast_switch&, + sc_fxnum_fast_observer* = 0 ); + sc_fix_fast( int, int, + const sc_fxcast_switch&, + sc_fxnum_fast_observer* = 0 ); + sc_fix_fast( sc_q_mode, sc_o_mode, + const sc_fxcast_switch&, + sc_fxnum_fast_observer* = 0 ); + sc_fix_fast( sc_q_mode, sc_o_mode, int, + const sc_fxcast_switch&, + sc_fxnum_fast_observer* = 0 ); + sc_fix_fast( int, int, sc_q_mode, sc_o_mode, + const sc_fxcast_switch&, + sc_fxnum_fast_observer* = 0 ); + sc_fix_fast( int, int, sc_q_mode, sc_o_mode, int, + const sc_fxcast_switch&, + sc_fxnum_fast_observer* = 0 ); + explicit sc_fix_fast( const sc_fxtype_params&, + sc_fxnum_fast_observer* = 0 ); + sc_fix_fast( const sc_fxtype_params&, + const sc_fxcast_switch&, + sc_fxnum_fast_observer* = 0 ); + +#define DECL_CTORS_T(tp) \ + sc_fix_fast( tp, \ + int, int, \ + sc_fxnum_fast_observer* = 0 ); \ + sc_fix_fast( tp, \ + sc_q_mode, sc_o_mode, \ + sc_fxnum_fast_observer* = 0 ); \ + sc_fix_fast( tp, \ + sc_q_mode, sc_o_mode, int, \ + sc_fxnum_fast_observer* = 0 ); \ + sc_fix_fast( tp, \ + int, int, sc_q_mode, sc_o_mode, \ + sc_fxnum_fast_observer* = 0 ); \ + sc_fix_fast( tp, \ + int, int, sc_q_mode, sc_o_mode, int, \ + sc_fxnum_fast_observer* = 0 ); \ + sc_fix_fast( tp, \ + const sc_fxcast_switch&, \ + sc_fxnum_fast_observer* = 0 ); \ + sc_fix_fast( tp, \ + int, int, \ + const sc_fxcast_switch&, \ + sc_fxnum_fast_observer* = 0 ); \ + sc_fix_fast( tp, \ + sc_q_mode, sc_o_mode, \ + const sc_fxcast_switch&, \ + sc_fxnum_fast_observer* = 0 ); \ + sc_fix_fast( tp, \ + sc_q_mode, sc_o_mode, int, \ + const sc_fxcast_switch&, \ + sc_fxnum_fast_observer* = 0 ); \ + sc_fix_fast( tp, \ + int, int, sc_q_mode, sc_o_mode, \ + const sc_fxcast_switch&, \ + sc_fxnum_fast_observer* = 0 ); \ + sc_fix_fast( tp, \ + int, int, sc_q_mode, sc_o_mode, int, \ + const sc_fxcast_switch&, \ + sc_fxnum_fast_observer* = 0 ); \ + sc_fix_fast( tp, \ + const sc_fxtype_params&, \ + sc_fxnum_fast_observer* = 0 ); \ + sc_fix_fast( tp, \ + const sc_fxtype_params&, \ + const sc_fxcast_switch&, \ + sc_fxnum_fast_observer* = 0 ); + +#define DECL_CTORS_T_A(tp) \ + sc_fix_fast( tp, \ + sc_fxnum_fast_observer* = 0 ); \ + DECL_CTORS_T(tp) + +#define DECL_CTORS_T_B(tp) \ + explicit sc_fix_fast( tp, \ + sc_fxnum_fast_observer* = 0 ); \ + DECL_CTORS_T(tp) + + DECL_CTORS_T_A(int) + DECL_CTORS_T_A(unsigned int) + DECL_CTORS_T_A(long) + DECL_CTORS_T_A(unsigned long) + DECL_CTORS_T_A(float) + DECL_CTORS_T_A(double) + DECL_CTORS_T_A(const char*) + DECL_CTORS_T_A(const sc_fxval&) + DECL_CTORS_T_A(const sc_fxval_fast&) + DECL_CTORS_T_A(const sc_fxnum&) + DECL_CTORS_T_A(const sc_fxnum_fast&) +#ifndef SC_FX_EXCLUDE_OTHER + DECL_CTORS_T_B(int64) + DECL_CTORS_T_B(uint64) + DECL_CTORS_T_B(const sc_int_base&) + DECL_CTORS_T_B(const sc_uint_base&) + DECL_CTORS_T_B(const sc_signed&) + DECL_CTORS_T_B(const sc_unsigned&) +#endif + +#undef DECL_CTORS_T +#undef DECL_CTORS_T_A +#undef DECL_CTORS_T_B + + // copy constructor + + sc_fix_fast( const sc_fix_fast& ); + + + // unary bitwise operators + + const sc_fix_fast operator ~ () const; + + + // unary bitwise functions + + friend void b_not( sc_fix_fast&, const sc_fix_fast& ); + + + // binary bitwise operators + + friend const sc_fix_fast operator & ( const sc_fix_fast&, + const sc_fix_fast& ); + friend const sc_fix_fast operator ^ ( const sc_fix_fast&, + const sc_fix_fast& ); + friend const sc_fix_fast operator | ( const sc_fix_fast&, + const sc_fix_fast& ); + + + // binary bitwise functions + + friend void b_and( sc_fix_fast&, const sc_fix_fast&, const sc_fix_fast& ); + friend void b_or ( sc_fix_fast&, const sc_fix_fast&, const sc_fix_fast& ); + friend void b_xor( sc_fix_fast&, const sc_fix_fast&, const sc_fix_fast& ); + + + // assignment operators + + sc_fix_fast& operator = ( const sc_fix_fast& ); + +#define DECL_ASN_OP_T(op,tp) \ + sc_fix_fast& operator op ( tp ); + +#ifndef SC_FX_EXCLUDE_OTHER +#define DECL_ASN_OP_OTHER(op) \ + DECL_ASN_OP_T(op,int64) \ + DECL_ASN_OP_T(op,uint64) \ + DECL_ASN_OP_T(op,const sc_int_base&) \ + DECL_ASN_OP_T(op,const sc_uint_base&) \ + DECL_ASN_OP_T(op,const sc_signed&) \ + DECL_ASN_OP_T(op,const sc_unsigned&) +#else +#define DECL_ASN_OP_OTHER(op) +#endif + +#define DECL_ASN_OP(op) \ + DECL_ASN_OP_T(op,int) \ + DECL_ASN_OP_T(op,unsigned int) \ + DECL_ASN_OP_T(op,long) \ + DECL_ASN_OP_T(op,unsigned long) \ + DECL_ASN_OP_T(op,float) \ + DECL_ASN_OP_T(op,double) \ + DECL_ASN_OP_T(op,const char*) \ + DECL_ASN_OP_T(op,const sc_fxval&) \ + DECL_ASN_OP_T(op,const sc_fxval_fast&) \ + DECL_ASN_OP_T(op,const sc_fxnum&) \ + DECL_ASN_OP_T(op,const sc_fxnum_fast&) \ + DECL_ASN_OP_OTHER(op) + + DECL_ASN_OP(=) + + DECL_ASN_OP(*=) + DECL_ASN_OP(/=) + DECL_ASN_OP(+=) + DECL_ASN_OP(-=) + + DECL_ASN_OP_T(<<=,int) + DECL_ASN_OP_T(>>=,int) + + DECL_ASN_OP_T(&=,const sc_fix&) + DECL_ASN_OP_T(&=,const sc_fix_fast&) + DECL_ASN_OP_T(|=,const sc_fix&) + DECL_ASN_OP_T(|=,const sc_fix_fast&) + DECL_ASN_OP_T(^=,const sc_fix&) + DECL_ASN_OP_T(^=,const sc_fix_fast&) + +#undef DECL_ASN_OP_T +#undef DECL_ASN_OP_OTHER +#undef DECL_ASN_OP + + + // auto-increment and auto-decrement + + const sc_fxval_fast operator ++ ( int ); + const sc_fxval_fast operator -- ( int ); + + sc_fix_fast& operator ++ (); + sc_fix_fast& operator -- (); + +}; + + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + +// ---------------------------------------------------------------------------- +// CLASS : sc_fix +// +// "Unconstrained" signed fixed-point class; arbitrary precision. +// ---------------------------------------------------------------------------- + +// constructors + +inline +sc_fix::sc_fix( sc_fxnum_observer* observer_ ) +: sc_fxnum( sc_fxtype_params(), + SC_TC_, + sc_fxcast_switch(), + observer_ ) +{} + +inline +sc_fix::sc_fix( int wl_, int iwl_, + sc_fxnum_observer* observer_ ) +: sc_fxnum( sc_fxtype_params( wl_, iwl_ ), + SC_TC_, + sc_fxcast_switch(), + observer_ ) +{} + +inline +sc_fix::sc_fix( sc_q_mode qm, sc_o_mode om, + sc_fxnum_observer* observer_ ) +: sc_fxnum( sc_fxtype_params( qm, om ), + SC_TC_, + sc_fxcast_switch(), + observer_ ) +{} + +inline +sc_fix::sc_fix( sc_q_mode qm, sc_o_mode om, int nb, + sc_fxnum_observer* observer_ ) +: sc_fxnum( sc_fxtype_params( qm, om, nb ), + SC_TC_, + sc_fxcast_switch(), + observer_ ) +{} + +inline +sc_fix::sc_fix( int wl_, int iwl_, sc_q_mode qm, sc_o_mode om, + sc_fxnum_observer* observer_ ) +: sc_fxnum( sc_fxtype_params( wl_, iwl_, qm, om ), + SC_TC_, + sc_fxcast_switch(), + observer_ ) +{} + +inline +sc_fix::sc_fix( int wl_, int iwl_, sc_q_mode qm, sc_o_mode om, int nb, + sc_fxnum_observer* observer_ ) +: sc_fxnum( sc_fxtype_params( wl_, iwl_, qm, om, nb ), + SC_TC_, + sc_fxcast_switch(), + observer_ ) +{} + +inline +sc_fix::sc_fix( const sc_fxcast_switch& cast_sw, + sc_fxnum_observer* observer_ ) +: sc_fxnum( sc_fxtype_params(), + SC_TC_, + cast_sw, + observer_ ) +{} + +inline +sc_fix::sc_fix( int wl_, int iwl_, + const sc_fxcast_switch& cast_sw, + sc_fxnum_observer* observer_ ) +: sc_fxnum( sc_fxtype_params( wl_, iwl_ ), + SC_TC_, + cast_sw, + observer_ ) +{} + +inline +sc_fix::sc_fix( sc_q_mode qm, sc_o_mode om, + const sc_fxcast_switch& cast_sw, + sc_fxnum_observer* observer_ ) +: sc_fxnum( sc_fxtype_params( qm, om ), + SC_TC_, + cast_sw, + observer_ ) +{} + +inline +sc_fix::sc_fix( sc_q_mode qm, sc_o_mode om, int nb, + const sc_fxcast_switch& cast_sw, + sc_fxnum_observer* observer_ ) +: sc_fxnum( sc_fxtype_params( qm, om, nb ), + SC_TC_, + cast_sw, + observer_ ) +{} + +inline +sc_fix::sc_fix( int wl_, int iwl_, sc_q_mode qm, sc_o_mode om, + const sc_fxcast_switch& cast_sw, + sc_fxnum_observer* observer_ ) +: sc_fxnum( sc_fxtype_params( wl_, iwl_, qm, om ), + SC_TC_, + cast_sw, + observer_ ) +{} + +inline +sc_fix::sc_fix( int wl_, int iwl_, sc_q_mode qm, sc_o_mode om, int nb, + const sc_fxcast_switch& cast_sw, + sc_fxnum_observer* observer_ ) +: sc_fxnum( sc_fxtype_params( wl_, iwl_, qm, om, nb ), + SC_TC_, + cast_sw, + observer_ ) +{} + +inline +sc_fix::sc_fix( const sc_fxtype_params& type_params, + sc_fxnum_observer* observer_ ) +: sc_fxnum( type_params, + SC_TC_, + sc_fxcast_switch(), + observer_ ) +{} + +inline +sc_fix::sc_fix( const sc_fxtype_params& type_params, + const sc_fxcast_switch& cast_sw, + sc_fxnum_observer* observer_ ) +: sc_fxnum( type_params, + SC_TC_, + cast_sw, + observer_ ) +{} + +#define DEFN_CTORS_T_A(tp) \ +inline \ +sc_fix::sc_fix( tp a, \ + sc_fxnum_observer* observer_ ) \ +: sc_fxnum( a, \ + sc_fxtype_params(), \ + SC_TC_, \ + sc_fxcast_switch(), \ + observer_ ) \ +{} \ + \ +inline \ +sc_fix::sc_fix( tp a, \ + int wl_, int iwl_, \ + sc_fxnum_observer* observer_ ) \ +: sc_fxnum( a, \ + sc_fxtype_params( wl_, iwl_ ), \ + SC_TC_, \ + sc_fxcast_switch(), \ + observer_ ) \ +{} \ + \ +inline \ +sc_fix::sc_fix( tp a, \ + sc_q_mode qm, sc_o_mode om, \ + sc_fxnum_observer* observer_ ) \ +: sc_fxnum( a, \ + sc_fxtype_params( qm, om ), \ + SC_TC_, \ + sc_fxcast_switch(), \ + observer_ ) \ +{} \ + \ +inline \ +sc_fix::sc_fix( tp a, \ + sc_q_mode qm, sc_o_mode om, int nb, \ + sc_fxnum_observer* observer_ ) \ +: sc_fxnum( a, \ + sc_fxtype_params( qm, om, nb ), \ + SC_TC_, \ + sc_fxcast_switch(), \ + observer_ ) \ +{} \ + \ +inline \ +sc_fix::sc_fix( tp a, \ + int wl_, int iwl_, sc_q_mode qm, sc_o_mode om, \ + sc_fxnum_observer* observer_ ) \ +: sc_fxnum( a, \ + sc_fxtype_params( wl_, iwl_, qm, om ), \ + SC_TC_, \ + sc_fxcast_switch(), \ + observer_ ) \ +{} \ + \ +inline \ +sc_fix::sc_fix( tp a, \ + int wl_, int iwl_, sc_q_mode qm, sc_o_mode om, int nb, \ + sc_fxnum_observer* observer_ ) \ +: sc_fxnum( a, \ + sc_fxtype_params( wl_, iwl_, qm, om, nb ), \ + SC_TC_, \ + sc_fxcast_switch(), \ + observer_ ) \ +{} \ + \ +inline \ +sc_fix::sc_fix( tp a, \ + const sc_fxcast_switch& cast_sw, \ + sc_fxnum_observer* observer_ ) \ +: sc_fxnum( a, \ + sc_fxtype_params(), \ + SC_TC_, \ + cast_sw, \ + observer_ ) \ +{} \ + \ +inline \ +sc_fix::sc_fix( tp a, \ + int wl_, int iwl_, \ + const sc_fxcast_switch& cast_sw, \ + sc_fxnum_observer* observer_ ) \ +: sc_fxnum( a, \ + sc_fxtype_params( wl_, iwl_ ), \ + SC_TC_, \ + cast_sw, \ + observer_ ) \ +{} \ + \ +inline \ +sc_fix::sc_fix( tp a, \ + sc_q_mode qm, sc_o_mode om, \ + const sc_fxcast_switch& cast_sw, \ + sc_fxnum_observer* observer_ ) \ +: sc_fxnum( a, \ + sc_fxtype_params( qm, om ), \ + SC_TC_, \ + cast_sw, \ + observer_ ) \ +{} \ + \ +inline \ +sc_fix::sc_fix( tp a, \ + sc_q_mode qm, sc_o_mode om, int nb, \ + const sc_fxcast_switch& cast_sw, \ + sc_fxnum_observer* observer_ ) \ +: sc_fxnum( a, \ + sc_fxtype_params( qm, om, nb ), \ + SC_TC_, \ + cast_sw, \ + observer_ ) \ +{} \ + \ +inline \ +sc_fix::sc_fix( tp a, \ + int wl_, int iwl_, sc_q_mode qm, sc_o_mode om, \ + const sc_fxcast_switch& cast_sw, \ + sc_fxnum_observer* observer_ ) \ +: sc_fxnum( a, \ + sc_fxtype_params( wl_, iwl_, qm, om ), \ + SC_TC_, \ + cast_sw, \ + observer_ ) \ +{} \ + \ +inline \ +sc_fix::sc_fix( tp a, \ + int wl_, int iwl_, sc_q_mode qm, sc_o_mode om, int nb, \ + const sc_fxcast_switch& cast_sw, \ + sc_fxnum_observer* observer_ ) \ +: sc_fxnum( a, \ + sc_fxtype_params( wl_, iwl_, qm, om, nb ), \ + SC_TC_, \ + cast_sw, \ + observer_ ) \ +{} \ + \ +inline \ +sc_fix::sc_fix( tp a, \ + const sc_fxtype_params& type_params, \ + sc_fxnum_observer* observer_ ) \ +: sc_fxnum( a, \ + type_params, \ + SC_TC_, \ + sc_fxcast_switch(), \ + observer_ ) \ +{} \ + \ +inline \ +sc_fix::sc_fix( tp a, \ + const sc_fxtype_params& type_params, \ + const sc_fxcast_switch& cast_sw, \ + sc_fxnum_observer* observer_ ) \ +: sc_fxnum( a, \ + type_params, \ + SC_TC_, \ + cast_sw, \ + observer_ ) \ +{} + +#define DEFN_CTORS_T_B(tp) \ +inline \ +sc_fix::sc_fix( tp a, \ + sc_fxnum_observer* observer_ ) \ +: sc_fxnum( a, \ + a.type_params(), \ + SC_TC_, \ + sc_fxcast_switch(), \ + observer_ ) \ +{} \ + \ +inline \ +sc_fix::sc_fix( tp a, \ + int wl_, int iwl_, \ + sc_fxnum_observer* observer_ ) \ +: sc_fxnum( a, \ + sc_fxtype_params( a.type_params(), wl_, iwl_ ), \ + SC_TC_, \ + sc_fxcast_switch(), \ + observer_ ) \ +{} \ + \ +inline \ +sc_fix::sc_fix( tp a, \ + sc_q_mode qm, sc_o_mode om, \ + sc_fxnum_observer* observer_ ) \ +: sc_fxnum( a, \ + sc_fxtype_params( a.type_params(), qm, om ), \ + SC_TC_, \ + sc_fxcast_switch(), \ + observer_ ) \ +{} \ + \ +inline \ +sc_fix::sc_fix( tp a, \ + sc_q_mode qm, sc_o_mode om, int nb, \ + sc_fxnum_observer* observer_ ) \ +: sc_fxnum( a, \ + sc_fxtype_params( a.type_params(), qm, om, nb ), \ + SC_TC_, \ + sc_fxcast_switch(), \ + observer_ ) \ +{} \ + \ +inline \ +sc_fix::sc_fix( tp a, \ + int wl_, int iwl_, sc_q_mode qm, sc_o_mode om, \ + sc_fxnum_observer* observer_ ) \ +: sc_fxnum( a, \ + sc_fxtype_params( wl_, iwl_, qm, om ), \ + SC_TC_, \ + sc_fxcast_switch(), \ + observer_ ) \ +{} \ + \ +inline \ +sc_fix::sc_fix( tp a, \ + int wl_, int iwl_, sc_q_mode qm, sc_o_mode om, int nb, \ + sc_fxnum_observer* observer_ ) \ +: sc_fxnum( a, \ + sc_fxtype_params( wl_, iwl_, qm, om, nb ), \ + SC_TC_, \ + sc_fxcast_switch(), \ + observer_ ) \ +{} \ + \ +inline \ +sc_fix::sc_fix( tp a, \ + const sc_fxcast_switch& cast_sw, \ + sc_fxnum_observer* observer_ ) \ +: sc_fxnum( a, \ + a.type_params(), \ + SC_TC_, \ + cast_sw, \ + observer_ ) \ +{} \ + \ +inline \ +sc_fix::sc_fix( tp a, \ + int wl_, int iwl_, \ + const sc_fxcast_switch& cast_sw, \ + sc_fxnum_observer* observer_ ) \ +: sc_fxnum( a, \ + sc_fxtype_params( a.type_params(), wl_, iwl_ ), \ + SC_TC_, \ + cast_sw, \ + observer_ ) \ +{} \ + \ +inline \ +sc_fix::sc_fix( tp a, \ + sc_q_mode qm, sc_o_mode om, \ + const sc_fxcast_switch& cast_sw, \ + sc_fxnum_observer* observer_ ) \ +: sc_fxnum( a, \ + sc_fxtype_params( a.type_params(), qm, om ), \ + SC_TC_, \ + cast_sw, \ + observer_ ) \ +{} \ + \ +inline \ +sc_fix::sc_fix( tp a, \ + sc_q_mode qm, sc_o_mode om, int nb, \ + const sc_fxcast_switch& cast_sw, \ + sc_fxnum_observer* observer_ ) \ +: sc_fxnum( a, \ + sc_fxtype_params( a.type_params(), qm, om, nb ), \ + SC_TC_, \ + cast_sw, \ + observer_ ) \ +{} \ + \ +inline \ +sc_fix::sc_fix( tp a, \ + int wl_, int iwl_, sc_q_mode qm, sc_o_mode om, \ + const sc_fxcast_switch& cast_sw, \ + sc_fxnum_observer* observer_ ) \ +: sc_fxnum( a, \ + sc_fxtype_params( wl_, iwl_, qm, om ), \ + SC_TC_, \ + cast_sw, \ + observer_ ) \ +{} \ + \ +inline \ +sc_fix::sc_fix( tp a, \ + int wl_, int iwl_, sc_q_mode qm, sc_o_mode om, int nb, \ + const sc_fxcast_switch& cast_sw, \ + sc_fxnum_observer* observer_ ) \ +: sc_fxnum( a, \ + sc_fxtype_params( wl_, iwl_, qm, om, nb ), \ + SC_TC_, \ + cast_sw, \ + observer_ ) \ +{} \ + \ +inline \ +sc_fix::sc_fix( tp a, \ + const sc_fxtype_params& type_params, \ + sc_fxnum_observer* observer_ ) \ +: sc_fxnum( a, \ + type_params, \ + SC_TC_, \ + sc_fxcast_switch(), \ + observer_ ) \ +{} \ + \ +inline \ +sc_fix::sc_fix( tp a, \ + const sc_fxtype_params& type_params, \ + const sc_fxcast_switch& cast_sw, \ + sc_fxnum_observer* observer_ ) \ +: sc_fxnum( a, \ + type_params, \ + SC_TC_, \ + cast_sw, \ + observer_ ) \ +{} + +DEFN_CTORS_T_A(int) +DEFN_CTORS_T_A(unsigned int) +DEFN_CTORS_T_A(long) +DEFN_CTORS_T_A(unsigned long) +DEFN_CTORS_T_A(float) +DEFN_CTORS_T_A(double) +DEFN_CTORS_T_A(const char*) +DEFN_CTORS_T_A(const sc_fxval&) +DEFN_CTORS_T_A(const sc_fxval_fast&) +DEFN_CTORS_T_B(const sc_fxnum&) +DEFN_CTORS_T_B(const sc_fxnum_fast&) +#ifndef SC_FX_EXCLUDE_OTHER +DEFN_CTORS_T_A(int64) +DEFN_CTORS_T_A(uint64) +DEFN_CTORS_T_A(const sc_int_base&) +DEFN_CTORS_T_A(const sc_uint_base&) +DEFN_CTORS_T_A(const sc_signed&) +DEFN_CTORS_T_A(const sc_unsigned&) +#endif + +#undef DEFN_CTORS_T_A +#undef DEFN_CTORS_T_B + +// copy constructor + +inline +sc_fix::sc_fix( const sc_fix& a ) +: sc_fxnum( a, + a.type_params(), + SC_TC_, + sc_fxcast_switch(), + 0 ) +{} + + +// unary bitwise operators + +inline +const sc_fix +sc_fix::operator ~ () const +{ + SC_FXNUM_OBSERVER_READ_( *this ) + int iwl_c = iwl(); + int wl_c = wl(); + sc_fix c( wl_c, iwl_c ); + for( int i = iwl_c - wl_c; i < iwl_c; ++ i ) + c.set_bit( i, ! get_bit( i ) ); + return sc_fix( c, wl_c, iwl_c ); +} + + +// unary bitwise functions + +inline +void +b_not( sc_fix& c, const sc_fix& a ) +{ + SC_FXNUM_OBSERVER_READ_( a ) + int iwl_c = c.iwl(); + for( int i = iwl_c - c.wl(); i < iwl_c; ++ i ) + c.set_bit( i, ! a.get_bit( i ) ); + c.cast(); + SC_FXNUM_OBSERVER_WRITE_( c ) +} + + +// binary bitwise operators + +#define DEFN_BIN_OP_T(op,op2,tp1,tp2) \ +inline \ +const sc_fix \ +operator op ( const tp1& a, const tp2& b ) \ +{ \ + a.observer_read(); \ + b.observer_read(); \ + int iwl_a = a.iwl(); \ + int iwl_b = b.iwl(); \ + int iwl_c = sc_max( iwl_a, iwl_b ); \ + int fwl_c = sc_max( a.wl() - iwl_a, b.wl() - iwl_b ); \ + sc_fix c( iwl_c + fwl_c, iwl_c ); \ + for( int i = -fwl_c; i < iwl_c; ++ i ) \ + c.set_bit( i, a.get_bit( i ) op2 b.get_bit( i ) ); \ + return sc_fix( c, iwl_c + fwl_c, iwl_c ); \ +} + +DEFN_BIN_OP_T(&,&&,sc_fix,sc_fix) +DEFN_BIN_OP_T(&,&&,sc_fix,sc_fix_fast) +DEFN_BIN_OP_T(&,&&,sc_fix_fast,sc_fix) + +DEFN_BIN_OP_T(|,||,sc_fix,sc_fix) +DEFN_BIN_OP_T(|,||,sc_fix,sc_fix_fast) +DEFN_BIN_OP_T(|,||,sc_fix_fast,sc_fix) + +DEFN_BIN_OP_T(^,!=,sc_fix,sc_fix) +DEFN_BIN_OP_T(^,!=,sc_fix,sc_fix_fast) +DEFN_BIN_OP_T(^,!=,sc_fix_fast,sc_fix) + +#undef DEFN_BIN_OP_T + + +// binary bitwise functions + +#define DEFN_BIN_FNC_T(fnc,op2,tp1,tp2) \ +inline \ +void \ +fnc ( sc_fix& c, const tp1& a, const tp2& b ) \ +{ \ + a.observer_read(); \ + b.observer_read(); \ + int iwl_c = c.iwl(); \ + for( int i = iwl_c - c.wl(); i < iwl_c; ++ i ) \ + c.set_bit( i, a.get_bit( i ) op2 b.get_bit( i ) ); \ + c.cast(); \ + SC_FXNUM_OBSERVER_WRITE_( c ) \ +} + +DEFN_BIN_FNC_T(b_and,&&,sc_fix,sc_fix) +DEFN_BIN_FNC_T(b_and,&&,sc_fix,sc_fix_fast) +DEFN_BIN_FNC_T(b_and,&&,sc_fix_fast,sc_fix) + +DEFN_BIN_FNC_T(b_or,||,sc_fix,sc_fix) +DEFN_BIN_FNC_T(b_or,||,sc_fix,sc_fix_fast) +DEFN_BIN_FNC_T(b_or,||,sc_fix_fast,sc_fix) + +DEFN_BIN_FNC_T(b_xor,!=,sc_fix,sc_fix) +DEFN_BIN_FNC_T(b_xor,!=,sc_fix,sc_fix_fast) +DEFN_BIN_FNC_T(b_xor,!=,sc_fix_fast,sc_fix) + +#undef DEFN_BIN_FNC_T + + +// assignment operators + +inline +sc_fix& +sc_fix::operator = ( const sc_fix& a ) +{ + sc_fxnum::operator = ( a ); + return *this; +} + +#define DEFN_ASN_OP_T(op,tp) \ +inline \ +sc_fix& \ +sc_fix::operator op ( tp a ) \ +{ \ + sc_fxnum::operator op( a ); \ + return *this; \ +} + +#ifndef SC_FX_EXCLUDE_OTHER +#define DEFN_ASN_OP_OTHER(op) \ +DEFN_ASN_OP_T(op,int64) \ +DEFN_ASN_OP_T(op,uint64) \ +DEFN_ASN_OP_T(op,const sc_int_base&) \ +DEFN_ASN_OP_T(op,const sc_uint_base&) \ +DEFN_ASN_OP_T(op,const sc_signed&) \ +DEFN_ASN_OP_T(op,const sc_unsigned&) +#else +#define DEFN_ASN_OP_OTHER(op) +#endif + +#define DEFN_ASN_OP(op) \ +DEFN_ASN_OP_T(op,int) \ +DEFN_ASN_OP_T(op,unsigned int) \ +DEFN_ASN_OP_T(op,long) \ +DEFN_ASN_OP_T(op,unsigned long) \ +DEFN_ASN_OP_T(op,float) \ +DEFN_ASN_OP_T(op,double) \ +DEFN_ASN_OP_T(op,const char*) \ +DEFN_ASN_OP_T(op,const sc_fxval&) \ +DEFN_ASN_OP_T(op,const sc_fxval_fast&) \ +DEFN_ASN_OP_T(op,const sc_fxnum&) \ +DEFN_ASN_OP_T(op,const sc_fxnum_fast&) \ +DEFN_ASN_OP_OTHER(op) + +DEFN_ASN_OP(=) + +DEFN_ASN_OP(*=) +DEFN_ASN_OP(/=) +DEFN_ASN_OP(+=) +DEFN_ASN_OP(-=) + +DEFN_ASN_OP_T(<<=,int) +DEFN_ASN_OP_T(>>=,int) + +#undef DEFN_ASN_OP_T +#undef DEFN_ASN_OP_OTHER +#undef DEFN_ASN_OP + + +#define DEFN_ASN_OP_T(op,op2,tp) \ +inline \ +sc_fix& \ +sc_fix::operator op ( const tp& b ) \ +{ \ + SC_FXNUM_OBSERVER_READ_( *this ) \ + b.observer_read(); \ + int iwl_c = iwl(); \ + for( int i = iwl_c - wl(); i < iwl_c; ++ i ) \ + set_bit( i, get_bit( i ) op2 b.get_bit( i ) ); \ + cast(); \ + SC_FXNUM_OBSERVER_WRITE_( *this ) \ + return *this; \ +} + +DEFN_ASN_OP_T(&=,&&,sc_fix) +DEFN_ASN_OP_T(&=,&&,sc_fix_fast) +DEFN_ASN_OP_T(|=,||,sc_fix) +DEFN_ASN_OP_T(|=,||,sc_fix_fast) +DEFN_ASN_OP_T(^=,!=,sc_fix) +DEFN_ASN_OP_T(^=,!=,sc_fix_fast) + +#undef DEFN_ASN_OP_T + + +// auto-increment and auto-decrement + +inline +const sc_fxval +sc_fix::operator ++ ( int ) +{ + return sc_fxval( sc_fxnum::operator ++ ( 0 ) ); +} + +inline +const sc_fxval +sc_fix::operator -- ( int ) +{ + return sc_fxval( sc_fxnum::operator -- ( 0 ) ); +} + +inline +sc_fix& +sc_fix::operator ++ () +{ + sc_fxnum::operator ++ (); + return *this; +} + +inline +sc_fix& +sc_fix::operator -- () +{ + sc_fxnum::operator -- (); + return *this; +} + + +// ---------------------------------------------------------------------------- +// CLASS : sc_fix_fast +// +// "Unconstrained" signed fixed-point class; limited precision. +// ---------------------------------------------------------------------------- + +// constructors + +inline +sc_fix_fast::sc_fix_fast( sc_fxnum_fast_observer* observer_ ) +: sc_fxnum_fast( sc_fxtype_params(), + SC_TC_, + sc_fxcast_switch(), + observer_ ) +{} + +inline +sc_fix_fast::sc_fix_fast( int wl_, int iwl_, + sc_fxnum_fast_observer* observer_ ) +: sc_fxnum_fast( sc_fxtype_params( wl_, iwl_ ), + SC_TC_, + sc_fxcast_switch(), + observer_ ) +{} + +inline +sc_fix_fast::sc_fix_fast( sc_q_mode qm, sc_o_mode om, + sc_fxnum_fast_observer* observer_ ) +: sc_fxnum_fast( sc_fxtype_params( qm, om ), + SC_TC_, + sc_fxcast_switch(), + observer_ ) +{} + +inline +sc_fix_fast::sc_fix_fast( sc_q_mode qm, sc_o_mode om, int nb, + sc_fxnum_fast_observer* observer_ ) +: sc_fxnum_fast( sc_fxtype_params( qm, om, nb ), + SC_TC_, + sc_fxcast_switch(), + observer_ ) +{} + +inline +sc_fix_fast::sc_fix_fast( int wl_, int iwl_, sc_q_mode qm, sc_o_mode om, + sc_fxnum_fast_observer* observer_ ) +: sc_fxnum_fast( sc_fxtype_params( wl_, iwl_, qm, om ), + SC_TC_, + sc_fxcast_switch(), + observer_ ) +{} + +inline +sc_fix_fast::sc_fix_fast( int wl_, int iwl_, + sc_q_mode qm, sc_o_mode om, int nb, + sc_fxnum_fast_observer* observer_ ) +: sc_fxnum_fast( sc_fxtype_params( wl_, iwl_, qm, om, nb ), + SC_TC_, + sc_fxcast_switch(), + observer_ ) +{} + +inline +sc_fix_fast::sc_fix_fast( const sc_fxcast_switch& cast_sw, + sc_fxnum_fast_observer* observer_ ) +: sc_fxnum_fast( sc_fxtype_params(), + SC_TC_, + cast_sw, + observer_ ) +{} + +inline +sc_fix_fast::sc_fix_fast( int wl_, int iwl_, + const sc_fxcast_switch& cast_sw, + sc_fxnum_fast_observer* observer_ ) +: sc_fxnum_fast( sc_fxtype_params( wl_, iwl_ ), + SC_TC_, + cast_sw, + observer_ ) +{} + +inline +sc_fix_fast::sc_fix_fast( sc_q_mode qm, sc_o_mode om, + const sc_fxcast_switch& cast_sw, + sc_fxnum_fast_observer* observer_ ) +: sc_fxnum_fast( sc_fxtype_params( qm, om ), + SC_TC_, + cast_sw, + observer_ ) +{} + +inline +sc_fix_fast::sc_fix_fast( sc_q_mode qm, sc_o_mode om, int nb, + const sc_fxcast_switch& cast_sw, + sc_fxnum_fast_observer* observer_ ) +: sc_fxnum_fast( sc_fxtype_params( qm, om, nb ), + SC_TC_, + cast_sw, + observer_ ) +{} + +inline +sc_fix_fast::sc_fix_fast( int wl_, int iwl_, sc_q_mode qm, sc_o_mode om, + const sc_fxcast_switch& cast_sw, + sc_fxnum_fast_observer* observer_ ) +: sc_fxnum_fast( sc_fxtype_params( wl_, iwl_, qm, om ), + SC_TC_, + cast_sw, + observer_ ) +{} + +inline +sc_fix_fast::sc_fix_fast( int wl_, int iwl_, + sc_q_mode qm, sc_o_mode om, int nb, + const sc_fxcast_switch& cast_sw, + sc_fxnum_fast_observer* observer_ ) +: sc_fxnum_fast( sc_fxtype_params( wl_, iwl_, qm, om, nb ), + SC_TC_, + cast_sw, + observer_ ) +{} + +inline +sc_fix_fast::sc_fix_fast( const sc_fxtype_params& type_params, + sc_fxnum_fast_observer* observer_ ) +: sc_fxnum_fast( type_params, + SC_TC_, + sc_fxcast_switch(), + observer_ ) +{} + +inline +sc_fix_fast::sc_fix_fast( const sc_fxtype_params& type_params, + const sc_fxcast_switch& cast_sw, + sc_fxnum_fast_observer* observer_ ) +: sc_fxnum_fast( type_params, + SC_TC_, + cast_sw, + observer_ ) +{} + +#define DEFN_CTORS_T_A(tp) \ +inline \ +sc_fix_fast::sc_fix_fast( tp a, \ + sc_fxnum_fast_observer* observer_ ) \ +: sc_fxnum_fast( a, \ + sc_fxtype_params(), \ + SC_TC_, \ + sc_fxcast_switch(), \ + observer_ ) \ +{} \ + \ +inline \ +sc_fix_fast::sc_fix_fast( tp a, \ + int wl_, int iwl_, \ + sc_fxnum_fast_observer* observer_ ) \ +: sc_fxnum_fast( a, \ + sc_fxtype_params( wl_, iwl_ ), \ + SC_TC_, \ + sc_fxcast_switch(), \ + observer_ ) \ +{} \ + \ +inline \ +sc_fix_fast::sc_fix_fast( tp a, \ + sc_q_mode qm, sc_o_mode om, \ + sc_fxnum_fast_observer* observer_ ) \ +: sc_fxnum_fast( a, \ + sc_fxtype_params( qm, om ), \ + SC_TC_, \ + sc_fxcast_switch(), \ + observer_ ) \ +{} \ + \ +inline \ +sc_fix_fast::sc_fix_fast( tp a, \ + sc_q_mode qm, sc_o_mode om, int nb, \ + sc_fxnum_fast_observer* observer_ ) \ +: sc_fxnum_fast( a, \ + sc_fxtype_params( qm, om, nb ), \ + SC_TC_, \ + sc_fxcast_switch(), \ + observer_ ) \ +{} \ + \ +inline \ +sc_fix_fast::sc_fix_fast( tp a, \ + int wl_, int iwl_, sc_q_mode qm, sc_o_mode om, \ + sc_fxnum_fast_observer* observer_ ) \ +: sc_fxnum_fast( a, \ + sc_fxtype_params( wl_, iwl_, qm, om ), \ + SC_TC_, \ + sc_fxcast_switch(), \ + observer_ ) \ +{} \ + \ +inline \ +sc_fix_fast::sc_fix_fast( tp a, \ + int wl_, int iwl_, \ + sc_q_mode qm, sc_o_mode om, int nb, \ + sc_fxnum_fast_observer* observer_ ) \ +: sc_fxnum_fast( a, \ + sc_fxtype_params( wl_, iwl_, qm, om, nb ), \ + SC_TC_, \ + sc_fxcast_switch(), \ + observer_ ) \ +{} \ + \ +inline \ +sc_fix_fast::sc_fix_fast( tp a, \ + const sc_fxcast_switch& cast_sw, \ + sc_fxnum_fast_observer* observer_ ) \ +: sc_fxnum_fast( a, \ + sc_fxtype_params(), \ + SC_TC_, \ + cast_sw, \ + observer_ ) \ +{} \ + \ +inline \ +sc_fix_fast::sc_fix_fast( tp a, \ + int wl_, int iwl_, \ + const sc_fxcast_switch& cast_sw, \ + sc_fxnum_fast_observer* observer_ ) \ +: sc_fxnum_fast( a, \ + sc_fxtype_params( wl_, iwl_ ), \ + SC_TC_, \ + cast_sw, \ + observer_ ) \ +{} \ + \ +inline \ +sc_fix_fast::sc_fix_fast( tp a, \ + sc_q_mode qm, sc_o_mode om, \ + const sc_fxcast_switch& cast_sw, \ + sc_fxnum_fast_observer* observer_ ) \ +: sc_fxnum_fast( a, \ + sc_fxtype_params( qm, om ), \ + SC_TC_, \ + cast_sw, \ + observer_ ) \ +{} \ + \ +inline \ +sc_fix_fast::sc_fix_fast( tp a, \ + sc_q_mode qm, sc_o_mode om, int nb, \ + const sc_fxcast_switch& cast_sw, \ + sc_fxnum_fast_observer* observer_ ) \ +: sc_fxnum_fast( a, \ + sc_fxtype_params( qm, om, nb ), \ + SC_TC_, \ + cast_sw, \ + observer_ ) \ +{} \ + \ +inline \ +sc_fix_fast::sc_fix_fast( tp a, \ + int wl_, int iwl_, sc_q_mode qm, sc_o_mode om, \ + const sc_fxcast_switch& cast_sw, \ + sc_fxnum_fast_observer* observer_ ) \ +: sc_fxnum_fast( a, \ + sc_fxtype_params( wl_, iwl_, qm, om ), \ + SC_TC_, \ + cast_sw, \ + observer_ ) \ +{} \ + \ +inline \ +sc_fix_fast::sc_fix_fast( tp a, \ + int wl_, int iwl_, \ + sc_q_mode qm, sc_o_mode om, int nb, \ + const sc_fxcast_switch& cast_sw, \ + sc_fxnum_fast_observer* observer_ ) \ +: sc_fxnum_fast( a, \ + sc_fxtype_params( wl_, iwl_, qm, om, nb ), \ + SC_TC_, \ + cast_sw, \ + observer_ ) \ +{} \ + \ +inline \ +sc_fix_fast::sc_fix_fast( tp a, \ + const sc_fxtype_params& type_params, \ + sc_fxnum_fast_observer* observer_ ) \ +: sc_fxnum_fast( a, \ + type_params, \ + SC_TC_, \ + sc_fxcast_switch(), \ + observer_ ) \ +{} \ + \ +inline \ +sc_fix_fast::sc_fix_fast( tp a, \ + const sc_fxtype_params& type_params, \ + const sc_fxcast_switch& cast_sw, \ + sc_fxnum_fast_observer* observer_ ) \ +: sc_fxnum_fast( a, \ + type_params, \ + SC_TC_, \ + cast_sw, \ + observer_ ) \ +{} + +#define DEFN_CTORS_T_B(tp) \ +inline \ +sc_fix_fast::sc_fix_fast( tp a, \ + sc_fxnum_fast_observer* observer_ ) \ +: sc_fxnum_fast( a, \ + a.type_params(), \ + SC_TC_, \ + sc_fxcast_switch(), \ + observer_ ) \ +{} \ + \ +inline \ +sc_fix_fast::sc_fix_fast( tp a, \ + int wl_, int iwl_, \ + sc_fxnum_fast_observer* observer_ ) \ +: sc_fxnum_fast( a, \ + sc_fxtype_params( a.type_params(), wl_, iwl_ ), \ + SC_TC_, \ + sc_fxcast_switch(), \ + observer_ ) \ +{} \ + \ +inline \ +sc_fix_fast::sc_fix_fast( tp a, \ + sc_q_mode qm, sc_o_mode om, \ + sc_fxnum_fast_observer* observer_ ) \ +: sc_fxnum_fast( a, \ + sc_fxtype_params( a.type_params(), qm, om ), \ + SC_TC_, \ + sc_fxcast_switch(), \ + observer_ ) \ +{} \ + \ +inline \ +sc_fix_fast::sc_fix_fast( tp a, \ + sc_q_mode qm, sc_o_mode om, int nb, \ + sc_fxnum_fast_observer* observer_ ) \ +: sc_fxnum_fast( a, \ + sc_fxtype_params( a.type_params(), qm, om, nb ), \ + SC_TC_, \ + sc_fxcast_switch(), \ + observer_ ) \ +{} \ + \ +inline \ +sc_fix_fast::sc_fix_fast( tp a, \ + int wl_, int iwl_, sc_q_mode qm, sc_o_mode om, \ + sc_fxnum_fast_observer* observer_ ) \ +: sc_fxnum_fast( a, \ + sc_fxtype_params( wl_, iwl_, qm, om ), \ + SC_TC_, \ + sc_fxcast_switch(), \ + observer_ ) \ +{} \ + \ +inline \ +sc_fix_fast::sc_fix_fast( tp a, \ + int wl_, int iwl_, \ + sc_q_mode qm, sc_o_mode om, int nb, \ + sc_fxnum_fast_observer* observer_ ) \ +: sc_fxnum_fast( a, \ + sc_fxtype_params( wl_, iwl_, qm, om, nb ), \ + SC_TC_, \ + sc_fxcast_switch(), \ + observer_ ) \ +{} \ + \ +inline \ +sc_fix_fast::sc_fix_fast( tp a, \ + const sc_fxcast_switch& cast_sw, \ + sc_fxnum_fast_observer* observer_ ) \ +: sc_fxnum_fast( a, \ + a.type_params(), \ + SC_TC_, \ + cast_sw, \ + observer_ ) \ +{} \ + \ +inline \ +sc_fix_fast::sc_fix_fast( tp a, \ + int wl_, int iwl_, \ + const sc_fxcast_switch& cast_sw, \ + sc_fxnum_fast_observer* observer_ ) \ +: sc_fxnum_fast( a, \ + sc_fxtype_params( a.type_params(), wl_, iwl_ ), \ + SC_TC_, \ + cast_sw, \ + observer_ ) \ +{} \ + \ +inline \ +sc_fix_fast::sc_fix_fast( tp a, \ + sc_q_mode qm, sc_o_mode om, \ + const sc_fxcast_switch& cast_sw, \ + sc_fxnum_fast_observer* observer_ ) \ +: sc_fxnum_fast( a, \ + sc_fxtype_params( a.type_params(), qm, om ), \ + SC_TC_, \ + cast_sw, \ + observer_ ) \ +{} \ + \ +inline \ +sc_fix_fast::sc_fix_fast( tp a, \ + sc_q_mode qm, sc_o_mode om, int nb, \ + const sc_fxcast_switch& cast_sw, \ + sc_fxnum_fast_observer* observer_ ) \ +: sc_fxnum_fast( a, \ + sc_fxtype_params( a.type_params(), qm, om, nb ), \ + SC_TC_, \ + cast_sw, \ + observer_ ) \ +{} \ + \ +inline \ +sc_fix_fast::sc_fix_fast( tp a, \ + int wl_, int iwl_, sc_q_mode qm, sc_o_mode om, \ + const sc_fxcast_switch& cast_sw, \ + sc_fxnum_fast_observer* observer_ ) \ +: sc_fxnum_fast( a, \ + sc_fxtype_params( wl_, iwl_, qm, om ), \ + SC_TC_, \ + cast_sw, \ + observer_ ) \ +{} \ + \ +inline \ +sc_fix_fast::sc_fix_fast( tp a, \ + int wl_, int iwl_, \ + sc_q_mode qm, sc_o_mode om, int nb, \ + const sc_fxcast_switch& cast_sw, \ + sc_fxnum_fast_observer* observer_ ) \ +: sc_fxnum_fast( a, \ + sc_fxtype_params( wl_, iwl_, qm, om, nb ), \ + SC_TC_, \ + cast_sw, \ + observer_ ) \ +{} \ + \ +inline \ +sc_fix_fast::sc_fix_fast( tp a, \ + const sc_fxtype_params& type_params, \ + sc_fxnum_fast_observer* observer_ ) \ +: sc_fxnum_fast( a, \ + type_params, \ + SC_TC_, \ + sc_fxcast_switch(), \ + observer_ ) \ +{} \ + \ +inline \ +sc_fix_fast::sc_fix_fast( tp a, \ + const sc_fxtype_params& type_params, \ + const sc_fxcast_switch& cast_sw, \ + sc_fxnum_fast_observer* observer_ ) \ +: sc_fxnum_fast( a, \ + type_params, \ + SC_TC_, \ + cast_sw, \ + observer_ ) \ +{} + +DEFN_CTORS_T_A(int) +DEFN_CTORS_T_A(unsigned int) +DEFN_CTORS_T_A(long) +DEFN_CTORS_T_A(unsigned long) +DEFN_CTORS_T_A(float) +DEFN_CTORS_T_A(double) +DEFN_CTORS_T_A(const char*) +DEFN_CTORS_T_A(const sc_fxval&) +DEFN_CTORS_T_A(const sc_fxval_fast&) +DEFN_CTORS_T_B(const sc_fxnum&) +DEFN_CTORS_T_B(const sc_fxnum_fast&) +#ifndef SC_FX_EXCLUDE_OTHER +DEFN_CTORS_T_A(int64) +DEFN_CTORS_T_A(uint64) +DEFN_CTORS_T_A(const sc_int_base&) +DEFN_CTORS_T_A(const sc_uint_base&) +DEFN_CTORS_T_A(const sc_signed&) +DEFN_CTORS_T_A(const sc_unsigned&) +#endif + +#undef DEFN_CTORS_T_A +#undef DEFN_CTORS_T_B + +// copy constructor + +inline +sc_fix_fast::sc_fix_fast( const sc_fix_fast& a ) +: sc_fxnum_fast( a, + a.type_params(), + SC_TC_, + sc_fxcast_switch(), + 0 ) +{} + + +// unary bitwise operators + +inline +const sc_fix_fast +sc_fix_fast::operator ~ () const +{ + SC_FXNUM_FAST_OBSERVER_READ_( *this ) + int iwl_c = iwl(); + int wl_c = wl(); + sc_fix_fast c( wl_c, iwl_c ); + for( int i = iwl_c - wl_c; i < iwl_c; ++ i ) + c.set_bit( i, ! get_bit( i ) ); + return sc_fix_fast( c, wl_c, iwl_c ); +} + + +// unary bitwise functions + +inline +void +b_not( sc_fix_fast& c, const sc_fix_fast& a ) +{ + SC_FXNUM_FAST_OBSERVER_READ_( a ) + int iwl_c = c.iwl(); + for( int i = iwl_c - c.wl(); i < iwl_c; ++ i ) + c.set_bit( i, ! a.get_bit( i ) ); + c.cast(); + SC_FXNUM_FAST_OBSERVER_WRITE_( c ) +} + + +// binary bitwise operators + +#define DEFN_BIN_OP_T(op,op2,tp1,tp2) \ +inline \ +const sc_fix_fast \ +operator op ( const tp1& a, const tp2& b ) \ +{ \ + a.observer_read(); \ + b.observer_read(); \ + int iwl_a = a.iwl(); \ + int iwl_b = b.iwl(); \ + int iwl_c = sc_max( iwl_a, iwl_b ); \ + int fwl_c = sc_max( a.wl() - iwl_a, b.wl() - iwl_b ); \ + sc_fix_fast c( iwl_c + fwl_c, iwl_c ); \ + for( int i = -fwl_c; i < iwl_c; ++ i ) \ + c.set_bit( i, a.get_bit( i ) op2 b.get_bit( i ) ); \ + return sc_fix_fast( c, iwl_c + fwl_c, iwl_c ); \ +} + +DEFN_BIN_OP_T(&,&&,sc_fix_fast,sc_fix_fast) +DEFN_BIN_OP_T(|,||,sc_fix_fast,sc_fix_fast) +DEFN_BIN_OP_T(^,!=,sc_fix_fast,sc_fix_fast) + +#undef DEFN_BIN_OP_T + + +// binary bitwise functions + +#define DEFN_BIN_FNC_T(fnc,op2,tp1,tp2) \ +inline \ +void \ +fnc ( sc_fix_fast& c, const tp1& a, const tp2& b ) \ +{ \ + a.observer_read(); \ + b.observer_read(); \ + int iwl_c = c.iwl(); \ + for( int i = iwl_c - c.wl(); i < iwl_c; ++ i ) \ + c.set_bit( i, a.get_bit( i ) op2 b.get_bit( i ) ); \ + c.cast(); \ + SC_FXNUM_FAST_OBSERVER_WRITE_( c ) \ +} + +DEFN_BIN_FNC_T(b_and,&&,sc_fix_fast,sc_fix_fast) +DEFN_BIN_FNC_T(b_or,||,sc_fix_fast,sc_fix_fast) +DEFN_BIN_FNC_T(b_xor,!=,sc_fix_fast,sc_fix_fast) + +#undef DEFN_BIN_FNC_T + + +// assignment operators + +inline +sc_fix_fast& +sc_fix_fast::operator = ( const sc_fix_fast& a ) +{ + sc_fxnum_fast::operator = ( a ); + return *this; +} + +#define DEFN_ASN_OP_T(op,tp) \ +inline \ +sc_fix_fast& \ +sc_fix_fast::operator op ( tp a ) \ +{ \ + sc_fxnum_fast::operator op( a ); \ + return *this; \ +} + +#ifndef SC_FX_EXCLUDE_OTHER +#define DEFN_ASN_OP_OTHER(op) \ +DEFN_ASN_OP_T(op,int64) \ +DEFN_ASN_OP_T(op,uint64) \ +DEFN_ASN_OP_T(op,const sc_int_base&) \ +DEFN_ASN_OP_T(op,const sc_uint_base&) \ +DEFN_ASN_OP_T(op,const sc_signed&) \ +DEFN_ASN_OP_T(op,const sc_unsigned&) +#else +#define DEFN_ASN_OP_OTHER(op) +#endif + +#define DEFN_ASN_OP(op) \ +DEFN_ASN_OP_T(op,int) \ +DEFN_ASN_OP_T(op,unsigned int) \ +DEFN_ASN_OP_T(op,long) \ +DEFN_ASN_OP_T(op,unsigned long) \ +DEFN_ASN_OP_T(op,float) \ +DEFN_ASN_OP_T(op,double) \ +DEFN_ASN_OP_T(op,const char*) \ +DEFN_ASN_OP_T(op,const sc_fxval&) \ +DEFN_ASN_OP_T(op,const sc_fxval_fast&) \ +DEFN_ASN_OP_T(op,const sc_fxnum&) \ +DEFN_ASN_OP_T(op,const sc_fxnum_fast&) \ +DEFN_ASN_OP_OTHER(op) + +DEFN_ASN_OP(=) + +DEFN_ASN_OP(*=) +DEFN_ASN_OP(/=) +DEFN_ASN_OP(+=) +DEFN_ASN_OP(-=) + +DEFN_ASN_OP_T(<<=,int) +DEFN_ASN_OP_T(>>=,int) + +#undef DEFN_ASN_OP_T +#undef DEFN_ASN_OP_OTHER +#undef DEFN_ASN_OP + + +#define DEFN_ASN_OP_T(op,op2,tp) \ +inline \ +sc_fix_fast& \ +sc_fix_fast::operator op ( const tp& b ) \ +{ \ + SC_FXNUM_FAST_OBSERVER_READ_( *this ) \ + b.observer_read(); \ + int iwl_c = iwl(); \ + for( int i = iwl_c - wl(); i < iwl_c; ++ i ) \ + set_bit( i, get_bit( i ) op2 b.get_bit( i ) ); \ + cast(); \ + SC_FXNUM_FAST_OBSERVER_WRITE_( *this ) \ + return *this; \ +} + +DEFN_ASN_OP_T(&=,&&,sc_fix) +DEFN_ASN_OP_T(&=,&&,sc_fix_fast) +DEFN_ASN_OP_T(|=,||,sc_fix) +DEFN_ASN_OP_T(|=,||,sc_fix_fast) +DEFN_ASN_OP_T(^=,!=,sc_fix) +DEFN_ASN_OP_T(^=,!=,sc_fix_fast) + +#undef DEFN_ASN_OP_T + + +// auto-increment and auto-decrement + +inline +const sc_fxval_fast +sc_fix_fast::operator ++ ( int ) +{ + return sc_fxval_fast( sc_fxnum_fast::operator ++ ( 0 ) ); +} + +inline +const sc_fxval_fast +sc_fix_fast::operator -- ( int ) +{ + return sc_fxval_fast( sc_fxnum_fast::operator -- ( 0 ) ); +} + +inline +sc_fix_fast& +sc_fix_fast::operator ++ () +{ + sc_fxnum_fast::operator ++ (); + return *this; +} + +inline +sc_fix_fast& +sc_fix_fast::operator -- () +{ + sc_fxnum_fast::operator -- (); + return *this; +} + +} // namespace sc_dt + + +#endif + +// Taf! diff --git a/ext/systemc/src/sysc/datatypes/fx/sc_fixed.h b/ext/systemc/src/sysc/datatypes/fx/sc_fixed.h new file mode 100644 index 000000000..b885da1f9 --- /dev/null +++ b/ext/systemc/src/sysc/datatypes/fx/sc_fixed.h @@ -0,0 +1,660 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_fixed.h - + + Original Author: Martin Janssen, Synopsys, Inc. + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + +// $Log: sc_fixed.h,v $ +// Revision 1.2 2011/01/19 18:57:40 acg +// Andy Goodrich: changes for IEEE_1666_2011. +// +// Revision 1.1.1.1 2006/12/15 20:20:04 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:53:57 acg +// Andy Goodrich: added $Log command so that CVS comments are reproduced in +// the source. +// + +#ifndef SC_FIXED_H +#define SC_FIXED_H + + +#include "sysc/datatypes/fx/sc_fix.h" + + +namespace sc_dt +{ + +// classes defined in this module +template <int W, int I, sc_q_mode Q, sc_o_mode O, int N> class sc_fixed; +template <int W, int I, sc_q_mode Q, sc_o_mode O, int N> class sc_fixed_fast; + + +// ---------------------------------------------------------------------------- +// TEMPLATE CLASS : sc_fixed +// +// "Constrained" signed fixed-point class; arbitrary precision. +// ---------------------------------------------------------------------------- + +template <int W, int I, + sc_q_mode Q = SC_DEFAULT_Q_MODE_, + sc_o_mode O = SC_DEFAULT_O_MODE_, int N = SC_DEFAULT_N_BITS_> +class sc_fixed : public sc_fix +{ + +public: + + // constructors + + explicit sc_fixed( sc_fxnum_observer* = 0 ); + explicit sc_fixed( const sc_fxcast_switch&, sc_fxnum_observer* = 0 ); + +#define DECL_CTORS_T_A(tp) \ + sc_fixed( tp, sc_fxnum_observer* = 0 ); \ + sc_fixed( tp, const sc_fxcast_switch&, sc_fxnum_observer* = 0 ); + +#define DECL_CTORS_T_B(tp) \ + explicit sc_fixed( tp, sc_fxnum_observer* = 0 ); \ + sc_fixed( tp, const sc_fxcast_switch&, sc_fxnum_observer* = 0 ); + + DECL_CTORS_T_A(int) + DECL_CTORS_T_A(unsigned int) + DECL_CTORS_T_A(long) + DECL_CTORS_T_A(unsigned long) + DECL_CTORS_T_A(float) + DECL_CTORS_T_A(double) + DECL_CTORS_T_A(const char*) + DECL_CTORS_T_A(const sc_fxval&) + DECL_CTORS_T_A(const sc_fxval_fast&) + DECL_CTORS_T_A(const sc_fxnum&) + DECL_CTORS_T_A(const sc_fxnum_fast&) +#ifndef SC_FX_EXCLUDE_OTHER + DECL_CTORS_T_B(int64) + DECL_CTORS_T_B(uint64) + DECL_CTORS_T_B(const sc_int_base&) + DECL_CTORS_T_B(const sc_uint_base&) + DECL_CTORS_T_B(const sc_signed&) + DECL_CTORS_T_B(const sc_unsigned&) +#endif + +#undef DECL_CTORS_T_A +#undef DECL_CTORS_T_B + + // copy constructor + + sc_fixed( const sc_fixed<W,I,Q,O,N>& ); + + + // assignment operators + + sc_fixed& operator = ( const sc_fixed<W,I,Q,O,N>& ); + +#define DECL_ASN_OP_T(op,tp) \ + sc_fixed& operator op ( tp ); + +#ifndef SC_FX_EXCLUDE_OTHER +#define DECL_ASN_OP_OTHER(op) \ + DECL_ASN_OP_T(op,int64) \ + DECL_ASN_OP_T(op,uint64) \ + DECL_ASN_OP_T(op,const sc_int_base&) \ + DECL_ASN_OP_T(op,const sc_uint_base&) \ + DECL_ASN_OP_T(op,const sc_signed&) \ + DECL_ASN_OP_T(op,const sc_unsigned&) +#else +#define DECL_ASN_OP_OTHER(op) +#endif + +#define DECL_ASN_OP(op) \ + DECL_ASN_OP_T(op,int) \ + DECL_ASN_OP_T(op,unsigned int) \ + DECL_ASN_OP_T(op,long) \ + DECL_ASN_OP_T(op,unsigned long) \ + DECL_ASN_OP_T(op,float) \ + DECL_ASN_OP_T(op,double) \ + DECL_ASN_OP_T(op,const char*) \ + DECL_ASN_OP_T(op,const sc_fxval&) \ + DECL_ASN_OP_T(op,const sc_fxval_fast&) \ + DECL_ASN_OP_T(op,const sc_fxnum&) \ + DECL_ASN_OP_T(op,const sc_fxnum_fast&) \ + DECL_ASN_OP_OTHER(op) + + DECL_ASN_OP(=) + + DECL_ASN_OP(*=) + DECL_ASN_OP(/=) + DECL_ASN_OP(+=) + DECL_ASN_OP(-=) + + DECL_ASN_OP_T(<<=,int) + DECL_ASN_OP_T(>>=,int) + + DECL_ASN_OP_T(&=,const sc_fix&) + DECL_ASN_OP_T(&=,const sc_fix_fast&) + DECL_ASN_OP_T(|=,const sc_fix&) + DECL_ASN_OP_T(|=,const sc_fix_fast&) + DECL_ASN_OP_T(^=,const sc_fix&) + DECL_ASN_OP_T(^=,const sc_fix_fast&) + +#undef DECL_ASN_OP_T +#undef DECL_ASN_OP_OTHER +#undef DECL_ASN_OP + + + // auto-increment and auto-decrement + + const sc_fxval operator ++ ( int ); + const sc_fxval operator -- ( int ); + + sc_fixed& operator ++ (); + sc_fixed& operator -- (); + +}; + + +// ---------------------------------------------------------------------------- +// TEMPLATE CLASS : sc_fixed_fast +// +// "Constrained" signed fixed-point class; limited precision. +// ---------------------------------------------------------------------------- + +template <int W, int I, + sc_q_mode Q = SC_DEFAULT_Q_MODE_, + sc_o_mode O = SC_DEFAULT_O_MODE_, int N = SC_DEFAULT_N_BITS_> +class sc_fixed_fast : public sc_fix_fast +{ + +public: + + // constructors + + explicit sc_fixed_fast( sc_fxnum_fast_observer* = 0 ); + explicit sc_fixed_fast( const sc_fxcast_switch&, + sc_fxnum_fast_observer* = 0 ); + +#define DECL_CTORS_T_A(tp) \ + sc_fixed_fast( tp, sc_fxnum_fast_observer* = 0 ); \ + sc_fixed_fast( tp, const sc_fxcast_switch&, \ + sc_fxnum_fast_observer* = 0 ); + +#define DECL_CTORS_T_B(tp) \ + explicit sc_fixed_fast( tp, sc_fxnum_fast_observer* = 0 ); \ + sc_fixed_fast( tp, const sc_fxcast_switch&, \ + sc_fxnum_fast_observer* = 0 ); + + DECL_CTORS_T_A(int) + DECL_CTORS_T_A(unsigned int) + DECL_CTORS_T_A(long) + DECL_CTORS_T_A(unsigned long) + DECL_CTORS_T_A(float) + DECL_CTORS_T_A(double) + DECL_CTORS_T_A(const char*) + DECL_CTORS_T_A(const sc_fxval&) + DECL_CTORS_T_A(const sc_fxval_fast&) + DECL_CTORS_T_A(const sc_fxnum&) + DECL_CTORS_T_A(const sc_fxnum_fast&) +#ifndef SC_FX_EXCLUDE_OTHER + DECL_CTORS_T_B(int64) + DECL_CTORS_T_B(uint64) + DECL_CTORS_T_B(const sc_int_base&) + DECL_CTORS_T_B(const sc_uint_base&) + DECL_CTORS_T_B(const sc_signed&) + DECL_CTORS_T_B(const sc_unsigned&) +#endif + +#undef DECL_CTORS_T_A +#undef DECL_CTORS_T_B + + // copy constructor + + sc_fixed_fast( const sc_fixed_fast<W,I,Q,O,N>& ); + + + // assignment operators + + sc_fixed_fast& operator = ( const sc_fixed_fast<W,I,Q,O,N>& ); + +#define DECL_ASN_OP_T(op,tp) \ + sc_fixed_fast& operator op ( tp ); + +#ifndef SC_FX_EXCLUDE_OTHER +#define DECL_ASN_OP_OTHER(op) \ + DECL_ASN_OP_T(op,int64) \ + DECL_ASN_OP_T(op,uint64) \ + DECL_ASN_OP_T(op,const sc_int_base&) \ + DECL_ASN_OP_T(op,const sc_uint_base&) \ + DECL_ASN_OP_T(op,const sc_signed&) \ + DECL_ASN_OP_T(op,const sc_unsigned&) +#else +#define DECL_ASN_OP_OTHER(op) +#endif + +#define DECL_ASN_OP(op) \ + DECL_ASN_OP_T(op,int) \ + DECL_ASN_OP_T(op,unsigned int) \ + DECL_ASN_OP_T(op,long) \ + DECL_ASN_OP_T(op,unsigned long) \ + DECL_ASN_OP_T(op,float) \ + DECL_ASN_OP_T(op,double) \ + DECL_ASN_OP_T(op,const char*) \ + DECL_ASN_OP_T(op,const sc_fxval&) \ + DECL_ASN_OP_T(op,const sc_fxval_fast&) \ + DECL_ASN_OP_T(op,const sc_fxnum&) \ + DECL_ASN_OP_T(op,const sc_fxnum_fast&) \ + DECL_ASN_OP_OTHER(op) + + DECL_ASN_OP(=) + + DECL_ASN_OP(*=) + DECL_ASN_OP(/=) + DECL_ASN_OP(+=) + DECL_ASN_OP(-=) + + DECL_ASN_OP_T(<<=,int) + DECL_ASN_OP_T(>>=,int) + + DECL_ASN_OP_T(&=,const sc_fix&) + DECL_ASN_OP_T(&=,const sc_fix_fast&) + DECL_ASN_OP_T(|=,const sc_fix&) + DECL_ASN_OP_T(|=,const sc_fix_fast&) + DECL_ASN_OP_T(^=,const sc_fix&) + DECL_ASN_OP_T(^=,const sc_fix_fast&) + +#undef DECL_ASN_OP_T +#undef DECL_ASN_OP_OTHER +#undef DECL_ASN_OP + + + // auto-increment and auto-decrement + + const sc_fxval_fast operator ++ ( int ); + const sc_fxval_fast operator -- ( int ); + + sc_fixed_fast& operator ++ (); + sc_fixed_fast& operator -- (); + +}; + + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + +// ---------------------------------------------------------------------------- +// TEMPLATE CLASS : sc_fixed +// +// "Constrained" signed fixed-point class; arbitrary precision. +// ---------------------------------------------------------------------------- + +template<int W, int I, sc_q_mode Q, sc_o_mode O, int N> +inline +sc_fixed<W,I,Q,O,N>::sc_fixed( sc_fxnum_observer* observer_ ) +: sc_fix( W, I, Q, O, N, observer_ ) +{} + +template<int W, int I, sc_q_mode Q, sc_o_mode O, int N> +inline +sc_fixed<W,I,Q,O,N>::sc_fixed( const sc_fxcast_switch& cast_sw, + sc_fxnum_observer* observer_ ) +: sc_fix( W, I, Q, O, N, cast_sw, observer_ ) +{} + +#define DEFN_CTORS_T(tp) \ +template<int W, int I, sc_q_mode Q, sc_o_mode O, int N> \ +inline \ +sc_fixed<W,I,Q,O,N>::sc_fixed( tp a, \ + sc_fxnum_observer* observer_ ) \ +: sc_fix( a, W, I, Q, O, N, observer_ ) \ +{} \ + \ +template<int W, int I, sc_q_mode Q, sc_o_mode O, int N> \ +inline \ +sc_fixed<W,I,Q,O,N>::sc_fixed( tp a, \ + const sc_fxcast_switch& cast_sw, \ + sc_fxnum_observer* observer_ ) \ +: sc_fix( a, W, I, Q, O, N, cast_sw, observer_ ) \ +{} + +DEFN_CTORS_T(int) +DEFN_CTORS_T(unsigned int) +DEFN_CTORS_T(long) +DEFN_CTORS_T(unsigned long) +DEFN_CTORS_T(float) +DEFN_CTORS_T(double) +DEFN_CTORS_T(const char*) +DEFN_CTORS_T(const sc_fxval&) +DEFN_CTORS_T(const sc_fxval_fast&) +DEFN_CTORS_T(const sc_fxnum&) +DEFN_CTORS_T(const sc_fxnum_fast&) +#ifndef SC_FX_EXCLUDE_OTHER +DEFN_CTORS_T(int64) +DEFN_CTORS_T(uint64) +DEFN_CTORS_T(const sc_int_base&) +DEFN_CTORS_T(const sc_uint_base&) +DEFN_CTORS_T(const sc_signed&) +DEFN_CTORS_T(const sc_unsigned&) +#endif + +#undef DEFN_CTORS_T + +// copy constructor + +template<int W, int I, sc_q_mode Q, sc_o_mode O, int N> +inline +sc_fixed<W,I,Q,O,N>::sc_fixed( const sc_fixed<W,I,Q,O,N>& a ) +: sc_fix( a, W, I, Q, O, N ) +{} + + +// assignment operators + +template<int W, int I, sc_q_mode Q, sc_o_mode O, int N> +inline +sc_fixed<W,I,Q,O,N>& +sc_fixed<W,I,Q,O,N>::operator = ( const sc_fixed<W,I,Q,O,N>& a ) +{ + sc_fix::operator = ( a ); + return *this; +} + +#define DEFN_ASN_OP_T(op,tp) \ +template<int W, int I, sc_q_mode Q, sc_o_mode O, int N> \ +inline \ +sc_fixed<W,I,Q,O,N>& \ +sc_fixed<W,I,Q,O,N>::operator op ( tp a ) \ +{ \ + sc_fix::operator op ( a ); \ + return *this; \ +} + +#ifndef SC_FX_EXCLUDE_OTHER +#define DEFN_ASN_OP_OTHER(op) \ +DEFN_ASN_OP_T(op,int64) \ +DEFN_ASN_OP_T(op,uint64) \ +DEFN_ASN_OP_T(op,const sc_int_base&) \ +DEFN_ASN_OP_T(op,const sc_uint_base&) \ +DEFN_ASN_OP_T(op,const sc_signed&) \ +DEFN_ASN_OP_T(op,const sc_unsigned&) +#else +#define DEFN_ASN_OP_OTHER(op) +#endif + +#define DEFN_ASN_OP(op) \ +DEFN_ASN_OP_T(op,int) \ +DEFN_ASN_OP_T(op,unsigned int) \ +DEFN_ASN_OP_T(op,long) \ +DEFN_ASN_OP_T(op,unsigned long) \ +DEFN_ASN_OP_T(op,float) \ +DEFN_ASN_OP_T(op,double) \ +DEFN_ASN_OP_T(op,const char*) \ +DEFN_ASN_OP_T(op,const sc_fxval&) \ +DEFN_ASN_OP_T(op,const sc_fxval_fast&) \ +DEFN_ASN_OP_T(op,const sc_fxnum&) \ +DEFN_ASN_OP_T(op,const sc_fxnum_fast&) \ +DEFN_ASN_OP_OTHER(op) + +DEFN_ASN_OP(=) + +DEFN_ASN_OP(*=) +DEFN_ASN_OP(/=) +DEFN_ASN_OP(+=) +DEFN_ASN_OP(-=) + +DEFN_ASN_OP_T(<<=,int) +DEFN_ASN_OP_T(>>=,int) + +DEFN_ASN_OP_T(&=,const sc_fix&) +DEFN_ASN_OP_T(&=,const sc_fix_fast&) +DEFN_ASN_OP_T(|=,const sc_fix&) +DEFN_ASN_OP_T(|=,const sc_fix_fast&) +DEFN_ASN_OP_T(^=,const sc_fix&) +DEFN_ASN_OP_T(^=,const sc_fix_fast&) + +#undef DEFN_ASN_OP_T +#undef DEFN_ASN_OP_OTHER +#undef DEFN_ASN_OP + + +// auto-increment and auto-decrement + +template<int W, int I, sc_q_mode Q, sc_o_mode O, int N> +inline +const sc_fxval +sc_fixed<W,I,Q,O,N>::operator ++ ( int ) +{ + return sc_fxval( sc_fix::operator ++ ( 0 ) ); +} + +template<int W, int I, sc_q_mode Q, sc_o_mode O, int N> +inline +const sc_fxval +sc_fixed<W,I,Q,O,N>::operator -- ( int ) +{ + return sc_fxval( sc_fix::operator -- ( 0 ) ); +} + +template<int W, int I, sc_q_mode Q, sc_o_mode O, int N> +inline +sc_fixed<W,I,Q,O,N>& +sc_fixed<W,I,Q,O,N>::operator ++ () +{ + sc_fix::operator ++ (); + return *this; +} + +template<int W, int I, sc_q_mode Q, sc_o_mode O, int N> +inline +sc_fixed<W,I,Q,O,N>& +sc_fixed<W,I,Q,O,N>::operator -- () +{ + sc_fix::operator -- (); + return *this; +} + + +// ---------------------------------------------------------------------------- +// TEMPLATE CLASS : sc_fixed_fast +// +// "Constrained" signed fixed-point class; limited precision. +// ---------------------------------------------------------------------------- + +template<int W, int I, sc_q_mode Q, sc_o_mode O, int N> +inline +sc_fixed_fast<W,I,Q,O,N>::sc_fixed_fast( sc_fxnum_fast_observer* observer_ ) +: sc_fix_fast( W, I, Q, O, N, observer_ ) +{} + +template<int W, int I, sc_q_mode Q, sc_o_mode O, int N> +inline +sc_fixed_fast<W,I,Q,O,N>::sc_fixed_fast( const sc_fxcast_switch& cast_sw, + sc_fxnum_fast_observer* observer_ ) +: sc_fix_fast( W, I, Q, O, N, cast_sw, observer_ ) +{} + +#define DEFN_CTORS_T(tp) \ +template<int W, int I, sc_q_mode Q, sc_o_mode O, int N> \ +inline \ +sc_fixed_fast<W,I,Q,O,N>::sc_fixed_fast( tp a, \ + sc_fxnum_fast_observer* observer_ ) \ +: sc_fix_fast( a, W, I, Q, O, N, observer_ ) \ +{} \ + \ +template<int W, int I, sc_q_mode Q, sc_o_mode O, int N> \ +inline \ +sc_fixed_fast<W,I,Q,O,N>::sc_fixed_fast( tp a, \ + const sc_fxcast_switch& cast_sw, \ + sc_fxnum_fast_observer* observer_ ) \ +: sc_fix_fast( a, W, I, Q, O, N, cast_sw, observer_ ) \ +{} + +DEFN_CTORS_T(int) +DEFN_CTORS_T(unsigned int) +DEFN_CTORS_T(long) +DEFN_CTORS_T(unsigned long) +DEFN_CTORS_T(float) +DEFN_CTORS_T(double) +DEFN_CTORS_T(const char*) +DEFN_CTORS_T(const sc_fxval&) +DEFN_CTORS_T(const sc_fxval_fast&) +DEFN_CTORS_T(const sc_fxnum&) +DEFN_CTORS_T(const sc_fxnum_fast&) +#ifndef SC_FX_EXCLUDE_OTHER +DEFN_CTORS_T(int64) +DEFN_CTORS_T(uint64) +DEFN_CTORS_T(const sc_int_base&) +DEFN_CTORS_T(const sc_uint_base&) +DEFN_CTORS_T(const sc_signed&) +DEFN_CTORS_T(const sc_unsigned&) +#endif + +#undef DEFN_CTORS_T + +// copy constructor + +template<int W, int I, sc_q_mode Q, sc_o_mode O, int N> +inline +sc_fixed_fast<W,I,Q,O,N>::sc_fixed_fast( const sc_fixed_fast<W,I,Q,O,N>& a ) +: sc_fix_fast( a, W, I, Q, O, N ) +{} + + +// assignment operators + +template<int W, int I, sc_q_mode Q, sc_o_mode O, int N> +inline +sc_fixed_fast<W,I,Q,O,N>& +sc_fixed_fast<W,I,Q,O,N>::operator = ( const sc_fixed_fast<W,I,Q,O,N>& a ) +{ + sc_fix_fast::operator = ( a ); + return *this; +} + +#define DEFN_ASN_OP_T(op,tp) \ +template<int W, int I, sc_q_mode Q, sc_o_mode O, int N> \ +inline \ +sc_fixed_fast<W,I,Q,O,N>& \ +sc_fixed_fast<W,I,Q,O,N>::operator op ( tp a ) \ +{ \ + sc_fix_fast::operator op ( a ); \ + return *this; \ +} + +#ifndef SC_FX_EXCLUDE_OTHER +#define DEFN_ASN_OP_OTHER(op) \ +DEFN_ASN_OP_T(op,int64) \ +DEFN_ASN_OP_T(op,uint64) \ +DEFN_ASN_OP_T(op,const sc_int_base&) \ +DEFN_ASN_OP_T(op,const sc_uint_base&) \ +DEFN_ASN_OP_T(op,const sc_signed&) \ +DEFN_ASN_OP_T(op,const sc_unsigned&) +#else +#define DEFN_ASN_OP_OTHER(op) +#endif + +#define DEFN_ASN_OP(op) \ +DEFN_ASN_OP_T(op,int) \ +DEFN_ASN_OP_T(op,unsigned int) \ +DEFN_ASN_OP_T(op,long) \ +DEFN_ASN_OP_T(op,unsigned long) \ +DEFN_ASN_OP_T(op,float) \ +DEFN_ASN_OP_T(op,double) \ +DEFN_ASN_OP_T(op,const char*) \ +DEFN_ASN_OP_T(op,const sc_fxval&) \ +DEFN_ASN_OP_T(op,const sc_fxval_fast&) \ +DEFN_ASN_OP_T(op,const sc_fxnum&) \ +DEFN_ASN_OP_T(op,const sc_fxnum_fast&) \ +DEFN_ASN_OP_OTHER(op) + +DEFN_ASN_OP(=) + +DEFN_ASN_OP(*=) +DEFN_ASN_OP(/=) +DEFN_ASN_OP(+=) +DEFN_ASN_OP(-=) + +DEFN_ASN_OP_T(<<=,int) +DEFN_ASN_OP_T(>>=,int) + +DEFN_ASN_OP_T(&=,const sc_fix&) +DEFN_ASN_OP_T(&=,const sc_fix_fast&) +DEFN_ASN_OP_T(|=,const sc_fix&) +DEFN_ASN_OP_T(|=,const sc_fix_fast&) +DEFN_ASN_OP_T(^=,const sc_fix&) +DEFN_ASN_OP_T(^=,const sc_fix_fast&) + +#undef DEFN_ASN_OP_T +#undef DEFN_ASN_OP_OTHER +#undef DEFN_ASN_OP + + +// auto-increment and auto-decrement + +template<int W, int I, sc_q_mode Q, sc_o_mode O, int N> +inline +const sc_fxval_fast +sc_fixed_fast<W,I,Q,O,N>::operator ++ ( int ) +{ + return sc_fxval_fast( sc_fix_fast::operator ++ ( 0 ) ); +} + +template<int W, int I, sc_q_mode Q, sc_o_mode O, int N> +inline +const sc_fxval_fast +sc_fixed_fast<W,I,Q,O,N>::operator -- ( int ) +{ + return sc_fxval_fast( sc_fix_fast::operator -- ( 0 ) ); +} + +template<int W, int I, sc_q_mode Q, sc_o_mode O, int N> +inline +sc_fixed_fast<W,I,Q,O,N>& +sc_fixed_fast<W,I,Q,O,N>::operator ++ () +{ + sc_fix_fast::operator ++ (); + return *this; +} + +template<int W, int I, sc_q_mode Q, sc_o_mode O, int N> +inline +sc_fixed_fast<W,I,Q,O,N>& +sc_fixed_fast<W,I,Q,O,N>::operator -- () +{ + sc_fix_fast::operator -- (); + return *this; +} + +} // namespace sc_dt + + +#endif + +// Taf! diff --git a/ext/systemc/src/sysc/datatypes/fx/sc_fx_ids.h b/ext/systemc/src/sysc/datatypes/fx/sc_fx_ids.h new file mode 100644 index 000000000..b40c2dc48 --- /dev/null +++ b/ext/systemc/src/sysc/datatypes/fx/sc_fx_ids.h @@ -0,0 +1,96 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_fx_ids.h -- Report ids for the datatypes/fx code. + + Original Author: Martin Janssen, Synopsys, Inc., 2002-01-17 + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + +// $Log: sc_fx_ids.h,v $ +// Revision 1.1.1.1 2006/12/15 20:20:04 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:53:57 acg +// Andy Goodrich: added $Log command so that CVS comments are reproduced in +// the source. +// + +#ifndef SC_FX_IDS_H +#define SC_FX_IDS_H + + +#include "sysc/utils/sc_report.h" + + +// ---------------------------------------------------------------------------- +// Report ids (datatypes/fx) +// +// Report ids in the range of 300-399. +// ---------------------------------------------------------------------------- + +#ifndef SC_DEFINE_MESSAGE +#define SC_DEFINE_MESSAGE(id,unused1,unused2) \ + namespace sc_core { extern const char id[]; } +namespace sc_core { + extern const char SC_ID_REGISTER_ID_FAILED_[]; // in sc_report_handler.cpp +} +#endif + + +SC_DEFINE_MESSAGE( SC_ID_INVALID_WL_, 300, + "total wordlength <= 0 is not valid" ) +SC_DEFINE_MESSAGE( SC_ID_INVALID_N_BITS_, 301, + "number of bits < 0 is not valid" ) +SC_DEFINE_MESSAGE( SC_ID_INVALID_DIV_WL_, 302, + "division wordlength <= 0 is not valid" ) +SC_DEFINE_MESSAGE( SC_ID_INVALID_CTE_WL_, 303, + "constant wordlength <= 0 is not valid" ) +SC_DEFINE_MESSAGE( SC_ID_INVALID_MAX_WL_, 304, + "maximum wordlength <= 0 and != -1 is not valid" ) +SC_DEFINE_MESSAGE( SC_ID_INVALID_FX_VALUE_, 305, + "invalid fixed-point value" ) +SC_DEFINE_MESSAGE( SC_ID_INVALID_O_MODE_, 306, + "invalid overflow mode" ) +SC_DEFINE_MESSAGE( SC_ID_OUT_OF_RANGE_, 307, + "index out of range" ) +SC_DEFINE_MESSAGE( SC_ID_CONTEXT_BEGIN_FAILED_, 308, + "context begin failed" ) +SC_DEFINE_MESSAGE( SC_ID_CONTEXT_END_FAILED_, 309, + "context end failed" ) +SC_DEFINE_MESSAGE( SC_ID_WRAP_SM_NOT_DEFINED_, 310, + "SC_WRAP_SM not defined for unsigned numbers" ) + + + +#endif + +// Taf! diff --git a/ext/systemc/src/sysc/datatypes/fx/sc_fxcast_switch.cpp b/ext/systemc/src/sysc/datatypes/fx/sc_fxcast_switch.cpp new file mode 100644 index 000000000..c5c5a939c --- /dev/null +++ b/ext/systemc/src/sysc/datatypes/fx/sc_fxcast_switch.cpp @@ -0,0 +1,88 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_fxcast_switch.cpp - + + Original Author: Martin Janssen, Synopsys, Inc. + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: Gene Bushuyev, Synopsys, Inc. + Description of Modification: - fix explicit instantiation syntax. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + + +// $Log: sc_fxcast_switch.cpp,v $ +// Revision 1.1.1.1 2006/12/15 20:20:04 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:53:57 acg +// Andy Goodrich: added $Log command so that CVS comments are reproduced in +// the source. +// + +#include "sysc/datatypes/fx/sc_fxcast_switch.h" + + +namespace sc_dt +{ + +// ---------------------------------------------------------------------------- +// CLASS : sc_fxcast_switch +// +// Fixed-point cast switch class. +// ---------------------------------------------------------------------------- + +const std::string +sc_fxcast_switch::to_string() const +{ + return sc_dt::to_string( m_sw ); +} + + +void +sc_fxcast_switch::print( ::std::ostream& os ) const +{ + os << sc_dt::to_string( m_sw ); +} + +void +sc_fxcast_switch::dump( ::std::ostream& os ) const +{ + os << "sc_fxcast_switch" << ::std::endl; + os << "(" << ::std::endl; + os << "sw = " << sc_dt::to_string( m_sw ) << ::std::endl; + os << ")" << ::std::endl; +} + +} // namespace sc_dt + + +// Taf! diff --git a/ext/systemc/src/sysc/datatypes/fx/sc_fxcast_switch.h b/ext/systemc/src/sysc/datatypes/fx/sc_fxcast_switch.h new file mode 100644 index 000000000..6bfbd25a4 --- /dev/null +++ b/ext/systemc/src/sysc/datatypes/fx/sc_fxcast_switch.h @@ -0,0 +1,174 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_fxcast_switch.h - + + Original Author: Martin Janssen, Synopsys, Inc. + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + +// $Log: sc_fxcast_switch.h,v $ +// Revision 1.2 2011/08/24 22:05:43 acg +// Torsten Maehne: initialization changes to remove warnings. +// +// Revision 1.1.1.1 2006/12/15 20:20:04 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:53:57 acg +// Andy Goodrich: added $Log command so that CVS comments are reproduced in +// the source. +// + +#ifndef SC_FXCAST_SWITCH_H +#define SC_FXCAST_SWITCH_H + + +#include "sysc/datatypes/fx/sc_context.h" + + +namespace sc_dt +{ + +// classes defined in this module +class sc_fxcast_switch; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_fxcast_switch +// +// Fixed-point cast switch class. +// ---------------------------------------------------------------------------- + +class sc_fxcast_switch +{ + +public: + + sc_fxcast_switch(); + sc_fxcast_switch( sc_switch ); + sc_fxcast_switch( const sc_fxcast_switch& ); + explicit sc_fxcast_switch( sc_without_context ); + + sc_fxcast_switch& operator = ( const sc_fxcast_switch& ); + + friend bool operator == ( const sc_fxcast_switch&, + const sc_fxcast_switch& ); + friend bool operator != ( const sc_fxcast_switch&, + const sc_fxcast_switch& ); + + const std::string to_string() const; + + void print( ::std::ostream& = ::std::cout ) const; + void dump( ::std::ostream& = ::std::cout ) const; + +private: + + sc_switch m_sw; + +}; + + +// ---------------------------------------------------------------------------- +// TYPEDEF : sc_fxcast_context +// +// Context type for the fixed-point cast switch parameter. +// ---------------------------------------------------------------------------- + +typedef sc_context<sc_fxcast_switch> sc_fxcast_context; + + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + +inline +sc_fxcast_switch::sc_fxcast_switch() +: m_sw() +{ + *this = sc_fxcast_context::default_value(); +} + +inline +sc_fxcast_switch::sc_fxcast_switch( sc_switch sw_ ) +: m_sw( sw_ ) +{} + +inline +sc_fxcast_switch::sc_fxcast_switch( const sc_fxcast_switch& a ) +: m_sw( a.m_sw ) +{} + +inline +sc_fxcast_switch::sc_fxcast_switch( sc_without_context ) +: m_sw( SC_DEFAULT_CAST_SWITCH_ ) +{} + + +inline +sc_fxcast_switch& +sc_fxcast_switch::operator = ( const sc_fxcast_switch& a ) +{ + if( &a != this ) + { + m_sw = a.m_sw; + } + return *this; +} + + +inline +bool +operator == ( const sc_fxcast_switch& a, const sc_fxcast_switch& b ) +{ + return ( a.m_sw == b.m_sw ); +} + + +inline +bool +operator != ( const sc_fxcast_switch& a, const sc_fxcast_switch& b ) +{ + return ( a.m_sw != b.m_sw ); +} + + +inline +::std::ostream& +operator << ( ::std::ostream& os, const sc_fxcast_switch& a ) +{ + a.print( os ); + return os; +} + +} // namespace sc_dt + + +#endif + +// Taf! diff --git a/ext/systemc/src/sysc/datatypes/fx/sc_fxdefs.cpp b/ext/systemc/src/sysc/datatypes/fx/sc_fxdefs.cpp new file mode 100644 index 000000000..66ade2076 --- /dev/null +++ b/ext/systemc/src/sysc/datatypes/fx/sc_fxdefs.cpp @@ -0,0 +1,175 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_fxdefs.cpp - + + Original Author: Martin Janssen, Synopsys, Inc. + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + + +// $Log: sc_fxdefs.cpp,v $ +// Revision 1.1.1.1 2006/12/15 20:20:04 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:53:57 acg +// Andy Goodrich: added $Log command so that CVS comments are reproduced in +// the source. +// + +#include "sysc/datatypes/fx/sc_fxdefs.h" + + +namespace sc_dt +{ + +// ---------------------------------------------------------------------------- +// ENUM : sc_enc +// +// Enumeration of sign encodings. +// ---------------------------------------------------------------------------- + +const std::string +to_string( sc_enc enc ) +{ + switch( enc ) + { + case SC_TC_: + return std::string( "SC_TC_" ); + case SC_US_: + return std::string( "SC_US_" ); + default: + return std::string( "unknown" ); + } +} + + +// ---------------------------------------------------------------------------- +// ENUM : sc_q_mode +// +// Enumeration of quantization modes. +// ---------------------------------------------------------------------------- + +const std::string +to_string( sc_q_mode q_mode ) +{ + switch( q_mode ) + { + case SC_RND: + return std::string( "SC_RND" ); + case SC_RND_ZERO: + return std::string( "SC_RND_ZERO" ); + case SC_RND_MIN_INF: + return std::string( "SC_RND_MIN_INF" ); + case SC_RND_INF: + return std::string( "SC_RND_INF" ); + case SC_RND_CONV: + return std::string( "SC_RND_CONV" ); + case SC_TRN: + return std::string( "SC_TRN" ); + case SC_TRN_ZERO: + return std::string( "SC_TRN_ZERO" ); + default: + return std::string( "unknown" ); + } +} + + +// ---------------------------------------------------------------------------- +// ENUM : sc_o_mode +// +// Enumeration of overflow modes. +// ---------------------------------------------------------------------------- + +const std::string +to_string( sc_o_mode o_mode ) +{ + switch( o_mode ) + { + case SC_SAT: + return std::string( "SC_SAT" ); + case SC_SAT_ZERO: + return std::string( "SC_SAT_ZERO" ); + case SC_SAT_SYM: + return std::string( "SC_SAT_SYM" ); + case SC_WRAP: + return std::string( "SC_WRAP" ); + case SC_WRAP_SM: + return std::string( "SC_WRAP_SM" ); + default: + return std::string( "unknown" ); + } +} + + +// ---------------------------------------------------------------------------- +// ENUM : sc_switch +// +// Enumeration of switch states. +// ---------------------------------------------------------------------------- + +const std::string +to_string( sc_switch sw ) +{ + switch( sw ) { + case SC_OFF: + return std::string( "SC_OFF" ); + case SC_ON: + return std::string( "SC_ON" ); + default: + return std::string( "unknown" ); + } +} + + +// ---------------------------------------------------------------------------- +// ENUM : sc_fmt +// +// Enumeration of formats for character string conversion. +// ---------------------------------------------------------------------------- + +const std::string +to_string( sc_fmt fmt ) +{ + switch( fmt ) { + case SC_F: + return std::string( "SC_F" ); + case SC_E: + return std::string( "SC_E" ); + default: + return std::string( "unknown" ); + } +} + +} // namespace sc_dt + + +// Taf! diff --git a/ext/systemc/src/sysc/datatypes/fx/sc_fxdefs.h b/ext/systemc/src/sysc/datatypes/fx/sc_fxdefs.h new file mode 100644 index 000000000..1ac1bb707 --- /dev/null +++ b/ext/systemc/src/sysc/datatypes/fx/sc_fxdefs.h @@ -0,0 +1,308 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_fxdefs.h - + + Original Author: Martin Janssen, Synopsys, Inc. + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + +// $Log: sc_fxdefs.h,v $ +// Revision 1.1.1.1 2006/12/15 20:20:04 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:53:57 acg +// Andy Goodrich: added $Log command so that CVS comments are reproduced in +// the source. +// + +#ifndef SC_FXDEFS_H +#define SC_FXDEFS_H + + +#include "sysc/utils/sc_machine.h" +#include "sysc/datatypes/fx/sc_fx_ids.h" +#include "sysc/datatypes/int/sc_nbutils.h" + + +namespace sc_dt +{ + +// ---------------------------------------------------------------------------- +// ENUM : sc_enc +// +// Enumeration of sign encodings. +// ---------------------------------------------------------------------------- + +enum sc_enc +{ + SC_TC_, // two's complement + SC_US_ // unsigned +}; + + +const std::string to_string( sc_enc ); + + +inline +::std::ostream& +operator << ( ::std::ostream& os, sc_enc enc ) +{ + return os << to_string( enc ); +} + + +// ---------------------------------------------------------------------------- +// ENUM : sc_q_mode +// +// Enumeration of quantization modes. +// ---------------------------------------------------------------------------- + +enum sc_q_mode +{ + SC_RND, // rounding to plus infinity + SC_RND_ZERO, // rounding to zero + SC_RND_MIN_INF, // rounding to minus infinity + SC_RND_INF, // rounding to infinity + SC_RND_CONV, // convergent rounding + SC_TRN, // truncation + SC_TRN_ZERO // truncation to zero +}; + + +const std::string to_string( sc_q_mode ); + + +inline +::std::ostream& +operator << ( ::std::ostream& os, sc_q_mode q_mode ) +{ + return os << to_string( q_mode ); +} + + +// ---------------------------------------------------------------------------- +// ENUM : sc_o_mode +// +// Enumeration of overflow modes. +// ---------------------------------------------------------------------------- + +enum sc_o_mode +{ + SC_SAT, // saturation + SC_SAT_ZERO, // saturation to zero + SC_SAT_SYM, // symmetrical saturation + SC_WRAP, // wrap-around (*) + SC_WRAP_SM // sign magnitude wrap-around (*) +}; + +// (*) uses the number of saturated bits argument, see the documentation. + + +const std::string to_string( sc_o_mode ); + + +inline +::std::ostream& +operator << ( ::std::ostream& os, sc_o_mode o_mode ) +{ + return os << to_string( o_mode ); +} + + +// ---------------------------------------------------------------------------- +// ENUM : sc_switch +// +// Enumeration of switch states. +// ---------------------------------------------------------------------------- + +enum sc_switch +{ + SC_OFF, + SC_ON +}; + + +const std::string to_string( sc_switch ); + + +inline +::std::ostream& +operator << ( ::std::ostream& os, sc_switch sw ) +{ + return os << to_string( sw ); +} + + +// ---------------------------------------------------------------------------- +// ENUM : sc_fmt +// +// Enumeration of formats for character string conversion. +// ---------------------------------------------------------------------------- + +enum sc_fmt +{ + SC_F, // fixed + SC_E // scientific +}; + + +const std::string to_string( sc_fmt ); + + +inline +::std::ostream& +operator << ( ::std::ostream& os, sc_fmt fmt ) +{ + return os << to_string( fmt ); +} + + +// ---------------------------------------------------------------------------- +// Built-in & default fixed-point type parameter values. +// ---------------------------------------------------------------------------- + +const int SC_BUILTIN_WL_ = 32; +const int SC_BUILTIN_IWL_ = 32; +const sc_q_mode SC_BUILTIN_Q_MODE_ = SC_TRN; +const sc_o_mode SC_BUILTIN_O_MODE_ = SC_WRAP; +const int SC_BUILTIN_N_BITS_ = 0; + + +const int SC_DEFAULT_WL_ = SC_BUILTIN_WL_; +const int SC_DEFAULT_IWL_ = SC_BUILTIN_IWL_; +const sc_q_mode SC_DEFAULT_Q_MODE_ = SC_BUILTIN_Q_MODE_; +const sc_o_mode SC_DEFAULT_O_MODE_ = SC_BUILTIN_O_MODE_; +const int SC_DEFAULT_N_BITS_ = SC_BUILTIN_N_BITS_; + + +// ---------------------------------------------------------------------------- +// Built-in & default fixed-point cast switch parameter values. +// ---------------------------------------------------------------------------- + +const sc_switch SC_BUILTIN_CAST_SWITCH_ = SC_ON; + + +const sc_switch SC_DEFAULT_CAST_SWITCH_ = SC_BUILTIN_CAST_SWITCH_; + + +// ---------------------------------------------------------------------------- +// Built-in & default fixed-point value type parameter values. +// ---------------------------------------------------------------------------- + +const int SC_BUILTIN_DIV_WL_ = 64; +const int SC_BUILTIN_CTE_WL_ = 64; +const int SC_BUILTIN_MAX_WL_ = 1024; + + +#if defined( SC_FXDIV_WL ) && ( SC_FXDIV_WL > 0 ) +const int SC_DEFAULT_DIV_WL_ = SC_FXDIV_WL; +#else +const int SC_DEFAULT_DIV_WL_ = SC_BUILTIN_DIV_WL_; +#endif + +#if defined( SC_FXCTE_WL ) && ( SC_FXCTE_WL > 0 ) +const int SC_DEFAULT_CTE_WL_ = SC_FXCTE_WL; +#else +const int SC_DEFAULT_CTE_WL_ = SC_BUILTIN_CTE_WL_; +#endif + +#if defined( SC_FXMAX_WL ) && ( SC_FXMAX_WL > 0 || SC_FXMAX_WL == -1 ) +const int SC_DEFAULT_MAX_WL_ = SC_FXMAX_WL; +#else +const int SC_DEFAULT_MAX_WL_ = SC_BUILTIN_MAX_WL_; +#endif + + +// ---------------------------------------------------------------------------- +// Dedicated error reporting and checking. +// ---------------------------------------------------------------------------- + +#ifdef DEBUG_SYSTEMC +#define SC_ASSERT_(cnd,msg) \ +{ \ + if( ! (cnd) ) \ + SC_REPORT_ERROR( sc_core::SC_ID_INTERNAL_ERROR_, msg ); \ +} +#else +#define SC_ASSERT_(cnd,msg) +#endif + +#define SC_ERROR_IF_(cnd,id) \ +{ \ + if( cnd ) \ + SC_REPORT_ERROR( id, 0 ); \ +} + + +#define SC_CHECK_WL_(wl) \ + SC_ERROR_IF_( (wl) <= 0, sc_core::SC_ID_INVALID_WL_ ) + +#define SC_CHECK_N_BITS_(n_bits) \ + SC_ERROR_IF_( (n_bits) < 0, sc_core::SC_ID_INVALID_N_BITS_ ) + +#define SC_CHECK_DIV_WL_(div_wl) \ + SC_ERROR_IF_( (div_wl) <= 0, sc_core::SC_ID_INVALID_DIV_WL_ ) + +#define SC_CHECK_CTE_WL_(cte_wl) \ + SC_ERROR_IF_( (cte_wl) <= 0, sc_core::SC_ID_INVALID_CTE_WL_ ) + +#define SC_CHECK_MAX_WL_(max_wl) \ + SC_ERROR_IF_( (max_wl) <= 0 && (max_wl) != -1, \ + sc_core::SC_ID_INVALID_MAX_WL_ ) + + +// ---------------------------------------------------------------------------- +// Generic observer macros. +// ---------------------------------------------------------------------------- + +#define SC_OBSERVER_(object,observer_type,event) \ +{ \ + if( (object).observer() != 0 ) \ + { \ + observer_type observer = (object).lock_observer(); \ + observer->event( (object) ); \ + (object).unlock_observer( observer ); \ + } \ +} + +#define SC_OBSERVER_DEFAULT_(observer_type) \ +{ \ + if( m_observer == 0 && observer_type ## ::default_observer != 0 ) \ + m_observer = (* ## observer_type ## ::default_observer)(); \ +} + +} // namespace sc_dt + + +#endif + +// Taf! diff --git a/ext/systemc/src/sysc/datatypes/fx/sc_fxnum.cpp b/ext/systemc/src/sysc/datatypes/fx/sc_fxnum.cpp new file mode 100644 index 000000000..520c41854 --- /dev/null +++ b/ext/systemc/src/sysc/datatypes/fx/sc_fxnum.cpp @@ -0,0 +1,958 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_fxnum.cpp - + + Original Author: Martin Janssen, Synopsys, Inc. + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + + +// $Log: sc_fxnum.cpp,v $ +// Revision 1.3 2011/01/19 18:57:40 acg +// Andy Goodrich: changes for IEEE_1666_2011. +// +// Revision 1.2 2010/12/07 20:09:08 acg +// Andy Goodrich: Philipp Hartmann's constructor disambiguation fix +// +// Revision 1.1.1.1 2006/12/15 20:20:04 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:53:57 acg +// Andy Goodrich: added $Log command so that CVS comments are reproduced in +// the source. +// + +#include <math.h> + +#include "sysc/datatypes/fx/sc_fxnum.h" + + +namespace sc_dt +{ + +// ---------------------------------------------------------------------------- +// CLASS : sc_fxnum_bitref +// +// Proxy class for bit-selection in class sc_fxnum, behaves like sc_bit. +// ---------------------------------------------------------------------------- + +bool +sc_fxnum_bitref::get() const +{ + return m_num.get_bit( m_idx ); +} + +void +sc_fxnum_bitref::set( bool high ) +{ + m_num.set_bit( m_idx, high ); +} + + +// print or dump content + +void +sc_fxnum_bitref::print( ::std::ostream& os ) const +{ + os << get(); +} + +void +sc_fxnum_bitref::scan( ::std::istream& is ) +{ + bool b; + is >> b; + *this = b; +} + +void +sc_fxnum_bitref::dump( ::std::ostream& os ) const +{ + os << "sc_fxnum_bitref" << ::std::endl; + os << "(" << ::std::endl; + os << "num = "; + m_num.dump( os ); + os << "idx = " << m_idx << ::std::endl; + os << ")" << ::std::endl; +} + + +// ---------------------------------------------------------------------------- +// CLASS : sc_fxnum_fast_bitref +// +// Proxy class for bit-selection in class sc_fxnum_fast, behaves like sc_bit. +// ---------------------------------------------------------------------------- + +bool +sc_fxnum_fast_bitref::get() const +{ + return m_num.get_bit( m_idx ); +} + +void +sc_fxnum_fast_bitref::set( bool high ) +{ + m_num.set_bit( m_idx, high ); +} + + +// print or dump content + +void +sc_fxnum_fast_bitref::print( ::std::ostream& os ) const +{ + os << get(); +} + +void +sc_fxnum_fast_bitref::scan( ::std::istream& is ) +{ + bool b; + is >> b; + *this = b; +} + +void +sc_fxnum_fast_bitref::dump( ::std::ostream& os ) const +{ + os << "sc_fxnum_fast_bitref" << ::std::endl; + os << "(" << ::std::endl; + os << "num = "; + m_num.dump( os ); + os << "idx = " << m_idx << ::std::endl; + os << ")" << ::std::endl; +} + + +// ---------------------------------------------------------------------------- +// CLASS : sc_fxnum_subref +// +// Proxy class for part-selection in class sc_fxnum, +// behaves like sc_bv_base. +// ---------------------------------------------------------------------------- + +bool +sc_fxnum_subref::get() const +{ + return m_num.get_slice( m_from, m_to, m_bv ); +} + +bool +sc_fxnum_subref::set() +{ + return m_num.set_slice( m_from, m_to, m_bv ); +} + + +// print or dump content + +void +sc_fxnum_subref::print( ::std::ostream& os ) const +{ + get(); + m_bv.print( os ); +} + +void +sc_fxnum_subref::scan( ::std::istream& is ) +{ + m_bv.scan( is ); + set(); +} + +void +sc_fxnum_subref::dump( ::std::ostream& os ) const +{ + os << "sc_fxnum_subref" << ::std::endl; + os << "(" << ::std::endl; + os << "num = "; + m_num.dump( os ); + os << "from = " << m_from << ::std::endl; + os << "to = " << m_to << ::std::endl; + os << ")" << ::std::endl; +} + + +// ---------------------------------------------------------------------------- +// CLASS : sc_fxnum_fast_subref +// +// Proxy class for part-selection in class sc_fxnum_fast, +// behaves like sc_bv_base. +// ---------------------------------------------------------------------------- + +bool +sc_fxnum_fast_subref::get() const +{ + return m_num.get_slice( m_from, m_to, m_bv ); +} + +bool +sc_fxnum_fast_subref::set() +{ + return m_num.set_slice( m_from, m_to, m_bv ); +} + + +// print or dump content + +void +sc_fxnum_fast_subref::print( ::std::ostream& os ) const +{ + get(); + m_bv.print( os ); +} + +void +sc_fxnum_fast_subref::scan( ::std::istream& is ) +{ + m_bv.scan( is ); + set(); +} + +void +sc_fxnum_fast_subref::dump( ::std::ostream& os ) const +{ + os << "sc_fxnum_fast_subref" << ::std::endl; + os << "(" << ::std::endl; + os << "num = "; + m_num.dump( os ); + os << "from = " << m_from << ::std::endl; + os << "to = " << m_to << ::std::endl; + os << ")" << ::std::endl; +} + + +// ---------------------------------------------------------------------------- +// CLASS : sc_fxnum +// +// Base class for the fixed-point types; arbitrary precision. +// ---------------------------------------------------------------------------- + +// explicit conversion to character string + +const std::string +sc_fxnum::to_string() const +{ + return std::string( m_rep->to_string( SC_DEC, -1, SC_F, &m_params ) ); +} + +const std::string +sc_fxnum::to_string( sc_numrep numrep ) const +{ + return std::string( m_rep->to_string( numrep, -1, SC_F, &m_params ) ); +} + +const std::string +sc_fxnum::to_string( sc_numrep numrep, bool w_prefix ) const +{ + return std::string( m_rep->to_string( numrep, (w_prefix ? 1 : 0), + SC_F, &m_params ) ); +} + +const std::string +sc_fxnum::to_string( sc_fmt fmt ) const +{ + return std::string( m_rep->to_string( SC_DEC, -1, fmt, &m_params ) ); +} + +const std::string +sc_fxnum::to_string( sc_numrep numrep, sc_fmt fmt ) const +{ + return std::string( m_rep->to_string( numrep, -1, fmt, &m_params ) ); +} + +const std::string +sc_fxnum::to_string( sc_numrep numrep, bool w_prefix, sc_fmt fmt ) const +{ + return std::string( m_rep->to_string( numrep, (w_prefix ? 1 : 0), + fmt, &m_params ) ); +} + + +const std::string +sc_fxnum::to_dec() const +{ + return std::string( m_rep->to_string( SC_DEC, -1, SC_F, &m_params ) ); +} + +const std::string +sc_fxnum::to_bin() const +{ + return std::string( m_rep->to_string( SC_BIN, -1, SC_F, &m_params ) ); +} + +const std::string +sc_fxnum::to_oct() const +{ + return std::string( m_rep->to_string( SC_OCT, -1, SC_F, &m_params ) ); +} + +const std::string +sc_fxnum::to_hex() const +{ + return std::string( m_rep->to_string( SC_HEX, -1, SC_F, &m_params ) ); +} + + +// print or dump content + +void +sc_fxnum::print( ::std::ostream& os ) const +{ + os << m_rep->to_string( SC_DEC, -1, SC_F, &m_params ); +} + +void +sc_fxnum::scan( ::std::istream& is ) +{ + std::string s; + is >> s; + *this = s.c_str(); +} + +void +sc_fxnum::dump( ::std::ostream& os ) const +{ + os << "sc_fxnum" << ::std::endl; + os << "(" << ::std::endl; + os << "rep = "; + m_rep->dump( os ); + os << "params = "; + m_params.dump( os ); + os << "q_flag = " << m_q_flag << ::std::endl; + os << "o_flag = " << m_o_flag << ::std::endl; + // TO BE COMPLETED + // os << "observer = "; + // if( m_observer != 0 ) + // m_observer->dump( os ); + // else + // os << "0" << ::std::endl; + os << ")" << ::std::endl; +} + + +sc_fxnum_observer* +sc_fxnum::lock_observer() const +{ + SC_ASSERT_( m_observer != 0, "lock observer failed" ); + sc_fxnum_observer* tmp = m_observer; + m_observer = 0; + return tmp; +} + +void +sc_fxnum::unlock_observer( sc_fxnum_observer* observer_ ) const +{ + SC_ASSERT_( observer_ != 0, "unlock observer failed" ); + m_observer = observer_; +} + + +// ---------------------------------------------------------------------------- +// CLASS : sc_fxnum_fast +// +// Base class for the fixed-point types; limited precision. +// ---------------------------------------------------------------------------- + +static +void +quantization( double& c, const scfx_params& params, bool& q_flag ) +{ + int fwl = params.wl() - params.iwl(); + double scale = scfx_pow2( fwl ); + double val = scale * c; + double int_part; + double frac_part = modf( val, &int_part ); + + q_flag = ( frac_part != 0.0 ); + + if( q_flag ) + { + val = int_part; + + switch( params.q_mode() ) + { + case SC_TRN: // truncation + { + if( c < 0.0 ) + val -= 1.0; + break; + } + case SC_RND: // rounding to plus infinity + { + if( frac_part >= 0.5 ) + val += 1.0; + else if( frac_part < -0.5 ) + val -= 1.0; + break; + } + case SC_TRN_ZERO: // truncation to zero + { + break; + } + case SC_RND_INF: // rounding to infinity + { + if( frac_part >= 0.5 ) + val += 1.0; + else if( frac_part <= -0.5 ) + val -= 1.0; + break; + } + case SC_RND_CONV: // convergent rounding + { + if( frac_part > 0.5 || + ( frac_part == 0.5 && fmod( int_part, 2.0 ) != 0.0 ) ) + val += 1.0; + else if( frac_part < -0.5 || + ( frac_part == -0.5 && fmod( int_part, 2.0 ) != 0.0 ) ) + val -= 1.0; + break; + } + case SC_RND_ZERO: // rounding to zero + { + if( frac_part > 0.5 ) + val += 1.0; + else if( frac_part < -0.5 ) + val -= 1.0; + break; + } + case SC_RND_MIN_INF: // rounding to minus infinity + { + if( frac_part > 0.5 ) + val += 1.0; + else if( frac_part <= -0.5 ) + val -= 1.0; + break; + } + default: + ; + } + } + + val /= scale; + c = val; +} + +static +void +overflow( double& c, const scfx_params& params, bool& o_flag ) +{ + int iwl = params.iwl(); + int fwl = params.wl() - iwl; + double full_circle = scfx_pow2( iwl ); + double resolution = scfx_pow2( -fwl ); + double low, high; + if( params.enc() == SC_TC_ ) + { + high = full_circle / 2.0 - resolution; + if( params.o_mode() == SC_SAT_SYM ) + low = - high; + else + low = - full_circle / 2.0; + } + else + { + low = 0.0; + high = full_circle - resolution; + } + double val = c; + sc_fxval_fast c2(c); + + bool under = ( val < low ); + bool over = ( val > high ); + + o_flag = ( under || over ); + + if( o_flag ) + { + switch( params.o_mode() ) + { + case SC_WRAP: // wrap-around + { + int n_bits = params.n_bits(); + + if( n_bits == 0 ) + { + // wrap-around all 'wl' bits + val -= floor( val / full_circle ) * full_circle; + if( val > high ) + val -= full_circle; + } + else if( n_bits < params.wl() ) + { + double X = scfx_pow2( iwl - n_bits ); + + // wrap-around least significant 'wl - n_bits' bits + val -= floor( val / X ) * X; + if( val > ( X - resolution ) ) + val -= X; + + // saturate most significant 'n_bits' bits + if( under ) + val += low; + else + { + if( params.enc() == SC_TC_ ) + val += full_circle / 2.0 - X; + else + val += full_circle - X; + } + } + else + { + // saturate all 'wl' bits + if( under ) + val = low; + else + val = high; + } + break; + } + case SC_SAT: // saturation + case SC_SAT_SYM: // symmetrical saturation + { + if( under ) + val = low; + else + val = high; + break; + } + case SC_SAT_ZERO: // saturation to zero + { + val = 0.0; + break; + } + case SC_WRAP_SM: // sign magnitude wrap-around + { + SC_ERROR_IF_( params.enc() == SC_US_, + sc_core::SC_ID_WRAP_SM_NOT_DEFINED_ ); + + int n_bits = params.n_bits(); + + if( n_bits == 0 ) + { + // invert conditionally + if( c2.get_bit( iwl ) != c2.get_bit( iwl - 1 ) ) + val = -val - resolution; + + // wrap-around all 'wl' bits + val -= floor( val / full_circle ) * full_circle; + if( val > high ) + val -= full_circle; + } + else if( n_bits == 1 ) + { + // invert conditionally + if( c2.is_neg() != c2.get_bit( iwl - 1 ) ) + val = -val - resolution; + + // wrap-around all 'wl' bits + val -= floor( val / full_circle ) * full_circle; + if( val > high ) + val -= full_circle; + } + else if( n_bits < params.wl() ) + { + // invert conditionally + if( c2.is_neg() == c2.get_bit( iwl - n_bits ) ) + val = -val - resolution; + + double X = scfx_pow2( iwl - n_bits ); + + // wrap-around least significant 'wl - n_bits' bits + val -= floor( val / X ) * X; + if( val > ( X - resolution ) ) + val -= X; + + // saturate most significant 'n_bits' bits + if( under ) + val += low; + else + val += full_circle / 2.0 - X; + } else { + // saturate all 'wl' bits + if( under ) + val = low; + else + val = high; + } + break; + } + default: + ; + } + + c = val; + } +} + + +void +sc_fxnum_fast::cast() +{ + scfx_ieee_double id( m_val ); + SC_ERROR_IF_( id.is_nan() || id.is_inf(), sc_core::SC_ID_INVALID_FX_VALUE_); + + if( m_params.cast_switch() == SC_ON ) + { + m_q_flag = false; + m_o_flag = false; + + // check for special cases + + if( id.is_zero() ) + { + if( id.negative() != 0 ) + m_val = -m_val; + return; + } + + // perform casting + + sc_dt::quantization( m_val, m_params, m_q_flag ); + sc_dt::overflow( m_val, m_params, m_o_flag ); + + // check for special case: -0 + + id = m_val; + if( id.is_zero() && id.negative() != 0 ) { + m_val = -m_val; + } + + // check for special case: NaN of Inf + + if( id.is_nan() || id.is_inf() ) { + m_val = 0.0; + } + } +} + + +// defined in sc_fxval.cpp; +extern +const char* +to_string( const scfx_ieee_double&, + sc_numrep, + int, + sc_fmt, + const scfx_params* = 0 ); + + +// explicit conversion to character string + +const std::string +sc_fxnum_fast::to_string() const +{ + return std::string( sc_dt::to_string( m_val, SC_DEC, -1, SC_F, &m_params ) ); +} + +const std::string +sc_fxnum_fast::to_string( sc_numrep numrep ) const +{ + return std::string( sc_dt::to_string( m_val, numrep, -1, SC_F, &m_params ) ); +} + +const std::string +sc_fxnum_fast::to_string( sc_numrep numrep, bool w_prefix ) const +{ + return std::string( sc_dt::to_string( m_val, numrep, (w_prefix ? 1 : 0), + SC_F, &m_params ) ); +} + +const std::string +sc_fxnum_fast::to_string( sc_fmt fmt ) const +{ + return std::string( sc_dt::to_string( m_val, SC_DEC, -1, fmt, &m_params ) ); +} + +const std::string +sc_fxnum_fast::to_string( sc_numrep numrep, sc_fmt fmt ) const +{ + return std::string( sc_dt::to_string( m_val, numrep, -1, fmt, &m_params ) ); +} + +const std::string +sc_fxnum_fast::to_string( sc_numrep numrep, bool w_prefix, sc_fmt fmt ) const +{ + return std::string( sc_dt::to_string( m_val, numrep, (w_prefix ? 1 : 0), + fmt, &m_params ) ); +} + + +const std::string +sc_fxnum_fast::to_dec() const +{ + return std::string( sc_dt::to_string( m_val, SC_DEC, -1, SC_F, &m_params ) ); +} + +const std::string +sc_fxnum_fast::to_bin() const +{ + return std::string( sc_dt::to_string( m_val, SC_BIN, -1, SC_F, &m_params ) ); +} + +const std::string +sc_fxnum_fast::to_oct() const +{ + return std::string( sc_dt::to_string( m_val, SC_OCT, -1, SC_F, &m_params ) ); +} + +const std::string +sc_fxnum_fast::to_hex() const +{ + return std::string( sc_dt::to_string( m_val, SC_HEX, -1, SC_F, &m_params ) ); +} + + +// print or dump content + +void +sc_fxnum_fast::print( ::std::ostream& os ) const +{ + os << sc_dt::to_string( m_val, SC_DEC, -1, SC_F, &m_params ); +} + +void +sc_fxnum_fast::scan( ::std::istream& is ) +{ + std::string s; + is >> s; + *this = s.c_str(); +} + +void +sc_fxnum_fast::dump( ::std::ostream& os ) const +{ + os << "sc_fxnum_fast" << ::std::endl; + os << "(" << ::std::endl; + os << "val = " << m_val << ::std::endl; + os << "params = "; + m_params.dump( os ); + os << "q_flag = " << m_q_flag << ::std::endl; + os << "o_flag = " << m_o_flag << ::std::endl; + // TO BE COMPLETED + // os << "observer = "; + // if( m_observer != 0 ) + // m_observer->dump( os ); + // else + // os << "0" << ::std::endl; + os << ")" << ::std::endl; +} + + +// internal use only; +bool +sc_fxnum_fast::get_bit( int i ) const +{ + scfx_ieee_double id( m_val ); + if( id.is_zero() || id.is_nan() || id.is_inf() ) + return false; + + // convert to two's complement + + unsigned int m0 = id.mantissa0(); + unsigned int m1 = id.mantissa1(); + + if( id.is_normal() ) + m0 += 1U << 20; + + if( id.negative() != 0 ) + { + m0 = ~ m0; + m1 = ~ m1; + unsigned int tmp = m1; + m1 += 1U; + if( m1 <= tmp ) + m0 += 1U; + } + + // get the right bit + + int j = i - id.exponent(); + if( ( j += 20 ) >= 32 ) + return ( ( m0 & 1U << 31 ) != 0 ); + else if( j >= 0 ) + return ( ( m0 & 1U << j ) != 0 ); + else if( ( j += 32 ) >= 0 ) + return ( ( m1 & 1U << j ) != 0 ); + else + return false; +} + + +bool +sc_fxnum_fast::set_bit( int i, bool high ) +{ + scfx_ieee_double id( m_val ); + if( id.is_nan() || id.is_inf() ) + return false; + + if( high ) + { + if( get_bit( i ) ) + return true; + + if( m_params.enc() == SC_TC_ && i == m_params.iwl() - 1 ) + m_val -= scfx_pow2( i ); + else + m_val += scfx_pow2( i ); + } + else + { + if( ! get_bit( i ) ) + return true; + + if( m_params.enc() == SC_TC_ && i == m_params.iwl() - 1 ) + m_val += scfx_pow2( i ); + else + m_val -= scfx_pow2( i ); + } + + return true; +} + + +bool +sc_fxnum_fast::get_slice( int i, int j, sc_bv_base& bv ) const +{ + scfx_ieee_double id( m_val ); + if( id.is_nan() || id.is_inf() ) + return false; + + // convert to two's complement + + unsigned int m0 = id.mantissa0(); + unsigned int m1 = id.mantissa1(); + + if( id.is_normal() ) + m0 += 1U << 20; + + if( id.negative() != 0 ) + { + m0 = ~ m0; + m1 = ~ m1; + unsigned int tmp = m1; + m1 += 1U; + if( m1 <= tmp ) + m0 += 1U; + } + + // get the bits + + int l = j; + for( int k = 0; k < bv.length(); ++ k ) + { + bool b = false; + + int n = l - id.exponent(); + if( ( n += 20 ) >= 32 ) + b = ( ( m0 & 1U << 31 ) != 0 ); + else if( n >= 0 ) + b = ( ( m0 & 1U << n ) != 0 ); + else if( ( n += 32 ) >= 0 ) + b = ( ( m1 & 1U << n ) != 0 ); + + bv[k] = b; + + if( i >= j ) + ++ l; + else + -- l; + } + + return true; +} + +bool +sc_fxnum_fast::set_slice( int i, int j, const sc_bv_base& bv ) +{ + scfx_ieee_double id( m_val ); + if( id.is_nan() || id.is_inf() ) + return false; + + // set the bits + + int l = j; + for( int k = 0; k < bv.length(); ++ k ) + { + if( bv[k].to_bool() ) + { + if( ! get_bit( l ) ) + { + if( m_params.enc() == SC_TC_ && l == m_params.iwl() - 1 ) + m_val -= scfx_pow2( l ); + else + m_val += scfx_pow2( l ); + } + } + else + { + if( get_bit( l ) ) + { + if( m_params.enc() == SC_TC_ && l == m_params.iwl() - 1 ) + m_val += scfx_pow2( l ); + else + m_val -= scfx_pow2( l ); + } + } + + + if( i >= j ) + ++ l; + else + -- l; + } + + return true; +} + + +sc_fxnum_fast_observer* +sc_fxnum_fast::lock_observer() const +{ + SC_ASSERT_( m_observer != 0, "lock observer failed" ); + sc_fxnum_fast_observer* tmp = m_observer; + m_observer = 0; + return tmp; +} + +void +sc_fxnum_fast::unlock_observer( sc_fxnum_fast_observer* observer_ ) const +{ + SC_ASSERT_( observer_ != 0, "unlock observer failed" ); + m_observer = observer_; +} + +} // namespace sc_dt + + +// Taf! diff --git a/ext/systemc/src/sysc/datatypes/fx/sc_fxnum.h b/ext/systemc/src/sysc/datatypes/fx/sc_fxnum.h new file mode 100644 index 000000000..ed3750811 --- /dev/null +++ b/ext/systemc/src/sysc/datatypes/fx/sc_fxnum.h @@ -0,0 +1,5102 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_fxnum.h - + + Original Author: Martin Janssen, Synopsys, Inc. + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + +// $Log: sc_fxnum.h,v $ +// Revision 1.5 2011/08/29 18:04:32 acg +// Philipp A. Hartmann: miscellaneous clean ups. +// +// Revision 1.4 2011/08/24 22:05:43 acg +// Torsten Maehne: initialization changes to remove warnings. +// +// Revision 1.3 2011/01/19 18:57:40 acg +// Andy Goodrich: changes for IEEE_1666_2011. +// +// Revision 1.2 2009/03/09 17:26:46 acg +// Andy Goodrich: removed ; from namespace { } +// +// Revision 1.1.1.1 2006/12/15 20:20:04 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:53:58 acg +// Andy Goodrich: added $Log command so that CVS comments are reproduced in +// the source. +// + +#ifndef SC_FXNUM_H +#define SC_FXNUM_H + + +#include "sysc/datatypes/bit/sc_lv_base.h" +#include "sysc/datatypes/fx/sc_fxval.h" +#include "sysc/datatypes/fx/scfx_params.h" +#include "sysc/datatypes/fx/sc_fxnum_observer.h" + + +namespace sc_core { + class vcd_sc_fxnum_trace; + class vcd_sc_fxnum_fast_trace; + class wif_sc_fxnum_trace; + class wif_sc_fxnum_fast_trace; +} + + +namespace sc_dt +{ + +// classes defined in this module +class sc_fxnum_bitref; +class sc_fxnum_fast_bitref; +class sc_fxnum_subref; +class sc_fxnum_fast_subref; +class sc_fxnum; +class sc_fxnum_fast; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_fxnum_bitref +// +// Proxy class for bit-selection in class sc_fxnum, behaves like sc_bit. +// ---------------------------------------------------------------------------- + +class sc_fxnum_bitref +{ + friend class sc_fxnum; + friend class sc_fxnum_fast_bitref; + + + bool get() const; + void set( bool ); + + + // constructor + + sc_fxnum_bitref( sc_fxnum&, int ); + +public: + + // copy constructor + + sc_fxnum_bitref( const sc_fxnum_bitref& ); + + + // assignment operators + +#define DECL_ASN_OP_T(op,tp) \ + sc_fxnum_bitref& operator op ( tp ); + +#define DECL_ASN_OP(op) \ + DECL_ASN_OP_T(op,const sc_fxnum_bitref&) \ + DECL_ASN_OP_T(op,const sc_fxnum_fast_bitref&) \ + DECL_ASN_OP_T(op,const sc_bit&) \ + DECL_ASN_OP_T(op,bool) + + DECL_ASN_OP(=) + + DECL_ASN_OP(&=) + DECL_ASN_OP(|=) + DECL_ASN_OP(^=) + +#undef DECL_ASN_OP_T +#undef DECL_ASN_OP + + + // implicit conversion + + operator bool() const; + + + // print or dump content + + void print( ::std::ostream& = ::std::cout ) const; + void scan( ::std::istream& = ::std::cin ); + void dump( ::std::ostream& = ::std::cout ) const; + +private: + + sc_fxnum& m_num; + int m_idx; + +private: + + // disabled + sc_fxnum_bitref(); +}; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_fxnum_fast_bitref +// +// Proxy class for bit-selection in class sc_fxnum_fast, behaves like sc_bit. +// ---------------------------------------------------------------------------- + +class sc_fxnum_fast_bitref +{ + friend class sc_fxnum_fast; + friend class sc_fxnum_bitref; + + + bool get() const; + void set( bool ); + + + // constructor + + sc_fxnum_fast_bitref( sc_fxnum_fast&, int ); + +public: + + // copy constructor + + sc_fxnum_fast_bitref( const sc_fxnum_fast_bitref& ); + + + // assignment operators + +#define DECL_ASN_OP_T(op,tp) \ + sc_fxnum_fast_bitref& operator op ( tp ); + +#define DECL_ASN_OP(op) \ + DECL_ASN_OP_T(op,const sc_fxnum_bitref&) \ + DECL_ASN_OP_T(op,const sc_fxnum_fast_bitref&) \ + DECL_ASN_OP_T(op,const sc_bit&) \ + DECL_ASN_OP_T(op,bool) + + DECL_ASN_OP(=) + + DECL_ASN_OP(&=) + DECL_ASN_OP(|=) + DECL_ASN_OP(^=) + +#undef DECL_ASN_OP_T +#undef DECL_ASN_OP + + + // implicit conversion + + operator bool() const; + + + // print or dump content + + void print( ::std::ostream& = ::std::cout ) const; + void scan( ::std::istream& = ::std::cin ); + void dump( ::std::ostream& = ::std::cout ) const; + +private: + + sc_fxnum_fast& m_num; + int m_idx; + +private: + + // disabled + sc_fxnum_fast_bitref(); +}; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_fxnum_subref +// +// Proxy class for part-selection in class sc_fxnum, +// behaves like sc_bv_base. +// ---------------------------------------------------------------------------- + +class sc_fxnum_subref +{ + friend class sc_fxnum; + friend class sc_fxnum_fast_subref; + + bool get() const; + bool set(); + + + // constructor + + sc_fxnum_subref( sc_fxnum&, int, int ); + +public: + + // copy constructor + + sc_fxnum_subref( const sc_fxnum_subref& ); + + + // destructor + + ~sc_fxnum_subref(); + + + // assignment operators + +#define DECL_ASN_OP_T(tp) \ + sc_fxnum_subref& operator = ( tp ); + + DECL_ASN_OP_T(const sc_fxnum_subref&) + DECL_ASN_OP_T(const sc_fxnum_fast_subref&) + DECL_ASN_OP_T(const sc_bv_base&) + DECL_ASN_OP_T(const sc_lv_base&) + DECL_ASN_OP_T(const char*) + DECL_ASN_OP_T(const bool*) + DECL_ASN_OP_T(const sc_signed&) + DECL_ASN_OP_T(const sc_unsigned&) + DECL_ASN_OP_T(const sc_int_base&) + DECL_ASN_OP_T(const sc_uint_base&) + DECL_ASN_OP_T(int64) + DECL_ASN_OP_T(uint64) + DECL_ASN_OP_T(int) + DECL_ASN_OP_T(unsigned int) + DECL_ASN_OP_T(long) + DECL_ASN_OP_T(unsigned long) + DECL_ASN_OP_T(char) + +#undef DECL_ASN_OP_T + +#define DECL_ASN_OP_T_A(op,tp) \ + sc_fxnum_subref& operator op ## = ( tp ); + +#define DECL_ASN_OP_A(op) \ + DECL_ASN_OP_T_A(op,const sc_fxnum_subref&) \ + DECL_ASN_OP_T_A(op,const sc_fxnum_fast_subref&) \ + DECL_ASN_OP_T_A(op,const sc_bv_base&) \ + DECL_ASN_OP_T_A(op,const sc_lv_base&) + + DECL_ASN_OP_A(&) + DECL_ASN_OP_A(|) + DECL_ASN_OP_A(^) + +#undef DECL_ASN_OP_T_A +#undef DECL_ASN_OP_A + + + // relational operators + +#define DECL_REL_OP_T(op,tp) \ + friend bool operator op ( const sc_fxnum_subref&, tp ); \ + friend bool operator op ( tp, const sc_fxnum_subref& ); + +#define DECL_REL_OP(op) \ + friend bool operator op ( const sc_fxnum_subref&, \ + const sc_fxnum_subref& ); \ + friend bool operator op ( const sc_fxnum_subref&, \ + const sc_fxnum_fast_subref& ); \ + DECL_REL_OP_T(op,const sc_bv_base&) \ + DECL_REL_OP_T(op,const sc_lv_base&) \ + DECL_REL_OP_T(op,const char*) \ + DECL_REL_OP_T(op,const bool*) \ + DECL_REL_OP_T(op,const sc_signed&) \ + DECL_REL_OP_T(op,const sc_unsigned&) \ + DECL_REL_OP_T(op,int) \ + DECL_REL_OP_T(op,unsigned int) \ + DECL_REL_OP_T(op,long) \ + DECL_REL_OP_T(op,unsigned long) + + DECL_REL_OP(==) + DECL_REL_OP(!=) + +#undef DECL_REL_OP_T +#undef DECL_REL_OP + + + // reduce functions + + bool and_reduce() const; + bool nand_reduce() const; + bool or_reduce() const; + bool nor_reduce() const; + bool xor_reduce() const; + bool xnor_reduce() const; + + + // query parameter + + int length() const; + + + // explicit conversions + + int to_int() const; + unsigned int to_uint() const; + long to_long() const; + unsigned long to_ulong() const; + int64 to_int64() const; + uint64 to_uint64() const; + +#ifdef SC_DT_DEPRECATED + int to_signed() const; + unsigned int to_unsigned() const; +#endif + + const std::string to_string() const; + const std::string to_string( sc_numrep ) const; + const std::string to_string( sc_numrep, bool ) const; + + + // implicit conversion + + operator sc_bv_base() const; + + + // print or dump content + + void print( ::std::ostream& = ::std::cout ) const; + void scan( ::std::istream& = ::std::cin ); + void dump( ::std::ostream& = ::std::cout ) const; + +private: + + sc_fxnum& m_num; + int m_from; + int m_to; + + sc_bv_base& m_bv; + +private: + + // disabled + sc_fxnum_subref(); +}; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_fxnum_fast_subref +// +// Proxy class for part-selection in class sc_fxnum_fast, +// behaves like sc_bv_base. +// ---------------------------------------------------------------------------- + +class sc_fxnum_fast_subref +{ + friend class sc_fxnum_fast; + friend class sc_fxnum_subref; + + bool get() const; + bool set(); + + + // constructor + + sc_fxnum_fast_subref( sc_fxnum_fast&, int, int ); + +public: + + // copy constructor + + sc_fxnum_fast_subref( const sc_fxnum_fast_subref& ); + + + // destructor + + ~sc_fxnum_fast_subref(); + + + // assignment operators + +#define DECL_ASN_OP_T(tp) \ + sc_fxnum_fast_subref& operator = ( tp ); + + DECL_ASN_OP_T(const sc_fxnum_subref&) + DECL_ASN_OP_T(const sc_fxnum_fast_subref&) + DECL_ASN_OP_T(const sc_bv_base&) + DECL_ASN_OP_T(const sc_lv_base&) + DECL_ASN_OP_T(const char*) + DECL_ASN_OP_T(const bool*) + DECL_ASN_OP_T(const sc_signed&) + DECL_ASN_OP_T(const sc_unsigned&) + DECL_ASN_OP_T(const sc_int_base&) + DECL_ASN_OP_T(const sc_uint_base&) + DECL_ASN_OP_T(int64) + DECL_ASN_OP_T(uint64) + DECL_ASN_OP_T(int) + DECL_ASN_OP_T(unsigned int) + DECL_ASN_OP_T(long) + DECL_ASN_OP_T(unsigned long) + DECL_ASN_OP_T(char) + +#undef DECL_ASN_OP_T + +#define DECL_ASN_OP_T_A(op,tp) \ + sc_fxnum_fast_subref& operator op ## = ( tp ); + +#define DECL_ASN_OP_A(op) \ + DECL_ASN_OP_T_A(op,const sc_fxnum_subref&) \ + DECL_ASN_OP_T_A(op,const sc_fxnum_fast_subref&) \ + DECL_ASN_OP_T_A(op,const sc_bv_base&) \ + DECL_ASN_OP_T_A(op,const sc_lv_base&) + + DECL_ASN_OP_A(&) + DECL_ASN_OP_A(|) + DECL_ASN_OP_A(^) + +#undef DECL_ASN_OP_T_A +#undef DECL_ASN_OP_A + + + // relational operators + +#define DECL_REL_OP_T(op,tp) \ + friend bool operator op ( const sc_fxnum_fast_subref&, tp ); \ + friend bool operator op ( tp, const sc_fxnum_fast_subref& ); + +#define DECL_REL_OP(op) \ + friend bool operator op ( const sc_fxnum_fast_subref&, \ + const sc_fxnum_fast_subref& ); \ + friend bool operator op ( const sc_fxnum_fast_subref&, \ + const sc_fxnum_subref& ); \ + DECL_REL_OP_T(op,const sc_bv_base&) \ + DECL_REL_OP_T(op,const sc_lv_base&) \ + DECL_REL_OP_T(op,const char*) \ + DECL_REL_OP_T(op,const bool*) \ + DECL_REL_OP_T(op,const sc_signed&) \ + DECL_REL_OP_T(op,const sc_unsigned&) \ + DECL_REL_OP_T(op,int) \ + DECL_REL_OP_T(op,unsigned int) \ + DECL_REL_OP_T(op,long) \ + DECL_REL_OP_T(op,unsigned long) + + DECL_REL_OP(==) + DECL_REL_OP(!=) + +#undef DECL_REL_OP_T +#undef DECL_REL_OP + + + // reduce functions + + bool and_reduce() const; + bool nand_reduce() const; + bool or_reduce() const; + bool nor_reduce() const; + bool xor_reduce() const; + bool xnor_reduce() const; + + + // query parameter + + int length() const; + + + // explicit conversions + + int to_int() const; + unsigned int to_uint() const; + long to_long() const; + unsigned long to_ulong() const; + int64 to_int64() const; + uint64 to_uint64() const; + +#ifdef SC_DT_DEPRECATED + int to_signed() const; + unsigned int to_unsigned() const; +#endif + + const std::string to_string() const; + const std::string to_string( sc_numrep ) const; + const std::string to_string( sc_numrep, bool ) const; + + + // implicit conversion + + operator sc_bv_base() const; + + + // print or dump content + + void print( ::std::ostream& = ::std::cout ) const; + void scan( ::std::istream& = ::std::cin ); + void dump( ::std::ostream& = ::std::cout ) const; + +private: + + sc_fxnum_fast& m_num; + int m_from; + int m_to; + + sc_bv_base& m_bv; + +private: + + // disabled + sc_fxnum_fast_subref(); +}; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_fxnum +// +// Base class for the fixed-point types; arbitrary precision. +// ---------------------------------------------------------------------------- + +class sc_fxnum +{ + friend class sc_fxval; + + friend class sc_fxnum_bitref; + friend class sc_fxnum_subref; + friend class sc_fxnum_fast_bitref; + friend class sc_fxnum_fast_subref; + + friend class sc_core::vcd_sc_fxnum_trace; + friend class sc_core::wif_sc_fxnum_trace; + +protected: + + sc_fxnum_observer* observer() const; + + + void cast(); + + + // constructors + + sc_fxnum( const sc_fxtype_params&, + sc_enc, + const sc_fxcast_switch&, + sc_fxnum_observer* ); + +#define DECL_CTOR_T(tp) \ + sc_fxnum( tp, \ + const sc_fxtype_params&, \ + sc_enc, \ + const sc_fxcast_switch&, \ + sc_fxnum_observer* ); + + DECL_CTOR_T(int) + DECL_CTOR_T(unsigned int) + DECL_CTOR_T(long) + DECL_CTOR_T(unsigned long) + DECL_CTOR_T(float) + DECL_CTOR_T(double) + DECL_CTOR_T(const char*) + DECL_CTOR_T(const sc_fxval&) + DECL_CTOR_T(const sc_fxval_fast&) + DECL_CTOR_T(const sc_fxnum&) + DECL_CTOR_T(const sc_fxnum_fast&) +#ifndef SC_FX_EXCLUDE_OTHER + DECL_CTOR_T(int64) + DECL_CTOR_T(uint64) + DECL_CTOR_T(const sc_int_base&) + DECL_CTOR_T(const sc_uint_base&) + DECL_CTOR_T(const sc_signed&) + DECL_CTOR_T(const sc_unsigned&) +#endif + +#undef DECL_CTOR_T + + ~sc_fxnum(); + + + // internal use only; + const scfx_rep* get_rep() const; + +public: + + // unary operators + + const sc_fxval operator - () const; + const sc_fxval operator + () const; + + + // unary functions + + friend void neg( sc_fxval&, const sc_fxnum& ); + friend void neg( sc_fxnum&, const sc_fxnum& ); + + + // binary operators + +#define DECL_BIN_OP_T(op,tp) \ + friend const sc_fxval operator op ( const sc_fxnum&, tp ); \ + friend const sc_fxval operator op ( tp, const sc_fxnum& ); + +#ifndef SC_FX_EXCLUDE_OTHER +#define DECL_BIN_OP_OTHER(op) \ + DECL_BIN_OP_T(op,int64) \ + DECL_BIN_OP_T(op,uint64) \ + DECL_BIN_OP_T(op,const sc_int_base&) \ + DECL_BIN_OP_T(op,const sc_uint_base&) \ + DECL_BIN_OP_T(op,const sc_signed&) \ + DECL_BIN_OP_T(op,const sc_unsigned&) +#else +#define DECL_BIN_OP_OTHER(op) +#endif + +#define DECL_BIN_OP(op,dummy) \ + friend const sc_fxval operator op ( const sc_fxnum&, const sc_fxnum& ); \ + DECL_BIN_OP_T(op,int) \ + DECL_BIN_OP_T(op,unsigned int) \ + DECL_BIN_OP_T(op,long) \ + DECL_BIN_OP_T(op,unsigned long) \ + DECL_BIN_OP_T(op,float) \ + DECL_BIN_OP_T(op,double) \ + DECL_BIN_OP_T(op,const char*) \ + DECL_BIN_OP_T(op,const sc_fxval&) \ + DECL_BIN_OP_T(op,const sc_fxval_fast&) \ + DECL_BIN_OP_T(op,const sc_fxnum_fast&) \ + DECL_BIN_OP_OTHER(op) + + DECL_BIN_OP(*,mult) + DECL_BIN_OP(+,add) + DECL_BIN_OP(-,sub) +// don't use macros +// DECL_BIN_OP(/,div) + friend const sc_fxval operator / ( const sc_fxnum&, const sc_fxnum& ); + DECL_BIN_OP_T(/,int) + DECL_BIN_OP_T(/,unsigned int) + DECL_BIN_OP_T(/,long) + DECL_BIN_OP_T(/,unsigned long) + DECL_BIN_OP_T(/,float) + DECL_BIN_OP_T(/,double) + DECL_BIN_OP_T(/,const char*) + DECL_BIN_OP_T(/,const sc_fxval&) + DECL_BIN_OP_T(/,const sc_fxval_fast&) + DECL_BIN_OP_T(/,const sc_fxnum_fast&) +// DECL_BIN_OP_OTHER(op) +#ifndef SC_FX_EXCLUDE_OTHER + DECL_BIN_OP_T(/,int64) + DECL_BIN_OP_T(/,uint64) + DECL_BIN_OP_T(/,const sc_int_base&) + DECL_BIN_OP_T(/,const sc_uint_base&) + DECL_BIN_OP_T(/,const sc_signed&) + DECL_BIN_OP_T(/,const sc_unsigned&) +#endif + +#undef DECL_BIN_OP_T +#undef DECL_BIN_OP_OTHER +#undef DECL_BIN_OP + + friend const sc_fxval operator << ( const sc_fxnum&, int ); + friend const sc_fxval operator >> ( const sc_fxnum&, int ); + + + // binary functions + +#define DECL_BIN_FNC_T(fnc,tp) \ + friend void fnc ( sc_fxval&, const sc_fxnum&, tp ); \ + friend void fnc ( sc_fxval&, tp, const sc_fxnum& ); \ + friend void fnc ( sc_fxnum&, const sc_fxnum&, tp ); \ + friend void fnc ( sc_fxnum&, tp, const sc_fxnum& ); + +#ifndef SC_FX_EXCLUDE_OTHER +#define DECL_BIN_FNC_OTHER(fnc) \ + DECL_BIN_FNC_T(fnc,int64) \ + DECL_BIN_FNC_T(fnc,uint64) \ + DECL_BIN_FNC_T(fnc,const sc_int_base&) \ + DECL_BIN_FNC_T(fnc,const sc_uint_base&) \ + DECL_BIN_FNC_T(fnc,const sc_signed&) \ + DECL_BIN_FNC_T(fnc,const sc_unsigned&) +#else +#define DECL_BIN_FNC_OTHER(fnc) +#endif + +#define DECL_BIN_FNC(fnc) \ + friend void fnc ( sc_fxval&, const sc_fxnum&, const sc_fxnum& ); \ + friend void fnc ( sc_fxnum&, const sc_fxnum&, const sc_fxnum& ); \ + DECL_BIN_FNC_T(fnc,int) \ + DECL_BIN_FNC_T(fnc,unsigned int) \ + DECL_BIN_FNC_T(fnc,long) \ + DECL_BIN_FNC_T(fnc,unsigned long) \ + DECL_BIN_FNC_T(fnc,float) \ + DECL_BIN_FNC_T(fnc,double) \ + DECL_BIN_FNC_T(fnc,const char*) \ + DECL_BIN_FNC_T(fnc,const sc_fxval&) \ + DECL_BIN_FNC_T(fnc,const sc_fxval_fast&) \ + DECL_BIN_FNC_T(fnc,const sc_fxnum_fast&) \ + DECL_BIN_FNC_OTHER(fnc) + + DECL_BIN_FNC(mult) + DECL_BIN_FNC(div) + DECL_BIN_FNC(add) + DECL_BIN_FNC(sub) + +#undef DECL_BIN_FNC_T +#undef DECL_BIN_FNC_OTHER +#undef DECL_BIN_FNC + + friend void lshift( sc_fxval&, const sc_fxnum&, int ); + friend void rshift( sc_fxval&, const sc_fxnum&, int ); + friend void lshift( sc_fxnum&, const sc_fxnum&, int ); + friend void rshift( sc_fxnum&, const sc_fxnum&, int ); + + + // relational (including equality) operators + +#define DECL_REL_OP_T(op,tp) \ + friend bool operator op ( const sc_fxnum&, tp ); \ + friend bool operator op ( tp, const sc_fxnum& ); + +#ifndef SC_FX_EXCLUDE_OTHER +#define DECL_REL_OP_OTHER(op) \ + DECL_REL_OP_T(op,int64) \ + DECL_REL_OP_T(op,uint64) \ + DECL_REL_OP_T(op,const sc_int_base&) \ + DECL_REL_OP_T(op,const sc_uint_base&) \ + DECL_REL_OP_T(op,const sc_signed&) \ + DECL_REL_OP_T(op,const sc_unsigned&) +#else +#define DECL_REL_OP_OTHER(op) +#endif + +#define DECL_REL_OP(op) \ + friend bool operator op ( const sc_fxnum&, const sc_fxnum& ); \ + DECL_REL_OP_T(op,int) \ + DECL_REL_OP_T(op,unsigned int) \ + DECL_REL_OP_T(op,long) \ + DECL_REL_OP_T(op,unsigned long) \ + DECL_REL_OP_T(op,float) \ + DECL_REL_OP_T(op,double) \ + DECL_REL_OP_T(op,const char*) \ + DECL_REL_OP_T(op,const sc_fxval&) \ + DECL_REL_OP_T(op,const sc_fxval_fast&) \ + DECL_REL_OP_T(op,const sc_fxnum_fast&) \ + DECL_REL_OP_OTHER(op) + + DECL_REL_OP(<) + DECL_REL_OP(<=) + DECL_REL_OP(>) + DECL_REL_OP(>=) + DECL_REL_OP(==) + DECL_REL_OP(!=) + +#undef DECL_REL_OP_T +#undef DECL_REL_OP_OTHER +#undef DECL_REL_OP + + + // assignment operators + +#define DECL_ASN_OP_T(op,tp) \ + sc_fxnum& operator op( tp ); + +#ifndef SC_FX_EXCLUDE_OTHER +#define DECL_ASN_OP_OTHER(op) \ + DECL_ASN_OP_T(op,int64) \ + DECL_ASN_OP_T(op,uint64) \ + DECL_ASN_OP_T(op,const sc_int_base&) \ + DECL_ASN_OP_T(op,const sc_uint_base&) \ + DECL_ASN_OP_T(op,const sc_signed&) \ + DECL_ASN_OP_T(op,const sc_unsigned&) +#else +#define DECL_ASN_OP_OTHER(op) +#endif + +#define DECL_ASN_OP(op) \ + DECL_ASN_OP_T(op,int) \ + DECL_ASN_OP_T(op,unsigned int) \ + DECL_ASN_OP_T(op,long) \ + DECL_ASN_OP_T(op,unsigned long) \ + DECL_ASN_OP_T(op,float) \ + DECL_ASN_OP_T(op,double) \ + DECL_ASN_OP_T(op,const char*) \ + DECL_ASN_OP_T(op,const sc_fxval&) \ + DECL_ASN_OP_T(op,const sc_fxval_fast&) \ + DECL_ASN_OP_T(op,const sc_fxnum&) \ + DECL_ASN_OP_T(op,const sc_fxnum_fast&) \ + DECL_ASN_OP_OTHER(op) + + DECL_ASN_OP(=) + + DECL_ASN_OP(*=) + DECL_ASN_OP(/=) + DECL_ASN_OP(+=) + DECL_ASN_OP(-=) + + DECL_ASN_OP_T(<<=,int) + DECL_ASN_OP_T(>>=,int) + +#undef DECL_ASN_OP_T +#undef DECL_ASN_OP_OTHER +#undef DECL_ASN_OP + + + // auto-increment and auto-decrement + + const sc_fxval operator ++ ( int ); + const sc_fxval operator -- ( int ); + + sc_fxnum& operator ++ (); + sc_fxnum& operator -- (); + + + // bit selection + + const sc_fxnum_bitref operator [] ( int ) const; + sc_fxnum_bitref operator [] ( int ); + + const sc_fxnum_bitref bit( int ) const; + sc_fxnum_bitref bit( int ); + + + // part selection + + const sc_fxnum_subref operator () ( int, int ) const; + sc_fxnum_subref operator () ( int, int ); + + const sc_fxnum_subref range( int, int ) const; + sc_fxnum_subref range( int, int ); + + + const sc_fxnum_subref operator () () const; + sc_fxnum_subref operator () (); + + const sc_fxnum_subref range() const; + sc_fxnum_subref range(); + + + // implicit conversion + + operator double() const; // necessary evil! + + + // explicit conversion to primitive types + + short to_short() const; + unsigned short to_ushort() const; + int to_int() const; + unsigned int to_uint() const; + long to_long() const; + unsigned long to_ulong() const; + int64 to_int64() const; + uint64 to_uint64() const; + float to_float() const; + double to_double() const; + + + // explicit conversion to character string + + const std::string to_string() const; + const std::string to_string( sc_numrep ) const; + const std::string to_string( sc_numrep, bool ) const; + const std::string to_string( sc_fmt ) const; + const std::string to_string( sc_numrep, sc_fmt ) const; + const std::string to_string( sc_numrep, bool, sc_fmt ) const; + + const std::string to_dec() const; + const std::string to_bin() const; + const std::string to_oct() const; + const std::string to_hex() const; + + + // query value + + bool is_neg() const; + bool is_zero() const; + + // internal use only; + bool is_normal() const; + + bool quantization_flag() const; + bool overflow_flag() const; + + const sc_fxval value() const; + + + // query parameters + + int wl() const; + int iwl() const; + sc_q_mode q_mode() const; + sc_o_mode o_mode() const; + int n_bits() const; + + const sc_fxtype_params& type_params() const; + + const sc_fxcast_switch& cast_switch() const; + + + // print or dump content + + void print( ::std::ostream& = ::std::cout ) const; + void scan( ::std::istream& = ::std::cin ); + void dump( ::std::ostream& = ::std::cout ) const; + + + // internal use only; + void observer_read() const; + + + // internal use only; + bool get_bit( int ) const; + +protected: + + bool set_bit( int, bool ); + + + bool get_slice( int, int, sc_bv_base& ) const; + bool set_slice( int, int, const sc_bv_base& ); + + + sc_fxnum_observer* lock_observer() const; + void unlock_observer( sc_fxnum_observer* ) const; + +private: + + scfx_rep* m_rep; + + scfx_params m_params; + bool m_q_flag; + bool m_o_flag; + + mutable sc_fxnum_observer* m_observer; + +private: + + // disabled + sc_fxnum(); + sc_fxnum( const sc_fxnum& ); +}; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_fxnum_fast +// +// Base class for the fixed-point types; limited precision. +// ---------------------------------------------------------------------------- + +class sc_fxnum_fast +{ + friend class sc_fxval_fast; + + friend class sc_fxnum_bitref; + friend class sc_fxnum_subref; + friend class sc_fxnum_fast_bitref; + friend class sc_fxnum_fast_subref; + + friend class sc_core::vcd_sc_fxnum_fast_trace; + friend class sc_core::wif_sc_fxnum_fast_trace; + +protected: + + sc_fxnum_fast_observer* observer() const; + + + void cast(); + + + // constructors + + sc_fxnum_fast( const sc_fxtype_params&, + sc_enc, + const sc_fxcast_switch&, + sc_fxnum_fast_observer* ); + +#define DECL_CTOR_T(tp) \ + sc_fxnum_fast( tp, \ + const sc_fxtype_params&, \ + sc_enc, \ + const sc_fxcast_switch&, \ + sc_fxnum_fast_observer* ); + + DECL_CTOR_T(int) + DECL_CTOR_T(unsigned int) + DECL_CTOR_T(long) + DECL_CTOR_T(unsigned long) + DECL_CTOR_T(float) + DECL_CTOR_T(double) + DECL_CTOR_T(const char*) + DECL_CTOR_T(const sc_fxval&) + DECL_CTOR_T(const sc_fxval_fast&) + DECL_CTOR_T(const sc_fxnum&) + DECL_CTOR_T(const sc_fxnum_fast&) +#ifndef SC_FX_EXCLUDE_OTHER + DECL_CTOR_T(int64) + DECL_CTOR_T(uint64) + DECL_CTOR_T(const sc_int_base&) + DECL_CTOR_T(const sc_uint_base&) + DECL_CTOR_T(const sc_signed&) + DECL_CTOR_T(const sc_unsigned&) +#endif + +#undef DECL_CTOR_T + + ~sc_fxnum_fast(); + + + // internal use only; + double get_val() const; + +public: + + // unary operators + + const sc_fxval_fast operator - () const; + const sc_fxval_fast operator + () const; + + + // unary functions + + friend void neg( sc_fxval_fast&, const sc_fxnum_fast& ); + friend void neg( sc_fxnum_fast&, const sc_fxnum_fast& ); + + + // binary operators + +#define DECL_BIN_OP_T(op,tp) \ + friend const sc_fxval_fast operator op ( const sc_fxnum_fast&, tp ); \ + friend const sc_fxval_fast operator op ( tp, const sc_fxnum_fast& ); + +#ifndef SC_FX_EXCLUDE_OTHER +#define DECL_BIN_OP_OTHER(op) \ + DECL_BIN_OP_T(op,int64) \ + DECL_BIN_OP_T(op,uint64) \ + DECL_BIN_OP_T(op,const sc_int_base&) \ + DECL_BIN_OP_T(op,const sc_uint_base&) \ + DECL_BIN_OP_T(op,const sc_signed&) \ + DECL_BIN_OP_T(op,const sc_unsigned&) +#else +#define DECL_BIN_OP_OTHER(op) +#endif + +#define DECL_BIN_OP(op,dummy) \ + friend const sc_fxval_fast operator op ( const sc_fxnum_fast&, \ + const sc_fxnum_fast& ); \ + DECL_BIN_OP_T(op,int) \ + DECL_BIN_OP_T(op,unsigned int) \ + DECL_BIN_OP_T(op,long) \ + DECL_BIN_OP_T(op,unsigned long) \ + DECL_BIN_OP_T(op,float) \ + DECL_BIN_OP_T(op,double) \ + DECL_BIN_OP_T(op,const char*) \ + DECL_BIN_OP_T(op,const sc_fxval_fast&) \ + DECL_BIN_OP_OTHER(op) + + DECL_BIN_OP(*,mult) + DECL_BIN_OP(+,add) + DECL_BIN_OP(-,sub) +// DECL_BIN_OP(/,div) + friend const sc_fxval_fast operator / ( const sc_fxnum_fast&, + const sc_fxnum_fast& ); + DECL_BIN_OP_T(/,int) + DECL_BIN_OP_T(/,unsigned int) + DECL_BIN_OP_T(/,long) + DECL_BIN_OP_T(/,unsigned long) + DECL_BIN_OP_T(/,float) + DECL_BIN_OP_T(/,double) + DECL_BIN_OP_T(/,const char*) + DECL_BIN_OP_T(/,const sc_fxval_fast&) +// DECL_BIN_OP_OTHER(op) +#ifndef SC_FX_EXCLUDE_OTHER + DECL_BIN_OP_T(/,int64) \ + DECL_BIN_OP_T(/,uint64) \ + DECL_BIN_OP_T(/,const sc_int_base&) \ + DECL_BIN_OP_T(/,const sc_uint_base&) \ + DECL_BIN_OP_T(/,const sc_signed&) \ + DECL_BIN_OP_T(/,const sc_unsigned&) +#endif + +#undef DECL_BIN_OP_T +#undef DECL_BIN_OP_OTHER +#undef DECL_BIN_OP + + friend const sc_fxval_fast operator << ( const sc_fxnum_fast&, int ); + friend const sc_fxval_fast operator >> ( const sc_fxnum_fast&, int ); + + + // binary functions + +#define DECL_BIN_FNC_T(fnc,tp) \ + friend void fnc ( sc_fxval_fast&, const sc_fxnum_fast&, tp ); \ + friend void fnc ( sc_fxval_fast&, tp, const sc_fxnum_fast& ); \ + friend void fnc ( sc_fxnum_fast&, const sc_fxnum_fast&, tp ); \ + friend void fnc ( sc_fxnum_fast&, tp, const sc_fxnum_fast& ); + +#ifndef SC_FX_EXCLUDE_OTHER +#define DECL_BIN_FNC_OTHER(fnc) \ + DECL_BIN_FNC_T(fnc,int64) \ + DECL_BIN_FNC_T(fnc,uint64) \ + DECL_BIN_FNC_T(fnc,const sc_int_base&) \ + DECL_BIN_FNC_T(fnc,const sc_uint_base&) \ + DECL_BIN_FNC_T(fnc,const sc_signed&) \ + DECL_BIN_FNC_T(fnc,const sc_unsigned&) +#else +#define DECL_BIN_FNC_OTHER(fnc) +#endif + +#define DECL_BIN_FNC(fnc) \ + friend void fnc ( sc_fxval_fast&, const sc_fxnum_fast&, \ + const sc_fxnum_fast& ); \ + friend void fnc ( sc_fxnum_fast&, const sc_fxnum_fast&, \ + const sc_fxnum_fast& ); \ + DECL_BIN_FNC_T(fnc,int) \ + DECL_BIN_FNC_T(fnc,unsigned int) \ + DECL_BIN_FNC_T(fnc,long) \ + DECL_BIN_FNC_T(fnc,unsigned long) \ + DECL_BIN_FNC_T(fnc,float) \ + DECL_BIN_FNC_T(fnc,double) \ + DECL_BIN_FNC_T(fnc,const char*) \ + DECL_BIN_FNC_T(fnc,const sc_fxval&) \ + DECL_BIN_FNC_T(fnc,const sc_fxval_fast&) \ + DECL_BIN_FNC_T(fnc,const sc_fxnum&) \ + DECL_BIN_FNC_OTHER(fnc) + + DECL_BIN_FNC(mult) + DECL_BIN_FNC(div) + DECL_BIN_FNC(add) + DECL_BIN_FNC(sub) + +#undef DECL_BIN_FNC_T +#undef DECL_BIN_FNC_OTHER +#undef DECL_BIN_FNC + + friend void lshift( sc_fxval_fast&, const sc_fxnum_fast&, int ); + friend void rshift( sc_fxval_fast&, const sc_fxnum_fast&, int ); + friend void lshift( sc_fxnum_fast&, const sc_fxnum_fast&, int ); + friend void rshift( sc_fxnum_fast&, const sc_fxnum_fast&, int ); + + + // relational (including equality) operators + +#define DECL_REL_OP_T(op,tp) \ + friend bool operator op ( const sc_fxnum_fast&, tp ); \ + friend bool operator op ( tp, const sc_fxnum_fast& ); + +#ifndef SC_FX_EXCLUDE_OTHER +#define DECL_REL_OP_OTHER(op) \ + DECL_REL_OP_T(op,int64) \ + DECL_REL_OP_T(op,uint64) \ + DECL_REL_OP_T(op,const sc_int_base&) \ + DECL_REL_OP_T(op,const sc_uint_base&) \ + DECL_REL_OP_T(op,const sc_signed&) \ + DECL_REL_OP_T(op,const sc_unsigned&) +#else +#define DECL_REL_OP_OTHER(op) +#endif + +#define DECL_REL_OP(op) \ + friend bool operator op ( const sc_fxnum_fast&, const sc_fxnum_fast& ); \ + DECL_REL_OP_T(op,int) \ + DECL_REL_OP_T(op,unsigned int) \ + DECL_REL_OP_T(op,long) \ + DECL_REL_OP_T(op,unsigned long) \ + DECL_REL_OP_T(op,float) \ + DECL_REL_OP_T(op,double) \ + DECL_REL_OP_T(op,const char*) \ + DECL_REL_OP_T(op,const sc_fxval_fast&) \ + DECL_REL_OP_OTHER(op) + + DECL_REL_OP(<) + DECL_REL_OP(<=) + DECL_REL_OP(>) + DECL_REL_OP(>=) + DECL_REL_OP(==) + DECL_REL_OP(!=) + +#undef DECL_REL_OP_T +#undef DECL_REL_OP_OTHER +#undef DECL_REL_OP + + + // assignment operators + +#define DECL_ASN_OP_T(op,tp) \ + sc_fxnum_fast& operator op( tp ); + +#ifndef SC_FX_EXCLUDE_OTHER +#define DECL_ASN_OP_OTHER(op) \ + DECL_ASN_OP_T(op,int64) \ + DECL_ASN_OP_T(op,uint64) \ + DECL_ASN_OP_T(op,const sc_int_base&) \ + DECL_ASN_OP_T(op,const sc_uint_base&) \ + DECL_ASN_OP_T(op,const sc_signed&) \ + DECL_ASN_OP_T(op,const sc_unsigned&) +#else +#define DECL_ASN_OP_OTHER(op) +#endif + +#define DECL_ASN_OP(op) \ + DECL_ASN_OP_T(op,int) \ + DECL_ASN_OP_T(op,unsigned int) \ + DECL_ASN_OP_T(op,long) \ + DECL_ASN_OP_T(op,unsigned long) \ + DECL_ASN_OP_T(op,float) \ + DECL_ASN_OP_T(op,double) \ + DECL_ASN_OP_T(op,const char*) \ + DECL_ASN_OP_T(op,const sc_fxval&) \ + DECL_ASN_OP_T(op,const sc_fxval_fast&) \ + DECL_ASN_OP_T(op,const sc_fxnum&) \ + DECL_ASN_OP_T(op,const sc_fxnum_fast&) \ + DECL_ASN_OP_OTHER(op) + + DECL_ASN_OP(=) + + DECL_ASN_OP(*=) + DECL_ASN_OP(/=) + DECL_ASN_OP(+=) + DECL_ASN_OP(-=) + + DECL_ASN_OP_T(<<=,int) + DECL_ASN_OP_T(>>=,int) + +#undef DECL_ASN_OP_T +#undef DECL_ASN_OP_OTHER +#undef DECL_ASN_OP + + + // auto-increment and auto-decrement + + const sc_fxval_fast operator ++ ( int ); + const sc_fxval_fast operator -- ( int ); + + sc_fxnum_fast& operator ++ (); + sc_fxnum_fast& operator -- (); + + + // bit selection + + const sc_fxnum_fast_bitref operator [] ( int ) const; + sc_fxnum_fast_bitref operator [] ( int ); + + const sc_fxnum_fast_bitref bit( int ) const; + sc_fxnum_fast_bitref bit( int ); + + + // part selection + + const sc_fxnum_fast_subref operator () ( int, int ) const; + sc_fxnum_fast_subref operator () ( int, int ); + + const sc_fxnum_fast_subref range( int, int ) const; + sc_fxnum_fast_subref range( int, int ); + + + const sc_fxnum_fast_subref operator () () const; + sc_fxnum_fast_subref operator () (); + + const sc_fxnum_fast_subref range() const; + sc_fxnum_fast_subref range(); + + + // implicit conversion + + operator double() const; // necessary evil! + + + // explicit conversion to primitive types + + short to_short() const; + unsigned short to_ushort() const; + int to_int() const; + unsigned int to_uint() const; + long to_long() const; + unsigned long to_ulong() const; + int64 to_int64() const; + uint64 to_uint64() const; + float to_float() const; + double to_double() const; + + + // explicit conversion to character string + + const std::string to_string() const; + const std::string to_string( sc_numrep ) const; + const std::string to_string( sc_numrep, bool ) const; + const std::string to_string( sc_fmt ) const; + const std::string to_string( sc_numrep, sc_fmt ) const; + const std::string to_string( sc_numrep, bool, sc_fmt ) const; + + const std::string to_dec() const; + const std::string to_bin() const; + const std::string to_oct() const; + const std::string to_hex() const; + + + // query value + + bool is_neg() const; + bool is_zero() const; + + // internal use only; + bool is_normal() const; + + bool quantization_flag() const; + bool overflow_flag() const; + + const sc_fxval_fast value() const; + + + // query parameters + + int wl() const; + int iwl() const; + sc_q_mode q_mode() const; + sc_o_mode o_mode() const; + int n_bits() const; + + const sc_fxtype_params& type_params() const; + + const sc_fxcast_switch& cast_switch() const; + + + // print or dump content + + void print( ::std::ostream& = ::std::cout ) const; + void scan( ::std::istream& = ::std::cin ); + void dump( ::std::ostream& = ::std::cout ) const; + + + // internal use only; + void observer_read() const; + + + // internal use only; + bool get_bit( int ) const; + +protected: + + bool set_bit( int, bool ); + + + bool get_slice( int, int, sc_bv_base& ) const; + bool set_slice( int, int, const sc_bv_base& ); + + + sc_fxnum_fast_observer* lock_observer() const; + void unlock_observer( sc_fxnum_fast_observer* ) const; + +private: + + double m_val; + + scfx_params m_params; + bool m_q_flag; + bool m_o_flag; + + mutable sc_fxnum_fast_observer* m_observer; + +private: + + // disabled + sc_fxnum_fast(); + sc_fxnum_fast( const sc_fxnum_fast& ); +}; + + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + +// ---------------------------------------------------------------------------- +// CLASS : sc_fxnum_bitref +// +// Proxy class for bit-selection in class sc_fxnum, behaves like sc_bit. +// ---------------------------------------------------------------------------- + +// constructor + +inline +sc_fxnum_bitref::sc_fxnum_bitref( sc_fxnum& num_, int idx_ ) + : m_num( num_ ), m_idx( idx_ ) +{} + + +// copy constructor + +inline +sc_fxnum_bitref::sc_fxnum_bitref( const sc_fxnum_bitref& a ) + : m_num( a.m_num ), m_idx( a.m_idx ) +{} + + +// assignment operators + +inline +sc_fxnum_bitref& +sc_fxnum_bitref::operator = ( const sc_fxnum_bitref& a ) +{ + if( &a != this ) + { + SC_FXNUM_OBSERVER_READ_( a.m_num ) + set( a.get() ); + SC_FXNUM_OBSERVER_WRITE_( m_num ) + } + return *this; +} + +inline +sc_fxnum_bitref& +sc_fxnum_bitref::operator = ( const sc_fxnum_fast_bitref& a ) +{ + SC_FXNUM_FAST_OBSERVER_READ_( a.m_num ) + set( a.get() ); + SC_FXNUM_OBSERVER_WRITE_( m_num ) + return *this; +} + +inline +sc_fxnum_bitref& +sc_fxnum_bitref::operator = ( const sc_bit& a ) +{ + set( static_cast<bool>( a ) ); + SC_FXNUM_OBSERVER_WRITE_( m_num ) + return *this; +} + +inline +sc_fxnum_bitref& +sc_fxnum_bitref::operator = ( bool a ) +{ + set( a ); + SC_FXNUM_OBSERVER_WRITE_( m_num ) + return *this; +} + + +inline +sc_fxnum_bitref& +sc_fxnum_bitref::operator &= ( const sc_fxnum_bitref& b ) +{ + SC_FXNUM_OBSERVER_READ_( m_num ) + SC_FXNUM_OBSERVER_READ_( b.m_num ) + set( get() && b.get() ); + SC_FXNUM_OBSERVER_WRITE_( m_num ) + return *this; +} + +inline +sc_fxnum_bitref& +sc_fxnum_bitref::operator &= ( const sc_fxnum_fast_bitref& b ) +{ + SC_FXNUM_OBSERVER_READ_( m_num ) + SC_FXNUM_FAST_OBSERVER_READ_( b.m_num ) + set( get() && b.get() ); + SC_FXNUM_OBSERVER_WRITE_( m_num ) + return *this; +} + +inline +sc_fxnum_bitref& +sc_fxnum_bitref::operator &= ( const sc_bit& b ) +{ + SC_FXNUM_OBSERVER_READ_( m_num ) + set( get() && static_cast<bool>( b ) ); + SC_FXNUM_OBSERVER_WRITE_( m_num ) + return *this; +} + +inline +sc_fxnum_bitref& +sc_fxnum_bitref::operator &= ( bool b ) +{ + SC_FXNUM_OBSERVER_READ_( m_num ) + set( get() && b ); + SC_FXNUM_OBSERVER_WRITE_( m_num ) + return *this; +} + + +inline +sc_fxnum_bitref& +sc_fxnum_bitref::operator |= ( const sc_fxnum_bitref& b ) +{ + SC_FXNUM_OBSERVER_READ_( m_num ) + SC_FXNUM_OBSERVER_READ_( b.m_num ) + set( get() || b.get() ); + SC_FXNUM_OBSERVER_WRITE_( m_num ) + return *this; +} + +inline +sc_fxnum_bitref& +sc_fxnum_bitref::operator |= ( const sc_fxnum_fast_bitref& b ) +{ + SC_FXNUM_OBSERVER_READ_( m_num ) + SC_FXNUM_FAST_OBSERVER_READ_( b.m_num ) + set( get() || b.get() ); + SC_FXNUM_OBSERVER_WRITE_( m_num ) + return *this; +} + +inline +sc_fxnum_bitref& +sc_fxnum_bitref::operator |= ( const sc_bit& b ) +{ + SC_FXNUM_OBSERVER_READ_( m_num ) + set( get() || static_cast<bool>( b ) ); + SC_FXNUM_OBSERVER_WRITE_( m_num ) + return *this; +} + +inline +sc_fxnum_bitref& +sc_fxnum_bitref::operator |= ( bool b ) +{ + SC_FXNUM_OBSERVER_READ_( m_num ) + set( get() || b ); + SC_FXNUM_OBSERVER_WRITE_( m_num ) + return *this; +} + + +inline +sc_fxnum_bitref& +sc_fxnum_bitref::operator ^= ( const sc_fxnum_bitref& b ) +{ + SC_FXNUM_OBSERVER_READ_( m_num ) + SC_FXNUM_OBSERVER_READ_( b.m_num ) + set( get() != b.get() ); + SC_FXNUM_OBSERVER_WRITE_( m_num ) + return *this; +} + +inline +sc_fxnum_bitref& +sc_fxnum_bitref::operator ^= ( const sc_fxnum_fast_bitref& b ) +{ + SC_FXNUM_OBSERVER_READ_( m_num ) + SC_FXNUM_FAST_OBSERVER_READ_( b.m_num ) + set( get() != b.get() ); + SC_FXNUM_OBSERVER_WRITE_( m_num ) + return *this; +} + +inline +sc_fxnum_bitref& +sc_fxnum_bitref::operator ^= ( const sc_bit& b ) +{ + SC_FXNUM_OBSERVER_READ_( m_num ) + set( get() != static_cast<bool>( b ) ); + SC_FXNUM_OBSERVER_WRITE_( m_num ) + return *this; +} + +inline +sc_fxnum_bitref& +sc_fxnum_bitref::operator ^= ( bool b ) +{ + SC_FXNUM_OBSERVER_READ_( m_num ) + set( get() != b ); + SC_FXNUM_OBSERVER_WRITE_( m_num ) + return *this; +} + + +// implicit conversion + +inline +sc_fxnum_bitref::operator bool() const +{ + SC_FXNUM_OBSERVER_READ_( m_num ) + return get(); +} + + +inline +::std::ostream& +operator << ( ::std::ostream& os, const sc_fxnum_bitref& a ) +{ + a.print( os ); + return os; +} + +inline +::std::istream& +operator >> ( ::std::istream& is, sc_fxnum_bitref& a ) +{ + a.scan( is ); + return is; +} + + +// ---------------------------------------------------------------------------- +// CLASS : sc_fxnum_fast_bitref +// +// Proxy class for bit-selection in class sc_fxnum_fast, behaves like sc_bit. +// ---------------------------------------------------------------------------- + +// constructor + +inline +sc_fxnum_fast_bitref::sc_fxnum_fast_bitref( sc_fxnum_fast& num_, int idx_ ) + : m_num( num_ ), m_idx( idx_ ) +{} + + +// copy constructor + +inline +sc_fxnum_fast_bitref::sc_fxnum_fast_bitref( const sc_fxnum_fast_bitref& a ) + : m_num( a.m_num ), m_idx( a.m_idx ) +{} + + +// assignment operators + +inline +sc_fxnum_fast_bitref& +sc_fxnum_fast_bitref::operator = ( const sc_fxnum_bitref& a ) +{ + SC_FXNUM_OBSERVER_READ_( a.m_num ) + set( a.get() ); + SC_FXNUM_FAST_OBSERVER_WRITE_( m_num ) + return *this; +} + +inline +sc_fxnum_fast_bitref& +sc_fxnum_fast_bitref::operator = ( const sc_fxnum_fast_bitref& a ) +{ + if( &a != this ) + { + SC_FXNUM_FAST_OBSERVER_READ_( a.m_num ) + set( a.get() ); + SC_FXNUM_FAST_OBSERVER_WRITE_( m_num ) + } + return *this; +} + +inline +sc_fxnum_fast_bitref& +sc_fxnum_fast_bitref::operator = ( const sc_bit& a ) +{ + set( static_cast<bool>( a ) ); + SC_FXNUM_FAST_OBSERVER_WRITE_( m_num ) + return *this; +} + +inline +sc_fxnum_fast_bitref& +sc_fxnum_fast_bitref::operator = ( bool a ) +{ + set( a ); + SC_FXNUM_FAST_OBSERVER_WRITE_( m_num ) + return *this; +} + + +inline +sc_fxnum_fast_bitref& +sc_fxnum_fast_bitref::operator &= ( const sc_fxnum_bitref& b ) +{ + SC_FXNUM_FAST_OBSERVER_READ_( m_num ) + SC_FXNUM_OBSERVER_READ_( b.m_num ) + set( get() && b.get() ); + SC_FXNUM_FAST_OBSERVER_WRITE_( m_num ) + return *this; +} + +inline +sc_fxnum_fast_bitref& +sc_fxnum_fast_bitref::operator &= ( const sc_fxnum_fast_bitref& b ) +{ + SC_FXNUM_FAST_OBSERVER_READ_( m_num ) + SC_FXNUM_FAST_OBSERVER_READ_( b.m_num ) + set( get() && b.get() ); + SC_FXNUM_FAST_OBSERVER_WRITE_( m_num ) + return *this; +} + +inline +sc_fxnum_fast_bitref& +sc_fxnum_fast_bitref::operator &= ( const sc_bit& b ) +{ + SC_FXNUM_FAST_OBSERVER_READ_( m_num ) + set( get() && static_cast<bool>( b ) ); + SC_FXNUM_FAST_OBSERVER_WRITE_( m_num ) + return *this; +} + +inline +sc_fxnum_fast_bitref& +sc_fxnum_fast_bitref::operator &= ( bool b ) +{ + SC_FXNUM_FAST_OBSERVER_READ_( m_num ) + set( get() && b ); + SC_FXNUM_FAST_OBSERVER_WRITE_( m_num ) + return *this; +} + + +inline +sc_fxnum_fast_bitref& +sc_fxnum_fast_bitref::operator |= ( const sc_fxnum_bitref& b ) +{ + SC_FXNUM_FAST_OBSERVER_READ_( m_num ) + SC_FXNUM_OBSERVER_READ_( b.m_num ) + set( get() || b.get() ); + SC_FXNUM_FAST_OBSERVER_WRITE_( m_num ) + return *this; +} + +inline +sc_fxnum_fast_bitref& +sc_fxnum_fast_bitref::operator |= ( const sc_fxnum_fast_bitref& b ) +{ + SC_FXNUM_FAST_OBSERVER_READ_( m_num ) + SC_FXNUM_FAST_OBSERVER_READ_( b.m_num ) + set( get() || b.get() ); + SC_FXNUM_FAST_OBSERVER_WRITE_( m_num ) + return *this; +} + +inline +sc_fxnum_fast_bitref& +sc_fxnum_fast_bitref::operator |= ( const sc_bit& b ) +{ + SC_FXNUM_FAST_OBSERVER_READ_( m_num ) + set( get() || static_cast<bool>( b ) ); + SC_FXNUM_FAST_OBSERVER_WRITE_( m_num ) + return *this; +} + +inline +sc_fxnum_fast_bitref& +sc_fxnum_fast_bitref::operator |= ( bool b ) +{ + SC_FXNUM_FAST_OBSERVER_READ_( m_num ) + set( get() || b ); + SC_FXNUM_FAST_OBSERVER_WRITE_( m_num ) + return *this; +} + + +inline +sc_fxnum_fast_bitref& +sc_fxnum_fast_bitref::operator ^= ( const sc_fxnum_bitref& b ) +{ + SC_FXNUM_FAST_OBSERVER_READ_( m_num ) + SC_FXNUM_OBSERVER_READ_( b.m_num ) + set( get() != b.get() ); + SC_FXNUM_FAST_OBSERVER_WRITE_( m_num ) + return *this; +} + +inline +sc_fxnum_fast_bitref& +sc_fxnum_fast_bitref::operator ^= ( const sc_fxnum_fast_bitref& b ) +{ + SC_FXNUM_FAST_OBSERVER_READ_( m_num ) + SC_FXNUM_FAST_OBSERVER_READ_( b.m_num ) + set( get() != b.get() ); + SC_FXNUM_FAST_OBSERVER_WRITE_( m_num ) + return *this; +} + +inline +sc_fxnum_fast_bitref& +sc_fxnum_fast_bitref::operator ^= ( const sc_bit& b ) +{ + SC_FXNUM_FAST_OBSERVER_READ_( m_num ) + set( get() != static_cast<bool>( b ) ); + SC_FXNUM_FAST_OBSERVER_WRITE_( m_num ) + return *this; +} + +inline +sc_fxnum_fast_bitref& +sc_fxnum_fast_bitref::operator ^= ( bool b ) +{ + SC_FXNUM_FAST_OBSERVER_READ_( m_num ) + set( get() != b ); + SC_FXNUM_FAST_OBSERVER_WRITE_( m_num ) + return *this; +} + + +// implicit conversion + +inline +sc_fxnum_fast_bitref::operator bool() const +{ + SC_FXNUM_FAST_OBSERVER_READ_( m_num ) + return get(); +} + + +inline +::std::ostream& +operator << ( ::std::ostream& os, const sc_fxnum_fast_bitref& a ) +{ + a.print( os ); + return os; +} + +inline +::std::istream& +operator >> ( ::std::istream& is, sc_fxnum_fast_bitref& a ) +{ + a.scan( is ); + return is; +} + + +// ---------------------------------------------------------------------------- +// CLASS : sc_fxnum_subref +// +// Proxy class for part-selection in class sc_fxnum, +// behaves like sc_bv_base. +// ---------------------------------------------------------------------------- + +// constructor + +inline +sc_fxnum_subref::sc_fxnum_subref( sc_fxnum& num_, int from_, int to_ ) + : m_num( num_ ), m_from( from_ ), m_to( to_ ), + m_bv( *new sc_bv_base( sc_max( m_from, m_to ) - + sc_min( m_from, m_to ) + 1 ) ) +{} + + +// copy constructor + +inline +sc_fxnum_subref::sc_fxnum_subref( const sc_fxnum_subref& a ) + : m_num( a.m_num ), m_from( a.m_from ), m_to( a.m_to ), + m_bv( *new sc_bv_base( a.m_bv ) ) +{} + + +// destructor + +inline +sc_fxnum_subref::~sc_fxnum_subref() +{ + delete &m_bv; +} + + +// assignment operators + +inline +sc_fxnum_subref& +sc_fxnum_subref::operator = ( const sc_fxnum_subref& a ) +{ + if( &a != this ) + { + m_bv = static_cast<sc_bv_base>( a ); + set(); + SC_FXNUM_OBSERVER_WRITE_( m_num ) + } + return *this; +} + +inline +sc_fxnum_subref& +sc_fxnum_subref::operator = ( const sc_fxnum_fast_subref& a ) +{ + m_bv = static_cast<sc_bv_base>( a ); + set(); + SC_FXNUM_OBSERVER_WRITE_( m_num ) + return *this; +} + +#define DEFN_ASN_OP_T(tp) \ +inline \ +sc_fxnum_subref& \ +sc_fxnum_subref::operator = ( tp a ) \ +{ \ + m_bv = a; \ + set(); \ + SC_FXNUM_OBSERVER_WRITE_( m_num ) \ + return *this; \ +} + +DEFN_ASN_OP_T(const sc_bv_base&) +DEFN_ASN_OP_T(const sc_lv_base&) +DEFN_ASN_OP_T(const char*) +DEFN_ASN_OP_T(const bool*) +DEFN_ASN_OP_T(const sc_signed&) +DEFN_ASN_OP_T(const sc_unsigned&) +DEFN_ASN_OP_T(const sc_int_base&) +DEFN_ASN_OP_T(const sc_uint_base&) +DEFN_ASN_OP_T(int64) +DEFN_ASN_OP_T(uint64) +DEFN_ASN_OP_T(int) +DEFN_ASN_OP_T(unsigned int) +DEFN_ASN_OP_T(long) +DEFN_ASN_OP_T(unsigned long) +DEFN_ASN_OP_T(char) + +#undef DEFN_ASN_OP_T + + +#define DEFN_ASN_OP_T(op,tp) \ +inline \ +sc_fxnum_subref& \ +sc_fxnum_subref::operator op ## = ( tp a ) \ +{ \ + SC_FXNUM_OBSERVER_READ_( m_num ) \ + get(); \ + m_bv = m_bv op a; \ + set(); \ + SC_FXNUM_OBSERVER_WRITE_( m_num ) \ + return *this; \ +} + +#define DEFN_ASN_OP(op) \ +inline \ +sc_fxnum_subref& \ +sc_fxnum_subref::operator op ## = ( const sc_fxnum_subref& a ) \ +{ \ + SC_FXNUM_OBSERVER_READ_( m_num ) \ + get(); \ + m_bv = m_bv op static_cast<sc_bv_base>( a ); \ + set(); \ + SC_FXNUM_OBSERVER_WRITE_( m_num ) \ + return *this; \ +} \ + \ +inline \ +sc_fxnum_subref& \ +sc_fxnum_subref::operator op ## = ( const sc_fxnum_fast_subref& a ) \ +{ \ + SC_FXNUM_OBSERVER_READ_( m_num ) \ + get(); \ + m_bv = m_bv op static_cast<sc_bv_base>( a ); \ + set(); \ + SC_FXNUM_OBSERVER_WRITE_( m_num ) \ + return *this; \ +} \ + \ +DEFN_ASN_OP_T(op,const sc_bv_base&) \ +DEFN_ASN_OP_T(op,const sc_lv_base&) + +DEFN_ASN_OP(&) +DEFN_ASN_OP(|) +DEFN_ASN_OP(^) + +#undef DEFN_ASN_OP_T +#undef DEFN_ASN_OP + + +// relational operators + +#define DEFN_REL_OP_T(op,tp) \ +inline \ +bool \ +operator op ( const sc_fxnum_subref& a, tp b ) \ +{ \ + return ( static_cast<sc_bv_base>( a ) op b ); \ +} \ + \ +inline \ +bool \ +operator op ( tp a, const sc_fxnum_subref& b ) \ +{ \ + return ( static_cast<sc_bv_base>( b ) op a ); \ +} + +#define DEFN_REL_OP(op) \ +inline \ +bool \ +operator op ( const sc_fxnum_subref& a, const sc_fxnum_subref& b ) \ +{ \ + return ( static_cast<sc_bv_base>( a ) op static_cast<sc_bv_base>( b ) ); \ +} \ + \ +inline \ +bool \ +operator op ( const sc_fxnum_subref& a, const sc_fxnum_fast_subref& b ) \ +{ \ + return ( static_cast<sc_bv_base>( a ) op static_cast<sc_bv_base>( b ) ); \ +} \ + \ +DEFN_REL_OP_T(op,const sc_bv_base&) \ +DEFN_REL_OP_T(op,const sc_lv_base&) \ +DEFN_REL_OP_T(op,const char*) \ +DEFN_REL_OP_T(op,const bool*) \ +DEFN_REL_OP_T(op,const sc_signed&) \ +DEFN_REL_OP_T(op,const sc_unsigned&) \ +DEFN_REL_OP_T(op,int) \ +DEFN_REL_OP_T(op,unsigned int) \ +DEFN_REL_OP_T(op,long) \ +DEFN_REL_OP_T(op,unsigned long) + +DEFN_REL_OP(==) +DEFN_REL_OP(!=) + +#undef DEFN_REL_OP_T +#undef DEFN_REL_OP + + +// reduce functions + +#define DEFN_RED_FNC(fnc) \ +inline \ +bool \ +sc_fxnum_subref::fnc() const \ +{ \ + SC_FXNUM_OBSERVER_READ_( m_num ) \ + get(); \ + return static_cast<bool>( m_bv.fnc() ); \ +} + +DEFN_RED_FNC(and_reduce) +DEFN_RED_FNC(nand_reduce) +DEFN_RED_FNC(or_reduce) +DEFN_RED_FNC(nor_reduce) +DEFN_RED_FNC(xor_reduce) +DEFN_RED_FNC(xnor_reduce) + +#undef DEFN_RED_FNC + + +// query parameter + +inline +int +sc_fxnum_subref::length() const +{ + return m_bv.length(); +} + + +// explicit conversions + +inline +int +sc_fxnum_subref::to_int() const +{ + SC_FXNUM_OBSERVER_READ_( m_num ) + get(); + return m_bv.to_int(); +} + +inline +int64 +sc_fxnum_subref::to_int64() const +{ + SC_FXNUM_OBSERVER_READ_( m_num ) + get(); + return m_bv.to_int64(); +} + +inline +unsigned int +sc_fxnum_subref::to_uint() const +{ + SC_FXNUM_OBSERVER_READ_( m_num ) + get(); + return m_bv.to_uint(); +} + +inline +uint64 +sc_fxnum_subref::to_uint64() const +{ + SC_FXNUM_OBSERVER_READ_( m_num ) + get(); + return m_bv.to_uint64(); +} + +inline +long +sc_fxnum_subref::to_long() const +{ + SC_FXNUM_OBSERVER_READ_( m_num ) + get(); + return m_bv.to_long(); +} + +inline +unsigned long +sc_fxnum_subref::to_ulong() const +{ + SC_FXNUM_OBSERVER_READ_( m_num ) + get(); + return m_bv.to_ulong(); +} + + +#ifdef SC_DT_DEPRECATED + +inline +int +sc_fxnum_subref::to_signed() const +{ + return to_int(); +} + +inline +unsigned int +sc_fxnum_subref::to_unsigned() const +{ + return to_uint(); +} + +#endif + + +inline +const std::string +sc_fxnum_subref::to_string() const +{ + get(); + return m_bv.to_string(); +} + +inline +const std::string +sc_fxnum_subref::to_string( sc_numrep numrep ) const +{ + get(); + return m_bv.to_string( numrep ); +} + +inline +const std::string +sc_fxnum_subref::to_string( sc_numrep numrep, bool w_prefix ) const +{ + get(); + return m_bv.to_string( numrep, w_prefix ); +} + + +// implicit conversion + +inline +sc_fxnum_subref::operator sc_bv_base () const +{ + SC_FXNUM_OBSERVER_READ_( m_num ) + get(); + return m_bv; +} + + +inline +::std::ostream& +operator << ( ::std::ostream& os, const sc_fxnum_subref& a ) +{ + a.print( os ); + return os; +} + +inline +::std::istream& +operator >> ( ::std::istream& is, sc_fxnum_subref& a ) +{ + a.scan( is ); + return is; +} + + +// ---------------------------------------------------------------------------- +// CLASS : sc_fxnum_fast_subref +// +// Proxy class for part-selection in class sc_fxnum_fast, +// behaves like sc_bv_base. +// ---------------------------------------------------------------------------- + +// constructor + +inline +sc_fxnum_fast_subref::sc_fxnum_fast_subref( sc_fxnum_fast& num_, + int from_, int to_ ) + : m_num( num_ ), m_from( from_ ), m_to( to_ ), + m_bv( *new sc_bv_base( sc_max( m_from, m_to ) - + sc_min( m_from, m_to ) + 1 ) ) +{} + + +// copy constructor + +inline +sc_fxnum_fast_subref::sc_fxnum_fast_subref( const sc_fxnum_fast_subref& a ) + : m_num( a.m_num ), m_from( a.m_from ), m_to( a.m_to ), + m_bv( *new sc_bv_base( a.m_bv ) ) +{} + + +// destructor + +inline +sc_fxnum_fast_subref::~sc_fxnum_fast_subref() +{ + delete &m_bv; +} + + +// assignment operators + +inline +sc_fxnum_fast_subref& +sc_fxnum_fast_subref::operator = ( const sc_fxnum_subref& a ) +{ + m_bv = static_cast<sc_bv_base>( a ); + set(); + SC_FXNUM_FAST_OBSERVER_WRITE_( m_num ) + return *this; +} + +inline +sc_fxnum_fast_subref& +sc_fxnum_fast_subref::operator = ( const sc_fxnum_fast_subref& a ) +{ + if( &a != this ) + { + m_bv = static_cast<sc_bv_base>( a ); + set(); + SC_FXNUM_FAST_OBSERVER_WRITE_( m_num ) + } + return *this; +} + +#define DEFN_ASN_OP_T(tp) \ +inline \ +sc_fxnum_fast_subref& \ +sc_fxnum_fast_subref::operator = ( tp a ) \ +{ \ + m_bv = a; \ + set(); \ + SC_FXNUM_FAST_OBSERVER_WRITE_( m_num ) \ + return *this; \ +} + +DEFN_ASN_OP_T(const sc_bv_base&) +DEFN_ASN_OP_T(const sc_lv_base&) +DEFN_ASN_OP_T(const char*) +DEFN_ASN_OP_T(const bool*) +DEFN_ASN_OP_T(const sc_signed&) +DEFN_ASN_OP_T(const sc_unsigned&) +DEFN_ASN_OP_T(const sc_int_base&) +DEFN_ASN_OP_T(const sc_uint_base&) +DEFN_ASN_OP_T(int64) +DEFN_ASN_OP_T(uint64) +DEFN_ASN_OP_T(int) +DEFN_ASN_OP_T(unsigned int) +DEFN_ASN_OP_T(long) +DEFN_ASN_OP_T(unsigned long) +DEFN_ASN_OP_T(char) + +#undef DEFN_ASN_OP_T + + +#define DEFN_ASN_OP_T(op,tp) \ +inline \ +sc_fxnum_fast_subref& \ +sc_fxnum_fast_subref::operator op ## = ( tp a ) \ +{ \ + SC_FXNUM_FAST_OBSERVER_READ_( m_num ) \ + get(); \ + m_bv = m_bv op a; \ + set(); \ + SC_FXNUM_FAST_OBSERVER_WRITE_( m_num ) \ + return *this; \ +} + +#define DEFN_ASN_OP(op) \ +inline \ +sc_fxnum_fast_subref& \ +sc_fxnum_fast_subref::operator op ## = ( const sc_fxnum_subref& a ) \ +{ \ + SC_FXNUM_FAST_OBSERVER_READ_( m_num ) \ + get(); \ + m_bv = m_bv op static_cast<sc_bv_base>( a ); \ + set(); \ + SC_FXNUM_FAST_OBSERVER_WRITE_( m_num ) \ + return *this; \ +} \ + \ +inline \ +sc_fxnum_fast_subref& \ +sc_fxnum_fast_subref::operator op ## = ( const sc_fxnum_fast_subref& a ) \ +{ \ + SC_FXNUM_FAST_OBSERVER_READ_( m_num ) \ + get(); \ + m_bv = m_bv op static_cast<sc_bv_base>( a ); \ + set(); \ + SC_FXNUM_FAST_OBSERVER_WRITE_( m_num ) \ + return *this; \ +} \ + \ +DEFN_ASN_OP_T(op,const sc_bv_base&) \ +DEFN_ASN_OP_T(op,const sc_lv_base&) + +DEFN_ASN_OP(&) +DEFN_ASN_OP(|) +DEFN_ASN_OP(^) + +#undef DEFN_ASN_OP_T +#undef DEFN_ASN_OP + + +// relational operators + +#define DEFN_REL_OP_T(op,tp) \ +inline \ +bool \ +operator op ( const sc_fxnum_fast_subref& a, tp b ) \ +{ \ + return ( static_cast<sc_bv_base>( a ) op b ); \ +} \ + \ +inline \ +bool \ +operator op ( tp a, const sc_fxnum_fast_subref& b ) \ +{ \ + return ( static_cast<sc_bv_base>( b ) op a ); \ +} + +#define DEFN_REL_OP(op) \ +inline \ +bool \ +operator op ( const sc_fxnum_fast_subref& a, const sc_fxnum_fast_subref& b ) \ +{ \ + return ( static_cast<sc_bv_base>( a ) op static_cast<sc_bv_base>( b ) ); \ +} \ + \ +inline \ +bool \ +operator op ( const sc_fxnum_fast_subref& a, const sc_fxnum_subref& b ) \ +{ \ + return ( static_cast<sc_bv_base>( a ) op static_cast<sc_bv_base>( b ) ); \ +} \ + \ +DEFN_REL_OP_T(op,const sc_bv_base&) \ +DEFN_REL_OP_T(op,const sc_lv_base&) \ +DEFN_REL_OP_T(op,const char*) \ +DEFN_REL_OP_T(op,const bool*) \ +DEFN_REL_OP_T(op,const sc_signed&) \ +DEFN_REL_OP_T(op,const sc_unsigned&) \ +DEFN_REL_OP_T(op,int) \ +DEFN_REL_OP_T(op,unsigned int) \ +DEFN_REL_OP_T(op,long) \ +DEFN_REL_OP_T(op,unsigned long) + +DEFN_REL_OP(==) +DEFN_REL_OP(!=) + +#undef DEFN_REL_OP_T +#undef DEFN_REL_OP + + +// reduce functions + +#define DEFN_RED_FNC(fnc) \ +inline \ +bool \ +sc_fxnum_fast_subref::fnc() const \ +{ \ + SC_FXNUM_FAST_OBSERVER_READ_( m_num ) \ + get(); \ + return static_cast<bool>( m_bv.fnc() ); \ +} + +DEFN_RED_FNC(and_reduce) +DEFN_RED_FNC(nand_reduce) +DEFN_RED_FNC(or_reduce) +DEFN_RED_FNC(nor_reduce) +DEFN_RED_FNC(xor_reduce) +DEFN_RED_FNC(xnor_reduce) + +#undef DEFN_RED_FNC + + +// query parameter + +inline +int +sc_fxnum_fast_subref::length() const +{ + return m_bv.length(); +} + + +// explicit conversions + +inline +int +sc_fxnum_fast_subref::to_int() const +{ + SC_FXNUM_FAST_OBSERVER_READ_( m_num ) + get(); + return m_bv.to_int(); +} + +inline +int64 +sc_fxnum_fast_subref::to_int64() const +{ + SC_FXNUM_FAST_OBSERVER_READ_( m_num ) + get(); + return m_bv.to_int64(); +} + +inline +unsigned int +sc_fxnum_fast_subref::to_uint() const +{ + SC_FXNUM_FAST_OBSERVER_READ_( m_num ) + get(); + return m_bv.to_uint(); +} + +inline +uint64 +sc_fxnum_fast_subref::to_uint64() const +{ + SC_FXNUM_FAST_OBSERVER_READ_( m_num ) + get(); + return m_bv.to_uint64(); +} + +inline +long +sc_fxnum_fast_subref::to_long() const +{ + SC_FXNUM_FAST_OBSERVER_READ_( m_num ) + get(); + return m_bv.to_long(); +} + +inline +unsigned long +sc_fxnum_fast_subref::to_ulong() const +{ + SC_FXNUM_FAST_OBSERVER_READ_( m_num ) + get(); + return m_bv.to_ulong(); +} + + +#ifdef SC_DT_DEPRECATED + +inline +int +sc_fxnum_fast_subref::to_signed() const +{ + return to_int(); +} + +inline +unsigned int +sc_fxnum_fast_subref::to_unsigned() const +{ + return to_uint(); +} + +#endif + + +inline +const std::string +sc_fxnum_fast_subref::to_string() const +{ + get(); + return m_bv.to_string(); +} + +inline +const std::string +sc_fxnum_fast_subref::to_string( sc_numrep numrep ) const +{ + get(); + return m_bv.to_string( numrep ); +} + +inline +const std::string +sc_fxnum_fast_subref::to_string( sc_numrep numrep, bool w_prefix ) const +{ + get(); + return m_bv.to_string( numrep, w_prefix ); +} + + +// implicit conversion + +inline +sc_fxnum_fast_subref::operator sc_bv_base () const +{ + SC_FXNUM_FAST_OBSERVER_READ_( m_num ) + get(); + return m_bv; +} + + +inline +::std::ostream& +operator << ( ::std::ostream& os, const sc_fxnum_fast_subref& a ) +{ + a.print( os ); + return os; +} + +inline +::std::istream& +operator >> ( ::std::istream& is, sc_fxnum_fast_subref& a ) +{ + a.scan( is ); + return is; +} + + +// ---------------------------------------------------------------------------- +// CLASS : sc_fxnum +// +// Base class for the fixed-point types; arbitrary precision. +// ---------------------------------------------------------------------------- + +inline +sc_fxnum_observer* +sc_fxnum::observer() const +{ + return m_observer; +} + + +inline +void +sc_fxnum::cast() +{ + SC_ERROR_IF_( ! m_rep->is_normal(), sc_core::SC_ID_INVALID_FX_VALUE_ ); + + if( m_params.cast_switch() == SC_ON ) + m_rep->cast( m_params, m_q_flag, m_o_flag ); +} + + +// constructors + +inline +sc_fxnum::sc_fxnum( const sc_fxtype_params& type_params_, + sc_enc enc_, + const sc_fxcast_switch& cast_sw, + sc_fxnum_observer* observer_ ) +: m_rep( new scfx_rep ), + m_params( type_params_, enc_, cast_sw ), + m_q_flag( false ), + m_o_flag( false ), + m_observer( observer_ ) +{ + SC_FXNUM_OBSERVER_DEFAULT_ + SC_FXNUM_OBSERVER_CONSTRUCT_( *this ) +} + +#define DEFN_CTOR_T(tp,arg) \ +inline \ +sc_fxnum::sc_fxnum( tp a, \ + const sc_fxtype_params& type_params_, \ + sc_enc enc_, \ + const sc_fxcast_switch& cast_sw, \ + sc_fxnum_observer* observer_ ) \ +: m_rep( new scfx_rep( arg ) ), \ + m_params( type_params_, enc_, cast_sw ), \ + m_q_flag( false ), \ + m_o_flag( false ), \ + m_observer( observer_ ) \ +{ \ + SC_FXNUM_OBSERVER_DEFAULT_ \ + cast(); \ + SC_FXNUM_OBSERVER_CONSTRUCT_( *this ) \ + SC_FXNUM_OBSERVER_WRITE_( *this ) \ +} + +#define DEFN_CTOR_T_A(tp) DEFN_CTOR_T(tp,a) +#define DEFN_CTOR_T_B(tp) DEFN_CTOR_T(tp,*a.m_rep) +#define DEFN_CTOR_T_C(tp) DEFN_CTOR_T(tp,a.to_double()) +#define DEFN_CTOR_T_D(tp) DEFN_CTOR_T(tp,a.value()) + +DEFN_CTOR_T_A(int) +DEFN_CTOR_T_A(unsigned int) +DEFN_CTOR_T_A(long) +DEFN_CTOR_T_A(unsigned long) +DEFN_CTOR_T_A(float) +DEFN_CTOR_T_A(double) +DEFN_CTOR_T_A(const char*) +DEFN_CTOR_T_B(const sc_fxval&) +DEFN_CTOR_T_C(const sc_fxval_fast&) +DEFN_CTOR_T_B(const sc_fxnum&) +DEFN_CTOR_T_C(const sc_fxnum_fast&) +#ifndef SC_FX_EXCLUDE_OTHER +DEFN_CTOR_T_A(int64) +DEFN_CTOR_T_A(uint64) +DEFN_CTOR_T_D(const sc_int_base&) +DEFN_CTOR_T_D(const sc_uint_base&) +DEFN_CTOR_T_A(const sc_signed&) +DEFN_CTOR_T_A(const sc_unsigned&) +#endif + +#undef DEFN_CTOR_T +#undef DEFN_CTOR_T_A +#undef DEFN_CTOR_T_B +#undef DEFN_CTOR_T_C +#undef DEFN_CTOR_T_D + + +inline +sc_fxnum::~sc_fxnum() +{ + SC_FXNUM_OBSERVER_DESTRUCT_( *this ) + delete m_rep; +} + + +// internal use only; +inline +const scfx_rep* +sc_fxnum::get_rep() const +{ + SC_FXNUM_OBSERVER_READ_( *this ) + return m_rep; +} + + +// unary operators + +inline +const sc_fxval +sc_fxnum::operator - () const +{ + SC_FXNUM_OBSERVER_READ_( *this ) + return sc_fxval( sc_dt::neg_scfx_rep( *m_rep ) ); +} + +inline +const sc_fxval +sc_fxnum::operator + () const +{ + SC_FXNUM_OBSERVER_READ_( *this ) + return sc_fxval( new scfx_rep( *m_rep ) ); +} + + +// unary functions + +inline +void +neg( sc_fxval& c, const sc_fxnum& a ) +{ + SC_FXNUM_OBSERVER_READ_( a ) + c.set_rep( sc_dt::neg_scfx_rep( *a.m_rep ) ); +} + +inline +void +neg( sc_fxnum& c, const sc_fxnum& a ) +{ + SC_FXNUM_OBSERVER_READ_( a ) + delete c.m_rep; + c.m_rep = sc_dt::neg_scfx_rep( *a.m_rep ); + c.cast(); + SC_FXNUM_OBSERVER_WRITE_( c ) +} + + +// binary operators + +#define DEFN_BIN_OP_T(op,fnc,tp) \ +inline \ +const sc_fxval \ +operator op ( const sc_fxnum& a, tp b ) \ +{ \ + SC_FXNUM_OBSERVER_READ_( a ) \ + sc_fxval tmp( b ); \ + return sc_fxval( sc_dt::fnc ## _scfx_rep( *a.m_rep, *tmp.get_rep() ) ); \ +} \ + \ +inline \ +const sc_fxval \ +operator op ( tp a, const sc_fxnum& b ) \ +{ \ + SC_FXNUM_OBSERVER_READ_( b ) \ + sc_fxval tmp( a ); \ + return sc_fxval( sc_dt::fnc ## _scfx_rep( *tmp.get_rep(), *b.m_rep ) ); \ +} + +#ifndef SC_FX_EXCLUDE_OTHER +#define DEFN_BIN_OP_OTHER(op,fnc) \ +DEFN_BIN_OP_T(op,fnc,int64) \ +DEFN_BIN_OP_T(op,fnc,uint64) \ +DEFN_BIN_OP_T(op,fnc,const sc_int_base&) \ +DEFN_BIN_OP_T(op,fnc,const sc_uint_base&) \ +DEFN_BIN_OP_T(op,fnc,const sc_signed&) \ +DEFN_BIN_OP_T(op,fnc,const sc_unsigned&) +#else +#define DEFN_BIN_OP_OTHER(op,fnc) +#endif + +#define DEFN_BIN_OP(op,fnc) \ +inline \ +const sc_fxval \ +operator op ( const sc_fxnum& a, const sc_fxnum& b ) \ +{ \ + SC_FXNUM_OBSERVER_READ_( a ) \ + SC_FXNUM_OBSERVER_READ_( b ) \ + return sc_fxval( sc_dt::fnc ## _scfx_rep( *a.m_rep, *b.m_rep ) ); \ +} \ + \ +inline \ +const sc_fxval \ +operator op ( const sc_fxnum& a, const sc_fxval& b ) \ +{ \ + SC_FXNUM_OBSERVER_READ_( a ) \ + return sc_fxval( sc_dt::fnc ## _scfx_rep( *a.m_rep, *b.get_rep() ) ); \ +} \ + \ +inline \ +const sc_fxval \ +operator op ( const sc_fxval& a, const sc_fxnum& b ) \ +{ \ + SC_FXNUM_OBSERVER_READ_( b ) \ + return sc_fxval( sc_dt::fnc ## _scfx_rep( *a.get_rep(), *b.m_rep ) ); \ +} \ + \ +DEFN_BIN_OP_T(op,fnc,int) \ +DEFN_BIN_OP_T(op,fnc,unsigned int) \ +DEFN_BIN_OP_T(op,fnc,long) \ +DEFN_BIN_OP_T(op,fnc,unsigned long) \ +DEFN_BIN_OP_T(op,fnc,float) \ +DEFN_BIN_OP_T(op,fnc,double) \ +DEFN_BIN_OP_T(op,fnc,const char*) \ +DEFN_BIN_OP_T(op,fnc,const sc_fxval_fast&) \ +DEFN_BIN_OP_T(op,fnc,const sc_fxnum_fast&) \ +DEFN_BIN_OP_OTHER(op,fnc) + +DEFN_BIN_OP(*,mult) +DEFN_BIN_OP(+,add) +DEFN_BIN_OP(-,sub) +// don't use macros +//DEFN_BIN_OP(/,div) +inline +const sc_fxval +operator / ( const sc_fxnum& a, const sc_fxnum& b ) +{ + SC_FXNUM_OBSERVER_READ_( a ) + SC_FXNUM_OBSERVER_READ_( b ) + return sc_fxval( sc_dt::div_scfx_rep( *a.m_rep, *b.m_rep ) ); +} + +inline +const sc_fxval +operator / ( const sc_fxnum& a, const sc_fxval& b ) +{ + SC_FXNUM_OBSERVER_READ_( a ) + return sc_fxval( sc_dt::div_scfx_rep( *a.m_rep, *b.get_rep() ) ); +} + +inline +const sc_fxval +operator / ( const sc_fxval& a, const sc_fxnum& b ) +{ + SC_FXNUM_OBSERVER_READ_( b ) + return sc_fxval( sc_dt::div_scfx_rep( *a.get_rep(), *b.m_rep ) ); +} + +DEFN_BIN_OP_T(/,div,int) +DEFN_BIN_OP_T(/,div,unsigned int) +DEFN_BIN_OP_T(/,div,long) +DEFN_BIN_OP_T(/,div,unsigned long) +DEFN_BIN_OP_T(/,div,float) +DEFN_BIN_OP_T(/,div,double) +DEFN_BIN_OP_T(/,div,const char*) +DEFN_BIN_OP_T(/,div,const sc_fxval_fast&) +DEFN_BIN_OP_T(/,div,const sc_fxnum_fast&) +//DEFN_BIN_OP_OTHER(/,div) +#ifndef SC_FX_EXCLUDE_OTHER +DEFN_BIN_OP_T(/,div,int64) +DEFN_BIN_OP_T(/,div,uint64) +DEFN_BIN_OP_T(/,div,const sc_int_base&) +DEFN_BIN_OP_T(/,div,const sc_uint_base&) +DEFN_BIN_OP_T(/,div,const sc_signed&) +DEFN_BIN_OP_T(/,div,const sc_unsigned&) +#endif + +#undef DEFN_BIN_OP_T +#undef DEFN_BIN_OP_OTHER +#undef DEFN_BIN_OP + + +inline +const sc_fxval +operator << ( const sc_fxnum& a, int b ) +{ + SC_FXNUM_OBSERVER_READ_( a ) + return sc_fxval( sc_dt::lsh_scfx_rep( *a.m_rep, b ) ); +} + +inline +const sc_fxval +operator >> ( const sc_fxnum& a, int b ) +{ + SC_FXNUM_OBSERVER_READ_( a ) + return sc_fxval( sc_dt::rsh_scfx_rep( *a.m_rep, b ) ); +} + + +// binary functions + +#define DEFN_BIN_FNC_T(fnc,tp) \ +inline \ +void \ +fnc ( sc_fxval& c, const sc_fxnum& a, tp b ) \ +{ \ + SC_FXNUM_OBSERVER_READ_( a ) \ + sc_fxval tmp( b ); \ + c.set_rep( sc_dt::fnc ## _scfx_rep( *a.m_rep, *tmp.get_rep() ) ); \ +} \ + \ +inline \ +void \ +fnc ( sc_fxval& c, tp a, const sc_fxnum& b ) \ +{ \ + SC_FXNUM_OBSERVER_READ_( b ) \ + sc_fxval tmp( a ); \ + c.set_rep( sc_dt::fnc ## _scfx_rep( *tmp.get_rep(), *b.m_rep ) ); \ +} \ + \ +inline \ +void \ +fnc ( sc_fxnum& c, const sc_fxnum& a, tp b ) \ +{ \ + SC_FXNUM_OBSERVER_READ_( a ) \ + sc_fxval tmp( b ); \ + delete c.m_rep; \ + c.m_rep = sc_dt::fnc ## _scfx_rep( *a.m_rep, *tmp.get_rep() ); \ + c.cast(); \ + SC_FXNUM_OBSERVER_WRITE_( c ) \ +} \ + \ +inline \ +void \ +fnc ( sc_fxnum& c, tp a, const sc_fxnum& b ) \ +{ \ + SC_FXNUM_OBSERVER_READ_( b ) \ + sc_fxval tmp( a ); \ + delete c.m_rep; \ + c.m_rep = sc_dt::fnc ## _scfx_rep( *tmp.get_rep(), *b.m_rep ); \ + c.cast(); \ + SC_FXNUM_OBSERVER_WRITE_( c ) \ +} + +#ifndef SC_FX_EXCLUDE_OTHER +#define DEFN_BIN_FNC_OTHER(fnc) \ +DEFN_BIN_FNC_T(fnc,int64) \ +DEFN_BIN_FNC_T(fnc,uint64) \ +DEFN_BIN_FNC_T(fnc,const sc_int_base&) \ +DEFN_BIN_FNC_T(fnc,const sc_uint_base&) \ +DEFN_BIN_FNC_T(fnc,const sc_signed&) \ +DEFN_BIN_FNC_T(fnc,const sc_unsigned&) +#else +#define DEFN_BIN_FNC_OTHER(fnc) +#endif + +#define DEFN_BIN_FNC(fnc) \ +inline \ +void \ +fnc ( sc_fxval& c, const sc_fxnum& a, const sc_fxnum& b ) \ +{ \ + SC_FXNUM_OBSERVER_READ_( a ) \ + SC_FXNUM_OBSERVER_READ_( b ) \ + c.set_rep( sc_dt::fnc ## _scfx_rep( *a.m_rep, *b.m_rep ) ); \ +} \ + \ +inline \ +void \ +fnc ( sc_fxnum& c, const sc_fxnum& a, const sc_fxnum& b ) \ +{ \ + SC_FXNUM_OBSERVER_READ_( a ) \ + SC_FXNUM_OBSERVER_READ_( b ) \ + delete c.m_rep; \ + c.m_rep = sc_dt::fnc ## _scfx_rep( *a.m_rep, *b.m_rep ); \ + c.cast(); \ + SC_FXNUM_OBSERVER_WRITE_( c ) \ +} \ + \ +inline \ +void \ +fnc ( sc_fxval& c, const sc_fxnum& a, const sc_fxval& b ) \ +{ \ + SC_FXNUM_OBSERVER_READ_( a ) \ + c.set_rep( sc_dt::fnc ## _scfx_rep( *a.m_rep, *b.get_rep() ) ); \ +} \ + \ +inline \ +void \ +fnc ( sc_fxval& c, const sc_fxval& a, const sc_fxnum& b ) \ +{ \ + SC_FXNUM_OBSERVER_READ_( b ) \ + c.set_rep( sc_dt::fnc ## _scfx_rep( *a.get_rep(), *b.m_rep ) ); \ +} \ + \ +inline \ +void \ +fnc ( sc_fxnum& c, const sc_fxnum& a, const sc_fxval& b ) \ +{ \ + SC_FXNUM_OBSERVER_READ_( a ) \ + delete c.m_rep; \ + c.m_rep = sc_dt::fnc ## _scfx_rep( *a.m_rep, *b.get_rep() ); \ + c.cast(); \ + SC_FXNUM_OBSERVER_WRITE_( c ) \ +} \ + \ +inline \ +void \ +fnc ( sc_fxnum& c, const sc_fxval& a, const sc_fxnum& b ) \ +{ \ + SC_FXNUM_OBSERVER_READ_( b ) \ + delete c.m_rep; \ + c.m_rep = sc_dt::fnc ## _scfx_rep( *a.get_rep(), *b.m_rep ); \ + c.cast(); \ + SC_FXNUM_OBSERVER_WRITE_( c ) \ +} \ + \ +DEFN_BIN_FNC_T(fnc,int) \ +DEFN_BIN_FNC_T(fnc,unsigned int) \ +DEFN_BIN_FNC_T(fnc,long) \ +DEFN_BIN_FNC_T(fnc,unsigned long) \ +DEFN_BIN_FNC_T(fnc,float) \ +DEFN_BIN_FNC_T(fnc,double) \ +DEFN_BIN_FNC_T(fnc,const char*) \ +DEFN_BIN_FNC_T(fnc,const sc_fxval_fast&) \ +DEFN_BIN_FNC_T(fnc,const sc_fxnum_fast&) \ +DEFN_BIN_FNC_OTHER(fnc) + +DEFN_BIN_FNC(mult) +DEFN_BIN_FNC(div) +DEFN_BIN_FNC(add) +DEFN_BIN_FNC(sub) + +#undef DEFN_BIN_FNC_T +#undef DEFN_BIN_FNC_OTHER +#undef DEFN_BIN_FNC + + +inline +void +lshift( sc_fxval& c, const sc_fxnum& a, int b ) +{ + SC_FXNUM_OBSERVER_READ_( a ) + c.set_rep( sc_dt::lsh_scfx_rep( *a.m_rep, b ) ); +} + +inline +void +rshift( sc_fxval& c, const sc_fxnum& a, int b ) +{ + SC_FXNUM_OBSERVER_READ_( a ) + c.set_rep( sc_dt::rsh_scfx_rep( *a.m_rep, b ) ); +} + +inline +void +lshift( sc_fxnum& c, const sc_fxnum& a, int b ) +{ + SC_FXNUM_OBSERVER_READ_( a ) + delete c.m_rep; + c.m_rep = sc_dt::lsh_scfx_rep( *a.m_rep, b ); + c.cast(); + SC_FXNUM_OBSERVER_WRITE_( c ) +} + +inline +void +rshift( sc_fxnum& c, const sc_fxnum& a, int b ) +{ + SC_FXNUM_OBSERVER_READ_( a ) + delete c.m_rep; + c.m_rep = sc_dt::rsh_scfx_rep( *a.m_rep, b ); + c.cast(); + SC_FXNUM_OBSERVER_WRITE_( c ) +} + + +// relational (including equality) operators + +#define DEFN_REL_OP_T(op,ret,tp) \ +inline \ +bool \ +operator op ( const sc_fxnum& a, tp b ) \ +{ \ + SC_FXNUM_OBSERVER_READ_( a ) \ + sc_fxval tmp( b ); \ + int result = sc_dt::cmp_scfx_rep( *a.m_rep, *tmp.get_rep() ); \ + return ( ret ); \ +} \ + \ +inline \ +bool \ +operator op ( tp a, const sc_fxnum& b ) \ +{ \ + SC_FXNUM_OBSERVER_READ_( b ) \ + sc_fxval tmp( a ); \ + int result = sc_dt::cmp_scfx_rep( *tmp.get_rep(), *b.m_rep ); \ + return ( ret ); \ +} + +#ifndef SC_FX_EXCLUDE_OTHER +#define DEFN_REL_OP_OTHER(op,ret) \ +DEFN_REL_OP_T(op,ret,int64) \ +DEFN_REL_OP_T(op,ret,uint64) \ +DEFN_REL_OP_T(op,ret,const sc_int_base&) \ +DEFN_REL_OP_T(op,ret,const sc_uint_base&) \ +DEFN_REL_OP_T(op,ret,const sc_signed&) \ +DEFN_REL_OP_T(op,ret,const sc_unsigned&) +#else +#define DEFN_REL_OP_OTHER(op,ret) +#endif + +#define DEFN_REL_OP(op,ret) \ +inline \ +bool \ +operator op ( const sc_fxnum& a, const sc_fxnum& b ) \ +{ \ + SC_FXNUM_OBSERVER_READ_( a ) \ + SC_FXNUM_OBSERVER_READ_( b ) \ + int result = sc_dt::cmp_scfx_rep( *a.m_rep, *b.m_rep ); \ + return ( ret ); \ +} \ + \ +inline \ +bool \ +operator op ( const sc_fxnum& a, const sc_fxval& b ) \ +{ \ + SC_FXNUM_OBSERVER_READ_( a ) \ + int result = sc_dt::cmp_scfx_rep( *a.m_rep, *b.get_rep() ); \ + return ( ret ); \ +} \ + \ +inline \ +bool \ +operator op ( const sc_fxval& a, const sc_fxnum& b ) \ +{ \ + SC_FXNUM_OBSERVER_READ_( b ) \ + int result = sc_dt::cmp_scfx_rep( *a.get_rep(), *b.m_rep ); \ + return ( ret ); \ +} \ + \ +DEFN_REL_OP_T(op,ret,int) \ +DEFN_REL_OP_T(op,ret,unsigned int) \ +DEFN_REL_OP_T(op,ret,long) \ +DEFN_REL_OP_T(op,ret,unsigned long) \ +DEFN_REL_OP_T(op,ret,float) \ +DEFN_REL_OP_T(op,ret,double) \ +DEFN_REL_OP_T(op,ret,const char*) \ +DEFN_REL_OP_T(op,ret,const sc_fxval_fast&) \ +DEFN_REL_OP_T(op,ret,const sc_fxnum_fast&) \ +DEFN_REL_OP_OTHER(op,ret) + +DEFN_REL_OP(<,result < 0) +DEFN_REL_OP(<=,result <= 0) +DEFN_REL_OP(>,result > 0 && result != 2) +DEFN_REL_OP(>=,result >= 0 && result != 2) +DEFN_REL_OP(==,result == 0) +DEFN_REL_OP(!=,result != 0) + +#undef DEFN_REL_OP_T +#undef DEFN_REL_OP_OTHER +#undef DEFN_REL_OP + + +// assignment operators + +inline +sc_fxnum& +sc_fxnum::operator = ( const sc_fxnum& a ) +{ + if( &a != this ) + { + SC_FXNUM_OBSERVER_READ_( a ) + *m_rep = *a.m_rep; + cast(); + SC_FXNUM_OBSERVER_WRITE_( *this ) + } + return *this; +} + +inline +sc_fxnum& +sc_fxnum::operator = ( const sc_fxval& a ) +{ + *m_rep = *a.get_rep(); + cast(); + SC_FXNUM_OBSERVER_WRITE_( *this ) + return *this; +} + +#define DEFN_ASN_OP_T(tp) \ +inline \ +sc_fxnum& \ +sc_fxnum::operator = ( tp a ) \ +{ \ + sc_fxval tmp( a ); \ + *m_rep = *tmp.get_rep(); \ + cast(); \ + SC_FXNUM_OBSERVER_WRITE_( *this ) \ + return *this; \ +} + +DEFN_ASN_OP_T(int) +DEFN_ASN_OP_T(unsigned int) +DEFN_ASN_OP_T(long) +DEFN_ASN_OP_T(unsigned long) +DEFN_ASN_OP_T(float) +DEFN_ASN_OP_T(double) +DEFN_ASN_OP_T(const char*) +DEFN_ASN_OP_T(const sc_fxval_fast&) +DEFN_ASN_OP_T(const sc_fxnum_fast&) +#ifndef SC_FX_EXCLUDE_OTHER +DEFN_ASN_OP_T(int64) +DEFN_ASN_OP_T(uint64) +DEFN_ASN_OP_T(const sc_int_base&) +DEFN_ASN_OP_T(const sc_uint_base&) +DEFN_ASN_OP_T(const sc_signed&) +DEFN_ASN_OP_T(const sc_unsigned&) +#endif + +#undef DEFN_ASN_OP_T + + +#define DEFN_ASN_OP_T(op,fnc,tp) \ +inline \ +sc_fxnum& \ +sc_fxnum::operator op ( tp b ) \ +{ \ + SC_FXNUM_OBSERVER_READ_( *this ) \ + sc_fxval tmp( b ); \ + scfx_rep* new_rep = sc_dt::fnc ## _scfx_rep( *m_rep, *tmp.get_rep() ); \ + delete m_rep; \ + m_rep = new_rep; \ + cast(); \ + SC_FXNUM_OBSERVER_WRITE_( *this ) \ + return *this; \ +} + +#ifndef SC_FX_EXCLUDE_OTHER +#define DEFN_ASN_OP_OTHER(op,fnc) \ +DEFN_ASN_OP_T(op,fnc,int64) \ +DEFN_ASN_OP_T(op,fnc,uint64) \ +DEFN_ASN_OP_T(op,fnc,const sc_int_base&) \ +DEFN_ASN_OP_T(op,fnc,const sc_uint_base&) \ +DEFN_ASN_OP_T(op,fnc,const sc_signed&) \ +DEFN_ASN_OP_T(op,fnc,const sc_unsigned&) +#else +#define DEFN_ASN_OP_OTHER(op,fnc) +#endif + +#define DEFN_ASN_OP(op,fnc) \ +inline \ +sc_fxnum& \ +sc_fxnum::operator op ( const sc_fxnum& b ) \ +{ \ + SC_FXNUM_OBSERVER_READ_( *this ) \ + SC_FXNUM_OBSERVER_READ_( b ) \ + scfx_rep* new_rep = sc_dt::fnc ## _scfx_rep( *m_rep, *b.m_rep ); \ + delete m_rep; \ + m_rep = new_rep; \ + cast(); \ + SC_FXNUM_OBSERVER_WRITE_( *this ) \ + return *this; \ +} \ + \ +inline \ +sc_fxnum& \ +sc_fxnum::operator op ( const sc_fxval& b ) \ +{ \ + SC_FXNUM_OBSERVER_READ_( *this ) \ + scfx_rep* new_rep = sc_dt::fnc ## _scfx_rep( *m_rep, *b.get_rep() ); \ + delete m_rep; \ + m_rep = new_rep; \ + cast(); \ + SC_FXNUM_OBSERVER_WRITE_( *this ) \ + return *this; \ +} \ + \ +DEFN_ASN_OP_T(op,fnc,int) \ +DEFN_ASN_OP_T(op,fnc,unsigned int) \ +DEFN_ASN_OP_T(op,fnc,long) \ +DEFN_ASN_OP_T(op,fnc,unsigned long) \ +DEFN_ASN_OP_T(op,fnc,float) \ +DEFN_ASN_OP_T(op,fnc,double) \ +DEFN_ASN_OP_T(op,fnc,const char*) \ +DEFN_ASN_OP_T(op,fnc,const sc_fxval_fast&) \ +DEFN_ASN_OP_T(op,fnc,const sc_fxnum_fast&) \ +DEFN_ASN_OP_OTHER(op,fnc) + +DEFN_ASN_OP(*=,mult) +DEFN_ASN_OP(/=,div) +DEFN_ASN_OP(+=,add) +DEFN_ASN_OP(-=,sub) + +#undef DEFN_ASN_OP_T +#undef DEFN_ASN_OP_OTHER +#undef DEFN_ASN_OP + + +inline +sc_fxnum& +sc_fxnum::operator <<= ( int b ) +{ + SC_FXNUM_OBSERVER_READ_( *this ) + m_rep->lshift( b ); + cast(); + SC_FXNUM_OBSERVER_WRITE_( *this ) + return *this; +} + +inline +sc_fxnum& +sc_fxnum::operator >>= ( int b ) +{ + SC_FXNUM_OBSERVER_READ_( *this ) + m_rep->rshift( b ); + cast(); + SC_FXNUM_OBSERVER_WRITE_( *this ) + return *this; +} + + +// auto-increment and auto-decrement + +inline +const sc_fxval +sc_fxnum::operator ++ ( int ) +{ + sc_fxval c( *this ); + (*this) += 1; + return c; +} + +inline +const sc_fxval +sc_fxnum::operator -- ( int ) +{ + sc_fxval c( *this ); + (*this) -= 1; + return c; +} + +inline +sc_fxnum& +sc_fxnum::operator ++ () +{ + (*this) += 1; + return *this; +} + +inline +sc_fxnum& +sc_fxnum::operator -- () +{ + (*this) -= 1; + return *this; +} + + +// bit selection + +inline +const sc_fxnum_bitref +sc_fxnum::operator [] ( int i ) const +{ + SC_ERROR_IF_( i < 0 || i >= m_params.wl(), sc_core::SC_ID_OUT_OF_RANGE_ ); + return sc_fxnum_bitref( const_cast<sc_fxnum&>( *this ), + i - m_params.fwl() ); +} + +inline +sc_fxnum_bitref +sc_fxnum::operator [] ( int i ) +{ + SC_ERROR_IF_( i < 0 || i >= m_params.wl(), sc_core::SC_ID_OUT_OF_RANGE_ ); + return sc_fxnum_bitref( *this, i - m_params.fwl() ); +} + +inline +const sc_fxnum_bitref +sc_fxnum::bit( int i ) const +{ + SC_ERROR_IF_( i < 0 || i >= m_params.wl(), sc_core::SC_ID_OUT_OF_RANGE_ ); + return sc_fxnum_bitref( const_cast<sc_fxnum&>( *this ), + i - m_params.fwl() ); +} + +inline +sc_fxnum_bitref +sc_fxnum::bit( int i ) +{ + SC_ERROR_IF_( i < 0 || i >= m_params.wl(), sc_core::SC_ID_OUT_OF_RANGE_ ); + return sc_fxnum_bitref( *this, i - m_params.fwl() ); +} + + +// part selection + +inline +const sc_fxnum_subref +sc_fxnum::operator () ( int i, int j ) const +{ + SC_ERROR_IF_( i < 0 || i >= m_params.wl(), sc_core::SC_ID_OUT_OF_RANGE_ ); + SC_ERROR_IF_( j < 0 || j >= m_params.wl(), sc_core::SC_ID_OUT_OF_RANGE_ ); + + return sc_fxnum_subref( const_cast<sc_fxnum&>( *this ), + i - m_params.fwl(), j - m_params.fwl() ); +} + +inline +sc_fxnum_subref +sc_fxnum::operator () ( int i, int j ) +{ + SC_ERROR_IF_( i < 0 || i >= m_params.wl(), sc_core::SC_ID_OUT_OF_RANGE_ ); + SC_ERROR_IF_( j < 0 || j >= m_params.wl(), sc_core::SC_ID_OUT_OF_RANGE_ ); + + return sc_fxnum_subref( *this, i - m_params.fwl(), j - m_params.fwl() ); +} + +inline +const sc_fxnum_subref +sc_fxnum::range( int i, int j ) const +{ + SC_ERROR_IF_( i < 0 || i >= m_params.wl(), sc_core::SC_ID_OUT_OF_RANGE_ ); + SC_ERROR_IF_( j < 0 || j >= m_params.wl(), sc_core::SC_ID_OUT_OF_RANGE_ ); + + return sc_fxnum_subref( const_cast<sc_fxnum&>( *this ), + i - m_params.fwl(), j - m_params.fwl() ); +} + +inline +sc_fxnum_subref +sc_fxnum::range( int i, int j ) +{ + SC_ERROR_IF_( i < 0 || i >= m_params.wl(), sc_core::SC_ID_OUT_OF_RANGE_ ); + SC_ERROR_IF_( j < 0 || j >= m_params.wl(), sc_core::SC_ID_OUT_OF_RANGE_ ); + + return sc_fxnum_subref( *this, i - m_params.fwl(), j - m_params.fwl() ); +} + + +inline +const sc_fxnum_subref +sc_fxnum::operator () () const +{ + return this->operator () ( m_params.wl() - 1, 0 ); +} + +inline +sc_fxnum_subref +sc_fxnum::operator () () +{ + return this->operator () ( m_params.wl() - 1, 0 ); +} + +inline +const sc_fxnum_subref +sc_fxnum::range() const +{ + return this->range( m_params.wl() - 1, 0 ); +} + +inline +sc_fxnum_subref +sc_fxnum::range() +{ + return this->range( m_params.wl() - 1, 0 ); +} + + +// implicit conversion + +inline +sc_fxnum::operator double() const +{ + SC_FXNUM_OBSERVER_READ_( *this ) + return m_rep->to_double(); +} + + +// explicit conversion to primitive types + +inline +short +sc_fxnum::to_short() const +{ + SC_FXNUM_OBSERVER_READ_( *this ) + return static_cast<short>( m_rep->to_double() ); +} + +inline +unsigned short +sc_fxnum::to_ushort() const +{ + SC_FXNUM_OBSERVER_READ_( *this ) + return static_cast<unsigned short>( m_rep->to_double() ); +} + +inline +int +sc_fxnum::to_int() const +{ + SC_FXNUM_OBSERVER_READ_( *this ) + return static_cast<int>( m_rep->to_double() ); +} + +inline +int64 +sc_fxnum::to_int64() const +{ + SC_FXNUM_OBSERVER_READ_( *this ) + return static_cast<int64>( m_rep->to_double() ); +} + +inline +unsigned int +sc_fxnum::to_uint() const +{ + SC_FXNUM_OBSERVER_READ_( *this ) + return static_cast<unsigned int>( m_rep->to_double() ); +} + +inline +uint64 +sc_fxnum::to_uint64() const +{ + SC_FXNUM_OBSERVER_READ_( *this ) + return static_cast<uint64>( m_rep->to_double() ); +} + +inline +long +sc_fxnum::to_long() const +{ + SC_FXNUM_OBSERVER_READ_( *this ) + return static_cast<long>( m_rep->to_double() ); +} + +inline +unsigned long +sc_fxnum::to_ulong() const +{ + SC_FXNUM_OBSERVER_READ_( *this ) + return static_cast<unsigned long>( m_rep->to_double() ); +} + +inline +float +sc_fxnum::to_float() const +{ + SC_FXNUM_OBSERVER_READ_( *this ) + return static_cast<float>( m_rep->to_double() ); +} + +inline +double +sc_fxnum::to_double() const +{ + SC_FXNUM_OBSERVER_READ_( *this ) + return m_rep->to_double(); +} + + +// query value + +inline +bool +sc_fxnum::is_neg() const +{ + SC_FXNUM_OBSERVER_READ_( *this ) + return m_rep->is_neg(); +} + +inline +bool +sc_fxnum::is_zero() const +{ + SC_FXNUM_OBSERVER_READ_( *this ) + return m_rep->is_zero(); +} + +// internal use only; +inline +bool +sc_fxnum::is_normal() const +{ + SC_FXNUM_OBSERVER_READ_( *this ) + return m_rep->is_normal(); +} + +inline +bool +sc_fxnum::quantization_flag() const +{ + return m_q_flag; +} + +inline +bool +sc_fxnum::overflow_flag() const +{ + return m_o_flag; +} + + +inline +const sc_fxval +sc_fxnum::value() const +{ + SC_FXNUM_OBSERVER_READ_( *this ) + return sc_fxval( new scfx_rep( *m_rep ) ); +} + + +// query parameters + +inline +int +sc_fxnum::wl() const +{ + return m_params.wl(); +} + +inline +int +sc_fxnum::iwl() const +{ + return m_params.iwl(); +} + +inline +sc_q_mode +sc_fxnum::q_mode() const +{ + return m_params.q_mode(); +} + +inline +sc_o_mode +sc_fxnum::o_mode() const +{ + return m_params.o_mode(); +} + +inline +int +sc_fxnum::n_bits() const +{ + return m_params.n_bits(); +} + + +inline +const sc_fxtype_params& +sc_fxnum::type_params() const +{ + return m_params.type_params(); +} + + +inline +const sc_fxcast_switch& +sc_fxnum::cast_switch() const +{ + return m_params.cast_switch(); +} + + +// internal use only; +inline +void +sc_fxnum::observer_read() const +{ + SC_FXNUM_OBSERVER_READ_( *this ); +} + + +// internal use only; +inline +bool +sc_fxnum::get_bit( int i ) const +{ + return m_rep->get_bit( i ); +} + + +// protected methods and friend functions + +inline +bool +sc_fxnum::set_bit( int i, bool high ) +{ + if( high ) + return m_rep->set( i, m_params ); + else + return m_rep->clear( i, m_params ); +} + + +inline +bool +sc_fxnum::get_slice( int i, int j, sc_bv_base& bv ) const +{ + return m_rep->get_slice( i, j, m_params, bv ); +} + +inline +bool +sc_fxnum::set_slice( int i, int j, const sc_bv_base& bv ) +{ + return m_rep->set_slice( i, j, m_params, bv ); +} + + +inline +::std::ostream& +operator << ( ::std::ostream& os, const sc_fxnum& a ) +{ + a.print( os ); + return os; +} + +inline +::std::istream& +operator >> ( ::std::istream& is, sc_fxnum& a ) +{ + a.scan( is ); + return is; +} + + +// ---------------------------------------------------------------------------- +// CLASS : sc_fxnum_fast +// +// Base class for the fixed-point types; limited precision. +// ---------------------------------------------------------------------------- + +inline +sc_fxnum_fast_observer* +sc_fxnum_fast::observer() const +{ + return m_observer; +} + + +// constructors + +inline +sc_fxnum_fast::sc_fxnum_fast( const sc_fxtype_params& type_params_, + sc_enc enc_, + const sc_fxcast_switch& cast_sw, + sc_fxnum_fast_observer* observer_ ) +: m_val( 0.0 ), + m_params( type_params_, enc_, cast_sw ), + m_q_flag( false ), + m_o_flag( false ), + m_observer( observer_ ) +{ + SC_FXNUM_FAST_OBSERVER_DEFAULT_ + SC_FXNUM_FAST_OBSERVER_CONSTRUCT_(*this) +} + +inline +sc_fxnum_fast::sc_fxnum_fast( const sc_fxnum_fast& a, + const sc_fxtype_params& type_params_, + sc_enc enc_, + const sc_fxcast_switch& cast_sw, + sc_fxnum_fast_observer* observer_ ) +: m_val( a.m_val ), + m_params( type_params_, enc_, cast_sw ), + m_q_flag( false ), + m_o_flag( false ), + m_observer( observer_ ) +{ + SC_FXNUM_FAST_OBSERVER_DEFAULT_ + SC_FXNUM_FAST_OBSERVER_READ_( a ) + cast(); + SC_FXNUM_FAST_OBSERVER_CONSTRUCT_( *this ) + SC_FXNUM_FAST_OBSERVER_WRITE_( *this ) +} + +#define DEFN_CTOR_T(tp,arg) \ +inline \ +sc_fxnum_fast::sc_fxnum_fast( tp a, \ + const sc_fxtype_params& type_params_, \ + sc_enc enc_, \ + const sc_fxcast_switch& cast_sw, \ + sc_fxnum_fast_observer* observer_ ) \ +: m_val( arg ), \ + m_params( type_params_, enc_, cast_sw ), \ + m_q_flag( false ), \ + m_o_flag( false ), \ + m_observer( observer_ ) \ +{ \ + SC_FXNUM_FAST_OBSERVER_DEFAULT_ \ + cast(); \ + SC_FXNUM_FAST_OBSERVER_CONSTRUCT_(*this) \ + SC_FXNUM_FAST_OBSERVER_WRITE_( *this ) \ +} + +#define DEFN_CTOR_T_A(tp) DEFN_CTOR_T(tp,static_cast<double>( a )) +#define DEFN_CTOR_T_B(tp) DEFN_CTOR_T(tp,sc_fxval_fast::from_string( a )) +#define DEFN_CTOR_T_C(tp) DEFN_CTOR_T(tp,a.to_double()) + +DEFN_CTOR_T_A(int) +DEFN_CTOR_T_A(unsigned int) +DEFN_CTOR_T_A(long) +DEFN_CTOR_T_A(unsigned long) +DEFN_CTOR_T_A(float) +DEFN_CTOR_T_A(double) +DEFN_CTOR_T_B(const char*) +DEFN_CTOR_T_C(const sc_fxval&) +DEFN_CTOR_T_C(const sc_fxval_fast&) +DEFN_CTOR_T_C(const sc_fxnum&) +#ifndef SC_FX_EXCLUDE_OTHER +DEFN_CTOR_T_A(int64) +DEFN_CTOR_T_A(uint64) +DEFN_CTOR_T_C(const sc_int_base&) +DEFN_CTOR_T_C(const sc_uint_base&) +DEFN_CTOR_T_C(const sc_signed&) +DEFN_CTOR_T_C(const sc_unsigned&) +#endif + +#undef DEFN_CTOR_T +#undef DEFN_CTOR_T_A +#undef DEFN_CTOR_T_B +#undef DEFN_CTOR_T_C +#undef DEFN_CTOR_T_D +#undef DEFN_CTOR_T_E + + +inline +sc_fxnum_fast::~sc_fxnum_fast() +{ + SC_FXNUM_FAST_OBSERVER_DESTRUCT_( *this ) +} + + +// internal use only; +inline +double +sc_fxnum_fast::get_val() const +{ + SC_FXNUM_FAST_OBSERVER_READ_( *this ) + return m_val; +} + + +// unary operators + +inline +const sc_fxval_fast +sc_fxnum_fast::operator - () const +{ + SC_FXNUM_FAST_OBSERVER_READ_( *this ) + return sc_fxval_fast( - m_val ); +} + +inline +const sc_fxval_fast +sc_fxnum_fast::operator + () const +{ + SC_FXNUM_FAST_OBSERVER_READ_( *this ) + return sc_fxval_fast( m_val ); +} + + +// unary functions + +inline +void +neg( sc_fxval_fast& c, const sc_fxnum_fast& a ) +{ + SC_FXNUM_FAST_OBSERVER_READ_( a ) + c.set_val( - a.m_val ); +} + +inline +void +neg( sc_fxnum_fast& c, const sc_fxnum_fast& a ) +{ + SC_FXNUM_FAST_OBSERVER_READ_( a ) + c.m_val = - a.m_val; + c.cast(); + SC_FXNUM_FAST_OBSERVER_WRITE_( c ) +} + + +// binary operators + +#define DEFN_BIN_OP_T(op,tp) \ +inline \ +const sc_fxval_fast \ +operator op ( const sc_fxnum_fast& a, tp b ) \ +{ \ + SC_FXNUM_FAST_OBSERVER_READ_( a ) \ + sc_fxval_fast tmp( b ); \ + return sc_fxval_fast( a.m_val op tmp.get_val() ); \ +} \ + \ +inline \ +const sc_fxval_fast \ +operator op ( tp a, const sc_fxnum_fast& b ) \ +{ \ + SC_FXNUM_FAST_OBSERVER_READ_( b ) \ + sc_fxval_fast tmp( a ); \ + return sc_fxval_fast( tmp.get_val() op b.m_val ); \ +} + +#ifndef SC_FX_EXCLUDE_OTHER +#define DEFN_BIN_OP_OTHER(op) \ +DEFN_BIN_OP_T(op,int64) \ +DEFN_BIN_OP_T(op,uint64) \ +DEFN_BIN_OP_T(op,const sc_int_base&) \ +DEFN_BIN_OP_T(op,const sc_uint_base&) \ +DEFN_BIN_OP_T(op,const sc_signed&) \ +DEFN_BIN_OP_T(op,const sc_unsigned&) +#else +#define DEFN_BIN_OP_OTHER(op) +#endif + +#define DEFN_BIN_OP(op,dummy) \ +inline \ +const sc_fxval_fast \ +operator op ( const sc_fxnum_fast& a, const sc_fxnum_fast& b ) \ +{ \ + SC_FXNUM_FAST_OBSERVER_READ_( a ) \ + SC_FXNUM_FAST_OBSERVER_READ_( b ) \ + return sc_fxval_fast( a.m_val op b.m_val ); \ +} \ + \ +inline \ +const sc_fxval_fast \ +operator op ( const sc_fxnum_fast& a, const sc_fxval_fast& b ) \ +{ \ + SC_FXNUM_FAST_OBSERVER_READ_( a ) \ + return sc_fxval_fast( a.m_val op b.get_val() ); \ +} \ + \ +inline \ +const sc_fxval_fast \ +operator op ( const sc_fxval_fast& a, const sc_fxnum_fast& b ) \ +{ \ + SC_FXNUM_FAST_OBSERVER_READ_( b ) \ + return sc_fxval_fast( a.get_val() op b.m_val ); \ +} \ + \ +DEFN_BIN_OP_T(op,int) \ +DEFN_BIN_OP_T(op,unsigned int) \ +DEFN_BIN_OP_T(op,long) \ +DEFN_BIN_OP_T(op,unsigned long) \ +DEFN_BIN_OP_T(op,float) \ +DEFN_BIN_OP_T(op,double) \ +DEFN_BIN_OP_T(op,const char*) \ +DEFN_BIN_OP_OTHER(op) + +DEFN_BIN_OP(*,mult) +DEFN_BIN_OP(+,add) +DEFN_BIN_OP(-,sub) +//DEFN_BIN_OP(/,div) +inline +const sc_fxval_fast +operator / ( const sc_fxnum_fast& a, const sc_fxnum_fast& b ) +{ + SC_FXNUM_FAST_OBSERVER_READ_( a ) + SC_FXNUM_FAST_OBSERVER_READ_( b ) + return sc_fxval_fast( a.m_val / b.m_val ); +} + +inline +const sc_fxval_fast +operator / ( const sc_fxnum_fast& a, const sc_fxval_fast& b ) +{ + SC_FXNUM_FAST_OBSERVER_READ_( a ) + return sc_fxval_fast( a.m_val / b.get_val() ); +} + +inline +const sc_fxval_fast +operator / ( const sc_fxval_fast& a, const sc_fxnum_fast& b ) +{ + SC_FXNUM_FAST_OBSERVER_READ_( b ) + return sc_fxval_fast( a.get_val() / b.m_val ); +} + +DEFN_BIN_OP_T(/,int) +DEFN_BIN_OP_T(/,unsigned int) +DEFN_BIN_OP_T(/,long) +DEFN_BIN_OP_T(/,unsigned long) +DEFN_BIN_OP_T(/,float) +DEFN_BIN_OP_T(/,double) +DEFN_BIN_OP_T(/,const char*) +//DEFN_BIN_OP_OTHER(/) +#ifndef SC_FX_EXCLUDE_OTHER +DEFN_BIN_OP_T(/,int64) +DEFN_BIN_OP_T(/,uint64) +DEFN_BIN_OP_T(/,const sc_int_base&) +DEFN_BIN_OP_T(/,const sc_uint_base&) +DEFN_BIN_OP_T(/,const sc_signed&) +DEFN_BIN_OP_T(/,const sc_unsigned&) +#endif + +#undef DEFN_BIN_OP_T +#undef DEFN_BIN_OP_OTHER +#undef DEFN_BIN_OP + + +inline +const sc_fxval_fast +operator << ( const sc_fxnum_fast& a, int b ) +{ + SC_FXNUM_FAST_OBSERVER_READ_( a ) + return sc_fxval_fast( a.m_val * scfx_pow2( b ) ); +} + +inline +const sc_fxval_fast +operator >> ( const sc_fxnum_fast& a, int b ) +{ + SC_FXNUM_FAST_OBSERVER_READ_( a ) + return sc_fxval_fast( a.m_val * scfx_pow2( -b ) ); +} + + +// binary functions + +#define DEFN_BIN_FNC_T(fnc,op,tp) \ +inline \ +void \ +fnc ( sc_fxval_fast& c, const sc_fxnum_fast& a, tp b ) \ +{ \ + SC_FXNUM_FAST_OBSERVER_READ_( a ) \ + sc_fxval_fast tmp( b ); \ + c.set_val( a.m_val op tmp.get_val() ); \ +} \ + \ +inline \ +void \ +fnc ( sc_fxval_fast& c, tp a, const sc_fxnum_fast& b ) \ +{ \ + SC_FXNUM_FAST_OBSERVER_READ_( b ) \ + sc_fxval_fast tmp( a ); \ + c.set_val( tmp.get_val() op b.m_val ); \ +} \ + \ +inline \ +void \ +fnc ( sc_fxnum_fast& c, const sc_fxnum_fast& a, tp b ) \ +{ \ + SC_FXNUM_FAST_OBSERVER_READ_( a ) \ + sc_fxval_fast tmp( b ); \ + c.m_val = a.m_val op tmp.get_val(); \ + c.cast(); \ + SC_FXNUM_FAST_OBSERVER_WRITE_( c ) \ +} \ + \ +inline \ +void \ +fnc ( sc_fxnum_fast& c, tp a, const sc_fxnum_fast& b ) \ +{ \ + SC_FXNUM_FAST_OBSERVER_READ_( b ) \ + sc_fxval_fast tmp( a ); \ + c.m_val = tmp.get_val() op b.m_val; \ + c.cast(); \ + SC_FXNUM_FAST_OBSERVER_WRITE_( c ) \ +} + +#ifndef SC_FX_EXCLUDE_OTHER +#define DEFN_BIN_FNC_OTHER(fnc,op) \ +DEFN_BIN_FNC_T(fnc,op,int64) \ +DEFN_BIN_FNC_T(fnc,op,uint64) \ +DEFN_BIN_FNC_T(fnc,op,const sc_int_base&) \ +DEFN_BIN_FNC_T(fnc,op,const sc_uint_base&) \ +DEFN_BIN_FNC_T(fnc,op,const sc_signed&) \ +DEFN_BIN_FNC_T(fnc,op,const sc_unsigned&) +#else +#define DEFN_BIN_FNC_OTHER(fnc,op) +#endif + +#define DEFN_BIN_FNC(fnc,op) \ +inline \ +void \ +fnc ( sc_fxval_fast& c, const sc_fxnum_fast& a, const sc_fxnum_fast& b ) \ +{ \ + SC_FXNUM_FAST_OBSERVER_READ_( a ) \ + SC_FXNUM_FAST_OBSERVER_READ_( b ) \ + c.set_val( a.m_val op b.m_val ); \ +} \ + \ +inline \ +void \ +fnc ( sc_fxnum_fast& c, const sc_fxnum_fast& a, const sc_fxnum_fast& b ) \ +{ \ + SC_FXNUM_FAST_OBSERVER_READ_( a ) \ + SC_FXNUM_FAST_OBSERVER_READ_( b ) \ + c.m_val = a.m_val op b.m_val; \ + c.cast(); \ + SC_FXNUM_FAST_OBSERVER_WRITE_( c ) \ +} \ + \ +inline \ +void \ +fnc ( sc_fxval_fast& c, const sc_fxnum_fast& a, const sc_fxval_fast& b ) \ +{ \ + SC_FXNUM_FAST_OBSERVER_READ_( a ) \ + c.set_val( a.m_val op b.get_val() ); \ +} \ + \ +inline \ +void \ +fnc ( sc_fxval_fast& c, const sc_fxval_fast& a, const sc_fxnum_fast& b ) \ +{ \ + SC_FXNUM_FAST_OBSERVER_READ_( b ) \ + c.set_val( a.get_val() op b.m_val ); \ +} \ + \ +inline \ +void \ +fnc ( sc_fxnum_fast& c, const sc_fxnum_fast& a, const sc_fxval_fast& b ) \ +{ \ + SC_FXNUM_FAST_OBSERVER_READ_( a ) \ + c.m_val = a.m_val op b.get_val(); \ + c.cast(); \ + SC_FXNUM_FAST_OBSERVER_WRITE_( c ) \ +} \ + \ +inline \ +void \ +fnc ( sc_fxnum_fast& c, const sc_fxval_fast& a, const sc_fxnum_fast& b ) \ +{ \ + SC_FXNUM_FAST_OBSERVER_READ_( b ) \ + c.m_val = a.get_val() op b.m_val; \ + c.cast(); \ + SC_FXNUM_FAST_OBSERVER_WRITE_( c ) \ +} \ + \ +DEFN_BIN_FNC_T(fnc,op,int) \ +DEFN_BIN_FNC_T(fnc,op,unsigned int) \ +DEFN_BIN_FNC_T(fnc,op,long) \ +DEFN_BIN_FNC_T(fnc,op,unsigned long) \ +DEFN_BIN_FNC_T(fnc,op,float) \ +DEFN_BIN_FNC_T(fnc,op,double) \ +DEFN_BIN_FNC_T(fnc,op,const char*) \ +DEFN_BIN_FNC_T(fnc,op,const sc_fxval&) \ +DEFN_BIN_FNC_T(fnc,op,const sc_fxnum&) \ +DEFN_BIN_FNC_OTHER(fnc,op) + +DEFN_BIN_FNC(mult,*) +DEFN_BIN_FNC(div,/) +DEFN_BIN_FNC(add,+) +DEFN_BIN_FNC(sub,-) + +#undef DEFN_BIN_FNC_T +#undef DEFN_BIN_FNC_OTHER +#undef DEFN_BIN_FNC + + +inline +void +lshift( sc_fxval_fast& c, const sc_fxnum_fast& a, int b ) +{ + SC_FXNUM_FAST_OBSERVER_READ_( a ) + c.set_val( a.m_val * scfx_pow2( b ) ); +} + +inline +void +rshift( sc_fxval_fast& c, const sc_fxnum_fast& a, int b ) +{ + SC_FXNUM_FAST_OBSERVER_READ_( a ) + c.set_val( a.m_val * scfx_pow2( -b ) ); +} + +inline +void +lshift( sc_fxnum_fast& c, const sc_fxnum_fast& a, int b ) +{ + SC_FXNUM_FAST_OBSERVER_READ_( a ) + c.m_val = a.m_val * scfx_pow2( b ); + c.cast(); + SC_FXNUM_FAST_OBSERVER_WRITE_( c ) +} + +inline +void +rshift( sc_fxnum_fast& c, const sc_fxnum_fast& a, int b ) +{ + SC_FXNUM_FAST_OBSERVER_READ_( a ) + c.m_val = a.m_val * scfx_pow2( -b ); + c.cast(); + SC_FXNUM_FAST_OBSERVER_WRITE_( c ) +} + + +// relational (including equality) operators + +#define DEFN_REL_OP_T(op,tp) \ +inline \ +bool \ +operator op ( const sc_fxnum_fast& a, tp b ) \ +{ \ + SC_FXNUM_FAST_OBSERVER_READ_( a ) \ + sc_fxval_fast tmp( b ); \ + return ( a.m_val op tmp.get_val() ); \ +} \ + \ +inline \ +bool \ +operator op ( tp a, const sc_fxnum_fast& b ) \ +{ \ + SC_FXNUM_FAST_OBSERVER_READ_( b ) \ + sc_fxval_fast tmp( a ); \ + return ( tmp.get_val() op b.m_val ); \ +} + +#ifndef SC_FX_EXCLUDE_OTHER +#define DEFN_REL_OP_OTHER(op) \ +DEFN_REL_OP_T(op,int64) \ +DEFN_REL_OP_T(op,uint64) \ +DEFN_REL_OP_T(op,const sc_int_base&) \ +DEFN_REL_OP_T(op,const sc_uint_base&) \ +DEFN_REL_OP_T(op,const sc_signed&) \ +DEFN_REL_OP_T(op,const sc_unsigned&) +#else +#define DEFN_REL_OP_OTHER(op) +#endif + +#define DEFN_REL_OP(op) \ +inline \ +bool \ +operator op ( const sc_fxnum_fast& a, const sc_fxnum_fast& b ) \ +{ \ + SC_FXNUM_FAST_OBSERVER_READ_( a ) \ + SC_FXNUM_FAST_OBSERVER_READ_( b ) \ + return ( a.m_val op b.m_val ); \ +} \ + \ +inline \ +bool \ +operator op ( const sc_fxnum_fast& a, const sc_fxval_fast& b ) \ +{ \ + SC_FXNUM_FAST_OBSERVER_READ_( a ) \ + return ( a.m_val op b.get_val() ); \ +} \ + \ +inline \ +bool \ +operator op ( const sc_fxval_fast& a, const sc_fxnum_fast& b ) \ +{ \ + SC_FXNUM_FAST_OBSERVER_READ_( b ) \ + return ( a.get_val() op b.m_val ); \ +} \ + \ +DEFN_REL_OP_T(op,int) \ +DEFN_REL_OP_T(op,unsigned int) \ +DEFN_REL_OP_T(op,long) \ +DEFN_REL_OP_T(op,unsigned long) \ +DEFN_REL_OP_T(op,float) \ +DEFN_REL_OP_T(op,double) \ +DEFN_REL_OP_T(op,const char*) \ +DEFN_REL_OP_OTHER(op) + +DEFN_REL_OP(<) +DEFN_REL_OP(<=) +DEFN_REL_OP(>) +DEFN_REL_OP(>=) +DEFN_REL_OP(==) +DEFN_REL_OP(!=) + +#undef DEFN_REL_OP_T +#undef DEFN_REL_OP_OTHER +#undef DEFN_REL_OP + + +// assignment operators + +inline +sc_fxnum_fast& +sc_fxnum_fast::operator = ( const sc_fxnum_fast& a ) +{ + if( &a != this ) + { + SC_FXNUM_FAST_OBSERVER_READ_( a ) + m_val = a.m_val; + cast(); + SC_FXNUM_FAST_OBSERVER_WRITE_( *this ) + } + return *this; +} + +inline +sc_fxnum_fast& +sc_fxnum_fast::operator = ( const sc_fxval_fast& a ) +{ + m_val = a.get_val(); + cast(); + SC_FXNUM_FAST_OBSERVER_WRITE_( *this ) + return *this; +} + +#define DEFN_ASN_OP_T(tp) \ +inline \ +sc_fxnum_fast& \ +sc_fxnum_fast::operator = ( tp a ) \ +{ \ + sc_fxval_fast tmp( a ); \ + m_val = tmp.get_val(); \ + cast(); \ + SC_FXNUM_FAST_OBSERVER_WRITE_( *this ) \ + return *this; \ +} + +DEFN_ASN_OP_T(int) +DEFN_ASN_OP_T(unsigned int) +DEFN_ASN_OP_T(long) +DEFN_ASN_OP_T(unsigned long) +DEFN_ASN_OP_T(float) +DEFN_ASN_OP_T(double) +DEFN_ASN_OP_T(const char*) +DEFN_ASN_OP_T(const sc_fxval&) +DEFN_ASN_OP_T(const sc_fxnum&) +#ifndef SC_FX_EXCLUDE_OTHER +DEFN_ASN_OP_T(int64) +DEFN_ASN_OP_T(uint64) +DEFN_ASN_OP_T(const sc_int_base&) +DEFN_ASN_OP_T(const sc_uint_base&) +DEFN_ASN_OP_T(const sc_signed&) +DEFN_ASN_OP_T(const sc_unsigned&) +#endif + +#undef DEFN_ASN_OP_T + + +#define DEFN_ASN_OP_T(op,tp) \ +inline \ +sc_fxnum_fast& \ +sc_fxnum_fast::operator op ( tp b ) \ +{ \ + SC_FXNUM_FAST_OBSERVER_READ_( *this ) \ + sc_fxval_fast tmp( b ); \ + m_val op tmp.get_val(); \ + cast(); \ + SC_FXNUM_FAST_OBSERVER_WRITE_( *this ) \ + return *this; \ +} + +#ifndef SC_FX_EXCLUDE_OTHER +#define DEFN_ASN_OP_OTHER(op) \ +DEFN_ASN_OP_T(op,int64) \ +DEFN_ASN_OP_T(op,uint64) \ +DEFN_ASN_OP_T(op,const sc_int_base&) \ +DEFN_ASN_OP_T(op,const sc_uint_base&) \ +DEFN_ASN_OP_T(op,const sc_signed&) \ +DEFN_ASN_OP_T(op,const sc_unsigned&) +#else +#define DEFN_ASN_OP_OTHER(op) +#endif + +#define DEFN_ASN_OP(op) \ +inline \ +sc_fxnum_fast& \ +sc_fxnum_fast::operator op ( const sc_fxnum_fast& b ) \ +{ \ + SC_FXNUM_FAST_OBSERVER_READ_( *this ) \ + SC_FXNUM_FAST_OBSERVER_READ_( b ) \ + m_val op b.m_val; \ + cast(); \ + SC_FXNUM_FAST_OBSERVER_WRITE_( *this ) \ + return *this; \ +} \ + \ +inline \ +sc_fxnum_fast& \ +sc_fxnum_fast::operator op ( const sc_fxval_fast& b ) \ +{ \ + SC_FXNUM_FAST_OBSERVER_READ_( *this ) \ + m_val op b.get_val(); \ + cast(); \ + SC_FXNUM_FAST_OBSERVER_WRITE_( *this ) \ + return *this; \ +} \ + \ +DEFN_ASN_OP_T(op,int) \ +DEFN_ASN_OP_T(op,unsigned int) \ +DEFN_ASN_OP_T(op,long) \ +DEFN_ASN_OP_T(op,unsigned long) \ +DEFN_ASN_OP_T(op,float) \ +DEFN_ASN_OP_T(op,double) \ +DEFN_ASN_OP_T(op,const char*) \ +DEFN_ASN_OP_T(op,const sc_fxval&) \ +DEFN_ASN_OP_T(op,const sc_fxnum&) \ +DEFN_ASN_OP_OTHER(op) + +DEFN_ASN_OP(*=) +DEFN_ASN_OP(/=) +DEFN_ASN_OP(+=) +DEFN_ASN_OP(-=) + +#undef DEFN_ASN_OP_T +#undef DEFN_ASN_OP_OTHER +#undef DEFN_ASN_OP + + +inline +sc_fxnum_fast& +sc_fxnum_fast::operator <<= ( int b ) +{ + SC_FXNUM_FAST_OBSERVER_READ_( *this ) + m_val *= scfx_pow2( b ); + cast(); + SC_FXNUM_FAST_OBSERVER_WRITE_( *this ) + return *this; +} + +inline +sc_fxnum_fast& +sc_fxnum_fast::operator >>= ( int b ) +{ + SC_FXNUM_FAST_OBSERVER_READ_( *this ) + m_val *= scfx_pow2( -b ); + cast(); + SC_FXNUM_FAST_OBSERVER_WRITE_( *this ) + return *this; +} + + +// auto-increment and auto-decrement + +inline +const sc_fxval_fast +sc_fxnum_fast::operator ++ ( int ) +{ + SC_FXNUM_FAST_OBSERVER_READ_( *this ) + SC_FXNUM_FAST_OBSERVER_READ_( *this ) + double c = m_val; + m_val = m_val + 1; + cast(); + SC_FXNUM_FAST_OBSERVER_WRITE_( *this ) + return sc_fxval_fast( c ); +} + +inline +const sc_fxval_fast +sc_fxnum_fast::operator -- ( int ) +{ + SC_FXNUM_FAST_OBSERVER_READ_( *this ) + SC_FXNUM_FAST_OBSERVER_READ_( *this ) + double c = m_val; + m_val = m_val - 1; + cast(); + SC_FXNUM_FAST_OBSERVER_WRITE_( *this ) + return sc_fxval_fast( c ); +} + +inline +sc_fxnum_fast& +sc_fxnum_fast::operator ++ () +{ + SC_FXNUM_FAST_OBSERVER_READ_( *this ) + m_val = m_val + 1; + cast(); + SC_FXNUM_FAST_OBSERVER_WRITE_( *this ) + return *this; +} + +inline +sc_fxnum_fast& +sc_fxnum_fast::operator -- () +{ + SC_FXNUM_FAST_OBSERVER_READ_( *this ) + m_val = m_val - 1; + cast(); + SC_FXNUM_FAST_OBSERVER_WRITE_( *this ) + return *this; +} + + +// bit selection + +inline +const sc_fxnum_fast_bitref +sc_fxnum_fast::operator [] ( int i ) const +{ + SC_ERROR_IF_( i < 0 || i >= m_params.wl(), sc_core::SC_ID_OUT_OF_RANGE_ ); + return sc_fxnum_fast_bitref( const_cast<sc_fxnum_fast&>( *this ), + i - m_params.fwl() ); +} + +inline +sc_fxnum_fast_bitref +sc_fxnum_fast::operator [] ( int i ) +{ + SC_ERROR_IF_( i < 0 || i >= m_params.wl(), sc_core::SC_ID_OUT_OF_RANGE_ ); + return sc_fxnum_fast_bitref( *this, i - m_params.fwl() ); +} + +inline +const sc_fxnum_fast_bitref +sc_fxnum_fast::bit( int i ) const +{ + SC_ERROR_IF_( i < 0 || i >= m_params.wl(), sc_core::SC_ID_OUT_OF_RANGE_ ); + return sc_fxnum_fast_bitref( const_cast<sc_fxnum_fast&>( *this ), + i - m_params.fwl() ); +} + +inline +sc_fxnum_fast_bitref +sc_fxnum_fast::bit( int i ) +{ + SC_ERROR_IF_( i < 0 || i >= m_params.wl(), sc_core::SC_ID_OUT_OF_RANGE_ ); + return sc_fxnum_fast_bitref( *this, i - m_params.fwl() ); +} + + +// part selection + +inline +const sc_fxnum_fast_subref +sc_fxnum_fast::operator () ( int i, int j ) const +{ + SC_ERROR_IF_( i < 0 || i >= m_params.wl(), sc_core::SC_ID_OUT_OF_RANGE_ ); + SC_ERROR_IF_( j < 0 || j >= m_params.wl(), sc_core::SC_ID_OUT_OF_RANGE_ ); + + return sc_fxnum_fast_subref( const_cast<sc_fxnum_fast&>( *this ), + i - m_params.fwl(), j - m_params.fwl() ); +} + +inline +sc_fxnum_fast_subref +sc_fxnum_fast::operator () ( int i, int j ) +{ + SC_ERROR_IF_( i < 0 || i >= m_params.wl(), sc_core::SC_ID_OUT_OF_RANGE_ ); + SC_ERROR_IF_( j < 0 || j >= m_params.wl(), sc_core::SC_ID_OUT_OF_RANGE_ ); + + return sc_fxnum_fast_subref( *this, + i - m_params.fwl(), j - m_params.fwl() ); +} + +inline +const sc_fxnum_fast_subref +sc_fxnum_fast::range( int i, int j ) const +{ + SC_ERROR_IF_( i < 0 || i >= m_params.wl(), sc_core::SC_ID_OUT_OF_RANGE_ ); + SC_ERROR_IF_( j < 0 || j >= m_params.wl(), sc_core::SC_ID_OUT_OF_RANGE_ ); + + return sc_fxnum_fast_subref( const_cast<sc_fxnum_fast&>( *this ), + i - m_params.fwl(), j - m_params.fwl() ); +} + +inline +sc_fxnum_fast_subref +sc_fxnum_fast::range( int i, int j ) +{ + SC_ERROR_IF_( i < 0 || i >= m_params.wl(), sc_core::SC_ID_OUT_OF_RANGE_ ); + SC_ERROR_IF_( j < 0 || j >= m_params.wl(), sc_core::SC_ID_OUT_OF_RANGE_ ); + + return sc_fxnum_fast_subref( *this, + i - m_params.fwl(), j - m_params.fwl() ); +} + +inline +const sc_fxnum_fast_subref +sc_fxnum_fast::operator () () const +{ + return this->operator () ( m_params.wl() - 1, 0 ); +} + +inline +sc_fxnum_fast_subref +sc_fxnum_fast::operator () () +{ + return this->operator () ( m_params.wl() - 1, 0 ); +} + +inline +const sc_fxnum_fast_subref +sc_fxnum_fast::range() const +{ + return this->range( m_params.wl() - 1, 0 ); +} + +inline +sc_fxnum_fast_subref +sc_fxnum_fast::range() +{ + return this->range( m_params.wl() - 1, 0 ); +} + + +// implicit conversion + +inline +sc_fxnum_fast::operator double() const +{ + SC_FXNUM_FAST_OBSERVER_READ_( *this ) + return m_val; +} + + +// explicit conversion to primitive types + +inline +short +sc_fxnum_fast::to_short() const +{ + SC_FXNUM_FAST_OBSERVER_READ_( *this ) + return static_cast<short>( m_val ); +} + +inline +unsigned short +sc_fxnum_fast::to_ushort() const +{ + SC_FXNUM_FAST_OBSERVER_READ_( *this ) + return static_cast<unsigned short>( m_val ); +} + +inline +int +sc_fxnum_fast::to_int() const +{ + SC_FXNUM_FAST_OBSERVER_READ_( *this ) + return static_cast<int>( m_val ); +} + +inline +int64 +sc_fxnum_fast::to_int64() const +{ + SC_FXNUM_FAST_OBSERVER_READ_( *this ) + return static_cast<int64>( m_val ); +} + +inline +unsigned int +sc_fxnum_fast::to_uint() const +{ + SC_FXNUM_FAST_OBSERVER_READ_( *this ) + return static_cast<unsigned int>( m_val ); +} + +inline +uint64 +sc_fxnum_fast::to_uint64() const +{ + SC_FXNUM_FAST_OBSERVER_READ_( *this ) + return static_cast<uint64>( m_val ); +} + +inline +long +sc_fxnum_fast::to_long() const +{ + SC_FXNUM_FAST_OBSERVER_READ_( *this ) + return static_cast<long>( m_val ); +} + +inline +unsigned long +sc_fxnum_fast::to_ulong() const +{ + SC_FXNUM_FAST_OBSERVER_READ_( *this ) + return static_cast<unsigned long>( m_val ); +} + +inline +float +sc_fxnum_fast::to_float() const +{ + SC_FXNUM_FAST_OBSERVER_READ_( *this ) + return static_cast<float>( m_val ); +} + +inline +double +sc_fxnum_fast::to_double() const +{ + SC_FXNUM_FAST_OBSERVER_READ_( *this ) + return m_val; +} + + +// query value + +inline +bool +sc_fxnum_fast::is_neg() const +{ + SC_FXNUM_FAST_OBSERVER_READ_( *this ) + scfx_ieee_double id( m_val ); + return ( id.negative() != 0 ); +} + +inline +bool +sc_fxnum_fast::is_zero() const +{ + SC_FXNUM_FAST_OBSERVER_READ_( *this ) + scfx_ieee_double id( m_val ); + return id.is_zero(); +} + +// internal use only; +inline +bool +sc_fxnum_fast::is_normal() const +{ + SC_FXNUM_FAST_OBSERVER_READ_( *this ) + scfx_ieee_double id( m_val ); + return ( id.is_normal() || id.is_subnormal() || id.is_zero() ); +} + + +inline +bool +sc_fxnum_fast::quantization_flag() const +{ + return m_q_flag; +} + +inline +bool +sc_fxnum_fast::overflow_flag() const +{ + return m_o_flag; +} + + +inline +const sc_fxval_fast +sc_fxnum_fast::value() const +{ + SC_FXNUM_FAST_OBSERVER_READ_( *this ) + return sc_fxval_fast( m_val ); +} + + +// query parameters + +inline +int +sc_fxnum_fast::wl() const +{ + return m_params.wl(); +} + +inline +int +sc_fxnum_fast::iwl() const +{ + return m_params.iwl(); +} + +inline +sc_q_mode +sc_fxnum_fast::q_mode() const +{ + return m_params.q_mode(); +} + +inline +sc_o_mode +sc_fxnum_fast::o_mode() const +{ + return m_params.o_mode(); +} + +inline +int +sc_fxnum_fast::n_bits() const +{ + return m_params.n_bits(); +} + + +inline +const sc_fxtype_params& +sc_fxnum_fast::type_params() const +{ + return m_params.type_params(); +} + + +inline +const sc_fxcast_switch& +sc_fxnum_fast::cast_switch() const +{ + return m_params.cast_switch(); +} + + +// internal use only; +inline +void +sc_fxnum_fast::observer_read() const +{ + SC_FXNUM_OBSERVER_READ_( *this ); +} + + +inline +::std::ostream& +operator << ( ::std::ostream& os, const sc_fxnum_fast& a ) +{ + a.print( os ); + return os; +} + +inline +::std::istream& +operator >> ( ::std::istream& is, sc_fxnum_fast& a ) +{ + a.scan( is ); + return is; +} + + +// ---------------------------------------------------------------------------- +// CLASS : sc_fxval +// +// Fixed-point value type; arbitrary precision. +// ---------------------------------------------------------------------------- + +// public constructors + +inline +sc_fxval::sc_fxval( const sc_fxnum& a, + sc_fxval_observer* observer_ ) +: m_rep( new scfx_rep( *a.get_rep() ) ), + m_observer( observer_ ) +{ + SC_FXVAL_OBSERVER_DEFAULT_ + SC_FXVAL_OBSERVER_CONSTRUCT_( *this ) + SC_FXVAL_OBSERVER_WRITE_( *this ) +} + +inline +sc_fxval::sc_fxval( const sc_fxnum_fast& a, + sc_fxval_observer* observer_ ) +: m_rep( new scfx_rep( a.to_double() ) ), + m_observer( observer_ ) +{ + SC_FXVAL_OBSERVER_DEFAULT_ + SC_FXVAL_OBSERVER_CONSTRUCT_( *this ) + SC_FXVAL_OBSERVER_WRITE_( *this ) +} + + +// binary operators + +#define DEFN_BIN_OP_T(op,fnc,tp) \ +inline \ +const sc_fxval \ +operator op ( const sc_fxval& a, tp b ) \ +{ \ + SC_FXVAL_OBSERVER_READ_( a ) \ + sc_fxval tmp( b ); \ + return sc_fxval( sc_dt::fnc ## _scfx_rep( *a.m_rep, *tmp.m_rep ) ); \ +} \ + \ +inline \ +const sc_fxval \ +operator op ( tp a, const sc_fxval& b ) \ +{ \ + SC_FXVAL_OBSERVER_READ_( b ) \ + sc_fxval tmp( a ); \ + return sc_fxval( sc_dt::fnc ## _scfx_rep( *tmp.m_rep, *b.m_rep ) ); \ +} + +#define DEFN_BIN_OP(op,fnc) \ +DEFN_BIN_OP_T(op,fnc,const sc_fxnum_fast&) + +DEFN_BIN_OP(*,mult) +DEFN_BIN_OP(+,add) +DEFN_BIN_OP(-,sub) +//DEFN_BIN_OP(/,div) +DEFN_BIN_OP_T(/,div,const sc_fxnum_fast&) + +#undef DEFN_BIN_OP_T +#undef DEFN_BIN_OP + + +// binary functions + +#define DEFN_BIN_FNC_T(fnc,tp) \ +inline \ +void \ +fnc ( sc_fxval& c, const sc_fxval& a, tp b ) \ +{ \ + SC_FXVAL_OBSERVER_READ_( a ) \ + sc_fxval tmp( b ); \ + delete c.m_rep; \ + c.m_rep = sc_dt::fnc ## _scfx_rep( *a.m_rep, *tmp.m_rep ); \ + SC_FXVAL_OBSERVER_WRITE_( c ) \ +} \ + \ +inline \ +void \ +fnc ( sc_fxval& c, tp a, const sc_fxval& b ) \ +{ \ + SC_FXVAL_OBSERVER_READ_( b ) \ + sc_fxval tmp( a ); \ + delete c.m_rep; \ + c.m_rep = sc_dt::fnc ## _scfx_rep( *tmp.m_rep, *b.m_rep ); \ + SC_FXVAL_OBSERVER_WRITE_( c ) \ +} + +#define DEFN_BIN_FNC(fnc) \ +DEFN_BIN_FNC_T(fnc,const sc_fxnum_fast&) + +DEFN_BIN_FNC(mult) +DEFN_BIN_FNC(div) +DEFN_BIN_FNC(add) +DEFN_BIN_FNC(sub) + +#undef DEFN_BIN_FNC_T +#undef DEFN_BIN_FNC + + +// relational (including equality) operators + +#define DEFN_REL_OP_T(op,ret,tp) \ +inline \ +bool \ +operator op ( const sc_fxval& a, tp b ) \ +{ \ + SC_FXVAL_OBSERVER_READ_( a ) \ + sc_fxval tmp( b ); \ + int result = sc_dt::cmp_scfx_rep( *a.m_rep, *tmp.m_rep ); \ + return ( ret ); \ +} \ + \ +inline \ +bool \ +operator op ( tp a, const sc_fxval& b ) \ +{ \ + SC_FXVAL_OBSERVER_READ_( b ) \ + sc_fxval tmp( a ); \ + int result = sc_dt::cmp_scfx_rep( *tmp.m_rep, *b.m_rep ); \ + return ( ret ); \ +} + + +#define DEFN_REL_OP(op,ret) \ +DEFN_REL_OP_T(op,ret,const sc_fxnum_fast&) + +DEFN_REL_OP(<,result < 0) +DEFN_REL_OP(<=,result <= 0) +DEFN_REL_OP(>,result > 0 && result != 2) +DEFN_REL_OP(>=,result >= 0 && result != 2) +DEFN_REL_OP(==,result == 0) +DEFN_REL_OP(!=,result != 0) + +#undef DEFN_REL_OP_T +#undef DEFN_REL_OP + + +// assignment operators + +inline +sc_fxval& +sc_fxval::operator = ( const sc_fxnum& a ) +{ + *m_rep = *a.get_rep(); + SC_FXVAL_OBSERVER_WRITE_( *this ) + return *this; +} + +#define DEFN_ASN_OP_T(tp) \ +inline \ +sc_fxval& \ +sc_fxval::operator = ( tp b ) \ +{ \ + sc_fxval tmp( b ); \ + *m_rep = *tmp.m_rep; \ + SC_FXVAL_OBSERVER_WRITE_( *this ) \ + return *this; \ +} + +DEFN_ASN_OP_T(const sc_fxnum_fast&) + +#undef DEFN_ASN_OP_T + + +#define DEFN_ASN_OP_T(op,fnc,tp) \ +inline \ +sc_fxval& \ +sc_fxval::operator op ( tp b ) \ +{ \ + SC_FXVAL_OBSERVER_READ_( *this ) \ + sc_fxval tmp( b ); \ + scfx_rep* new_rep = sc_dt::fnc ## _scfx_rep( *m_rep, *tmp.m_rep ); \ + delete m_rep; \ + m_rep = new_rep; \ + SC_FXVAL_OBSERVER_WRITE_( *this ) \ + return *this; \ +} + +#define DEFN_ASN_OP(op,fnc) \ +inline \ +sc_fxval& \ +sc_fxval::operator op ( const sc_fxnum& b ) \ +{ \ + SC_FXVAL_OBSERVER_READ_( *this ) \ + scfx_rep* new_rep = sc_dt::fnc ## _scfx_rep( *m_rep, *b.get_rep() ); \ + delete m_rep; \ + m_rep = new_rep; \ + SC_FXVAL_OBSERVER_WRITE_( *this ) \ + return *this; \ +} \ + \ +DEFN_ASN_OP_T(op,fnc,const sc_fxnum_fast&) + +DEFN_ASN_OP(*=,mult) +DEFN_ASN_OP(/=,div) +DEFN_ASN_OP(+=,add) +DEFN_ASN_OP(-=,sub) + +#undef DEFN_ASN_OP_T +#undef DEFN_ASN_OP + + +// ---------------------------------------------------------------------------- +// CLASS : sc_fxval_fast +// +// Fixed-point value types; limited precision. +// ---------------------------------------------------------------------------- + +// public constructors + +inline +sc_fxval_fast::sc_fxval_fast( const sc_fxnum& a, + sc_fxval_fast_observer* observer_ ) +: m_val( a.to_double() ), + m_observer( observer_ ) +{ + SC_FXVAL_FAST_OBSERVER_DEFAULT_ + SC_FXVAL_FAST_OBSERVER_CONSTRUCT_( *this ) + SC_FXVAL_FAST_OBSERVER_WRITE_( *this ) +} + +inline +sc_fxval_fast::sc_fxval_fast( const sc_fxnum_fast& a, + sc_fxval_fast_observer* observer_ ) +: m_val( a.get_val() ), + m_observer( observer_ ) +{ + SC_FXVAL_FAST_OBSERVER_DEFAULT_ + SC_FXVAL_FAST_OBSERVER_CONSTRUCT_( *this ) + SC_FXVAL_FAST_OBSERVER_WRITE_( *this ) +} + + +// binary functions + +#define DEFN_BIN_FNC_T(fnc,op,tp) \ +inline \ +void \ +fnc ( sc_fxval_fast& c, const sc_fxval_fast& a, tp b ) \ +{ \ + SC_FXVAL_FAST_OBSERVER_READ_( a ) \ + sc_fxval_fast tmp( b ); \ + c.m_val = a.m_val op tmp.m_val; \ + SC_FXVAL_FAST_OBSERVER_WRITE_( c ) \ +} \ + \ +inline \ +void \ +fnc ( sc_fxval_fast& c, tp a, const sc_fxval_fast& b ) \ +{ \ + SC_FXVAL_FAST_OBSERVER_READ_( b ) \ + sc_fxval_fast tmp( a ); \ + c.m_val = tmp.m_val op b.m_val; \ + SC_FXVAL_FAST_OBSERVER_WRITE_( c ) \ +} + +#define DEFN_BIN_FNC(fnc,op) \ +DEFN_BIN_FNC_T(fnc,op,const sc_fxval&) \ +DEFN_BIN_FNC_T(fnc,op,const sc_fxnum&) + +DEFN_BIN_FNC(mult,*) +DEFN_BIN_FNC(div,/) +DEFN_BIN_FNC(add,+) +DEFN_BIN_FNC(sub,-) + +#undef DEFN_BIN_FNC_T +#undef DEFN_BIN_FNC + + +// assignment operators + +inline +sc_fxval_fast& +sc_fxval_fast::operator = ( const sc_fxnum_fast& a ) +{ + m_val = a.get_val(); + SC_FXVAL_FAST_OBSERVER_WRITE_( *this ) + return *this; +} + +#define DEFN_ASN_OP_T(tp) \ +inline \ +sc_fxval_fast& \ +sc_fxval_fast::operator = ( tp a ) \ +{ \ + sc_fxval_fast tmp( a ); \ + m_val = tmp.m_val; \ + SC_FXVAL_FAST_OBSERVER_WRITE_( *this ) \ + return *this; \ +} + +DEFN_ASN_OP_T(const sc_fxnum&) + +#undef DEFN_ASN_OP_T + + +#define DEFN_ASN_OP_T(op,tp) \ +inline \ +sc_fxval_fast& \ +sc_fxval_fast::operator op ( tp b ) \ +{ \ + SC_FXVAL_FAST_OBSERVER_READ_( *this ) \ + sc_fxval_fast tmp( b ); \ + m_val op tmp.m_val; \ + SC_FXVAL_FAST_OBSERVER_WRITE_( *this ) \ + return *this; \ +} + +#define DEFN_ASN_OP(op) \ +inline \ +sc_fxval_fast& \ +sc_fxval_fast::operator op ( const sc_fxnum_fast& b ) \ +{ \ + SC_FXVAL_FAST_OBSERVER_READ_( *this ) \ + m_val op b.get_val(); \ + SC_FXVAL_FAST_OBSERVER_WRITE_( *this ) \ + return *this; \ +} \ + \ +DEFN_ASN_OP_T(op,const sc_fxnum&) + +DEFN_ASN_OP(*=) +DEFN_ASN_OP(/=) +DEFN_ASN_OP(+=) +DEFN_ASN_OP(-=) + +#undef DEFN_ASN_OP_T +#undef DEFN_ASN_OP + +} // namespace sc_dt + + +#endif + +// Taf! diff --git a/ext/systemc/src/sysc/datatypes/fx/sc_fxnum_observer.cpp b/ext/systemc/src/sysc/datatypes/fx/sc_fxnum_observer.cpp new file mode 100644 index 000000000..709a3c50b --- /dev/null +++ b/ext/systemc/src/sysc/datatypes/fx/sc_fxnum_observer.cpp @@ -0,0 +1,74 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_fxnum_observer.cpp - + + Original Author: Martin Janssen, Synopsys, Inc. + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + + +// $Log: sc_fxnum_observer.cpp,v $ +// Revision 1.1.1.1 2006/12/15 20:20:04 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:53:58 acg +// Andy Goodrich: added $Log command so that CVS comments are reproduced in +// the source. +// + +#include "sysc/datatypes/fx/sc_fxnum_observer.h" + + +namespace sc_dt +{ + +// ---------------------------------------------------------------------------- +// CLASS : sc_fxnum_observer +// +// Abstract base class for fixed-point types observers; arbitrary precision. +// ---------------------------------------------------------------------------- + +sc_fxnum_observer* (*sc_fxnum_observer::default_observer) () = 0; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_fxnum_fast_observer +// +// Abstract base class for fixed-point types observers; limited precision. +// ---------------------------------------------------------------------------- + +sc_fxnum_fast_observer* (*sc_fxnum_fast_observer::default_observer) () = 0; + +} // namespace sc_dt + + +// Taf! diff --git a/ext/systemc/src/sysc/datatypes/fx/sc_fxnum_observer.h b/ext/systemc/src/sysc/datatypes/fx/sc_fxnum_observer.h new file mode 100644 index 000000000..2769df31b --- /dev/null +++ b/ext/systemc/src/sysc/datatypes/fx/sc_fxnum_observer.h @@ -0,0 +1,219 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_fxnum_observer.h - + + Original Author: Martin Janssen, Synopsys, Inc. + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + +// $Log: sc_fxnum_observer.h,v $ +// Revision 1.1.1.1 2006/12/15 20:20:04 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:53:58 acg +// Andy Goodrich: added $Log command so that CVS comments are reproduced in +// the source. +// + +#ifndef SC_FXNUM_OBSERVER_H +#define SC_FXNUM_OBSERVER_H + + +#include "sysc/datatypes/fx/sc_fxdefs.h" + + +namespace sc_dt +{ + +// classes defined in this module +class sc_fxnum_observer; +class sc_fxnum_fast_observer; + +// forward class declarations +class sc_fxnum; +class sc_fxnum_fast; + + +#ifdef SC_ENABLE_OBSERVERS + +#define SC_FXNUM_OBSERVER_CONSTRUCT_(object) \ + SC_OBSERVER_(object,sc_fxnum_observer*,construct) +#define SC_FXNUM_OBSERVER_DESTRUCT_(object) \ + SC_OBSERVER_(object,sc_fxnum_observer*,destruct) +#define SC_FXNUM_OBSERVER_READ_(object) \ + SC_OBSERVER_(object,sc_fxnum_observer*,read) +#define SC_FXNUM_OBSERVER_WRITE_(object) \ + SC_OBSERVER_(object,sc_fxnum_observer*,write) +#define SC_FXNUM_OBSERVER_DEFAULT_ \ + SC_OBSERVER_DEFAULT_(sc_fxnum_observer) + +#define SC_FXNUM_FAST_OBSERVER_CONSTRUCT_(object) \ + SC_OBSERVER_(object,sc_fxnum_fast_observer*,construct) +#define SC_FXNUM_FAST_OBSERVER_DESTRUCT_(object) \ + SC_OBSERVER_(object,sc_fxnum_fast_observer*,destruct) +#define SC_FXNUM_FAST_OBSERVER_READ_(object) \ + SC_OBSERVER_(object,sc_fxnum_fast_observer*,read) +#define SC_FXNUM_FAST_OBSERVER_WRITE_(object) \ + SC_OBSERVER_(object,sc_fxnum_fast_observer*,write) +#define SC_FXNUM_FAST_OBSERVER_DEFAULT_ \ + SC_OBSERVER_DEFAULT_(sc_fxnum_fast_observer) + +#else + +#define SC_FXNUM_OBSERVER_CONSTRUCT_(object) +#define SC_FXNUM_OBSERVER_DESTRUCT_(object) +#define SC_FXNUM_OBSERVER_READ_(object) +#define SC_FXNUM_OBSERVER_WRITE_(object) +#define SC_FXNUM_OBSERVER_DEFAULT_ + +#define SC_FXNUM_FAST_OBSERVER_CONSTRUCT_(object) +#define SC_FXNUM_FAST_OBSERVER_DESTRUCT_(object) +#define SC_FXNUM_FAST_OBSERVER_READ_(object) +#define SC_FXNUM_FAST_OBSERVER_WRITE_(object) +#define SC_FXNUM_FAST_OBSERVER_DEFAULT_ + +#endif + + +// ---------------------------------------------------------------------------- +// CLASS : sc_fxnum_observer +// +// Abstract base class for fixed-point types observers; arbitrary precision. +// ---------------------------------------------------------------------------- + +class sc_fxnum_observer +{ + +protected: + + sc_fxnum_observer() {} + virtual ~sc_fxnum_observer() {} + +public: + + virtual void construct( const sc_fxnum& ); + virtual void destruct( const sc_fxnum& ); + virtual void read( const sc_fxnum& ); + virtual void write( const sc_fxnum& ); + + static sc_fxnum_observer* (*default_observer) (); + +}; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_fxnum_fast_observer +// +// Abstract base class for fixed-point types observers; limited precision. +// ---------------------------------------------------------------------------- + +class sc_fxnum_fast_observer +{ + +protected: + + sc_fxnum_fast_observer() {} + virtual ~sc_fxnum_fast_observer() {} + +public: + + virtual void construct( const sc_fxnum_fast& ); + virtual void destruct( const sc_fxnum_fast& ); + virtual void read( const sc_fxnum_fast& ); + virtual void write( const sc_fxnum_fast& ); + + static sc_fxnum_fast_observer* (*default_observer) (); + +}; + + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + +// ---------------------------------------------------------------------------- +// CLASS : sc_fxnum_observer +// +// Abstract base class for fixed-point types observers; arbitrary precision. +// ---------------------------------------------------------------------------- + +inline +void +sc_fxnum_observer::construct( const sc_fxnum& ) +{} + +inline +void +sc_fxnum_observer::destruct( const sc_fxnum& ) +{} + +inline +void +sc_fxnum_observer::read( const sc_fxnum& ) +{} + +inline +void +sc_fxnum_observer::write( const sc_fxnum& ) +{} + + +// ---------------------------------------------------------------------------- +// CLASS : sc_fxnum_fast_observer +// +// Abstract base class for fixed-point types observers; limited precision. +// ---------------------------------------------------------------------------- + +inline +void +sc_fxnum_fast_observer::construct( const sc_fxnum_fast& ) +{} + +inline +void +sc_fxnum_fast_observer::destruct( const sc_fxnum_fast& ) +{} + +inline +void +sc_fxnum_fast_observer::read( const sc_fxnum_fast& ) +{} + +inline +void +sc_fxnum_fast_observer::write( const sc_fxnum_fast& ) +{} + +} // namespace sc_dt + + +#endif + +// Taf! diff --git a/ext/systemc/src/sysc/datatypes/fx/sc_fxtype_params.cpp b/ext/systemc/src/sysc/datatypes/fx/sc_fxtype_params.cpp new file mode 100644 index 000000000..60c18a2b5 --- /dev/null +++ b/ext/systemc/src/sysc/datatypes/fx/sc_fxtype_params.cpp @@ -0,0 +1,108 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_fxtype_params.cpp - + + Original Author: Martin Janssen, Synopsys, Inc. + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + + +// $Log: sc_fxtype_params.cpp,v $ +// Revision 1.1.1.1 2006/12/15 20:20:04 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:53:58 acg +// Andy Goodrich: added $Log command so that CVS comments are reproduced in +// the source. +// + +#include "sysc/datatypes/fx/sc_fxtype_params.h" + + +namespace sc_dt +{ + +// ---------------------------------------------------------------------------- +// CLASS : sc_fxtype_params +// +// Fixed-point type parameters class. +// ---------------------------------------------------------------------------- + +const std::string +sc_fxtype_params::to_string() const +{ + std::string s; + + char buf[BUFSIZ]; + + s += "("; + std::sprintf( buf, "%d", m_wl ); + s += buf; + s += ","; + std::sprintf( buf, "%d", m_iwl ); + s += buf; + s += ","; + s += sc_dt::to_string( m_q_mode ); + s += ","; + s += sc_dt::to_string( m_o_mode ); + s += ","; + std::sprintf( buf, "%d", m_n_bits ); + s += buf; + s += ")"; + + return s; +} + + +void +sc_fxtype_params::print( ::std::ostream& os ) const +{ + os << to_string(); +} + +void +sc_fxtype_params::dump( ::std::ostream& os ) const +{ + os << "sc_fxtype_params" << ::std::endl; + os << "(" << ::std::endl; + os << "wl = " << m_wl << ::std::endl; + os << "iwl = " << m_iwl << ::std::endl; + os << "q_mode = " << m_q_mode << ::std::endl; + os << "o_mode = " << m_o_mode << ::std::endl; + os << "n_bits = " << m_n_bits << ::std::endl; + os << ")" << ::std::endl; +} + +} // namespace sc_dt + + +// Taf! diff --git a/ext/systemc/src/sysc/datatypes/fx/sc_fxtype_params.h b/ext/systemc/src/sysc/datatypes/fx/sc_fxtype_params.h new file mode 100644 index 000000000..a59ba293b --- /dev/null +++ b/ext/systemc/src/sysc/datatypes/fx/sc_fxtype_params.h @@ -0,0 +1,342 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_fxtype_params.h - + + Original Author: Martin Janssen, Synopsys, Inc. + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + +// $Log: sc_fxtype_params.h,v $ +// Revision 1.2 2011/08/24 22:05:43 acg +// Torsten Maehne: initialization changes to remove warnings. +// +// Revision 1.1.1.1 2006/12/15 20:20:04 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:53:58 acg +// Andy Goodrich: added $Log command so that CVS comments are reproduced in +// the source. +// + +#ifndef SC_FXTYPE_PARAMS_H +#define SC_FXTYPE_PARAMS_H + + +#include "sysc/datatypes/fx/sc_context.h" + + +namespace sc_dt +{ + +// classes defined in this module +class sc_fxtype_params; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_fxtype_params +// +// Fixed-point type parameters class. +// ---------------------------------------------------------------------------- + +class sc_fxtype_params +{ +public: + + sc_fxtype_params(); + sc_fxtype_params( int, int ); + sc_fxtype_params( sc_q_mode, sc_o_mode, int = 0 ); + sc_fxtype_params( int, int, sc_q_mode, sc_o_mode, int = 0 ); + sc_fxtype_params( const sc_fxtype_params& ); + sc_fxtype_params( const sc_fxtype_params&, + int, int ); + sc_fxtype_params( const sc_fxtype_params&, + sc_q_mode, sc_o_mode, int = 0 ); + explicit sc_fxtype_params( sc_without_context ); + + sc_fxtype_params& operator = ( const sc_fxtype_params& ); + + friend bool operator == ( const sc_fxtype_params&, + const sc_fxtype_params& ); + friend bool operator != ( const sc_fxtype_params&, + const sc_fxtype_params& ); + + int wl() const; + void wl( int ); + + int iwl() const; + void iwl( int ); + + sc_q_mode q_mode() const; + void q_mode( sc_q_mode ); + + sc_o_mode o_mode() const; + void o_mode( sc_o_mode ); + + int n_bits() const; + void n_bits( int ); + + const std::string to_string() const; + + void print( ::std::ostream& = ::std::cout ) const; + void dump( ::std::ostream& = ::std::cout ) const; + +private: + + int m_wl; + int m_iwl; + sc_q_mode m_q_mode; + sc_o_mode m_o_mode; + int m_n_bits; +}; + + +// ---------------------------------------------------------------------------- +// TYPEDEF : sc_fxtype_context +// +// Context type for the fixed-point type parameters. +// ---------------------------------------------------------------------------- + +typedef sc_context<sc_fxtype_params> sc_fxtype_context; + + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + +inline +sc_fxtype_params::sc_fxtype_params() +: m_wl(), m_iwl(), m_q_mode(), m_o_mode(), m_n_bits() +{ + *this = sc_fxtype_context::default_value(); +} + +inline +sc_fxtype_params::sc_fxtype_params( int wl_, int iwl_ ) +: m_wl(), m_iwl(), m_q_mode(), m_o_mode(), m_n_bits() +{ + *this = sc_fxtype_context::default_value(); + + SC_CHECK_WL_( wl_ ); + m_wl = wl_; + m_iwl = iwl_; +} + +inline +sc_fxtype_params::sc_fxtype_params( sc_q_mode q_mode_, + sc_o_mode o_mode_, int n_bits_ ) +: m_wl(), m_iwl(), m_q_mode(), m_o_mode(), m_n_bits() +{ + *this = sc_fxtype_context::default_value(); + + SC_CHECK_N_BITS_( n_bits_ ); + m_q_mode = q_mode_; + m_o_mode = o_mode_; + m_n_bits = n_bits_; +} + +inline +sc_fxtype_params::sc_fxtype_params( int wl_, int iwl_, + sc_q_mode q_mode_, + sc_o_mode o_mode_, int n_bits_ ) +: m_wl(), m_iwl(), m_q_mode(), m_o_mode(), m_n_bits() +{ + SC_CHECK_WL_( wl_ ); + SC_CHECK_N_BITS_( n_bits_ ); + m_wl = wl_; + m_iwl = iwl_; + m_q_mode = q_mode_; + m_o_mode = o_mode_; + m_n_bits = n_bits_; +} + +inline +sc_fxtype_params::sc_fxtype_params( const sc_fxtype_params& a ) +: m_wl( a.m_wl ), m_iwl( a.m_iwl ), + m_q_mode( a.m_q_mode ), + m_o_mode( a.m_o_mode ), m_n_bits( a.m_n_bits ) +{} + +inline +sc_fxtype_params::sc_fxtype_params( const sc_fxtype_params& a, + int wl_, int iwl_ ) +: m_wl( wl_ ), m_iwl( iwl_ ), + m_q_mode( a.m_q_mode ), + m_o_mode( a.m_o_mode ), m_n_bits( a.m_n_bits ) +{} + +inline +sc_fxtype_params::sc_fxtype_params( const sc_fxtype_params& a, + sc_q_mode q_mode_, + sc_o_mode o_mode_, int n_bits_ ) +: m_wl( a.m_wl ), m_iwl( a.m_iwl ), + m_q_mode( q_mode_ ), + m_o_mode( o_mode_ ), m_n_bits( n_bits_ ) +{} + +inline +sc_fxtype_params::sc_fxtype_params( sc_without_context ) +: m_wl ( SC_DEFAULT_WL_ ), + m_iwl ( SC_DEFAULT_IWL_ ), + m_q_mode( SC_DEFAULT_Q_MODE_ ), + m_o_mode( SC_DEFAULT_O_MODE_ ), + m_n_bits( SC_DEFAULT_N_BITS_ ) +{} + + +inline +sc_fxtype_params& +sc_fxtype_params::operator = ( const sc_fxtype_params& a ) +{ + if( &a != this ) + { + m_wl = a.m_wl; + m_iwl = a.m_iwl; + m_q_mode = a.m_q_mode; + m_o_mode = a.m_o_mode; + m_n_bits = a.m_n_bits; + } + return *this; +} + + +inline +bool +operator == ( const sc_fxtype_params& a, const sc_fxtype_params& b ) +{ + return ( a.m_wl == b.m_wl && + a.m_iwl == b.m_iwl && + a.m_q_mode == b.m_q_mode && + a.m_o_mode == b.m_o_mode && + a.m_n_bits == b.m_n_bits ); +} + +inline +bool +operator != ( const sc_fxtype_params& a, const sc_fxtype_params& b ) +{ + return ( a.m_wl != b.m_wl || + a.m_iwl != b.m_iwl || + a.m_q_mode != b.m_q_mode || + a.m_o_mode != b.m_o_mode || + a.m_n_bits != b.m_n_bits ); +} + + +inline +int +sc_fxtype_params::wl() const +{ + return m_wl; +} + +inline +void +sc_fxtype_params::wl( int wl_ ) +{ + SC_CHECK_WL_( wl_ ); + m_wl = wl_; +} + + +inline +int +sc_fxtype_params::iwl() const +{ + return m_iwl; +} + +inline +void +sc_fxtype_params::iwl( int iwl_ ) +{ + m_iwl = iwl_; +} + + +inline +sc_q_mode +sc_fxtype_params::q_mode() const +{ + return m_q_mode; +} + +inline +void +sc_fxtype_params::q_mode( sc_q_mode q_mode_ ) +{ + m_q_mode = q_mode_; +} + + +inline +sc_o_mode +sc_fxtype_params::o_mode() const +{ + return m_o_mode; +} + +inline +void +sc_fxtype_params::o_mode( sc_o_mode o_mode_ ) +{ + m_o_mode = o_mode_; +} + + +inline +int +sc_fxtype_params::n_bits() const +{ + return m_n_bits; +} + +inline +void +sc_fxtype_params::n_bits( int n_bits_ ) +{ + SC_CHECK_N_BITS_( n_bits_ ); + m_n_bits = n_bits_; +} + + +inline +::std::ostream& +operator << ( ::std::ostream& os, const sc_fxtype_params& a ) +{ + a.print( os ); + return os; +} + +} // namespace sc_dt + + +#endif + +// Taf! diff --git a/ext/systemc/src/sysc/datatypes/fx/sc_fxval.cpp b/ext/systemc/src/sysc/datatypes/fx/sc_fxval.cpp new file mode 100644 index 000000000..3ba5fbacd --- /dev/null +++ b/ext/systemc/src/sysc/datatypes/fx/sc_fxval.cpp @@ -0,0 +1,884 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_fxval.cpp - + + Original Author: Martin Janssen, Synopsys, Inc. + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + + +// $Log: sc_fxval.cpp,v $ +// Revision 1.1.1.1 2006/12/15 20:20:04 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:53:58 acg +// Andy Goodrich: added $Log command so that CVS comments are reproduced in +// the source. +// + +#include <ctype.h> +#include <stdlib.h> +#include <math.h> +#include <float.h> + +#include "sysc/datatypes/fx/sc_fxval.h" + + +namespace sc_dt +{ + +// ---------------------------------------------------------------------------- +// CLASS : sc_fxval +// +// Fixed-point value type; arbitrary precision. +// ---------------------------------------------------------------------------- + +// explicit conversion to character string + +const std::string +sc_fxval::to_string() const +{ + return std::string( m_rep->to_string( SC_DEC, -1, SC_E ) ); +} + +const std::string +sc_fxval::to_string( sc_numrep numrep ) const +{ + return std::string( m_rep->to_string( numrep, -1, SC_E ) ); +} + +const std::string +sc_fxval::to_string( sc_numrep numrep, bool w_prefix ) const +{ + return std::string( m_rep->to_string( numrep, (w_prefix ? 1 : 0), SC_E ) ); +} + +const std::string +sc_fxval::to_string( sc_fmt fmt ) const +{ + return std::string( m_rep->to_string( SC_DEC, -1, fmt ) ); +} + +const std::string +sc_fxval::to_string( sc_numrep numrep, sc_fmt fmt ) const +{ + return std::string( m_rep->to_string( numrep, -1, fmt ) ); +} + +const std::string +sc_fxval::to_string( sc_numrep numrep, bool w_prefix, sc_fmt fmt ) const +{ + return std::string( m_rep->to_string( numrep, (w_prefix ? 1 : 0), fmt ) ); +} + + +const std::string +sc_fxval::to_dec() const +{ + return std::string( m_rep->to_string( SC_DEC, -1, SC_E ) ); +} + +const std::string +sc_fxval::to_bin() const +{ + return std::string( m_rep->to_string( SC_BIN, -1, SC_E ) ); +} + +const std::string +sc_fxval::to_oct() const +{ + return std::string( m_rep->to_string( SC_OCT, -1, SC_E ) ); +} + +const std::string +sc_fxval::to_hex() const +{ + return std::string( m_rep->to_string( SC_HEX, -1, SC_E ) ); +} + + +// print or dump content + +void +sc_fxval::print( ::std::ostream& os ) const +{ + m_rep->print( os ); +} + +void +sc_fxval::scan( ::std::istream& is ) +{ + std::string s; + is >> s; + *this = s.c_str(); +} + +void +sc_fxval::dump( ::std::ostream& os ) const +{ + os << "sc_fxval" << ::std::endl; + os << "(" << ::std::endl; + os << "rep = "; + m_rep->dump( os ); + // TO BE COMPLETED + // os << "r_flag = " << m_r_flag << ::std::endl; + // os << "observer = "; + // if( m_observer != 0 ) + // m_observer->dump( os ); + // else + // os << "0" << ::std::endl; + os << ")" << ::std::endl; +} + + +// protected methods and friend functions + +sc_fxval_observer* +sc_fxval::lock_observer() const +{ + SC_ASSERT_( m_observer != 0, "lock observer failed" ); + sc_fxval_observer* tmp = m_observer; + m_observer = 0; + return tmp; +} + +void +sc_fxval::unlock_observer( sc_fxval_observer* observer_ ) const +{ + SC_ASSERT_( observer_ != 0, "unlock observer failed" ); + m_observer = observer_; +} + + +// ---------------------------------------------------------------------------- +// CLASS : sc_fxval_fast +// +// Fixed-point value types; limited precision. +// ---------------------------------------------------------------------------- + +static +void +print_dec( scfx_string& s, scfx_ieee_double id, int w_prefix, sc_fmt fmt ) +{ + if( id.negative() != 0 ) + { + id.negative( 0 ); + s += '-'; + } + + if( w_prefix == 1 ) { + scfx_print_prefix( s, SC_DEC ); + } + + if( id.is_zero() ) + { + s += '0'; + return; + } + + // split 'id' into its integer and fractional part + + double int_part; + double frac_part = modf( static_cast<double>( id ), &int_part ); + + int i; + + // print integer part + + int int_digits = 0; + int int_zeros = 0; + + if( int_part != 0.0 ) + { + int_digits = (int) ceil( log10( int_part + 1.0 ) ); + + int len = s.length(); + s.append( int_digits ); + + bool zero_digits = ( frac_part == 0.0 && fmt != SC_F ); + + for( i = int_digits + len - 1; i >= len; i-- ) + { + unsigned int remainder = (unsigned int) fmod( int_part, 10.0 ); + s[i] = static_cast<char>( '0' + remainder ); + + if( zero_digits ) + { + if( remainder == 0 ) + int_zeros ++; + else + zero_digits = false; + } + + int_part /= 10.0; + } + + // discard trailing zeros from int_part + s.discard( int_zeros ); + + if( s[len] == '0' ) + { + // int_digits was overestimated by one + s.remove( len ); + -- int_digits; + } + } + + // print fractional part + + int frac_digits = 0; + int frac_zeros = 0; + + if( frac_part != 0.0 ) + { + s += '.'; + + bool zero_digits = ( int_digits == 0 && fmt != SC_F ); + + frac_zeros = (int) floor( - log10( frac_part + DBL_EPSILON ) ); + + frac_part *= pow( 10.0, frac_zeros ); + + frac_digits = frac_zeros; + if( ! zero_digits ) + { + for( i = 0; i < frac_zeros; i ++ ) + s += '0'; + frac_zeros = 0; + } + + while( frac_part != 0.0 ) + { + frac_part *= 10.0; + int n = static_cast<int>( frac_part ); + + if( zero_digits ) + { + if( n == 0 ) + frac_zeros ++; + else + zero_digits = false; + } + + if( ! zero_digits ) + s += static_cast<char>( '0' + n ); + + frac_part -= n; + frac_digits ++; + } + } + + // print exponent + + if( fmt != SC_F ) + { + if( frac_digits == 0 ) + scfx_print_exp( s, int_zeros ); + else if( int_digits == 0 ) + scfx_print_exp( s, - frac_zeros ); + } +} + + +static +void +print_other( scfx_string& s, const scfx_ieee_double& id, sc_numrep numrep, + int w_prefix, sc_fmt fmt, const scfx_params* params ) +{ + scfx_ieee_double id2 = id; + + sc_numrep numrep2 = numrep; + + bool numrep_is_sm = ( numrep == SC_BIN_SM || + numrep == SC_OCT_SM || + numrep == SC_HEX_SM ); + + if( numrep_is_sm ) + { + if( id2.negative() != 0 ) + { + s += '-'; + id2.negative( 0 ); + } + switch( numrep ) + { + case SC_BIN_SM: + numrep2 = SC_BIN_US; + break; + case SC_OCT_SM: + numrep2 = SC_OCT_US; + break; + case SC_HEX_SM: + numrep2 = SC_HEX_US; + break; + default: + ; + } + } + + if( w_prefix != 0 ) { + scfx_print_prefix( s, numrep ); + } + + numrep = numrep2; + + sc_fxval_fast a( id2 ); + + int msb, lsb; + + if( params != 0 ) + { + msb = params->iwl() - 1; + lsb = params->iwl() - params->wl(); + + if( params->enc() == SC_TC_ && + ( numrep == SC_BIN_US || + numrep == SC_OCT_US || + numrep == SC_HEX_US ) && + ! numrep_is_sm && + params->wl() > 1 ) + -- msb; + else if( params->enc() == SC_US_ && + ( numrep == SC_BIN || + numrep == SC_OCT || + numrep == SC_HEX || + numrep == SC_CSD ) ) + ++ msb; + } + else + { + if( a.is_zero() ) + { + msb = 0; + lsb = 0; + } + else + { + msb = id2.exponent() + 1; + while( a.get_bit( msb ) == a.get_bit( msb - 1 ) ) + -- msb; + + if( numrep == SC_BIN_US || + numrep == SC_OCT_US || + numrep == SC_HEX_US ) + -- msb; + + lsb = id2.exponent() - 52; + while( ! a.get_bit( lsb ) ) + ++ lsb; + } + } + + int step; + + switch( numrep ) + { + case SC_BIN: + case SC_BIN_US: + case SC_CSD: + step = 1; + break; + case SC_OCT: + case SC_OCT_US: + step = 3; + break; + case SC_HEX: + case SC_HEX_US: + step = 4; + break; + default: + step = 0; + } + + msb = (int) ceil( double( msb + 1 ) / step ) * step - 1; + + lsb = (int) floor( double( lsb ) / step ) * step; + + if( msb < 0 ) + { + s += '.'; + if( fmt == SC_F ) + { + int sign = ( id2.negative() != 0 ) ? ( 1 << step ) - 1 : 0; + for( int i = ( msb + 1 ) / step; i < 0; i ++ ) + { + if( sign < 10 ) + s += static_cast<char>( sign + '0' ); + else + s += static_cast<char>( sign + 'a' - 10 ); + } + } + } + + int i = msb; + while( i >= lsb ) + { + int value = 0; + for( int j = step - 1; j >= 0; -- j ) + { + value += static_cast<int>( a.get_bit( i ) ) << j; + -- i; + } + if( value < 10 ) + s += static_cast<char>( value + '0' ); + else + s += static_cast<char>( value + 'a' - 10 ); + if( i == -1 ) + s += '.'; + } + + if( lsb > 0 && fmt == SC_F ) + { + for( int i = lsb / step; i > 0; i -- ) + s += '0'; + } + + if( s[s.length() - 1] == '.' ) + s.discard( 1 ); + + if( fmt != SC_F ) + { + if( msb < 0 ) + scfx_print_exp( s, ( msb + 1 ) / step ); + else if( lsb > 0 ) + scfx_print_exp( s, lsb / step ); + } + + if( numrep == SC_CSD ) + scfx_tc2csd( s, w_prefix ); +} + + +const char* +to_string( const scfx_ieee_double& id, sc_numrep numrep, int w_prefix, + sc_fmt fmt, const scfx_params* params = 0 ) +{ + static scfx_string s; + + s.clear(); + + if( id.is_nan() ) + scfx_print_nan( s ); + else if( id.is_inf() ) + scfx_print_inf( s, static_cast<bool>( id.negative() ) ); + else if( id.negative() && ! id.is_zero() && + ( numrep == SC_BIN_US || + numrep == SC_OCT_US || + numrep == SC_HEX_US ) ) + s += "negative"; + else if( numrep == SC_DEC ) + sc_dt::print_dec( s, id, w_prefix, fmt ); + else + sc_dt::print_other( s, id, numrep, w_prefix, fmt, params ); + + return s; +} + + +// explicit conversion to character string + +const std::string +sc_fxval_fast::to_string() const +{ + return std::string( sc_dt::to_string( m_val, SC_DEC, -1, SC_E ) ); +} + +const std::string +sc_fxval_fast::to_string( sc_numrep numrep ) const +{ + return std::string( sc_dt::to_string( m_val, numrep, -1, SC_E ) ); +} + +const std::string +sc_fxval_fast::to_string( sc_numrep numrep, bool w_prefix ) const +{ + return std::string( sc_dt::to_string( m_val, numrep, (w_prefix ? 1 : 0), + SC_E ) ); +} + +const std::string +sc_fxval_fast::to_string( sc_fmt fmt ) const +{ + return std::string( sc_dt::to_string( m_val, SC_DEC, -1, fmt ) ); +} + +const std::string +sc_fxval_fast::to_string( sc_numrep numrep, sc_fmt fmt ) const +{ + return std::string( sc_dt::to_string( m_val, numrep, -1, fmt ) ); +} + +const std::string +sc_fxval_fast::to_string( sc_numrep numrep, bool w_prefix, sc_fmt fmt ) const +{ + return std::string( sc_dt::to_string( m_val, numrep, (w_prefix ? 1 : 0), + fmt ) ); +} + + +const std::string +sc_fxval_fast::to_dec() const +{ + return std::string( sc_dt::to_string( m_val, SC_DEC, -1, SC_E ) ); +} + +const std::string +sc_fxval_fast::to_bin() const +{ + return std::string( sc_dt::to_string( m_val, SC_BIN, -1, SC_E ) ); +} + +const std::string +sc_fxval_fast::to_oct() const +{ + return std::string( sc_dt::to_string( m_val, SC_OCT, -1, SC_E ) ); +} + +const std::string +sc_fxval_fast::to_hex() const +{ + return std::string( sc_dt::to_string( m_val, SC_HEX, -1, SC_E ) ); +} + + +// print or dump content + +void +sc_fxval_fast::print( ::std::ostream& os ) const +{ + os << sc_dt::to_string( m_val, SC_DEC, -1, SC_E ); +} + +void +sc_fxval_fast::scan( ::std::istream& is ) +{ + std::string s; + is >> s; + *this = s.c_str(); +} + +void +sc_fxval_fast::dump( ::std::ostream& os ) const +{ + os << "sc_fxval_fast" << ::std::endl; + os << "(" << ::std::endl; + os << "val = " << m_val << ::std::endl; + // TO BE COMPLETED + // os << "r_flag = " << m_r_flag << ::std::endl; + // os << "observer = "; + // if( m_observer != 0 ) + // m_observer->dump( os ); + // else + // os << "0" << ::std::endl; + os << ")" << ::std::endl; +} + + +// internal use only; +bool +sc_fxval_fast::get_bit( int i ) const +{ + scfx_ieee_double id( m_val ); + if( id.is_zero() || id.is_nan() || id.is_inf() ) + return false; + + // convert to two's complement + + unsigned int m0 = id.mantissa0(); + unsigned int m1 = id.mantissa1(); + + if( id.is_normal() ) + m0 += 1U << 20; + + if( id.negative() != 0 ) + { + m0 = ~ m0; + m1 = ~ m1; + unsigned int tmp = m1; + m1 += 1U; + if( m1 <= tmp ) + m0 += 1U; + } + + // get the right bit + + int j = i - id.exponent(); + if( ( j += 20 ) >= 32 ) + return ( ( m0 & 1U << 31 ) != 0 ); + else if( j >= 0 ) + return ( ( m0 & 1U << j ) != 0 ); + else if( ( j += 32 ) >= 0 ) + return ( ( m1 & 1U << j ) != 0 ); + else + return false; +} + + +// protected methods and friend functions + +sc_fxval_fast_observer* +sc_fxval_fast::lock_observer() const +{ + SC_ASSERT_( m_observer != 0, "lock observer failed" ); + sc_fxval_fast_observer* tmp = m_observer; + m_observer = 0; + return tmp; +} + +void +sc_fxval_fast::unlock_observer( sc_fxval_fast_observer* observer_ ) const +{ + SC_ASSERT_( observer_ != 0, "unlock observer failed" ); + m_observer = observer_; +} + + +#define SCFX_FAIL_IF_(cnd) \ +{ \ + if( ( cnd ) ) \ + return static_cast<double>( scfx_ieee_double::nan() ); \ +} + +double +sc_fxval_fast::from_string( const char* s ) +{ + SCFX_FAIL_IF_( s == 0 || *s == 0 ); + + scfx_string s2; + s2 += s; + s2 += '\0'; + + bool sign_char; + int sign = scfx_parse_sign( s, sign_char ); + + sc_numrep numrep = scfx_parse_prefix( s ); + + int base = 0; + + switch( numrep ) + { + case SC_DEC: + { + base = 10; + if( scfx_is_nan( s ) ) // special case: NaN + return static_cast<double>( scfx_ieee_double::nan() ); + if( scfx_is_inf( s ) ) // special case: Infinity + return static_cast<double>( scfx_ieee_double::inf( sign ) ); + break; + } + case SC_BIN: + case SC_BIN_US: + { + SCFX_FAIL_IF_( sign_char ); + base = 2; + break; + } + + case SC_BIN_SM: + { + base = 2; + break; + } + case SC_OCT: + case SC_OCT_US: + { + SCFX_FAIL_IF_( sign_char ); + base = 8; + break; + } + case SC_OCT_SM: + { + base = 8; + break; + } + case SC_HEX: + case SC_HEX_US: + { + SCFX_FAIL_IF_( sign_char ); + base = 16; + break; + } + case SC_HEX_SM: + { + base = 16; + break; + } + case SC_CSD: + { + SCFX_FAIL_IF_( sign_char ); + base = 2; + scfx_csd2tc( s2 ); + s = (const char*) s2 + 4; + numrep = SC_BIN; + break; + } + default:;// Martin, what is default??? + } + + // + // find end of mantissa and count the digits and points + // + + const char *end = s; + bool based_point = false; + int int_digits = 0; + int frac_digits = 0; + + while( *end ) + { + if( scfx_exp_start( end ) ) + break; + + if( *end == '.' ) + { + SCFX_FAIL_IF_( based_point ); + based_point = true; + } + else + { + SCFX_FAIL_IF_( ! scfx_is_digit( *end, numrep ) ); + if( based_point ) + frac_digits ++; + else + int_digits ++; + } + + end ++; + } + + SCFX_FAIL_IF_( int_digits == 0 && frac_digits == 0 ); + + // [ exponent ] + + int exponent = 0; + + if( *end ) + { + for( const char *e = end + 2; *e; e ++ ) + SCFX_FAIL_IF_( ! scfx_is_digit( *e, SC_DEC ) ); + exponent = atoi( end + 1 ); + } + + // + // convert the mantissa + // + + double integer = 0.0; + + if( int_digits != 0 ) + { + + bool first_digit = true; + + for( ; s < end; s ++ ) + { + if( *s == '.' ) + break; + + if( first_digit ) + { + integer = scfx_to_digit( *s, numrep ); + switch( numrep ) + { + case SC_BIN: + case SC_OCT: + case SC_HEX: + { + if( integer >= ( base >> 1 ) ) + integer -= base; // two's complement + break; + } + default: + ; + } + first_digit = false; + } + else + { + integer *= base; + integer += scfx_to_digit( *s, numrep ); + } + } + } + + // [ . fraction ] + + double fraction = 0.0; + + if( frac_digits != 0 ) + { + s ++; // skip '.' + + bool first_digit = ( int_digits == 0 ); + + double scale = 1.0; + + for( ; s < end; s ++ ) + { + scale /= base; + + if( first_digit ) + { + fraction = scfx_to_digit( *s, numrep ); + switch( numrep ) + { + case SC_BIN: + case SC_OCT: + case SC_HEX: + { + if( fraction >= ( base >> 1 ) ) + fraction -= base; // two's complement + break; + } + default: + ; + } + fraction *= scale; + first_digit = false; + } + else + fraction += scfx_to_digit( *s, numrep ) * scale; + } + } + + double exp = ( exponent != 0 ) ? pow( (double) base, (double) exponent ) + : 1; + + return ( sign * ( integer + fraction ) * exp ); +} + +#undef SCFX_FAIL_IF_ + +} // namespace sc_dt + + +// Taf! diff --git a/ext/systemc/src/sysc/datatypes/fx/sc_fxval.h b/ext/systemc/src/sysc/datatypes/fx/sc_fxval.h new file mode 100644 index 000000000..1f199875c --- /dev/null +++ b/ext/systemc/src/sysc/datatypes/fx/sc_fxval.h @@ -0,0 +1,2269 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_fxval.h - + + Original Author: Martin Janssen, Synopsys, Inc. + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + +// $Log: sc_fxval.h,v $ +// Revision 1.3 2011/01/19 18:57:40 acg +// Andy Goodrich: changes for IEEE_1666_2011. +// +// Revision 1.2 2010/12/07 20:09:08 acg +// Andy Goodrich: Philipp Hartmann's constructor disambiguation fix +// +// Revision 1.1.1.1 2006/12/15 20:20:04 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:53:58 acg +// Andy Goodrich: added $Log command so that CVS comments are reproduced in +// the source. +// + +#ifndef SC_FXVAL_H +#define SC_FXVAL_H + + +#include "sysc/datatypes/fx/scfx_rep.h" +#ifndef SC_FX_EXCLUDE_OTHER +#include "sysc/datatypes/int/sc_int_base.h" +#include "sysc/datatypes/int/sc_uint_base.h" +#include "sysc/datatypes/int/sc_signed.h" +#include "sysc/datatypes/int/sc_unsigned.h" +#endif +#include "sysc/datatypes/fx/sc_fxval_observer.h" + +#ifdef SC_FXVAL_IMPLICIT_CONV +# define SCFX_EXPLICIT_ // nothing +#else +# define SCFX_EXPLICIT_ explicit +#endif +#ifdef SC_FXVAL_IMPLICIT_OTHER +# define SCFX_EXPLICIT_OTHER_ +#else +# define SCFX_EXPLICIT_OTHER_ explicit +#endif + +namespace sc_dt +{ + +// classes defined in this module +class sc_fxval; +class sc_fxval_fast; + +// forward class declarations +class sc_fxnum; +class sc_fxnum_fast; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_fxval +// +// Fixed-point value type; arbitrary precision. +// ---------------------------------------------------------------------------- + +class sc_fxval +{ + + friend class sc_fxnum; + +protected: + + sc_fxval_observer* observer() const; + +public: + + // internal use only; + explicit sc_fxval( scfx_rep* ); + + + explicit sc_fxval( sc_fxval_observer* = 0 ); + SCFX_EXPLICIT_ sc_fxval( int, sc_fxval_observer* = 0 ); + SCFX_EXPLICIT_ sc_fxval( unsigned int, sc_fxval_observer* = 0 ); + SCFX_EXPLICIT_ sc_fxval( long, sc_fxval_observer* = 0 ); + SCFX_EXPLICIT_ sc_fxval( unsigned long, sc_fxval_observer* = 0 ); + SCFX_EXPLICIT_ sc_fxval( float, sc_fxval_observer* = 0 ); + SCFX_EXPLICIT_ sc_fxval( double, sc_fxval_observer* = 0 ); + SCFX_EXPLICIT_ sc_fxval( const char*, sc_fxval_observer* = 0 ); + sc_fxval( const sc_fxval&, sc_fxval_observer* = 0 ); + sc_fxval( const sc_fxval_fast&, sc_fxval_observer* = 0 ); + sc_fxval( const sc_fxnum&, sc_fxval_observer* = 0 ); + sc_fxval( const sc_fxnum_fast&, sc_fxval_observer* = 0 ); +#ifndef SC_FX_EXCLUDE_OTHER + SCFX_EXPLICIT_OTHER_ sc_fxval( int64, sc_fxval_observer* = 0 ); + SCFX_EXPLICIT_OTHER_ sc_fxval( uint64, sc_fxval_observer* = 0 ); + SCFX_EXPLICIT_OTHER_ sc_fxval( const sc_int_base&, sc_fxval_observer* = 0 ); + SCFX_EXPLICIT_OTHER_ sc_fxval( const sc_uint_base&, sc_fxval_observer* = 0 ); + SCFX_EXPLICIT_OTHER_ sc_fxval( const sc_signed&, sc_fxval_observer* = 0 ); + SCFX_EXPLICIT_OTHER_ sc_fxval( const sc_unsigned&, sc_fxval_observer* = 0 ); +#endif + + ~sc_fxval(); + + + // internal use only; + const scfx_rep* get_rep() const; + void set_rep( scfx_rep* ); + + + // unary operators + + const sc_fxval operator - () const; + const sc_fxval& operator + () const; + + + // unary functions + + friend void neg( sc_fxval&, const sc_fxval& ); + + + // binary operators + +#define DECL_BIN_OP_T(op,tp) \ + friend const sc_fxval operator op ( const sc_fxval&, tp ); \ + friend const sc_fxval operator op ( tp, const sc_fxval& ); + +#ifndef SC_FX_EXCLUDE_OTHER +#define DECL_BIN_OP_OTHER(op) \ + DECL_BIN_OP_T(op,int64) \ + DECL_BIN_OP_T(op,uint64) \ + DECL_BIN_OP_T(op,const sc_int_base&) \ + DECL_BIN_OP_T(op,const sc_uint_base&) \ + DECL_BIN_OP_T(op,const sc_signed&) \ + DECL_BIN_OP_T(op,const sc_unsigned&) +#else +#define DECL_BIN_OP_OTHER(op) +#endif + +#define DECL_BIN_OP(op,dummy) \ + friend const sc_fxval operator op ( const sc_fxval&, const sc_fxval& ); \ + DECL_BIN_OP_T(op,int) \ + DECL_BIN_OP_T(op,unsigned int) \ + DECL_BIN_OP_T(op,long) \ + DECL_BIN_OP_T(op,unsigned long) \ + DECL_BIN_OP_T(op,float) \ + DECL_BIN_OP_T(op,double) \ + DECL_BIN_OP_T(op,const char*) \ + DECL_BIN_OP_T(op,const sc_fxval_fast&) \ + DECL_BIN_OP_T(op,const sc_fxnum_fast&) \ + DECL_BIN_OP_OTHER(op) + + DECL_BIN_OP(*,mult) + DECL_BIN_OP(+,add) + DECL_BIN_OP(-,sub) +// declaration below doesn't compile with BCB5 (E2206) +// DECL_BIN_OP(/,div) +// previous macro expanded + friend const sc_fxval operator / ( const sc_fxval&, const sc_fxval& ); + DECL_BIN_OP_T(/,int) + DECL_BIN_OP_T(/,unsigned int) + DECL_BIN_OP_T(/,long) + DECL_BIN_OP_T(/,unsigned long) + DECL_BIN_OP_T(/,float) + DECL_BIN_OP_T(/,double) + DECL_BIN_OP_T(/,const char*) + DECL_BIN_OP_T(/,const sc_fxval_fast&) + DECL_BIN_OP_T(/,const sc_fxnum_fast&) +// DECL_BIN_OP_OTHER(/) +#ifndef SC_FX_EXCLUDE_OTHER + DECL_BIN_OP_T(/,int64) \ + DECL_BIN_OP_T(/,uint64) \ + DECL_BIN_OP_T(/,const sc_int_base&) \ + DECL_BIN_OP_T(/,const sc_uint_base&) \ + DECL_BIN_OP_T(/,const sc_signed&) \ + DECL_BIN_OP_T(/,const sc_unsigned&) +#endif + + +#undef DECL_BIN_OP_T +#undef DECL_BIN_OP_OTHER +#undef DECL_BIN_OP + + friend const sc_fxval operator << ( const sc_fxval&, int ); + friend const sc_fxval operator >> ( const sc_fxval&, int ); + + + // binary functions + +#define DECL_BIN_FNC_T(fnc,tp) \ + friend void fnc ( sc_fxval&, const sc_fxval&, tp ); \ + friend void fnc ( sc_fxval&, tp, const sc_fxval& ); + +#ifndef SC_FX_EXCLUDE_OTHER +#define DECL_BIN_FNC_OTHER(fnc) \ + DECL_BIN_FNC_T(fnc,int64) \ + DECL_BIN_FNC_T(fnc,uint64) \ + DECL_BIN_FNC_T(fnc,const sc_int_base&) \ + DECL_BIN_FNC_T(fnc,const sc_uint_base&) \ + DECL_BIN_FNC_T(fnc,const sc_signed&) \ + DECL_BIN_FNC_T(fnc,const sc_unsigned&) +#else +#define DECL_BIN_FNC_OTHER(fnc) +#endif + +#define DECL_BIN_FNC(fnc) \ + friend void fnc ( sc_fxval&, const sc_fxval&, const sc_fxval& ); \ + DECL_BIN_FNC_T(fnc,int) \ + DECL_BIN_FNC_T(fnc,unsigned int) \ + DECL_BIN_FNC_T(fnc,long) \ + DECL_BIN_FNC_T(fnc,unsigned long) \ + DECL_BIN_FNC_T(fnc,float) \ + DECL_BIN_FNC_T(fnc,double) \ + DECL_BIN_FNC_T(fnc,const char*) \ + DECL_BIN_FNC_T(fnc,const sc_fxval_fast&) \ + DECL_BIN_FNC_T(fnc,const sc_fxnum_fast&) \ + DECL_BIN_FNC_OTHER(fnc) + + DECL_BIN_FNC(mult) + DECL_BIN_FNC(div) + DECL_BIN_FNC(add) + DECL_BIN_FNC(sub) + +#undef DECL_BIN_FNC_T +#undef DECL_BIN_FNC_OTHER +#undef DECL_BIN_FNC + + friend void lshift( sc_fxval&, const sc_fxval&, int ); + friend void rshift( sc_fxval&, const sc_fxval&, int ); + + + // relational (including equality) operators + +#define DECL_REL_OP_T(op,tp) \ + friend bool operator op ( const sc_fxval&, tp ); \ + friend bool operator op ( tp, const sc_fxval& ); + +#ifndef SC_FX_EXCLUDE_OTHER +#define DECL_REL_OP_OTHER(op) \ + DECL_REL_OP_T(op,int64) \ + DECL_REL_OP_T(op,uint64) \ + DECL_REL_OP_T(op,const sc_int_base&) \ + DECL_REL_OP_T(op,const sc_uint_base&) \ + DECL_REL_OP_T(op,const sc_signed&) \ + DECL_REL_OP_T(op,const sc_unsigned&) +#else +#define DECL_REL_OP_OTHER(op) +#endif + +#define DECL_REL_OP(op) \ + friend bool operator op ( const sc_fxval&, const sc_fxval& ); \ + DECL_REL_OP_T(op,int) \ + DECL_REL_OP_T(op,unsigned int) \ + DECL_REL_OP_T(op,long) \ + DECL_REL_OP_T(op,unsigned long) \ + DECL_REL_OP_T(op,float) \ + DECL_REL_OP_T(op,double) \ + DECL_REL_OP_T(op,const char*) \ + DECL_REL_OP_T(op,const sc_fxval_fast&) \ + DECL_REL_OP_T(op,const sc_fxnum_fast&) \ + DECL_REL_OP_OTHER(op) + + DECL_REL_OP(<) + DECL_REL_OP(<=) + DECL_REL_OP(>) + DECL_REL_OP(>=) + DECL_REL_OP(==) + DECL_REL_OP(!=) + +#undef DECL_REL_OP_T +#undef DECL_REL_OP_OTHER +#undef DECL_REL_OP + + + // assignment operators + +#define DECL_ASN_OP_T(op,tp) \ + sc_fxval& operator op( tp ); + +#ifndef SC_FX_EXCLUDE_OTHER +#define DECL_ASN_OP_OTHER(op) \ + DECL_ASN_OP_T(op,int64) \ + DECL_ASN_OP_T(op,uint64) \ + DECL_ASN_OP_T(op,const sc_int_base&) \ + DECL_ASN_OP_T(op,const sc_uint_base&) \ + DECL_ASN_OP_T(op,const sc_signed&) \ + DECL_ASN_OP_T(op,const sc_unsigned&) +#else +#define DECL_ASN_OP_OTHER(op) +#endif + +#define DECL_ASN_OP(op) \ + DECL_ASN_OP_T(op,int) \ + DECL_ASN_OP_T(op,unsigned int) \ + DECL_ASN_OP_T(op,long) \ + DECL_ASN_OP_T(op,unsigned long) \ + DECL_ASN_OP_T(op,float) \ + DECL_ASN_OP_T(op,double) \ + DECL_ASN_OP_T(op,const char*) \ + DECL_ASN_OP_T(op,const sc_fxval&) \ + DECL_ASN_OP_T(op,const sc_fxval_fast&) \ + DECL_ASN_OP_T(op,const sc_fxnum&) \ + DECL_ASN_OP_T(op,const sc_fxnum_fast&) \ + DECL_ASN_OP_OTHER(op) + + DECL_ASN_OP(=) + + DECL_ASN_OP(*=) + DECL_ASN_OP(/=) + DECL_ASN_OP(+=) + DECL_ASN_OP(-=) + + DECL_ASN_OP_T(<<=,int) + DECL_ASN_OP_T(>>=,int) + +#undef DECL_ASN_OP_T +#undef DECL_ASN_OP_OTHER +#undef DECL_ASN_OP + + + // auto-increment and auto-decrement + + const sc_fxval operator ++ ( int ); + const sc_fxval operator -- ( int ); + + sc_fxval& operator ++ (); + sc_fxval& operator -- (); + + + // implicit conversion + + operator double() const; // necessary evil! + + + // explicit conversion to primitive types + + short to_short() const; + unsigned short to_ushort() const; + int to_int() const; + unsigned int to_uint() const; + long to_long() const; + unsigned long to_ulong() const; + int64 to_int64() const; + uint64 to_uint64() const; + float to_float() const; + double to_double() const; + + + // explicit conversion to character string + + const std::string to_string() const; + const std::string to_string( sc_numrep ) const; + const std::string to_string( sc_numrep, bool ) const; + const std::string to_string( sc_fmt ) const; + const std::string to_string( sc_numrep, sc_fmt ) const; + const std::string to_string( sc_numrep, bool, sc_fmt ) const; + + const std::string to_dec() const; + const std::string to_bin() const; + const std::string to_oct() const; + const std::string to_hex() const; + + + // query value + + bool is_neg() const; + bool is_zero() const; + bool is_nan() const; + bool is_inf() const; + bool is_normal() const; + + bool rounding_flag() const; + + + // print or dump content + + void print( ::std::ostream& = ::std::cout ) const; + void scan( ::std::istream& = ::std::cin ); + void dump( ::std::ostream& = ::std::cout ) const; + + + // internal use only; + bool get_bit( int ) const; + +protected: + + sc_fxval_observer* lock_observer() const; + void unlock_observer( sc_fxval_observer* ) const; + + + void get_type( int&, int&, sc_enc& ) const; + + const sc_fxval quantization( const scfx_params&, bool& ) const; + const sc_fxval overflow( const scfx_params&, bool& ) const; + +private: + + scfx_rep* m_rep; + + mutable sc_fxval_observer* m_observer; + +}; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_fxval_fast +// +// Fixed-point value type; limited precision. +// ---------------------------------------------------------------------------- + +class sc_fxval_fast +{ + + friend class sc_fxnum_fast; + +protected: + + sc_fxval_fast_observer* observer() const; + +public: + + explicit sc_fxval_fast( sc_fxval_fast_observer* = 0 ); + SCFX_EXPLICIT_ sc_fxval_fast( int, sc_fxval_fast_observer* = 0 ); + SCFX_EXPLICIT_ sc_fxval_fast( unsigned int, sc_fxval_fast_observer* = 0 ); + SCFX_EXPLICIT_ sc_fxval_fast( long, sc_fxval_fast_observer* = 0 ); + SCFX_EXPLICIT_ sc_fxval_fast( unsigned long, sc_fxval_fast_observer* = 0 ); + SCFX_EXPLICIT_ sc_fxval_fast( float, sc_fxval_fast_observer* = 0 ); + SCFX_EXPLICIT_ sc_fxval_fast( double, sc_fxval_fast_observer* = 0 ); + SCFX_EXPLICIT_ sc_fxval_fast( const char*, sc_fxval_fast_observer* = 0 ); + sc_fxval_fast( const sc_fxval&, sc_fxval_fast_observer* = 0 ); + sc_fxval_fast( const sc_fxval_fast&, sc_fxval_fast_observer* = 0 ); + sc_fxval_fast( const sc_fxnum&, sc_fxval_fast_observer* = 0 ); + sc_fxval_fast( const sc_fxnum_fast&, sc_fxval_fast_observer* = 0 ); +#ifndef SC_FX_EXCLUDE_OTHER + SCFX_EXPLICIT_OTHER_ sc_fxval_fast( int64, sc_fxval_fast_observer* = 0 ); + SCFX_EXPLICIT_OTHER_ sc_fxval_fast( uint64, sc_fxval_fast_observer* = 0 ); + SCFX_EXPLICIT_OTHER_ sc_fxval_fast( const sc_int_base&, sc_fxval_fast_observer* = 0 ); + SCFX_EXPLICIT_OTHER_ sc_fxval_fast( const sc_uint_base&, sc_fxval_fast_observer* = 0 ); + SCFX_EXPLICIT_OTHER_ sc_fxval_fast( const sc_signed&, sc_fxval_fast_observer* = 0 ); + SCFX_EXPLICIT_OTHER_ sc_fxval_fast( const sc_unsigned&, sc_fxval_fast_observer* = 0 ); +#endif + + ~sc_fxval_fast(); + + // internal use only; + double get_val() const; + void set_val( double ); + + + // unary operators + + const sc_fxval_fast operator - () const; + const sc_fxval_fast& operator + () const; + + + // unary functions + + friend void neg( sc_fxval_fast&, const sc_fxval_fast& ); + + + // binary operators + +#define DECL_BIN_OP_T(op,tp) \ + friend const sc_fxval_fast operator op ( const sc_fxval_fast&, tp ); \ + friend const sc_fxval_fast operator op ( tp, const sc_fxval_fast& ); + +#ifndef SC_FX_EXCLUDE_OTHER +#define DECL_BIN_OP_OTHER(op) \ + DECL_BIN_OP_T(op,int64) \ + DECL_BIN_OP_T(op,uint64) \ + DECL_BIN_OP_T(op,const sc_int_base&) \ + DECL_BIN_OP_T(op,const sc_uint_base&) \ + DECL_BIN_OP_T(op,const sc_signed&) \ + DECL_BIN_OP_T(op,const sc_unsigned&) +#else +#define DECL_BIN_OP_OTHER(op) +#endif + +#define DECL_BIN_OP(op,dummy) \ + friend const sc_fxval_fast operator op ( const sc_fxval_fast&, \ + const sc_fxval_fast& ); \ + DECL_BIN_OP_T(op,int) \ + DECL_BIN_OP_T(op,unsigned int) \ + DECL_BIN_OP_T(op,long) \ + DECL_BIN_OP_T(op,unsigned long) \ + DECL_BIN_OP_T(op,float) \ + DECL_BIN_OP_T(op,double) \ + DECL_BIN_OP_T(op,const char*) \ + DECL_BIN_OP_OTHER(op) + + DECL_BIN_OP(*,mult) + DECL_BIN_OP(+,add) + DECL_BIN_OP(-,sub) +// don't use macro +// DECL_BIN_OP(/,div) + friend const sc_fxval_fast operator / ( const sc_fxval_fast&, + const sc_fxval_fast& ); + DECL_BIN_OP_T(/,int) + DECL_BIN_OP_T(/,unsigned int) + DECL_BIN_OP_T(/,long) + DECL_BIN_OP_T(/,unsigned long) + DECL_BIN_OP_T(/,float) + DECL_BIN_OP_T(/,double) + DECL_BIN_OP_T(/,const char*) +// DECL_BIN_OP_OTHER(/) +#ifndef SC_FX_EXCLUDE_OTHER + DECL_BIN_OP_T(/,int64) \ + DECL_BIN_OP_T(/,uint64) \ + DECL_BIN_OP_T(/,const sc_int_base&) \ + DECL_BIN_OP_T(/,const sc_uint_base&) \ + DECL_BIN_OP_T(/,const sc_signed&) \ + DECL_BIN_OP_T(/,const sc_unsigned&) +#endif + +#undef DECL_BIN_OP_T +#undef DECL_BIN_OP_OTHER +#undef DECL_BIN_OP + + friend const sc_fxval_fast operator << ( const sc_fxval_fast&, int ); + friend const sc_fxval_fast operator >> ( const sc_fxval_fast&, int ); + + + // binary functions + +#define DECL_BIN_FNC_T(fnc,tp) \ + friend void fnc ( sc_fxval_fast&, const sc_fxval_fast&, tp ); \ + friend void fnc ( sc_fxval_fast&, tp, const sc_fxval_fast& ); + +#ifndef SC_FX_EXCLUDE_OTHER +#define DECL_BIN_FNC_OTHER(fnc) \ + DECL_BIN_FNC_T(fnc,int64) \ + DECL_BIN_FNC_T(fnc,uint64) \ + DECL_BIN_FNC_T(fnc,const sc_int_base&) \ + DECL_BIN_FNC_T(fnc,const sc_uint_base&) \ + DECL_BIN_FNC_T(fnc,const sc_signed&) \ + DECL_BIN_FNC_T(fnc,const sc_unsigned&) +#else +#define DECL_BIN_FNC_OTHER(fnc) +#endif + +#define DECL_BIN_FNC(fnc) \ + friend void fnc ( sc_fxval_fast&, const sc_fxval_fast&, \ + const sc_fxval_fast& ); \ + DECL_BIN_FNC_T(fnc,int) \ + DECL_BIN_FNC_T(fnc,unsigned int) \ + DECL_BIN_FNC_T(fnc,long) \ + DECL_BIN_FNC_T(fnc,unsigned long) \ + DECL_BIN_FNC_T(fnc,float) \ + DECL_BIN_FNC_T(fnc,double) \ + DECL_BIN_FNC_T(fnc,const char*) \ + DECL_BIN_FNC_T(fnc,const sc_fxval&) \ + DECL_BIN_FNC_T(fnc,const sc_fxnum&) \ + DECL_BIN_FNC_OTHER(fnc) + + DECL_BIN_FNC(mult) + DECL_BIN_FNC(div) + DECL_BIN_FNC(add) + DECL_BIN_FNC(sub) + +#undef DECL_BIN_FNC_T +#undef DECL_BIN_FNC_OTHER +#undef DECL_BIN_FNC + + friend void lshift( sc_fxval_fast&, const sc_fxval_fast&, int ); + friend void rshift( sc_fxval_fast&, const sc_fxval_fast&, int ); + + + // relational (including equality) operators + +#define DECL_REL_OP_T(op,tp) \ + friend bool operator op ( const sc_fxval_fast&, tp ); \ + friend bool operator op ( tp, const sc_fxval_fast& ); + +#ifndef SC_FX_EXCLUDE_OTHER +#define DECL_REL_OP_OTHER(op) \ + DECL_REL_OP_T(op,int64) \ + DECL_REL_OP_T(op,uint64) \ + DECL_REL_OP_T(op,const sc_int_base&) \ + DECL_REL_OP_T(op,const sc_uint_base&) \ + DECL_REL_OP_T(op,const sc_signed&) \ + DECL_REL_OP_T(op,const sc_unsigned&) +#else +#define DECL_REL_OP_OTHER(op) +#endif + +#define DECL_REL_OP(op) \ + friend bool operator op ( const sc_fxval_fast&, const sc_fxval_fast& ); \ + DECL_REL_OP_T(op,int) \ + DECL_REL_OP_T(op,unsigned int) \ + DECL_REL_OP_T(op,long) \ + DECL_REL_OP_T(op,unsigned long) \ + DECL_REL_OP_T(op,float) \ + DECL_REL_OP_T(op,double) \ + DECL_REL_OP_T(op,const char*) \ + DECL_REL_OP_OTHER(op) + + DECL_REL_OP(<) + DECL_REL_OP(<=) + DECL_REL_OP(>) + DECL_REL_OP(>=) + DECL_REL_OP(==) + DECL_REL_OP(!=) + +#undef DECL_REL_OP_T +#undef DECL_REL_OP_OTHER +#undef DECL_REL_OP + + + // assignment operators + +#define DECL_ASN_OP_T(op,tp) \ + sc_fxval_fast& operator op( tp ); + +#ifndef SC_FX_EXCLUDE_OTHER +#define DECL_ASN_OP_OTHER(op) \ + DECL_ASN_OP_T(op,int64) \ + DECL_ASN_OP_T(op,uint64) \ + DECL_ASN_OP_T(op,const sc_int_base&) \ + DECL_ASN_OP_T(op,const sc_uint_base&) \ + DECL_ASN_OP_T(op,const sc_signed&) \ + DECL_ASN_OP_T(op,const sc_unsigned&) +#else +#define DECL_ASN_OP_OTHER(op) +#endif + +#define DECL_ASN_OP(op) \ + DECL_ASN_OP_T(op,int) \ + DECL_ASN_OP_T(op,unsigned int) \ + DECL_ASN_OP_T(op,long) \ + DECL_ASN_OP_T(op,unsigned long) \ + DECL_ASN_OP_T(op,float) \ + DECL_ASN_OP_T(op,double) \ + DECL_ASN_OP_T(op,const char*) \ + DECL_ASN_OP_T(op,const sc_fxval&) \ + DECL_ASN_OP_T(op,const sc_fxval_fast&) \ + DECL_ASN_OP_T(op,const sc_fxnum&) \ + DECL_ASN_OP_T(op,const sc_fxnum_fast&) \ + DECL_ASN_OP_OTHER(op) + + DECL_ASN_OP(=) + + DECL_ASN_OP(*=) + DECL_ASN_OP(/=) + DECL_ASN_OP(+=) + DECL_ASN_OP(-=) + + DECL_ASN_OP_T(<<=,int) + DECL_ASN_OP_T(>>=,int) + +#undef DECL_ASN_OP_T +#undef DECL_ASN_OP_OTHER +#undef DECL_ASN_OP + + + // auto-increment and auto-decrement + + const sc_fxval_fast operator ++ ( int ); + const sc_fxval_fast operator -- ( int ); + + sc_fxval_fast& operator ++ (); + sc_fxval_fast& operator -- (); + + + // implicit conversion + + operator double() const; // necessary evil! + + + // explicit conversion to primitive types + + short to_short() const; + unsigned short to_ushort() const; + int to_int() const; + unsigned int to_uint() const; + long to_long() const; + unsigned long to_ulong() const; + int64 to_int64() const; + uint64 to_uint64() const; + float to_float() const; + double to_double() const; + + + // explicit conversion to character string + + const std::string to_string() const; + const std::string to_string( sc_numrep ) const; + const std::string to_string( sc_numrep, bool ) const; + const std::string to_string( sc_fmt ) const; + const std::string to_string( sc_numrep, sc_fmt ) const; + const std::string to_string( sc_numrep, bool, sc_fmt ) const; + + const std::string to_dec() const; + const std::string to_bin() const; + const std::string to_oct() const; + const std::string to_hex() const; + + + // query value + + bool is_neg() const; + bool is_zero() const; + bool is_nan() const; + bool is_inf() const; + bool is_normal() const; + + bool rounding_flag() const; + + + // print or dump content + + void print( ::std::ostream& = ::std::cout ) const; + void scan( ::std::istream& = ::std::cin ); + void dump( ::std::ostream& = ::std::cout ) const; + + + // internal use only; + bool get_bit( int ) const; + +protected: + + sc_fxval_fast_observer* lock_observer() const; + void unlock_observer( sc_fxval_fast_observer* ) const; + + + static double from_string( const char* ); + +private: + + double m_val; + + mutable sc_fxval_fast_observer* m_observer; + +}; + + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + +// ---------------------------------------------------------------------------- +// CLASS : sc_fxval +// +// Fixed-point value type; arbitrary precision. +// ---------------------------------------------------------------------------- + +// protected method + +inline +sc_fxval_observer* +sc_fxval::observer() const +{ + return m_observer; +} + + +// internal use only; +inline +sc_fxval::sc_fxval( scfx_rep* a ) +: m_rep( a != 0 ? a : new scfx_rep ), + m_observer( 0 ) +{} + + +// public constructors + +inline +sc_fxval::sc_fxval( sc_fxval_observer* observer_ ) +: m_rep( new scfx_rep ), + m_observer( observer_ ) +{ + SC_FXVAL_OBSERVER_DEFAULT_ + SC_FXVAL_OBSERVER_CONSTRUCT_( *this ) +} + +inline +sc_fxval::sc_fxval( const sc_fxval& a, + sc_fxval_observer* observer_ ) +: m_rep( new scfx_rep( *a.m_rep ) ), + m_observer( observer_ ) +{ + SC_FXVAL_OBSERVER_DEFAULT_ + SC_FXVAL_OBSERVER_READ_( a ) + SC_FXVAL_OBSERVER_CONSTRUCT_( *this ) + SC_FXVAL_OBSERVER_WRITE_( *this ) +} + +#define DEFN_CTOR_T(tp,arg) \ +inline \ +sc_fxval::sc_fxval( tp a, \ + sc_fxval_observer* observer_ ) \ +: m_rep( new scfx_rep( arg ) ), \ + m_observer( observer_ ) \ +{ \ + SC_FXVAL_OBSERVER_DEFAULT_ \ + SC_FXVAL_OBSERVER_CONSTRUCT_( *this ) \ + SC_FXVAL_OBSERVER_WRITE_( *this ) \ +} + +#define DEFN_CTOR_T_A(tp) DEFN_CTOR_T(tp,a) +#define DEFN_CTOR_T_B(tp) DEFN_CTOR_T(tp,a.to_double()) +#define DEFN_CTOR_T_C(tp) DEFN_CTOR_T(tp,a.value()) + +DEFN_CTOR_T_A(int) +DEFN_CTOR_T_A(unsigned int) +DEFN_CTOR_T_A(long) +DEFN_CTOR_T_A(unsigned long) +DEFN_CTOR_T_A(float) +DEFN_CTOR_T_A(double) +DEFN_CTOR_T_A(const char*) +DEFN_CTOR_T_B(const sc_fxval_fast&) +#ifndef SC_FX_EXCLUDE_OTHER +DEFN_CTOR_T_A(int64) +DEFN_CTOR_T_A(uint64) +DEFN_CTOR_T_C(const sc_int_base&) +DEFN_CTOR_T_C(const sc_uint_base&) +DEFN_CTOR_T_A(const sc_signed&) +DEFN_CTOR_T_A(const sc_unsigned&) +#endif + +#undef DEFN_CTOR_T +#undef DEFN_CTOR_T_A +#undef DEFN_CTOR_T_B +#undef DEFN_CTOR_T_C + + +inline +sc_fxval::~sc_fxval() +{ + SC_FXVAL_OBSERVER_DESTRUCT_( *this ) + delete m_rep; +} + + +// internal use only; +inline +const scfx_rep* +sc_fxval::get_rep() const +{ + SC_FXVAL_OBSERVER_READ_( *this ) + return m_rep; +} + +// internal use only; +inline +void +sc_fxval::set_rep( scfx_rep* rep_ ) +{ + delete m_rep; + m_rep = rep_; + SC_FXVAL_OBSERVER_WRITE_( *this ) +} + + +// unary operators + +inline +const sc_fxval +sc_fxval::operator - () const +{ + SC_FXVAL_OBSERVER_READ_( *this ) + return sc_fxval( sc_dt::neg_scfx_rep( *m_rep ) ); +} + +inline +const sc_fxval& +sc_fxval::operator + () const +{ + // SC_FXVAL_OBSERVER_READ_( *this ) + return *this; +} + + +// unary functions + +inline +void +neg( sc_fxval& c, const sc_fxval& a ) +{ + SC_FXVAL_OBSERVER_READ_( a ) + delete c.m_rep; + c.m_rep = sc_dt::neg_scfx_rep( *a.m_rep ); + SC_FXVAL_OBSERVER_WRITE_( c ) +} + + +// binary operators + +#define DEFN_BIN_OP_T(op,fnc,tp) \ +inline \ +const sc_fxval \ +operator op ( const sc_fxval& a, tp b ) \ +{ \ + SC_FXVAL_OBSERVER_READ_( a ) \ + sc_fxval tmp( b ); \ + return sc_fxval( sc_dt::fnc ## _scfx_rep( *a.m_rep, *tmp.m_rep ) ); \ +} \ + \ +inline \ +const sc_fxval \ +operator op ( tp a, const sc_fxval& b ) \ +{ \ + SC_FXVAL_OBSERVER_READ_( b ) \ + sc_fxval tmp( a ); \ + return sc_fxval( sc_dt::fnc ## _scfx_rep( *tmp.m_rep, *b.m_rep ) ); \ +} + +#ifndef SC_FX_EXCLUDE_OTHER +#define DEFN_BIN_OP_OTHER(op,fnc) \ +DEFN_BIN_OP_T(op,fnc,int64) \ +DEFN_BIN_OP_T(op,fnc,uint64) \ +DEFN_BIN_OP_T(op,fnc,const sc_int_base&) \ +DEFN_BIN_OP_T(op,fnc,const sc_uint_base&) \ +DEFN_BIN_OP_T(op,fnc,const sc_signed&) \ +DEFN_BIN_OP_T(op,fnc,const sc_unsigned&) +#else +#define DEFN_BIN_OP_OTHER(op,fnc) +#endif + +#define DEFN_BIN_OP(op,fnc) \ +inline \ +const sc_fxval \ +operator op ( const sc_fxval& a, const sc_fxval& b ) \ +{ \ + SC_FXVAL_OBSERVER_READ_( a ) \ + SC_FXVAL_OBSERVER_READ_( b ) \ + return sc_fxval( sc_dt::fnc ## _scfx_rep( *a.m_rep, *b.m_rep ) ); \ +} \ + \ +DEFN_BIN_OP_T(op,fnc,int) \ +DEFN_BIN_OP_T(op,fnc,unsigned int) \ +DEFN_BIN_OP_T(op,fnc,long) \ +DEFN_BIN_OP_T(op,fnc,unsigned long) \ +DEFN_BIN_OP_T(op,fnc,float) \ +DEFN_BIN_OP_T(op,fnc,double) \ +DEFN_BIN_OP_T(op,fnc,const char*) \ +DEFN_BIN_OP_T(op,fnc,const sc_fxval_fast&) \ +DEFN_BIN_OP_OTHER(op,fnc) + +DEFN_BIN_OP(*,mult) +DEFN_BIN_OP(+,add) +DEFN_BIN_OP(-,sub) +// don't use macro +//DEFN_BIN_OP(/,div) +inline +const sc_fxval +operator / ( const sc_fxval& a, const sc_fxval& b ) +{ + SC_FXVAL_OBSERVER_READ_( a ) + SC_FXVAL_OBSERVER_READ_( b ) + return sc_fxval( sc_dt::div_scfx_rep( *a.m_rep, *b.m_rep ) ); +} + +DEFN_BIN_OP_T(/,div,int) +DEFN_BIN_OP_T(/,div,unsigned int) +DEFN_BIN_OP_T(/,div,long) +DEFN_BIN_OP_T(/,div,unsigned long) +DEFN_BIN_OP_T(/,div,float) +DEFN_BIN_OP_T(/,div,double) +DEFN_BIN_OP_T(/,div,const char*) +DEFN_BIN_OP_T(/,div,const sc_fxval_fast&) +//DEFN_BIN_OP_OTHER(/,div) +#ifndef SC_FX_EXCLUDE_OTHER +DEFN_BIN_OP_T(/,div,int64) \ +DEFN_BIN_OP_T(/,div,uint64) \ +DEFN_BIN_OP_T(/,div,const sc_int_base&) \ +DEFN_BIN_OP_T(/,div,const sc_uint_base&) \ +DEFN_BIN_OP_T(/,div,const sc_signed&) \ +DEFN_BIN_OP_T(/,div,const sc_unsigned&) +#endif + +#undef DEFN_BIN_OP_T +#undef DEFN_BIN_OP_OTHER +#undef DEFN_BIN_OP + + +inline +const sc_fxval +operator << ( const sc_fxval& a, int b ) +{ + SC_FXVAL_OBSERVER_READ_( a ) + return sc_fxval( sc_dt::lsh_scfx_rep( *a.m_rep, b ) ); +} + +inline +const sc_fxval +operator >> ( const sc_fxval& a, int b ) +{ + SC_FXVAL_OBSERVER_READ_( a ) + return sc_fxval( sc_dt::rsh_scfx_rep( *a.m_rep, b ) ); +} + + +// binary functions + +#define DEFN_BIN_FNC_T(fnc,tp) \ +inline \ +void \ +fnc ( sc_fxval& c, const sc_fxval& a, tp b ) \ +{ \ + SC_FXVAL_OBSERVER_READ_( a ) \ + sc_fxval tmp( b ); \ + delete c.m_rep; \ + c.m_rep = sc_dt::fnc ## _scfx_rep( *a.m_rep, *tmp.m_rep ); \ + SC_FXVAL_OBSERVER_WRITE_( c ) \ +} \ + \ +inline \ +void \ +fnc ( sc_fxval& c, tp a, const sc_fxval& b ) \ +{ \ + SC_FXVAL_OBSERVER_READ_( b ) \ + sc_fxval tmp( a ); \ + delete c.m_rep; \ + c.m_rep = sc_dt::fnc ## _scfx_rep( *tmp.m_rep, *b.m_rep ); \ + SC_FXVAL_OBSERVER_WRITE_( c ) \ +} + +#ifndef SC_FX_EXCLUDE_OTHER +#define DEFN_BIN_FNC_OTHER(fnc) \ +DEFN_BIN_FNC_T(fnc,int64) \ +DEFN_BIN_FNC_T(fnc,uint64) \ +DEFN_BIN_FNC_T(fnc,const sc_int_base&) \ +DEFN_BIN_FNC_T(fnc,const sc_uint_base&) \ +DEFN_BIN_FNC_T(fnc,const sc_signed&) \ +DEFN_BIN_FNC_T(fnc,const sc_unsigned&) +#else +#define DEFN_BIN_FNC_OTHER(fnc) +#endif + +#define DEFN_BIN_FNC(fnc) \ +inline \ +void \ +fnc( sc_fxval& c, const sc_fxval& a, const sc_fxval& b ) \ +{ \ + SC_FXVAL_OBSERVER_READ_( a ) \ + SC_FXVAL_OBSERVER_READ_( b ) \ + delete c.m_rep; \ + c.m_rep = sc_dt::fnc ## _scfx_rep( *a.m_rep, *b.m_rep ); \ + SC_FXVAL_OBSERVER_WRITE_( c ) \ +} \ + \ +DEFN_BIN_FNC_T(fnc,int) \ +DEFN_BIN_FNC_T(fnc,unsigned int) \ +DEFN_BIN_FNC_T(fnc,long) \ +DEFN_BIN_FNC_T(fnc,unsigned long) \ +DEFN_BIN_FNC_T(fnc,float) \ +DEFN_BIN_FNC_T(fnc,double) \ +DEFN_BIN_FNC_T(fnc,const char*) \ +DEFN_BIN_FNC_T(fnc,const sc_fxval_fast&) \ +DEFN_BIN_FNC_OTHER(fnc) + +DEFN_BIN_FNC(mult) +DEFN_BIN_FNC(div) +DEFN_BIN_FNC(add) +DEFN_BIN_FNC(sub) + +#undef DEFN_BIN_FNC_T +#undef DEFN_BIN_FNC_OTHER +#undef DEFN_BIN_FNC + + +inline +void +lshift( sc_fxval& c, const sc_fxval& a, int b ) +{ + SC_FXVAL_OBSERVER_READ_( a ) + delete c.m_rep; + c.m_rep = sc_dt::lsh_scfx_rep( *a.m_rep, b ); + SC_FXVAL_OBSERVER_WRITE_( c ) +} + +inline +void +rshift( sc_fxval& c, const sc_fxval& a, int b ) +{ + SC_FXVAL_OBSERVER_READ_( a ) + delete c.m_rep; + c.m_rep = sc_dt::rsh_scfx_rep( *a.m_rep, b ); + SC_FXVAL_OBSERVER_WRITE_( c ) +} + + +// relational (including equality) operators + +#define DEFN_REL_OP_T(op,ret,tp) \ +inline \ +bool \ +operator op ( const sc_fxval& a, tp b ) \ +{ \ + SC_FXVAL_OBSERVER_READ_( a ) \ + sc_fxval tmp( b ); \ + int result = sc_dt::cmp_scfx_rep( *a.m_rep, *tmp.m_rep ); \ + return ( ret ); \ +} \ + \ +inline \ +bool \ +operator op ( tp a, const sc_fxval& b ) \ +{ \ + SC_FXVAL_OBSERVER_READ_( b ) \ + sc_fxval tmp( a ); \ + int result = sc_dt::cmp_scfx_rep( *tmp.m_rep, *b.m_rep ); \ + return ( ret ); \ +} + +#ifndef SC_FX_EXCLUDE_OTHER +#define DEFN_REL_OP_OTHER(op,ret) \ +DEFN_REL_OP_T(op,ret,int64) \ +DEFN_REL_OP_T(op,ret,uint64) \ +DEFN_REL_OP_T(op,ret,const sc_int_base&) \ +DEFN_REL_OP_T(op,ret,const sc_uint_base&) \ +DEFN_REL_OP_T(op,ret,const sc_signed&) \ +DEFN_REL_OP_T(op,ret,const sc_unsigned&) +#else +#define DEFN_REL_OP_OTHER(op,ret) +#endif + +#define DEFN_REL_OP(op,ret) \ +inline \ +bool \ +operator op ( const sc_fxval& a, const sc_fxval& b) \ +{ \ + SC_FXVAL_OBSERVER_READ_( a ) \ + SC_FXVAL_OBSERVER_READ_( b ) \ + int result = sc_dt::cmp_scfx_rep( *a.m_rep, *b.m_rep ); \ + return ( ret ); \ +} \ + \ +DEFN_REL_OP_T(op,ret,int) \ +DEFN_REL_OP_T(op,ret,unsigned int) \ +DEFN_REL_OP_T(op,ret,long) \ +DEFN_REL_OP_T(op,ret,unsigned long) \ +DEFN_REL_OP_T(op,ret,float) \ +DEFN_REL_OP_T(op,ret,double) \ +DEFN_REL_OP_T(op,ret,const char*) \ +DEFN_REL_OP_T(op,ret,const sc_fxval_fast&) \ +DEFN_REL_OP_OTHER(op,ret) + +DEFN_REL_OP(<,result < 0) +DEFN_REL_OP(<=,result <= 0) +DEFN_REL_OP(>,result > 0 && result != 2) +DEFN_REL_OP(>=,result >= 0 && result != 2) +DEFN_REL_OP(==,result == 0) +DEFN_REL_OP(!=,result != 0) + +#undef DEFN_REL_OP_T +#undef DEFN_REL_OP_OTHER +#undef DEFN_REL_OP + + +// assignment operators + +inline +sc_fxval& +sc_fxval::operator = ( const sc_fxval& a ) +{ + if( &a != this ) + { + SC_FXVAL_OBSERVER_READ_( a ) + *m_rep = *a.m_rep; + SC_FXVAL_OBSERVER_WRITE_( *this ) + } + return *this; +} + +#define DEFN_ASN_OP_T(tp) \ +inline \ +sc_fxval& \ +sc_fxval::operator = ( tp b ) \ +{ \ + sc_fxval tmp( b ); \ + *m_rep = *tmp.m_rep; \ + SC_FXVAL_OBSERVER_WRITE_( *this ) \ + return *this; \ +} + +DEFN_ASN_OP_T(int) +DEFN_ASN_OP_T(unsigned int) +DEFN_ASN_OP_T(long) +DEFN_ASN_OP_T(unsigned long) +DEFN_ASN_OP_T(float) +DEFN_ASN_OP_T(double) +DEFN_ASN_OP_T(const char*) +DEFN_ASN_OP_T(const sc_fxval_fast&) +#ifndef SC_FX_EXCLUDE_OTHER +DEFN_ASN_OP_T(int64) +DEFN_ASN_OP_T(uint64) +DEFN_ASN_OP_T(const sc_int_base&) +DEFN_ASN_OP_T(const sc_uint_base&) +DEFN_ASN_OP_T(const sc_signed&) +DEFN_ASN_OP_T(const sc_unsigned&) +#endif + +#undef DEFN_ASN_OP_T + + +#define DEFN_ASN_OP_T(op,fnc,tp) \ +inline \ +sc_fxval& \ +sc_fxval::operator op ( tp b ) \ +{ \ + SC_FXVAL_OBSERVER_READ_( *this ) \ + sc_fxval tmp( b ); \ + scfx_rep* new_rep = sc_dt::fnc ## _scfx_rep( *m_rep, *tmp.m_rep ); \ + delete m_rep; \ + m_rep = new_rep; \ + SC_FXVAL_OBSERVER_WRITE_( *this ) \ + return *this; \ +} + +#ifndef SC_FX_EXCLUDE_OTHER +#define DEFN_ASN_OP_OTHER(op,fnc) \ +DEFN_ASN_OP_T(op,fnc,int64) \ +DEFN_ASN_OP_T(op,fnc,uint64) \ +DEFN_ASN_OP_T(op,fnc,const sc_int_base&) \ +DEFN_ASN_OP_T(op,fnc,const sc_uint_base&) \ +DEFN_ASN_OP_T(op,fnc,const sc_signed&) \ +DEFN_ASN_OP_T(op,fnc,const sc_unsigned&) +#else +#define DEFN_ASN_OP_OTHER(op,fnc) +#endif + +#define DEFN_ASN_OP(op,fnc) \ +inline \ +sc_fxval& \ +sc_fxval::operator op ( const sc_fxval& b ) \ +{ \ + SC_FXVAL_OBSERVER_READ_( *this ) \ + SC_FXVAL_OBSERVER_READ_( b ) \ + scfx_rep* new_rep = sc_dt::fnc ## _scfx_rep( *m_rep, *b.m_rep ); \ + delete m_rep; \ + m_rep = new_rep; \ + SC_FXVAL_OBSERVER_WRITE_( *this ) \ + return *this; \ +} \ + \ +DEFN_ASN_OP_T(op,fnc,int) \ +DEFN_ASN_OP_T(op,fnc,unsigned int) \ +DEFN_ASN_OP_T(op,fnc,long) \ +DEFN_ASN_OP_T(op,fnc,unsigned long) \ +DEFN_ASN_OP_T(op,fnc,float) \ +DEFN_ASN_OP_T(op,fnc,double) \ +DEFN_ASN_OP_T(op,fnc,const char*) \ +DEFN_ASN_OP_T(op,fnc,const sc_fxval_fast&) \ +DEFN_ASN_OP_OTHER(op,fnc) + +DEFN_ASN_OP(*=,mult) +DEFN_ASN_OP(/=,div) +DEFN_ASN_OP(+=,add) +DEFN_ASN_OP(-=,sub) + +#undef DEFN_ASN_OP_T +#undef DEFN_ASN_OP_OTHER +#undef DEFN_ASN_OP + + +inline +sc_fxval& +sc_fxval::operator <<= ( int b ) +{ + SC_FXVAL_OBSERVER_READ_( *this ) + m_rep->lshift( b ); + SC_FXVAL_OBSERVER_WRITE_( *this ) + return *this; +} + +inline +sc_fxval& +sc_fxval::operator >>= ( int b ) +{ + SC_FXVAL_OBSERVER_READ_( *this ) + m_rep->rshift( b ); + SC_FXVAL_OBSERVER_WRITE_( *this ) + return *this; +} + + +// auto-increment and auto-decrement + +inline +const sc_fxval +sc_fxval::operator ++ ( int ) +{ + sc_fxval c = *this; + (*this) += 1; + return c; +} + +inline +const sc_fxval +sc_fxval::operator -- ( int ) +{ + sc_fxval c = *this; + (*this) -= 1; + return c; +} + +inline +sc_fxval& +sc_fxval::operator ++ () +{ + (*this) += 1; + return *this; +} + +inline +sc_fxval& +sc_fxval::operator -- () +{ + (*this) -= 1; + return *this; +} + + +// implicit conversion + +inline +sc_fxval::operator double() const +{ + SC_FXVAL_OBSERVER_READ_( *this ) + return m_rep->to_double(); +} + + +// explicit conversion to primitive types + +inline +short +sc_fxval::to_short() const +{ + SC_FXVAL_OBSERVER_READ_( *this ) + return static_cast<short>( m_rep->to_double() ); +} + +inline +unsigned short +sc_fxval::to_ushort() const +{ + SC_FXVAL_OBSERVER_READ_( *this ) + return static_cast<unsigned short>( m_rep->to_double() ); +} + +inline +int +sc_fxval::to_int() const +{ + SC_FXVAL_OBSERVER_READ_( *this ) + return static_cast<int>( m_rep->to_double() ); +} + +inline +int64 +sc_fxval::to_int64() const +{ + SC_FXVAL_OBSERVER_READ_( *this ) + return static_cast<int64>( m_rep->to_double() ); +} + +inline +uint64 +sc_fxval::to_uint64() const +{ + SC_FXVAL_OBSERVER_READ_( *this ) + return static_cast<uint64>( m_rep->to_double() ); +} + +inline +long +sc_fxval::to_long() const +{ + SC_FXVAL_OBSERVER_READ_( *this ) + return static_cast<long>( m_rep->to_double() ); +} + +inline +unsigned int +sc_fxval::to_uint() const +{ + SC_FXVAL_OBSERVER_READ_( *this ) + return static_cast<unsigned int>( m_rep->to_double() ); +} + +inline +unsigned long +sc_fxval::to_ulong() const +{ + SC_FXVAL_OBSERVER_READ_( *this ) + return static_cast<unsigned long>( m_rep->to_double() ); +} + +inline +float +sc_fxval::to_float() const +{ + SC_FXVAL_OBSERVER_READ_( *this ) + return static_cast<float>( m_rep->to_double() ); +} + +inline +double +sc_fxval::to_double() const +{ + SC_FXVAL_OBSERVER_READ_( *this ) + return m_rep->to_double(); +} + + +// query value + +inline +bool +sc_fxval::is_neg() const +{ + SC_FXVAL_OBSERVER_READ_( *this ) + return m_rep->is_neg(); +} + +inline +bool +sc_fxval::is_zero() const +{ + SC_FXVAL_OBSERVER_READ_( *this ) + return m_rep->is_zero(); +} + +inline +bool +sc_fxval::is_nan() const +{ + SC_FXVAL_OBSERVER_READ_( *this ) + return m_rep->is_nan(); +} + +inline +bool +sc_fxval::is_inf() const +{ + SC_FXVAL_OBSERVER_READ_( *this ) + return m_rep->is_inf(); +} + +inline +bool +sc_fxval::is_normal() const +{ + SC_FXVAL_OBSERVER_READ_( *this ) + return m_rep->is_normal(); +} + + +inline +bool +sc_fxval::rounding_flag() const +{ + return m_rep->rounding_flag(); +} + + +// internal use only; +inline +bool +sc_fxval::get_bit( int i ) const +{ + return m_rep->get_bit( i ); +} + + +// protected methods and friend functions + +inline +void +sc_fxval::get_type( int& wl, int& iwl, sc_enc& enc ) const +{ + m_rep->get_type( wl, iwl, enc ); +} + + +inline +const sc_fxval +sc_fxval::quantization( const scfx_params& params, bool& q_flag ) const +{ + return sc_fxval( sc_dt::quantization_scfx_rep( *m_rep, params, q_flag ) ); +} + +inline +const sc_fxval +sc_fxval::overflow( const scfx_params& params, bool& o_flag ) const +{ + return sc_fxval( sc_dt::overflow_scfx_rep( *m_rep, params, o_flag ) ); +} + + +inline +::std::ostream& +operator << ( ::std::ostream& os, const sc_fxval& a ) +{ + a.print( os ); + return os; +} + +inline +::std::istream& +operator >> ( ::std::istream& is, sc_fxval& a ) +{ + a.scan( is ); + return is; +} + + +// ---------------------------------------------------------------------------- +// CLASS : sc_fxval_fast +// +// Fixed-point value type; limited precision. +// ---------------------------------------------------------------------------- + +// protected method + +inline +sc_fxval_fast_observer* +sc_fxval_fast::observer() const +{ + return m_observer; +} + + +// public constructors + +inline +sc_fxval_fast::sc_fxval_fast( sc_fxval_fast_observer* observer_ ) +: m_val( 0.0 ), + m_observer( observer_ ) +{ + SC_FXVAL_FAST_OBSERVER_DEFAULT_ + SC_FXVAL_FAST_OBSERVER_CONSTRUCT_( *this ) +} + +inline +sc_fxval_fast::sc_fxval_fast( const sc_fxval_fast& a, + sc_fxval_fast_observer* observer_ ) +: m_val( a.m_val ), + m_observer( observer_ ) +{ + SC_FXVAL_FAST_OBSERVER_DEFAULT_ + SC_FXVAL_FAST_OBSERVER_READ_( a ) + SC_FXVAL_FAST_OBSERVER_CONSTRUCT_( *this ) + SC_FXVAL_FAST_OBSERVER_WRITE_( *this ) +} + +#define DEFN_CTOR_T(tp,arg) \ +inline \ +sc_fxval_fast::sc_fxval_fast( tp a, \ + sc_fxval_fast_observer* observer_ ) \ +: m_val( arg ), \ + m_observer( observer_ ) \ +{ \ + SC_FXVAL_FAST_OBSERVER_DEFAULT_ \ + SC_FXVAL_FAST_OBSERVER_CONSTRUCT_( *this ) \ + SC_FXVAL_FAST_OBSERVER_WRITE_( *this ) \ +} + +#define DEFN_CTOR_T_A(tp) DEFN_CTOR_T(tp,static_cast<double>( a )) +#define DEFN_CTOR_T_B(tp) DEFN_CTOR_T(tp,from_string( a )) +#define DEFN_CTOR_T_C(tp) DEFN_CTOR_T(tp,a.to_double()) + +DEFN_CTOR_T_A(int) +DEFN_CTOR_T_A(unsigned int) +DEFN_CTOR_T_A(long) +DEFN_CTOR_T_A(unsigned long) +DEFN_CTOR_T_A(float) +DEFN_CTOR_T_A(double) +DEFN_CTOR_T_B(const char*) +DEFN_CTOR_T_C(const sc_fxval&) +#ifndef SC_FX_EXCLUDE_OTHER +DEFN_CTOR_T_A(int64) +DEFN_CTOR_T_A(uint64) +DEFN_CTOR_T_C(const sc_int_base&) +DEFN_CTOR_T_C(const sc_uint_base&) +DEFN_CTOR_T_C(const sc_signed&) +DEFN_CTOR_T_C(const sc_unsigned&) +#endif + +#undef DEFN_CTOR_T +#undef DEFN_CTOR_T_A +#undef DEFN_CTOR_T_B +#undef DEFN_CTOR_T_C +#undef DEFN_CTOR_T_D +#undef DEFN_CTOR_T_E + + +inline +sc_fxval_fast::~sc_fxval_fast() +{ + SC_FXVAL_FAST_OBSERVER_DESTRUCT_( *this ) +} + + +// internal use only; +inline +double +sc_fxval_fast::get_val() const +{ + SC_FXVAL_FAST_OBSERVER_READ_( *this ) + return m_val; +} + +// internal use only; +inline +void +sc_fxval_fast::set_val( double val_ ) +{ + m_val = val_; + SC_FXVAL_FAST_OBSERVER_WRITE_( *this ) +} + + +// unary operators + +inline +const sc_fxval_fast +sc_fxval_fast::operator - () const +{ + SC_FXVAL_FAST_OBSERVER_READ_( *this ) + return sc_fxval_fast( - m_val ); +} + +inline +const sc_fxval_fast& +sc_fxval_fast::operator + () const +{ + // SC_FXVAL_FAST_OBSERVER_READ_( *this ) + return *this; +} + + +// unary functions + +inline +void +neg( sc_fxval_fast& c, const sc_fxval_fast& a ) +{ + SC_FXVAL_FAST_OBSERVER_READ_( a ) + c.m_val = - a.m_val; + SC_FXVAL_FAST_OBSERVER_WRITE_( c ) +} + + +// binary operators + +#define DEFN_BIN_OP_T(op,tp) \ +inline \ +const sc_fxval_fast \ +operator op ( const sc_fxval_fast& a, tp b ) \ +{ \ + SC_FXVAL_FAST_OBSERVER_READ_( a ) \ + sc_fxval_fast tmp( b ); \ + return sc_fxval_fast( a.m_val op tmp.m_val ); \ +} \ + \ +inline \ +const sc_fxval_fast \ +operator op ( tp a, const sc_fxval_fast& b ) \ +{ \ + SC_FXVAL_FAST_OBSERVER_READ_( b ) \ + sc_fxval_fast tmp( a ); \ + return sc_fxval_fast( tmp.m_val op b.m_val ); \ +} + +#ifndef SC_FX_EXCLUDE_OTHER +#define DEFN_BIN_OP_OTHER(op) \ +DEFN_BIN_OP_T(op,int64) \ +DEFN_BIN_OP_T(op,uint64) \ +DEFN_BIN_OP_T(op,const sc_int_base&) \ +DEFN_BIN_OP_T(op,const sc_uint_base&) \ +DEFN_BIN_OP_T(op,const sc_signed&) \ +DEFN_BIN_OP_T(op,const sc_unsigned&) +#else +#define DEFN_BIN_OP_OTHER(op) +#endif + +#define DEFN_BIN_OP(op,dummy) \ +inline \ +const sc_fxval_fast \ +operator op ( const sc_fxval_fast& a, const sc_fxval_fast& b ) \ +{ \ + SC_FXVAL_FAST_OBSERVER_READ_( a ) \ + SC_FXVAL_FAST_OBSERVER_READ_( b ) \ + return sc_fxval_fast( a.m_val op b.m_val ); \ +} \ + \ +DEFN_BIN_OP_T(op,int) \ +DEFN_BIN_OP_T(op,unsigned int) \ +DEFN_BIN_OP_T(op,long) \ +DEFN_BIN_OP_T(op,unsigned long) \ +DEFN_BIN_OP_T(op,float) \ +DEFN_BIN_OP_T(op,double) \ +DEFN_BIN_OP_T(op,const char*) \ +DEFN_BIN_OP_OTHER(op) + +DEFN_BIN_OP(*,mult) +DEFN_BIN_OP(+,add) +DEFN_BIN_OP(-,sub) +//DEFN_BIN_OP(/,div) +inline +const sc_fxval_fast +operator / ( const sc_fxval_fast& a, const sc_fxval_fast& b ) +{ + SC_FXVAL_FAST_OBSERVER_READ_( a ) + SC_FXVAL_FAST_OBSERVER_READ_( b ) + return sc_fxval_fast( a.m_val / b.m_val ); +} + +DEFN_BIN_OP_T(/,int) +DEFN_BIN_OP_T(/,unsigned int) +DEFN_BIN_OP_T(/,long) +DEFN_BIN_OP_T(/,unsigned long) +DEFN_BIN_OP_T(/,float) +DEFN_BIN_OP_T(/,double) +DEFN_BIN_OP_T(/,const char*) +//DEFN_BIN_OP_OTHER(/) +#ifndef SC_FX_EXCLUDE_OTHER +DEFN_BIN_OP_T(/,int64) +DEFN_BIN_OP_T(/,uint64) +DEFN_BIN_OP_T(/,const sc_int_base&) +DEFN_BIN_OP_T(/,const sc_uint_base&) +DEFN_BIN_OP_T(/,const sc_signed&) +DEFN_BIN_OP_T(/,const sc_unsigned&) +#endif + + +#undef DEFN_BIN_OP_T +#undef DEFN_BIN_OP_OTHER +#undef DEFN_BIN_OP + + +inline +const sc_fxval_fast +operator << ( const sc_fxval_fast& a, int b ) +{ + SC_FXVAL_FAST_OBSERVER_READ_( a ) + return sc_fxval_fast( a.m_val * scfx_pow2( b ) ); +} + +inline +const sc_fxval_fast +operator >> ( const sc_fxval_fast& a, int b ) +{ + SC_FXVAL_FAST_OBSERVER_READ_( a ) + return sc_fxval_fast( a.m_val * scfx_pow2( -b ) ); +} + + +// binary functions + +#define DEFN_BIN_FNC_T(fnc,op,tp) \ +inline \ +void \ +fnc ( sc_fxval_fast& c, const sc_fxval_fast& a, tp b ) \ +{ \ + SC_FXVAL_FAST_OBSERVER_READ_( a ) \ + sc_fxval_fast tmp( b ); \ + c.m_val = a.m_val op tmp.m_val; \ + SC_FXVAL_FAST_OBSERVER_WRITE_( c ) \ +} \ + \ +inline \ +void \ +fnc ( sc_fxval_fast& c, tp a, const sc_fxval_fast& b ) \ +{ \ + SC_FXVAL_FAST_OBSERVER_READ_( b ) \ + sc_fxval_fast tmp( a ); \ + c.m_val = tmp.m_val op b.m_val; \ + SC_FXVAL_FAST_OBSERVER_WRITE_( c ) \ +} + +#ifndef SC_FX_EXCLUDE_OTHER +#define DEFN_BIN_FNC_OTHER(fnc,op) \ +DEFN_BIN_FNC_T(fnc,op,int64) \ +DEFN_BIN_FNC_T(fnc,op,uint64) \ +DEFN_BIN_FNC_T(fnc,op,const sc_int_base&) \ +DEFN_BIN_FNC_T(fnc,op,const sc_uint_base&) \ +DEFN_BIN_FNC_T(fnc,op,const sc_signed&) \ +DEFN_BIN_FNC_T(fnc,op,const sc_unsigned&) +#else +#define DEFN_BIN_FNC_OTHER(fnc,op) +#endif + +#define DEFN_BIN_FNC(fnc,op) \ +inline \ +void \ +fnc ( sc_fxval_fast& c, const sc_fxval_fast& a, const sc_fxval_fast& b ) \ +{ \ + SC_FXVAL_FAST_OBSERVER_READ_( a ) \ + SC_FXVAL_FAST_OBSERVER_READ_( b ) \ + c.m_val = a.m_val op b.m_val; \ + SC_FXVAL_FAST_OBSERVER_WRITE_( c ) \ +} \ + \ +DEFN_BIN_FNC_T(fnc,op,int) \ +DEFN_BIN_FNC_T(fnc,op,unsigned int) \ +DEFN_BIN_FNC_T(fnc,op,long) \ +DEFN_BIN_FNC_T(fnc,op,unsigned long) \ +DEFN_BIN_FNC_T(fnc,op,float) \ +DEFN_BIN_FNC_T(fnc,op,double) \ +DEFN_BIN_FNC_T(fnc,op,const char*) \ +DEFN_BIN_FNC_OTHER(fnc,op) + +DEFN_BIN_FNC(mult,*) +DEFN_BIN_FNC(div,/) +DEFN_BIN_FNC(add,+) +DEFN_BIN_FNC(sub,-) + +#undef DEFN_BIN_FNC_T +#undef DEFN_BIN_FNC_OTHER +#undef DEFN_BIN_FNC + + +inline +void +lshift( sc_fxval_fast& c, const sc_fxval_fast& a, int b ) +{ + SC_FXVAL_FAST_OBSERVER_READ_( a ) + c.m_val = a.m_val * scfx_pow2( b ); + SC_FXVAL_FAST_OBSERVER_WRITE_( c ) +} + +inline +void +rshift( sc_fxval_fast& c, const sc_fxval_fast& a, int b ) +{ + SC_FXVAL_FAST_OBSERVER_READ_( a ) + c.m_val = a.m_val * scfx_pow2( -b ); + SC_FXVAL_FAST_OBSERVER_WRITE_( c ) +} + + +// relational (including equality) operators + +#define DEFN_REL_OP_T(op,tp) \ +inline \ +bool \ +operator op ( const sc_fxval_fast& a, tp b ) \ +{ \ + SC_FXVAL_FAST_OBSERVER_READ_( a ) \ + sc_fxval_fast tmp( b ); \ + return ( a.m_val op tmp.m_val ); \ +} \ + \ +inline \ +bool \ +operator op ( tp a, const sc_fxval_fast& b ) \ +{ \ + SC_FXVAL_FAST_OBSERVER_READ_( b ) \ + sc_fxval_fast tmp( a ); \ + return ( tmp.m_val op b.m_val ); \ +} + +#ifndef SC_FX_EXCLUDE_OTHER +#define DEFN_REL_OP_OTHER(op) \ +DEFN_REL_OP_T(op,int64) \ +DEFN_REL_OP_T(op,uint64) \ +DEFN_REL_OP_T(op,const sc_int_base&) \ +DEFN_REL_OP_T(op,const sc_uint_base&) \ +DEFN_REL_OP_T(op,const sc_signed&) \ +DEFN_REL_OP_T(op,const sc_unsigned&) +#else +#define DEFN_REL_OP_OTHER(op) +#endif + +#define DEFN_REL_OP(op) \ +inline \ +bool \ +operator op ( const sc_fxval_fast& a, const sc_fxval_fast& b ) \ +{ \ + SC_FXVAL_FAST_OBSERVER_READ_( a ) \ + SC_FXVAL_FAST_OBSERVER_READ_( b ) \ + return ( a.m_val op b.m_val ); \ +} \ + \ +DEFN_REL_OP_T(op,int) \ +DEFN_REL_OP_T(op,unsigned int) \ +DEFN_REL_OP_T(op,long) \ +DEFN_REL_OP_T(op,unsigned long) \ +DEFN_REL_OP_T(op,float) \ +DEFN_REL_OP_T(op,double) \ +DEFN_REL_OP_T(op,const char*) \ +DEFN_REL_OP_OTHER(op) + +DEFN_REL_OP(<) +DEFN_REL_OP(<=) +DEFN_REL_OP(>) +DEFN_REL_OP(>=) +DEFN_REL_OP(==) +DEFN_REL_OP(!=) + +#undef DEFN_REL_OP_T +#undef DEFN_REL_OP_OTHER +#undef DEFN_REL_OP + + +// assignment operators + +inline +sc_fxval_fast& +sc_fxval_fast::operator = ( const sc_fxval_fast& a ) +{ + if( &a != this ) + { + SC_FXVAL_FAST_OBSERVER_READ_( a ) + m_val = a.m_val; + SC_FXVAL_FAST_OBSERVER_WRITE_( *this ) + } + return *this; +} + +#define DEFN_ASN_OP_T(tp) \ +inline \ +sc_fxval_fast& \ +sc_fxval_fast::operator = ( tp a ) \ +{ \ + sc_fxval_fast tmp( a ); \ + m_val = tmp.m_val; \ + SC_FXVAL_FAST_OBSERVER_WRITE_( *this ) \ + return *this; \ +} + +DEFN_ASN_OP_T(int) +DEFN_ASN_OP_T(unsigned int) +DEFN_ASN_OP_T(long) +DEFN_ASN_OP_T(unsigned long) +DEFN_ASN_OP_T(float) +DEFN_ASN_OP_T(double) +DEFN_ASN_OP_T(const char*) +DEFN_ASN_OP_T(const sc_fxval&) +#ifndef SC_FX_EXCLUDE_OTHER +DEFN_ASN_OP_T(int64) +DEFN_ASN_OP_T(uint64) +DEFN_ASN_OP_T(const sc_int_base&) +DEFN_ASN_OP_T(const sc_uint_base&) +DEFN_ASN_OP_T(const sc_signed&) +DEFN_ASN_OP_T(const sc_unsigned&) +#endif + +#undef DEFN_ASN_OP_T + + +#define DEFN_ASN_OP_T(op,tp) \ +inline \ +sc_fxval_fast& \ +sc_fxval_fast::operator op ( tp b ) \ +{ \ + SC_FXVAL_FAST_OBSERVER_READ_( *this ) \ + sc_fxval_fast tmp( b ); \ + m_val op tmp.m_val; \ + SC_FXVAL_FAST_OBSERVER_WRITE_( *this ) \ + return *this; \ +} + +#ifndef SC_FX_EXCLUDE_OTHER +#define DEFN_ASN_OP_OTHER(op) \ +DEFN_ASN_OP_T(op,int64) \ +DEFN_ASN_OP_T(op,uint64) \ +DEFN_ASN_OP_T(op,const sc_int_base&) \ +DEFN_ASN_OP_T(op,const sc_uint_base&) \ +DEFN_ASN_OP_T(op,const sc_signed&) \ +DEFN_ASN_OP_T(op,const sc_unsigned&) +#else +#define DEFN_ASN_OP_OTHER(op) +#endif + +#define DEFN_ASN_OP(op) \ +inline \ +sc_fxval_fast& \ +sc_fxval_fast::operator op ( const sc_fxval_fast& b ) \ +{ \ + SC_FXVAL_FAST_OBSERVER_READ_( *this ) \ + SC_FXVAL_FAST_OBSERVER_READ_( b ) \ + m_val op b.m_val; \ + SC_FXVAL_FAST_OBSERVER_WRITE_( *this ) \ + return *this; \ +} \ + \ +DEFN_ASN_OP_T(op,int) \ +DEFN_ASN_OP_T(op,unsigned int) \ +DEFN_ASN_OP_T(op,long) \ +DEFN_ASN_OP_T(op,unsigned long) \ +DEFN_ASN_OP_T(op,float) \ +DEFN_ASN_OP_T(op,double) \ +DEFN_ASN_OP_T(op,const char*) \ +DEFN_ASN_OP_T(op,const sc_fxval&) \ +DEFN_ASN_OP_OTHER(op) + +DEFN_ASN_OP(*=) +DEFN_ASN_OP(/=) +DEFN_ASN_OP(+=) +DEFN_ASN_OP(-=) + +#undef DEFN_ASN_OP_T +#undef DEFN_ASN_OP_OTHER +#undef DEFN_ASN_OP + + +inline +sc_fxval_fast& +sc_fxval_fast::operator <<= ( int b ) +{ + SC_FXVAL_FAST_OBSERVER_READ_( *this ) + m_val *= scfx_pow2( b ); + SC_FXVAL_FAST_OBSERVER_WRITE_( *this ) + return *this; +} + +inline +sc_fxval_fast& +sc_fxval_fast::operator >>= ( int b ) +{ + SC_FXVAL_FAST_OBSERVER_READ_( *this ) + m_val *= scfx_pow2( -b ); + SC_FXVAL_FAST_OBSERVER_WRITE_( *this ) + return *this; +} + + +// auto-increment and auto-decrement + +inline +const sc_fxval_fast +sc_fxval_fast::operator ++ ( int ) +{ + SC_FXVAL_FAST_OBSERVER_READ_( *this ) + SC_FXVAL_FAST_OBSERVER_READ_( *this ) + double c = m_val; + m_val = m_val + 1; + SC_FXVAL_FAST_OBSERVER_WRITE_( *this ) + return sc_fxval_fast( c ); +} + +inline +const sc_fxval_fast +sc_fxval_fast::operator -- ( int ) +{ + SC_FXVAL_FAST_OBSERVER_READ_( *this ) + SC_FXVAL_FAST_OBSERVER_READ_( *this ) + double c = m_val; + m_val = m_val - 1; + SC_FXVAL_FAST_OBSERVER_WRITE_( *this ) + return sc_fxval_fast( c ); +} + +inline +sc_fxval_fast& +sc_fxval_fast::operator ++ () +{ + SC_FXVAL_FAST_OBSERVER_READ_( *this ) + m_val = m_val + 1; + SC_FXVAL_FAST_OBSERVER_WRITE_( *this ) + return *this; +} + +inline +sc_fxval_fast& +sc_fxval_fast::operator -- () +{ + SC_FXVAL_FAST_OBSERVER_READ_( *this ) + m_val = m_val - 1; + SC_FXVAL_FAST_OBSERVER_WRITE_( *this ) + return *this; +} + + +// implicit conversion + +inline +sc_fxval_fast::operator double() const +{ + SC_FXVAL_FAST_OBSERVER_READ_( *this ) + return m_val; +} + + +// explicit conversion to primitive types + +inline +short +sc_fxval_fast::to_short() const +{ + SC_FXVAL_FAST_OBSERVER_READ_( *this ) + return static_cast<short>( m_val ); +} + +inline +unsigned short +sc_fxval_fast::to_ushort() const +{ + SC_FXVAL_FAST_OBSERVER_READ_( *this ) + return static_cast<unsigned short>( m_val ); +} + +inline +int64 +sc_fxval_fast::to_int64() const +{ + SC_FXVAL_FAST_OBSERVER_READ_( *this ) + return static_cast<int64>( m_val ); +} + +inline +int +sc_fxval_fast::to_int() const +{ + SC_FXVAL_FAST_OBSERVER_READ_( *this ) + return static_cast<int>( m_val ); +} + +inline +unsigned int +sc_fxval_fast::to_uint() const +{ + SC_FXVAL_FAST_OBSERVER_READ_( *this ) + return static_cast<unsigned int>( m_val ); +} + +inline +uint64 +sc_fxval_fast::to_uint64() const +{ + SC_FXVAL_FAST_OBSERVER_READ_( *this ) + return static_cast<uint64>( m_val ); +} + +inline +long +sc_fxval_fast::to_long() const +{ + SC_FXVAL_FAST_OBSERVER_READ_( *this ) + return static_cast<long>( m_val ); +} + +inline +unsigned long +sc_fxval_fast::to_ulong() const +{ + SC_FXVAL_FAST_OBSERVER_READ_( *this ) + return static_cast<unsigned long>( m_val ); +} + +inline +float +sc_fxval_fast::to_float() const +{ + SC_FXVAL_FAST_OBSERVER_READ_( *this ) + return static_cast<float>( m_val ); +} + +inline +double +sc_fxval_fast::to_double() const +{ + SC_FXVAL_FAST_OBSERVER_READ_( *this ) + return m_val; +} + + +// query value + +inline +bool +sc_fxval_fast::is_neg() const +{ + SC_FXVAL_FAST_OBSERVER_READ_( *this ) + scfx_ieee_double id( m_val ); + return ( id.negative() != 0 ); +} + +inline +bool +sc_fxval_fast::is_zero() const +{ + SC_FXVAL_FAST_OBSERVER_READ_( *this ) + scfx_ieee_double id( m_val ); + return id.is_zero(); +} + +inline +bool +sc_fxval_fast::is_nan() const +{ + SC_FXVAL_FAST_OBSERVER_READ_( *this ) + scfx_ieee_double id( m_val ); + return id.is_nan(); +} + +inline +bool +sc_fxval_fast::is_inf() const +{ + SC_FXVAL_FAST_OBSERVER_READ_( *this ) + scfx_ieee_double id( m_val ); + return id.is_inf(); +} + +inline +bool +sc_fxval_fast::is_normal() const +{ + SC_FXVAL_FAST_OBSERVER_READ_( *this ) + scfx_ieee_double id( m_val ); + return ( id.is_normal() || id.is_subnormal() || id.is_zero() ); +} + + +inline +bool +sc_fxval_fast::rounding_flag() const +{ + // does not apply to sc_fxval_fast; included for API compatibility + return false; +} + + +inline +::std::ostream& +operator << ( ::std::ostream& os, const sc_fxval_fast& a ) +{ + a.print( os ); + return os; +} + +inline +::std::istream& +operator >> ( ::std::istream& is, sc_fxval_fast& a ) +{ + a.scan( is ); + return is; +} + +} // namespace sc_dt + +#undef SCFX_EXPLICIT_ +#undef SCFX_EXPLICIT_OTHER_ + +#endif + +// Taf! diff --git a/ext/systemc/src/sysc/datatypes/fx/sc_fxval_observer.cpp b/ext/systemc/src/sysc/datatypes/fx/sc_fxval_observer.cpp new file mode 100644 index 000000000..ae651cc14 --- /dev/null +++ b/ext/systemc/src/sysc/datatypes/fx/sc_fxval_observer.cpp @@ -0,0 +1,76 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_fxval_observer.cpp - + + Original Author: Martin Janssen, Synopsys, Inc. + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + + +// $Log: sc_fxval_observer.cpp,v $ +// Revision 1.1.1.1 2006/12/15 20:20:04 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:53:58 acg +// Andy Goodrich: added $Log command so that CVS comments are reproduced in +// the source. +// + +#include "sysc/datatypes/fx/sc_fxval_observer.h" + + +namespace sc_dt +{ + +// ---------------------------------------------------------------------------- +// CLASS : sc_fxval_observer +// +// Abstract base class for fixed-point value type observers; +// arbitrary precision. +// ---------------------------------------------------------------------------- + +sc_fxval_observer* (*sc_fxval_observer::default_observer) () = 0; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_fxval_fast_observer +// +// Abstract base class for fixed-point value type observers; +// limited precision. +// ---------------------------------------------------------------------------- + +sc_fxval_fast_observer* (*sc_fxval_fast_observer::default_observer) () = 0; + +} // namespace sc_dt + + +// Taf! diff --git a/ext/systemc/src/sysc/datatypes/fx/sc_fxval_observer.h b/ext/systemc/src/sysc/datatypes/fx/sc_fxval_observer.h new file mode 100644 index 000000000..e34d85c1b --- /dev/null +++ b/ext/systemc/src/sysc/datatypes/fx/sc_fxval_observer.h @@ -0,0 +1,223 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_fxval_observer.h - + + Original Author: Martin Janssen, Synopsys, Inc. + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + +// $Log: sc_fxval_observer.h,v $ +// Revision 1.1.1.1 2006/12/15 20:20:04 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:53:58 acg +// Andy Goodrich: added $Log command so that CVS comments are reproduced in +// the source. +// + +#ifndef SC_FXVAL_OBSERVER_H +#define SC_FXVAL_OBSERVER_H + + +#include "sysc/datatypes/fx/sc_fxdefs.h" + + +namespace sc_dt +{ + +// classes defined in this module +class sc_fxval_observer; +class sc_fxval_fast_observer; + +// forward class declarations +class sc_fxval; +class sc_fxval_fast; + + +#ifdef SC_ENABLE_OBSERVERS + +#define SC_FXVAL_OBSERVER_CONSTRUCT_(object) \ + SC_OBSERVER_(object,sc_fxval_observer*,construct) +#define SC_FXVAL_OBSERVER_DESTRUCT_(object) \ + SC_OBSERVER_(object,sc_fxval_observer*,destruct) +#define SC_FXVAL_OBSERVER_READ_(object) \ + SC_OBSERVER_(object,sc_fxval_observer*,read) +#define SC_FXVAL_OBSERVER_WRITE_(object) \ + SC_OBSERVER_(object,sc_fxval_observer*,write) +#define SC_FXVAL_OBSERVER_DEFAULT_ \ + SC_OBSERVER_DEFAULT_(sc_fxval_observer) + +#define SC_FXVAL_FAST_OBSERVER_CONSTRUCT_(object) \ + SC_OBSERVER_(object,sc_fxval_fast_observer*,construct) +#define SC_FXVAL_FAST_OBSERVER_DESTRUCT_(object) \ + SC_OBSERVER_(object,sc_fxval_fast_observer*,destruct) +#define SC_FXVAL_FAST_OBSERVER_READ_(object) \ + SC_OBSERVER_(object,sc_fxval_fast_observer*,read) +#define SC_FXVAL_FAST_OBSERVER_WRITE_(object) \ + SC_OBSERVER_(object,sc_fxval_fast_observer*,write) +#define SC_FXVAL_FAST_OBSERVER_DEFAULT_ \ + SC_OBSERVER_DEFAULT_(sc_fxval_fast_observer) + +#else + +#define SC_FXVAL_OBSERVER_CONSTRUCT_(object) +#define SC_FXVAL_OBSERVER_DESTRUCT_(object) +#define SC_FXVAL_OBSERVER_READ_(object) +#define SC_FXVAL_OBSERVER_WRITE_(object) +#define SC_FXVAL_OBSERVER_DEFAULT_ + +#define SC_FXVAL_FAST_OBSERVER_CONSTRUCT_(object) +#define SC_FXVAL_FAST_OBSERVER_DESTRUCT_(object) +#define SC_FXVAL_FAST_OBSERVER_READ_(object) +#define SC_FXVAL_FAST_OBSERVER_WRITE_(object) +#define SC_FXVAL_FAST_OBSERVER_DEFAULT_ + +#endif + + +// ---------------------------------------------------------------------------- +// CLASS : sc_fxval_observer +// +// Abstract base class for fixed-point value type observers; +// arbitrary precision. +// ---------------------------------------------------------------------------- + +class sc_fxval_observer +{ + +protected: + + sc_fxval_observer() {} + virtual ~sc_fxval_observer() {} + +public: + + virtual void construct( const sc_fxval& ); + virtual void destruct( const sc_fxval& ); + virtual void read( const sc_fxval& ); + virtual void write( const sc_fxval& ); + + static sc_fxval_observer* (*default_observer) (); + +}; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_fxval_fast_observer +// +// Abstract base class for fixed-point value type observers; +// limited precision. +// ---------------------------------------------------------------------------- + +class sc_fxval_fast_observer +{ + +protected: + + sc_fxval_fast_observer() {} + virtual ~sc_fxval_fast_observer() {} + +public: + + virtual void construct( const sc_fxval_fast& ); + virtual void destruct( const sc_fxval_fast& ); + virtual void read( const sc_fxval_fast& ); + virtual void write( const sc_fxval_fast& ); + + static sc_fxval_fast_observer* (*default_observer) (); + +}; + + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + +// ---------------------------------------------------------------------------- +// CLASS : sc_fxval_observer +// +// Abstract base class for fixed-point value type observers; +// arbitrary precision. +// ---------------------------------------------------------------------------- + +inline +void +sc_fxval_observer::construct( const sc_fxval& ) +{} + +inline +void +sc_fxval_observer::destruct( const sc_fxval& ) +{} + +inline +void +sc_fxval_observer::read( const sc_fxval& ) +{} + +inline +void +sc_fxval_observer::write( const sc_fxval& ) +{} + + +// ---------------------------------------------------------------------------- +// CLASS : sc_fxval_fast_observer +// +// Abstract base class for fixed-point value type observers; +// limited precision. +// ---------------------------------------------------------------------------- + +inline +void +sc_fxval_fast_observer::construct( const sc_fxval_fast& ) +{} + +inline +void +sc_fxval_fast_observer::destruct( const sc_fxval_fast& ) +{} + +inline +void +sc_fxval_fast_observer::read( const sc_fxval_fast& ) +{} + +inline +void +sc_fxval_fast_observer::write( const sc_fxval_fast& ) +{} + +} // namespace sc_dt + + +#endif + +// Taf! diff --git a/ext/systemc/src/sysc/datatypes/fx/sc_ufix.h b/ext/systemc/src/sysc/datatypes/fx/sc_ufix.h new file mode 100644 index 000000000..b8d9acaa1 --- /dev/null +++ b/ext/systemc/src/sysc/datatypes/fx/sc_ufix.h @@ -0,0 +1,1941 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_ufix.h - + + Original Author: Martin Janssen, Synopsys, Inc. + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + +// $Log: sc_ufix.h,v $ +// Revision 1.2 2011/01/20 22:52:30 acg +// Andy Goodrich: Add float constructors. +// +// Revision 1.1.1.1 2006/12/15 20:20:04 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:53:58 acg +// Andy Goodrich: added $Log command so that CVS comments are reproduced in +// the source. +// + +#ifndef SC_UFIX_H +#define SC_UFIX_H + + +#include "sysc/datatypes/fx/sc_fxnum.h" + + +namespace sc_dt +{ + +// classes defined in this module +class sc_ufix; +class sc_ufix_fast; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_ufix +// +// "Unconstrained" unsigned fixed-point class; arbitrary precision. +// ---------------------------------------------------------------------------- + +class sc_ufix : public sc_fxnum +{ + +public: + + // constructors + + explicit sc_ufix( sc_fxnum_observer* = 0 ); + sc_ufix( int, int, + sc_fxnum_observer* = 0 ); + sc_ufix( sc_q_mode, sc_o_mode, + sc_fxnum_observer* = 0 ); + sc_ufix( sc_q_mode, sc_o_mode, int, + sc_fxnum_observer* = 0 ); + sc_ufix( int, int, sc_q_mode, sc_o_mode, + sc_fxnum_observer* = 0 ); + sc_ufix( int, int, sc_q_mode, sc_o_mode, int, + sc_fxnum_observer* = 0 ); + explicit sc_ufix( const sc_fxcast_switch&, + sc_fxnum_observer* = 0 ); + sc_ufix( int, int, + const sc_fxcast_switch&, + sc_fxnum_observer* = 0 ); + sc_ufix( sc_q_mode, sc_o_mode, + const sc_fxcast_switch&, + sc_fxnum_observer* = 0 ); + sc_ufix( sc_q_mode, sc_o_mode, int, + const sc_fxcast_switch&, + sc_fxnum_observer* = 0 ); + sc_ufix( int, int, sc_q_mode, sc_o_mode, + const sc_fxcast_switch&, + sc_fxnum_observer* = 0 ); + sc_ufix( int, int, sc_q_mode, sc_o_mode, int, + const sc_fxcast_switch&, + sc_fxnum_observer* = 0 ); + explicit sc_ufix( const sc_fxtype_params&, + sc_fxnum_observer* = 0 ); + sc_ufix( const sc_fxtype_params&, + const sc_fxcast_switch&, + sc_fxnum_observer* = 0 ); + +#define DECL_CTORS_T(tp) \ + sc_ufix( tp, \ + int, int, \ + sc_fxnum_observer* = 0 ); \ + sc_ufix( tp, \ + sc_q_mode, sc_o_mode, \ + sc_fxnum_observer* = 0 ); \ + sc_ufix( tp, \ + sc_q_mode, sc_o_mode, int, \ + sc_fxnum_observer* = 0 ); \ + sc_ufix( tp, \ + int, int, sc_q_mode, sc_o_mode, \ + sc_fxnum_observer* = 0 ); \ + sc_ufix( tp, \ + int, int, sc_q_mode, sc_o_mode, int, \ + sc_fxnum_observer* = 0 ); \ + sc_ufix( tp, \ + const sc_fxcast_switch&, \ + sc_fxnum_observer* = 0 ); \ + sc_ufix( tp, \ + int, int, \ + const sc_fxcast_switch&, \ + sc_fxnum_observer* = 0 ); \ + sc_ufix( tp, \ + sc_q_mode, sc_o_mode, \ + const sc_fxcast_switch&, \ + sc_fxnum_observer* = 0 ); \ + sc_ufix( tp, \ + sc_q_mode, sc_o_mode, int, \ + const sc_fxcast_switch&, \ + sc_fxnum_observer* = 0 ); \ + sc_ufix( tp, \ + int, int, sc_q_mode, sc_o_mode, \ + const sc_fxcast_switch&, \ + sc_fxnum_observer* = 0 ); \ + sc_ufix( tp, \ + int, int, sc_q_mode, sc_o_mode, int, \ + const sc_fxcast_switch&, \ + sc_fxnum_observer* = 0 ); \ + sc_ufix( tp, \ + const sc_fxtype_params&, \ + sc_fxnum_observer* = 0 ); \ + sc_ufix( tp, \ + const sc_fxtype_params&, \ + const sc_fxcast_switch&, \ + sc_fxnum_observer* = 0 ); + +#define DECL_CTORS_T_A(tp) \ + sc_ufix( tp, \ + sc_fxnum_observer* = 0 ); \ + DECL_CTORS_T(tp) + +#define DECL_CTORS_T_B(tp) \ + explicit sc_ufix( tp, \ + sc_fxnum_observer* = 0 ); \ + DECL_CTORS_T(tp) + + DECL_CTORS_T_A(int) + DECL_CTORS_T_A(unsigned int) + DECL_CTORS_T_A(long) + DECL_CTORS_T_A(unsigned long) + DECL_CTORS_T_A(float) + DECL_CTORS_T_A(double) + DECL_CTORS_T_A(const char*) + DECL_CTORS_T_A(const sc_fxval&) + DECL_CTORS_T_A(const sc_fxval_fast&) + DECL_CTORS_T_A(const sc_fxnum&) + DECL_CTORS_T_A(const sc_fxnum_fast&) +#ifndef SC_FX_EXCLUDE_OTHER + DECL_CTORS_T_B(int64) + DECL_CTORS_T_B(uint64) + DECL_CTORS_T_B(const sc_int_base&) + DECL_CTORS_T_B(const sc_uint_base&) + DECL_CTORS_T_B(const sc_signed&) + DECL_CTORS_T_B(const sc_unsigned&) +#endif + +#undef DECL_CTORS_T +#undef DECL_CTORS_T_A +#undef DECL_CTORS_T_B + + // copy constructor + + sc_ufix( const sc_ufix& ); + + + // unary bitwise operators + + const sc_ufix operator ~ () const; + + + // unary bitwise functions + + friend void b_not( sc_ufix&, const sc_ufix& ); + + + // binary bitwise operators + + friend const sc_ufix operator & ( const sc_ufix&, const sc_ufix& ); + friend const sc_ufix operator & ( const sc_ufix&, const sc_ufix_fast& ); + friend const sc_ufix operator & ( const sc_ufix_fast&, const sc_ufix& ); + friend const sc_ufix operator | ( const sc_ufix&, const sc_ufix& ); + friend const sc_ufix operator | ( const sc_ufix&, const sc_ufix_fast& ); + friend const sc_ufix operator | ( const sc_ufix_fast&, const sc_ufix& ); + friend const sc_ufix operator ^ ( const sc_ufix&, const sc_ufix& ); + friend const sc_ufix operator ^ ( const sc_ufix&, const sc_ufix_fast& ); + friend const sc_ufix operator ^ ( const sc_ufix_fast&, const sc_ufix& ); + + + // binary bitwise functions + + friend void b_and( sc_ufix&, const sc_ufix&, const sc_ufix& ); + friend void b_and( sc_ufix&, const sc_ufix&, const sc_ufix_fast& ); + friend void b_and( sc_ufix&, const sc_ufix_fast&, const sc_ufix& ); + friend void b_or ( sc_ufix&, const sc_ufix&, const sc_ufix& ); + friend void b_or ( sc_ufix&, const sc_ufix&, const sc_ufix_fast& ); + friend void b_or ( sc_ufix&, const sc_ufix_fast&, const sc_ufix& ); + friend void b_xor( sc_ufix&, const sc_ufix&, const sc_ufix& ); + friend void b_xor( sc_ufix&, const sc_ufix&, const sc_ufix_fast& ); + friend void b_xor( sc_ufix&, const sc_ufix_fast&, const sc_ufix& ); + + + // assignment operators + + sc_ufix& operator = ( const sc_ufix& ); + +#define DECL_ASN_OP_T(op,tp) \ + sc_ufix& operator op ( tp ); + +#ifndef SC_FX_EXCLUDE_OTHER +#define DECL_ASN_OP_OTHER(op) \ + DECL_ASN_OP_T(op,int64) \ + DECL_ASN_OP_T(op,uint64) \ + DECL_ASN_OP_T(op,const sc_int_base&) \ + DECL_ASN_OP_T(op,const sc_uint_base&) \ + DECL_ASN_OP_T(op,const sc_signed&) \ + DECL_ASN_OP_T(op,const sc_unsigned&) +#else +#define DECL_ASN_OP_OTHER(op) +#endif + +#define DECL_ASN_OP(op) \ + DECL_ASN_OP_T(op,int) \ + DECL_ASN_OP_T(op,unsigned int) \ + DECL_ASN_OP_T(op,long) \ + DECL_ASN_OP_T(op,unsigned long) \ + DECL_ASN_OP_T(op,float) \ + DECL_ASN_OP_T(op,double) \ + DECL_ASN_OP_T(op,const char*) \ + DECL_ASN_OP_T(op,const sc_fxval&) \ + DECL_ASN_OP_T(op,const sc_fxval_fast&) \ + DECL_ASN_OP_T(op,const sc_fxnum&) \ + DECL_ASN_OP_T(op,const sc_fxnum_fast&) \ + DECL_ASN_OP_OTHER(op) + + DECL_ASN_OP(=) + + DECL_ASN_OP(*=) + DECL_ASN_OP(/=) + DECL_ASN_OP(+=) + DECL_ASN_OP(-=) + + DECL_ASN_OP_T(<<=,int) + DECL_ASN_OP_T(>>=,int) + + DECL_ASN_OP_T(&=,const sc_ufix&) + DECL_ASN_OP_T(&=,const sc_ufix_fast&) + DECL_ASN_OP_T(|=,const sc_ufix&) + DECL_ASN_OP_T(|=,const sc_ufix_fast&) + DECL_ASN_OP_T(^=,const sc_ufix&) + DECL_ASN_OP_T(^=,const sc_ufix_fast&) + +#undef DECL_ASN_OP_T +#undef DECL_ASN_OP_OTHER +#undef DECL_ASN_OP + + + // auto-increment and auto-decrement + + const sc_fxval operator ++ ( int ); + const sc_fxval operator -- ( int ); + + sc_ufix& operator ++ (); + sc_ufix& operator -- (); + +}; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_ufix_fast +// +// "Unconstrained" unsigned fixed-point class; limited precision. +// ---------------------------------------------------------------------------- + +class sc_ufix_fast : public sc_fxnum_fast +{ + +public: + + // constructors + + explicit sc_ufix_fast( sc_fxnum_fast_observer* = 0 ); + sc_ufix_fast( int, int, + sc_fxnum_fast_observer* = 0 ); + sc_ufix_fast( sc_q_mode, sc_o_mode, + sc_fxnum_fast_observer* = 0 ); + sc_ufix_fast( sc_q_mode, sc_o_mode, int, + sc_fxnum_fast_observer* = 0 ); + sc_ufix_fast( int, int, sc_q_mode, sc_o_mode, + sc_fxnum_fast_observer* = 0 ); + sc_ufix_fast( int, int, sc_q_mode, sc_o_mode, int, + sc_fxnum_fast_observer* = 0 ); + explicit sc_ufix_fast( const sc_fxcast_switch&, + sc_fxnum_fast_observer* = 0 ); + sc_ufix_fast( int, int, + const sc_fxcast_switch&, + sc_fxnum_fast_observer* = 0 ); + sc_ufix_fast( sc_q_mode, sc_o_mode, + const sc_fxcast_switch&, + sc_fxnum_fast_observer* = 0 ); + sc_ufix_fast( sc_q_mode, sc_o_mode, int, + const sc_fxcast_switch&, + sc_fxnum_fast_observer* = 0 ); + sc_ufix_fast( int, int, sc_q_mode, sc_o_mode, + const sc_fxcast_switch&, + sc_fxnum_fast_observer* = 0 ); + sc_ufix_fast( int, int, sc_q_mode, sc_o_mode, int, + const sc_fxcast_switch&, + sc_fxnum_fast_observer* = 0 ); + explicit sc_ufix_fast( const sc_fxtype_params&, + sc_fxnum_fast_observer* = 0 ); + sc_ufix_fast( const sc_fxtype_params&, + const sc_fxcast_switch&, + sc_fxnum_fast_observer* = 0 ); + +#define DECL_CTORS_T(tp) \ + sc_ufix_fast( tp, \ + int, int, \ + sc_fxnum_fast_observer* = 0 ); \ + sc_ufix_fast( tp, \ + sc_q_mode, sc_o_mode, \ + sc_fxnum_fast_observer* = 0 ); \ + sc_ufix_fast( tp, \ + sc_q_mode, sc_o_mode, int, \ + sc_fxnum_fast_observer* = 0 ); \ + sc_ufix_fast( tp, \ + int, int, sc_q_mode, sc_o_mode, \ + sc_fxnum_fast_observer* = 0 ); \ + sc_ufix_fast( tp, \ + int, int, sc_q_mode, sc_o_mode, int, \ + sc_fxnum_fast_observer* = 0 ); \ + sc_ufix_fast( tp, \ + const sc_fxcast_switch&, \ + sc_fxnum_fast_observer* = 0 ); \ + sc_ufix_fast( tp, \ + int, int, \ + const sc_fxcast_switch&, \ + sc_fxnum_fast_observer* = 0 ); \ + sc_ufix_fast( tp, \ + sc_q_mode, sc_o_mode, \ + const sc_fxcast_switch&, \ + sc_fxnum_fast_observer* = 0 ); \ + sc_ufix_fast( tp, \ + sc_q_mode, sc_o_mode, int, \ + const sc_fxcast_switch&, \ + sc_fxnum_fast_observer* = 0 ); \ + sc_ufix_fast( tp, \ + int, int, sc_q_mode, sc_o_mode, \ + const sc_fxcast_switch&, \ + sc_fxnum_fast_observer* = 0 ); \ + sc_ufix_fast( tp, \ + int, int, sc_q_mode, sc_o_mode, int, \ + const sc_fxcast_switch&, \ + sc_fxnum_fast_observer* = 0 ); \ + sc_ufix_fast( tp, \ + const sc_fxtype_params&, \ + sc_fxnum_fast_observer* = 0 ); \ + sc_ufix_fast( tp, \ + const sc_fxtype_params&, \ + const sc_fxcast_switch&, \ + sc_fxnum_fast_observer* = 0 ); + +#define DECL_CTORS_T_A(tp) \ + sc_ufix_fast( tp, \ + sc_fxnum_fast_observer* = 0 ); \ + DECL_CTORS_T(tp) + +#define DECL_CTORS_T_B(tp) \ + explicit sc_ufix_fast( tp, \ + sc_fxnum_fast_observer* = 0 ); \ + DECL_CTORS_T(tp) + + DECL_CTORS_T_A(int) + DECL_CTORS_T_A(unsigned int) + DECL_CTORS_T_A(long) + DECL_CTORS_T_A(unsigned long) + DECL_CTORS_T_A(float) + DECL_CTORS_T_A(double) + DECL_CTORS_T_A(const char*) + DECL_CTORS_T_A(const sc_fxval&) + DECL_CTORS_T_A(const sc_fxval_fast&) + DECL_CTORS_T_A(const sc_fxnum&) + DECL_CTORS_T_A(const sc_fxnum_fast&) +#ifndef SC_FX_EXCLUDE_OTHER + DECL_CTORS_T_B(int64) + DECL_CTORS_T_B(uint64) + DECL_CTORS_T_B(const sc_int_base&) + DECL_CTORS_T_B(const sc_uint_base&) + DECL_CTORS_T_B(const sc_signed&) + DECL_CTORS_T_B(const sc_unsigned&) +#endif + +#undef DECL_CTORS_T +#undef DECL_CTORS_T_A +#undef DECL_CTORS_T_B + + // copy constructor + + sc_ufix_fast( const sc_ufix_fast& ); + + + // unary bitwise operators + + const sc_ufix_fast operator ~ () const; + + + // unary bitwise functions + + friend void b_not( sc_ufix_fast&, const sc_ufix_fast& ); + + + // binary bitwise operators + + friend const sc_ufix_fast operator & ( const sc_ufix_fast&, + const sc_ufix_fast& ); + friend const sc_ufix_fast operator ^ ( const sc_ufix_fast&, + const sc_ufix_fast& ); + friend const sc_ufix_fast operator | ( const sc_ufix_fast&, + const sc_ufix_fast& ); + + + // binary bitwise functions + + friend void b_and( sc_ufix_fast&, const sc_ufix_fast&, + const sc_ufix_fast& ); + friend void b_or ( sc_ufix_fast&, const sc_ufix_fast&, + const sc_ufix_fast& ); + friend void b_xor( sc_ufix_fast&, const sc_ufix_fast&, + const sc_ufix_fast& ); + + + // assignment operators + + sc_ufix_fast& operator = ( const sc_ufix_fast& ); + +#define DECL_ASN_OP_T(op,tp) \ + sc_ufix_fast& operator op ( tp ); + +#ifndef SC_FX_EXCLUDE_OTHER +#define DECL_ASN_OP_OTHER(op) \ + DECL_ASN_OP_T(op,int64) \ + DECL_ASN_OP_T(op,uint64) \ + DECL_ASN_OP_T(op,const sc_int_base&) \ + DECL_ASN_OP_T(op,const sc_uint_base&) \ + DECL_ASN_OP_T(op,const sc_signed&) \ + DECL_ASN_OP_T(op,const sc_unsigned&) +#else +#define DECL_ASN_OP_OTHER(op) +#endif + +#define DECL_ASN_OP(op) \ + DECL_ASN_OP_T(op,int) \ + DECL_ASN_OP_T(op,unsigned int) \ + DECL_ASN_OP_T(op,long) \ + DECL_ASN_OP_T(op,unsigned long) \ + DECL_ASN_OP_T(op,float) \ + DECL_ASN_OP_T(op,double) \ + DECL_ASN_OP_T(op,const char*) \ + DECL_ASN_OP_T(op,const sc_fxval&) \ + DECL_ASN_OP_T(op,const sc_fxval_fast&) \ + DECL_ASN_OP_T(op,const sc_fxnum&) \ + DECL_ASN_OP_T(op,const sc_fxnum_fast&) \ + DECL_ASN_OP_OTHER(op) + + DECL_ASN_OP(=) + + DECL_ASN_OP(*=) + DECL_ASN_OP(/=) + DECL_ASN_OP(+=) + DECL_ASN_OP(-=) + + DECL_ASN_OP_T(<<=,int) + DECL_ASN_OP_T(>>=,int) + + DECL_ASN_OP_T(&=,const sc_ufix&) + DECL_ASN_OP_T(&=,const sc_ufix_fast&) + DECL_ASN_OP_T(|=,const sc_ufix&) + DECL_ASN_OP_T(|=,const sc_ufix_fast&) + DECL_ASN_OP_T(^=,const sc_ufix&) + DECL_ASN_OP_T(^=,const sc_ufix_fast&) + +#undef DECL_ASN_OP_T +#undef DECL_ASN_OP_OTHER +#undef DECL_ASN_OP + + + // auto-increment and auto-decrement + + const sc_fxval_fast operator ++ ( int ); + const sc_fxval_fast operator -- ( int ); + + sc_ufix_fast& operator ++ (); + sc_ufix_fast& operator -- (); + +}; + + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + +// ---------------------------------------------------------------------------- +// CLASS : sc_ufix +// +// "Unconstrained" unsigned fixed-point class; arbitrary precision. +// ---------------------------------------------------------------------------- + +// constructors + +inline +sc_ufix::sc_ufix( sc_fxnum_observer* observer_ ) +: sc_fxnum( sc_fxtype_params(), + SC_US_, + sc_fxcast_switch(), + observer_ ) +{} + +inline +sc_ufix::sc_ufix( int wl_, int iwl_, + sc_fxnum_observer* observer_ ) +: sc_fxnum( sc_fxtype_params( wl_, iwl_ ), + SC_US_, + sc_fxcast_switch(), + observer_ ) +{} + +inline +sc_ufix::sc_ufix( sc_q_mode qm, sc_o_mode om, + sc_fxnum_observer* observer_ ) +: sc_fxnum( sc_fxtype_params( qm, om ), + SC_US_, + sc_fxcast_switch(), + observer_ ) +{} + +inline +sc_ufix::sc_ufix( sc_q_mode qm, sc_o_mode om, int nb, + sc_fxnum_observer* observer_ ) +: sc_fxnum( sc_fxtype_params( qm, om, nb ), + SC_US_, + sc_fxcast_switch(), + observer_ ) +{} + +inline +sc_ufix::sc_ufix( int wl_, int iwl_, sc_q_mode qm, sc_o_mode om, + sc_fxnum_observer* observer_ ) +: sc_fxnum( sc_fxtype_params( wl_, iwl_, qm, om ), + SC_US_, + sc_fxcast_switch(), + observer_ ) +{} + +inline +sc_ufix::sc_ufix( int wl_, int iwl_, sc_q_mode qm, sc_o_mode om, int nb, + sc_fxnum_observer* observer_ ) +: sc_fxnum( sc_fxtype_params( wl_, iwl_, qm, om, nb ), + SC_US_, + sc_fxcast_switch(), + observer_ ) +{} + +inline +sc_ufix::sc_ufix( const sc_fxcast_switch& cast_sw, + sc_fxnum_observer* observer_ ) +: sc_fxnum( sc_fxtype_params(), + SC_US_, + cast_sw, + observer_ ) +{} + +inline +sc_ufix::sc_ufix( int wl_, int iwl_, + const sc_fxcast_switch& cast_sw, + sc_fxnum_observer* observer_ ) +: sc_fxnum( sc_fxtype_params( wl_, iwl_ ), + SC_US_, + cast_sw, + observer_ ) +{} + +inline +sc_ufix::sc_ufix( sc_q_mode qm, sc_o_mode om, + const sc_fxcast_switch& cast_sw, + sc_fxnum_observer* observer_ ) +: sc_fxnum( sc_fxtype_params( qm, om ), + SC_US_, + cast_sw, + observer_ ) +{} + +inline +sc_ufix::sc_ufix( sc_q_mode qm, sc_o_mode om, int nb, + const sc_fxcast_switch& cast_sw, + sc_fxnum_observer* observer_ ) +: sc_fxnum( sc_fxtype_params( qm, om, nb ), + SC_US_, + cast_sw, + observer_ ) +{} + +inline +sc_ufix::sc_ufix( int wl_, int iwl_, sc_q_mode qm, sc_o_mode om, + const sc_fxcast_switch& cast_sw, + sc_fxnum_observer* observer_ ) +: sc_fxnum( sc_fxtype_params( wl_, iwl_, qm, om ), + SC_US_, + cast_sw, + observer_ ) +{} + +inline +sc_ufix::sc_ufix( int wl_, int iwl_, sc_q_mode qm, sc_o_mode om, int nb, + const sc_fxcast_switch& cast_sw, + sc_fxnum_observer* observer_ ) +: sc_fxnum( sc_fxtype_params( wl_, iwl_, qm, om, nb ), + SC_US_, + cast_sw, + observer_ ) +{} + +inline +sc_ufix::sc_ufix( const sc_fxtype_params& type_params, + sc_fxnum_observer* observer_ ) +: sc_fxnum( type_params, + SC_US_, + sc_fxcast_switch(), + observer_ ) +{} + +inline +sc_ufix::sc_ufix( const sc_fxtype_params& type_params, + const sc_fxcast_switch& cast_sw, + sc_fxnum_observer* observer_ ) +: sc_fxnum( type_params, + SC_US_, + cast_sw, + observer_ ) +{} + +#define DEFN_CTORS_T_A(tp) \ +inline \ +sc_ufix::sc_ufix( tp a, \ + sc_fxnum_observer* observer_ ) \ +: sc_fxnum( a, \ + sc_fxtype_params(), \ + SC_US_, \ + sc_fxcast_switch(), \ + observer_ ) \ +{} \ + \ +inline \ +sc_ufix::sc_ufix( tp a, \ + int wl_, int iwl_, \ + sc_fxnum_observer* observer_ ) \ +: sc_fxnum( a, \ + sc_fxtype_params( wl_, iwl_ ), \ + SC_US_, \ + sc_fxcast_switch(), \ + observer_ ) \ +{} \ + \ +inline \ +sc_ufix::sc_ufix( tp a, \ + sc_q_mode qm, sc_o_mode om, \ + sc_fxnum_observer* observer_ ) \ +: sc_fxnum( a, \ + sc_fxtype_params( qm, om ), \ + SC_US_, \ + sc_fxcast_switch(), \ + observer_ ) \ +{} \ + \ +inline \ +sc_ufix::sc_ufix( tp a, \ + sc_q_mode qm, sc_o_mode om, int nb, \ + sc_fxnum_observer* observer_ ) \ +: sc_fxnum( a, \ + sc_fxtype_params( qm, om, nb ), \ + SC_US_, \ + sc_fxcast_switch(), \ + observer_ ) \ +{} \ + \ +inline \ +sc_ufix::sc_ufix( tp a, \ + int wl_, int iwl_, sc_q_mode qm, sc_o_mode om, \ + sc_fxnum_observer* observer_ ) \ +: sc_fxnum( a, \ + sc_fxtype_params( wl_, iwl_, qm, om ), \ + SC_US_, \ + sc_fxcast_switch(), \ + observer_ ) \ +{} \ + \ +inline \ +sc_ufix::sc_ufix( tp a, \ + int wl_, int iwl_, sc_q_mode qm, sc_o_mode om, int nb, \ + sc_fxnum_observer* observer_ ) \ +: sc_fxnum( a, \ + sc_fxtype_params( wl_, iwl_, qm, om, nb ), \ + SC_US_, \ + sc_fxcast_switch(), \ + observer_ ) \ +{} \ + \ +inline \ +sc_ufix::sc_ufix( tp a, \ + const sc_fxcast_switch& cast_sw, \ + sc_fxnum_observer* observer_ ) \ +: sc_fxnum( a, \ + sc_fxtype_params(), \ + SC_US_, \ + cast_sw, \ + observer_ ) \ +{} \ + \ +inline \ +sc_ufix::sc_ufix( tp a, \ + int wl_, int iwl_, \ + const sc_fxcast_switch& cast_sw, \ + sc_fxnum_observer* observer_ ) \ +: sc_fxnum( a, \ + sc_fxtype_params( wl_, iwl_ ), \ + SC_US_, \ + cast_sw, \ + observer_ ) \ +{} \ + \ +inline \ +sc_ufix::sc_ufix( tp a, \ + sc_q_mode qm, sc_o_mode om, \ + const sc_fxcast_switch& cast_sw, \ + sc_fxnum_observer* observer_ ) \ +: sc_fxnum( a, \ + sc_fxtype_params( qm, om ), \ + SC_US_, \ + cast_sw, \ + observer_ ) \ +{} \ + \ +inline \ +sc_ufix::sc_ufix( tp a, \ + sc_q_mode qm, sc_o_mode om, int nb, \ + const sc_fxcast_switch& cast_sw, \ + sc_fxnum_observer* observer_ ) \ +: sc_fxnum( a, \ + sc_fxtype_params( qm, om, nb ), \ + SC_US_, \ + cast_sw, \ + observer_ ) \ +{} \ + \ +inline \ +sc_ufix::sc_ufix( tp a, \ + int wl_, int iwl_, sc_q_mode qm, sc_o_mode om, \ + const sc_fxcast_switch& cast_sw, \ + sc_fxnum_observer* observer_ ) \ +: sc_fxnum( a, \ + sc_fxtype_params( wl_, iwl_, qm, om ), \ + SC_US_, \ + cast_sw, \ + observer_ ) \ +{} \ + \ +inline \ +sc_ufix::sc_ufix( tp a, \ + int wl_, int iwl_, sc_q_mode qm, sc_o_mode om, int nb, \ + const sc_fxcast_switch& cast_sw, \ + sc_fxnum_observer* observer_ ) \ +: sc_fxnum( a, \ + sc_fxtype_params( wl_, iwl_, qm, om, nb ), \ + SC_US_, \ + cast_sw, \ + observer_ ) \ +{} \ + \ +inline \ +sc_ufix::sc_ufix( tp a, \ + const sc_fxtype_params& type_params, \ + sc_fxnum_observer* observer_ ) \ +: sc_fxnum( a, \ + type_params, \ + SC_US_, \ + sc_fxcast_switch(), \ + observer_ ) \ +{} \ + \ +inline \ +sc_ufix::sc_ufix( tp a, \ + const sc_fxtype_params& type_params, \ + const sc_fxcast_switch& cast_sw, \ + sc_fxnum_observer* observer_ ) \ +: sc_fxnum( a, \ + type_params, \ + SC_US_, \ + cast_sw, \ + observer_ ) \ +{} + +#define DEFN_CTORS_T_B(tp) \ +inline \ +sc_ufix::sc_ufix( tp a, \ + sc_fxnum_observer* observer_ ) \ +: sc_fxnum( a, \ + a.type_params(), \ + SC_US_, \ + sc_fxcast_switch(), \ + observer_ ) \ +{} \ + \ +inline \ +sc_ufix::sc_ufix( tp a, \ + int wl_, int iwl_, \ + sc_fxnum_observer* observer_ ) \ +: sc_fxnum( a, \ + sc_fxtype_params( a.type_params(), wl_, iwl_ ), \ + SC_US_, \ + sc_fxcast_switch(), \ + observer_ ) \ +{} \ + \ +inline \ +sc_ufix::sc_ufix( tp a, \ + sc_q_mode qm, sc_o_mode om, \ + sc_fxnum_observer* observer_ ) \ +: sc_fxnum( a, \ + sc_fxtype_params( a.type_params(), qm, om ), \ + SC_US_, \ + sc_fxcast_switch(), \ + observer_ ) \ +{} \ + \ +inline \ +sc_ufix::sc_ufix( tp a, \ + sc_q_mode qm, sc_o_mode om, int nb, \ + sc_fxnum_observer* observer_ ) \ +: sc_fxnum( a, \ + sc_fxtype_params( a.type_params(), qm, om, nb ), \ + SC_US_, \ + sc_fxcast_switch(), \ + observer_ ) \ +{} \ + \ +inline \ +sc_ufix::sc_ufix( tp a, \ + int wl_, int iwl_, sc_q_mode qm, sc_o_mode om, \ + sc_fxnum_observer* observer_ ) \ +: sc_fxnum( a, \ + sc_fxtype_params( wl_, iwl_, qm, om ), \ + SC_US_, \ + sc_fxcast_switch(), \ + observer_ ) \ +{} \ + \ +inline \ +sc_ufix::sc_ufix( tp a, \ + int wl_, int iwl_, sc_q_mode qm, sc_o_mode om, int nb, \ + sc_fxnum_observer* observer_ ) \ +: sc_fxnum( a, \ + sc_fxtype_params( wl_, iwl_, qm, om, nb ), \ + SC_US_, \ + sc_fxcast_switch(), \ + observer_ ) \ +{} \ + \ +inline \ +sc_ufix::sc_ufix( tp a, \ + const sc_fxcast_switch& cast_sw, \ + sc_fxnum_observer* observer_ ) \ +: sc_fxnum( a, \ + a.type_params(), \ + SC_US_, \ + cast_sw, \ + observer_ ) \ +{} \ + \ +inline \ +sc_ufix::sc_ufix( tp a, \ + int wl_, int iwl_, \ + const sc_fxcast_switch& cast_sw, \ + sc_fxnum_observer* observer_ ) \ +: sc_fxnum( a, \ + sc_fxtype_params( a.type_params(), wl_, iwl_ ), \ + SC_US_, \ + cast_sw, \ + observer_ ) \ +{} \ + \ +inline \ +sc_ufix::sc_ufix( tp a, \ + sc_q_mode qm, sc_o_mode om, \ + const sc_fxcast_switch& cast_sw, \ + sc_fxnum_observer* observer_ ) \ +: sc_fxnum( a, \ + sc_fxtype_params( a.type_params(), qm, om ), \ + SC_US_, \ + cast_sw, \ + observer_ ) \ +{} \ + \ +inline \ +sc_ufix::sc_ufix( tp a, \ + sc_q_mode qm, sc_o_mode om, int nb, \ + const sc_fxcast_switch& cast_sw, \ + sc_fxnum_observer* observer_ ) \ +: sc_fxnum( a, \ + sc_fxtype_params( a.type_params(), qm, om, nb ), \ + SC_US_, \ + cast_sw, \ + observer_ ) \ +{} \ + \ +inline \ +sc_ufix::sc_ufix( tp a, \ + int wl_, int iwl_, sc_q_mode qm, sc_o_mode om, \ + const sc_fxcast_switch& cast_sw, \ + sc_fxnum_observer* observer_ ) \ +: sc_fxnum( a, \ + sc_fxtype_params( wl_, iwl_, qm, om ), \ + SC_US_, \ + cast_sw, \ + observer_ ) \ +{} \ + \ +inline \ +sc_ufix::sc_ufix( tp a, \ + int wl_, int iwl_, sc_q_mode qm, sc_o_mode om, int nb, \ + const sc_fxcast_switch& cast_sw, \ + sc_fxnum_observer* observer_ ) \ +: sc_fxnum( a, \ + sc_fxtype_params( wl_, iwl_, qm, om, nb ), \ + SC_US_, \ + cast_sw, \ + observer_ ) \ +{} \ + \ +inline \ +sc_ufix::sc_ufix( tp a, \ + const sc_fxtype_params& type_params, \ + sc_fxnum_observer* observer_ ) \ +: sc_fxnum( a, \ + type_params, \ + SC_US_, \ + sc_fxcast_switch(), \ + observer_ ) \ +{} \ + \ +inline \ +sc_ufix::sc_ufix( tp a, \ + const sc_fxtype_params& type_params, \ + const sc_fxcast_switch& cast_sw, \ + sc_fxnum_observer* observer_ ) \ +: sc_fxnum( a, \ + type_params, \ + SC_US_, \ + cast_sw, \ + observer_ ) \ +{} + +DEFN_CTORS_T_A(int) +DEFN_CTORS_T_A(unsigned int) +DEFN_CTORS_T_A(long) +DEFN_CTORS_T_A(unsigned long) +DEFN_CTORS_T_A(float) +DEFN_CTORS_T_A(double) +DEFN_CTORS_T_A(const char*) +DEFN_CTORS_T_A(const sc_fxval&) +DEFN_CTORS_T_A(const sc_fxval_fast&) +DEFN_CTORS_T_B(const sc_fxnum&) +DEFN_CTORS_T_B(const sc_fxnum_fast&) +#ifndef SC_FX_EXCLUDE_OTHER +DEFN_CTORS_T_A(int64) +DEFN_CTORS_T_A(uint64) +DEFN_CTORS_T_A(const sc_int_base&) +DEFN_CTORS_T_A(const sc_uint_base&) +DEFN_CTORS_T_A(const sc_signed&) +DEFN_CTORS_T_A(const sc_unsigned&) +#endif + +#undef DEFN_CTORS_T_A +#undef DEFN_CTORS_T_B + +// copy constructor + +inline +sc_ufix::sc_ufix( const sc_ufix& a ) +: sc_fxnum( a, + a.type_params(), + SC_US_, + sc_fxcast_switch(), + 0 ) +{} + + +// unary bitwise operators + +inline +const sc_ufix +sc_ufix::operator ~ () const +{ + SC_FXNUM_OBSERVER_READ_( *this ) + int iwl_c = iwl(); + int wl_c = wl(); + sc_ufix c( wl_c, iwl_c ); + for( int i = iwl_c - wl_c; i < iwl_c; ++ i ) + c.set_bit( i, ! get_bit( i ) ); + return sc_ufix( c, wl_c, iwl_c ); +} + + +// unary bitwise functions + +inline +void +b_not( sc_ufix& c, const sc_ufix& a ) +{ + SC_FXNUM_OBSERVER_READ_( a ) + int iwl_c = c.iwl(); + for( int i = iwl_c - c.wl(); i < iwl_c; ++ i ) + c.set_bit( i, ! a.get_bit( i ) ); + c.cast(); + SC_FXNUM_OBSERVER_WRITE_( c ) +} + + +// binary bitwise operators + +#define DEFN_BIN_OP_T(op,op2,tp1,tp2) \ +inline \ +const sc_ufix \ +operator op ( const tp1& a, const tp2& b ) \ +{ \ + a.observer_read(); \ + b.observer_read(); \ + int iwl_a = a.iwl(); \ + int iwl_b = b.iwl(); \ + int iwl_c = sc_max( iwl_a, iwl_b ); \ + int fwl_c = sc_max( a.wl() - iwl_a, b.wl() - iwl_b ); \ + sc_ufix c( iwl_c + fwl_c, iwl_c ); \ + for( int i = -fwl_c; i < iwl_c; ++ i ) \ + c.set_bit( i, a.get_bit( i ) op2 b.get_bit( i ) ); \ + return sc_ufix( c, iwl_c + fwl_c, iwl_c ); \ +} + +DEFN_BIN_OP_T(&,&&,sc_ufix,sc_ufix) +DEFN_BIN_OP_T(&,&&,sc_ufix,sc_ufix_fast) +DEFN_BIN_OP_T(&,&&,sc_ufix_fast,sc_ufix) + +DEFN_BIN_OP_T(|,||,sc_ufix,sc_ufix) +DEFN_BIN_OP_T(|,||,sc_ufix,sc_ufix_fast) +DEFN_BIN_OP_T(|,||,sc_ufix_fast,sc_ufix) + +DEFN_BIN_OP_T(^,!=,sc_ufix,sc_ufix) +DEFN_BIN_OP_T(^,!=,sc_ufix,sc_ufix_fast) +DEFN_BIN_OP_T(^,!=,sc_ufix_fast,sc_ufix) + +#undef DEFN_BIN_OP_T + + +// binary bitwise functions + +#define DEFN_BIN_FNC_T(fnc,op2,tp1,tp2) \ +inline \ +void \ +fnc ( sc_ufix& c, const tp1& a, const tp2& b ) \ +{ \ + a.observer_read(); \ + b.observer_read(); \ + int iwl_c = c.iwl(); \ + for( int i = iwl_c - c.wl(); i < iwl_c; ++ i ) \ + c.set_bit( i, a.get_bit( i ) op2 b.get_bit( i ) ); \ + c.cast(); \ + SC_FXNUM_OBSERVER_WRITE_( c ) \ +} + +DEFN_BIN_FNC_T(b_and,&&,sc_ufix,sc_ufix) +DEFN_BIN_FNC_T(b_and,&&,sc_ufix,sc_ufix_fast) +DEFN_BIN_FNC_T(b_and,&&,sc_ufix_fast,sc_ufix) + +DEFN_BIN_FNC_T(b_or,||,sc_ufix,sc_ufix) +DEFN_BIN_FNC_T(b_or,||,sc_ufix,sc_ufix_fast) +DEFN_BIN_FNC_T(b_or,||,sc_ufix_fast,sc_ufix) + +DEFN_BIN_FNC_T(b_xor,!=,sc_ufix,sc_ufix) +DEFN_BIN_FNC_T(b_xor,!=,sc_ufix,sc_ufix_fast) +DEFN_BIN_FNC_T(b_xor,!=,sc_ufix_fast,sc_ufix) + +#undef DEFN_BIN_FNC_T + + +// assignment operators + +inline +sc_ufix& +sc_ufix::operator = ( const sc_ufix& a ) +{ + sc_fxnum::operator = ( a ); + return *this; +} + +#define DEFN_ASN_OP_T(op,tp) \ +inline \ +sc_ufix& \ +sc_ufix::operator op ( tp a ) \ +{ \ + sc_fxnum::operator op( a ); \ + return *this; \ +} + +#ifndef SC_FX_EXCLUDE_OTHER +#define DEFN_ASN_OP_OTHER(op) \ +DEFN_ASN_OP_T(op,int64) \ +DEFN_ASN_OP_T(op,uint64) \ +DEFN_ASN_OP_T(op,const sc_int_base&) \ +DEFN_ASN_OP_T(op,const sc_uint_base&) \ +DEFN_ASN_OP_T(op,const sc_signed&) \ +DEFN_ASN_OP_T(op,const sc_unsigned&) +#else +#define DEFN_ASN_OP_OTHER(op) +#endif + +#define DEFN_ASN_OP(op) \ +DEFN_ASN_OP_T(op,int) \ +DEFN_ASN_OP_T(op,unsigned int) \ +DEFN_ASN_OP_T(op,long) \ +DEFN_ASN_OP_T(op,unsigned long) \ +DEFN_ASN_OP_T(op,float) \ +DEFN_ASN_OP_T(op,double) \ +DEFN_ASN_OP_T(op,const char*) \ +DEFN_ASN_OP_T(op,const sc_fxval&) \ +DEFN_ASN_OP_T(op,const sc_fxval_fast&) \ +DEFN_ASN_OP_T(op,const sc_fxnum&) \ +DEFN_ASN_OP_T(op,const sc_fxnum_fast&) \ +DEFN_ASN_OP_OTHER(op) + +DEFN_ASN_OP(=) + +DEFN_ASN_OP(*=) +DEFN_ASN_OP(/=) +DEFN_ASN_OP(+=) +DEFN_ASN_OP(-=) + +DEFN_ASN_OP_T(<<=,int) +DEFN_ASN_OP_T(>>=,int) + +#undef DEFN_ASN_OP_T +#undef DEFN_ASN_OP_OTHER +#undef DEFN_ASN_OP + + +#define DEFN_ASN_OP_T(op,op2,tp) \ +inline \ +sc_ufix& \ +sc_ufix::operator op ( const tp& b ) \ +{ \ + SC_FXNUM_OBSERVER_READ_( *this ) \ + b.observer_read(); \ + int iwl_c = iwl(); \ + for( int i = iwl_c - wl(); i < iwl_c; ++ i ) \ + set_bit( i, get_bit( i ) op2 b.get_bit( i ) ); \ + cast(); \ + SC_FXNUM_OBSERVER_WRITE_( *this ) \ + return *this; \ +} + +DEFN_ASN_OP_T(&=,&&,sc_ufix) +DEFN_ASN_OP_T(&=,&&,sc_ufix_fast) +DEFN_ASN_OP_T(|=,||,sc_ufix) +DEFN_ASN_OP_T(|=,||,sc_ufix_fast) +DEFN_ASN_OP_T(^=,!=,sc_ufix) +DEFN_ASN_OP_T(^=,!=,sc_ufix_fast) + +#undef DEFN_ASN_OP_T + + +// auto-increment and auto-decrement + +inline +const sc_fxval +sc_ufix::operator ++ ( int ) +{ + return sc_fxval( sc_fxnum::operator ++ ( 0 ) ); +} + +inline +const sc_fxval +sc_ufix::operator -- ( int ) +{ + return sc_fxval( sc_fxnum::operator -- ( 0 ) ); +} + +inline +sc_ufix& +sc_ufix::operator ++ () +{ + sc_fxnum::operator ++ (); + return *this; +} + +inline +sc_ufix& +sc_ufix::operator -- () +{ + sc_fxnum::operator -- (); + return *this; +} + + +// ---------------------------------------------------------------------------- +// CLASS : sc_ufix_fast +// +// "Unconstrained" unsigned fixed-point class; limited precision. +// ---------------------------------------------------------------------------- + +// constructors + +inline +sc_ufix_fast::sc_ufix_fast( sc_fxnum_fast_observer* observer_ ) +: sc_fxnum_fast( sc_fxtype_params(), + SC_US_, + sc_fxcast_switch(), + observer_ ) +{} + +inline +sc_ufix_fast::sc_ufix_fast( int wl_, int iwl_, + sc_fxnum_fast_observer* observer_ ) +: sc_fxnum_fast( sc_fxtype_params( wl_, iwl_ ), + SC_US_, + sc_fxcast_switch(), + observer_ ) +{} + +inline +sc_ufix_fast::sc_ufix_fast( sc_q_mode qm, sc_o_mode om, + sc_fxnum_fast_observer* observer_ ) +: sc_fxnum_fast( sc_fxtype_params( qm, om ), + SC_US_, + sc_fxcast_switch(), + observer_ ) +{} + +inline +sc_ufix_fast::sc_ufix_fast( sc_q_mode qm, sc_o_mode om, int nb, + sc_fxnum_fast_observer* observer_ ) +: sc_fxnum_fast( sc_fxtype_params( qm, om, nb ), + SC_US_, + sc_fxcast_switch(), + observer_ ) +{} + +inline +sc_ufix_fast::sc_ufix_fast( int wl_, int iwl_, sc_q_mode qm, sc_o_mode om, + sc_fxnum_fast_observer* observer_ ) +: sc_fxnum_fast( sc_fxtype_params( wl_, iwl_, qm, om ), + SC_US_, + sc_fxcast_switch(), + observer_ ) +{} + +inline +sc_ufix_fast::sc_ufix_fast( int wl_, int iwl_, + sc_q_mode qm, sc_o_mode om, int nb, + sc_fxnum_fast_observer* observer_ ) +: sc_fxnum_fast( sc_fxtype_params( wl_, iwl_, qm, om, nb ), + SC_US_, + sc_fxcast_switch(), + observer_ ) +{} + +inline +sc_ufix_fast::sc_ufix_fast( const sc_fxcast_switch& cast_sw, + sc_fxnum_fast_observer* observer_ ) +: sc_fxnum_fast( sc_fxtype_params(), + SC_US_, + cast_sw, + observer_ ) +{} + +inline +sc_ufix_fast::sc_ufix_fast( int wl_, int iwl_, + const sc_fxcast_switch& cast_sw, + sc_fxnum_fast_observer* observer_ ) +: sc_fxnum_fast( sc_fxtype_params( wl_, iwl_ ), + SC_US_, + cast_sw, + observer_ ) +{} + +inline +sc_ufix_fast::sc_ufix_fast( sc_q_mode qm, sc_o_mode om, + const sc_fxcast_switch& cast_sw, + sc_fxnum_fast_observer* observer_ ) +: sc_fxnum_fast( sc_fxtype_params( qm, om ), + SC_US_, + cast_sw, + observer_ ) +{} + +inline +sc_ufix_fast::sc_ufix_fast( sc_q_mode qm, sc_o_mode om, int nb, + const sc_fxcast_switch& cast_sw, + sc_fxnum_fast_observer* observer_ ) +: sc_fxnum_fast( sc_fxtype_params( qm, om, nb ), + SC_US_, + cast_sw, + observer_ ) +{} + +inline +sc_ufix_fast::sc_ufix_fast( int wl_, int iwl_, sc_q_mode qm, sc_o_mode om, + const sc_fxcast_switch& cast_sw, + sc_fxnum_fast_observer* observer_ ) +: sc_fxnum_fast( sc_fxtype_params( wl_, iwl_, qm, om ), + SC_US_, + cast_sw, + observer_ ) +{} + +inline +sc_ufix_fast::sc_ufix_fast( int wl_, int iwl_, + sc_q_mode qm, sc_o_mode om, int nb, + const sc_fxcast_switch& cast_sw, + sc_fxnum_fast_observer* observer_ ) +: sc_fxnum_fast( sc_fxtype_params( wl_, iwl_, qm, om, nb ), + SC_US_, + cast_sw, + observer_ ) +{} + +inline +sc_ufix_fast::sc_ufix_fast( const sc_fxtype_params& type_params, + sc_fxnum_fast_observer* observer_ ) +: sc_fxnum_fast( type_params, + SC_US_, + sc_fxcast_switch(), + observer_ ) +{} + +inline +sc_ufix_fast::sc_ufix_fast( const sc_fxtype_params& type_params, + const sc_fxcast_switch& cast_sw, + sc_fxnum_fast_observer* observer_ ) +: sc_fxnum_fast( type_params, + SC_US_, + cast_sw, + observer_ ) +{} + +#define DEFN_CTORS_T_A(tp) \ +inline \ +sc_ufix_fast::sc_ufix_fast( tp a, \ + sc_fxnum_fast_observer* observer_ ) \ +: sc_fxnum_fast( a, \ + sc_fxtype_params(), \ + SC_US_, \ + sc_fxcast_switch(), \ + observer_ ) \ +{} \ + \ +inline \ +sc_ufix_fast::sc_ufix_fast( tp a, \ + int wl_, int iwl_, \ + sc_fxnum_fast_observer* observer_ ) \ +: sc_fxnum_fast( a, \ + sc_fxtype_params( wl_, iwl_ ), \ + SC_US_, \ + sc_fxcast_switch(), \ + observer_ ) \ +{} \ + \ +inline \ +sc_ufix_fast::sc_ufix_fast( tp a, \ + sc_q_mode qm, sc_o_mode om, \ + sc_fxnum_fast_observer* observer_ ) \ +: sc_fxnum_fast( a, \ + sc_fxtype_params( qm, om ), \ + SC_US_, \ + sc_fxcast_switch(), \ + observer_ ) \ +{} \ + \ +inline \ +sc_ufix_fast::sc_ufix_fast( tp a, \ + sc_q_mode qm, sc_o_mode om, int nb, \ + sc_fxnum_fast_observer* observer_ ) \ +: sc_fxnum_fast( a, \ + sc_fxtype_params( qm, om, nb ), \ + SC_US_, \ + sc_fxcast_switch(), \ + observer_ ) \ +{} \ + \ +inline \ +sc_ufix_fast::sc_ufix_fast( tp a, \ + int wl_, int iwl_, sc_q_mode qm, sc_o_mode om, \ + sc_fxnum_fast_observer* observer_ ) \ +: sc_fxnum_fast( a, \ + sc_fxtype_params( wl_, iwl_, qm, om ), \ + SC_US_, \ + sc_fxcast_switch(), \ + observer_ ) \ +{} \ + \ +inline \ +sc_ufix_fast::sc_ufix_fast( tp a, \ + int wl_, int iwl_, \ + sc_q_mode qm, sc_o_mode om, int nb, \ + sc_fxnum_fast_observer* observer_ ) \ +: sc_fxnum_fast( a, \ + sc_fxtype_params( wl_, iwl_, qm, om, nb ), \ + SC_US_, \ + sc_fxcast_switch(), \ + observer_ ) \ +{} \ + \ +inline \ +sc_ufix_fast::sc_ufix_fast( tp a, \ + const sc_fxcast_switch& cast_sw, \ + sc_fxnum_fast_observer* observer_ ) \ +: sc_fxnum_fast( a, \ + sc_fxtype_params(), \ + SC_US_, \ + cast_sw, \ + observer_ ) \ +{} \ + \ +inline \ +sc_ufix_fast::sc_ufix_fast( tp a, \ + int wl_, int iwl_, \ + const sc_fxcast_switch& cast_sw, \ + sc_fxnum_fast_observer* observer_ ) \ +: sc_fxnum_fast( a, \ + sc_fxtype_params( wl_, iwl_ ), \ + SC_US_, \ + cast_sw, \ + observer_ ) \ +{} \ + \ +inline \ +sc_ufix_fast::sc_ufix_fast( tp a, \ + sc_q_mode qm, sc_o_mode om, \ + const sc_fxcast_switch& cast_sw, \ + sc_fxnum_fast_observer* observer_ ) \ +: sc_fxnum_fast( a, \ + sc_fxtype_params( qm, om ), \ + SC_US_, \ + cast_sw, \ + observer_ ) \ +{} \ + \ +inline \ +sc_ufix_fast::sc_ufix_fast( tp a, \ + sc_q_mode qm, sc_o_mode om, int nb, \ + const sc_fxcast_switch& cast_sw, \ + sc_fxnum_fast_observer* observer_ ) \ +: sc_fxnum_fast( a, \ + sc_fxtype_params( qm, om, nb ), \ + SC_US_, \ + cast_sw, \ + observer_ ) \ +{} \ + \ +inline \ +sc_ufix_fast::sc_ufix_fast( tp a, \ + int wl_, int iwl_, sc_q_mode qm, sc_o_mode om, \ + const sc_fxcast_switch& cast_sw, \ + sc_fxnum_fast_observer* observer_ ) \ +: sc_fxnum_fast( a, \ + sc_fxtype_params( wl_, iwl_, qm, om ), \ + SC_US_, \ + cast_sw, \ + observer_ ) \ +{} \ + \ +inline \ +sc_ufix_fast::sc_ufix_fast( tp a, \ + int wl_, int iwl_, \ + sc_q_mode qm, sc_o_mode om, int nb, \ + const sc_fxcast_switch& cast_sw, \ + sc_fxnum_fast_observer* observer_ ) \ +: sc_fxnum_fast( a, \ + sc_fxtype_params( wl_, iwl_, qm, om, nb ), \ + SC_US_, \ + cast_sw, \ + observer_ ) \ +{} \ + \ +inline \ +sc_ufix_fast::sc_ufix_fast( tp a, \ + const sc_fxtype_params& type_params, \ + sc_fxnum_fast_observer* observer_ ) \ +: sc_fxnum_fast( a, \ + type_params, \ + SC_US_, \ + sc_fxcast_switch(), \ + observer_ ) \ +{} \ + \ +inline \ +sc_ufix_fast::sc_ufix_fast( tp a, \ + const sc_fxtype_params& type_params, \ + const sc_fxcast_switch& cast_sw, \ + sc_fxnum_fast_observer* observer_ ) \ +: sc_fxnum_fast( a, \ + type_params, \ + SC_US_, \ + cast_sw, \ + observer_ ) \ +{} + +#define DEFN_CTORS_T_B(tp) \ +inline \ +sc_ufix_fast::sc_ufix_fast( tp a, \ + sc_fxnum_fast_observer* observer_ ) \ +: sc_fxnum_fast( a, \ + a.type_params(), \ + SC_US_, \ + sc_fxcast_switch(), \ + observer_ ) \ +{} \ + \ +inline \ +sc_ufix_fast::sc_ufix_fast( tp a, \ + int wl_, int iwl_, \ + sc_fxnum_fast_observer* observer_ ) \ +: sc_fxnum_fast( a, \ + sc_fxtype_params( a.type_params(), wl_, iwl_ ), \ + SC_US_, \ + sc_fxcast_switch(), \ + observer_ ) \ +{} \ + \ +inline \ +sc_ufix_fast::sc_ufix_fast( tp a, \ + sc_q_mode qm, sc_o_mode om, \ + sc_fxnum_fast_observer* observer_ ) \ +: sc_fxnum_fast( a, \ + sc_fxtype_params( a.type_params(), qm, om ), \ + SC_US_, \ + sc_fxcast_switch(), \ + observer_ ) \ +{} \ + \ +inline \ +sc_ufix_fast::sc_ufix_fast( tp a, \ + sc_q_mode qm, sc_o_mode om, int nb, \ + sc_fxnum_fast_observer* observer_ ) \ +: sc_fxnum_fast( a, \ + sc_fxtype_params( a.type_params(), qm, om, nb ), \ + SC_US_, \ + sc_fxcast_switch(), \ + observer_ ) \ +{} \ + \ +inline \ +sc_ufix_fast::sc_ufix_fast( tp a, \ + int wl_, int iwl_, sc_q_mode qm, sc_o_mode om, \ + sc_fxnum_fast_observer* observer_ ) \ +: sc_fxnum_fast( a, \ + sc_fxtype_params( wl_, iwl_, qm, om ), \ + SC_US_, \ + sc_fxcast_switch(), \ + observer_ ) \ +{} \ + \ +inline \ +sc_ufix_fast::sc_ufix_fast( tp a, \ + int wl_, int iwl_, \ + sc_q_mode qm, sc_o_mode om, int nb, \ + sc_fxnum_fast_observer* observer_ ) \ +: sc_fxnum_fast( a, \ + sc_fxtype_params( wl_, iwl_, qm, om, nb ), \ + SC_US_, \ + sc_fxcast_switch(), \ + observer_ ) \ +{} \ + \ +inline \ +sc_ufix_fast::sc_ufix_fast( tp a, \ + const sc_fxcast_switch& cast_sw, \ + sc_fxnum_fast_observer* observer_ ) \ +: sc_fxnum_fast( a, \ + a.type_params(), \ + SC_US_, \ + cast_sw, \ + observer_ ) \ +{} \ + \ +inline \ +sc_ufix_fast::sc_ufix_fast( tp a, \ + int wl_, int iwl_, \ + const sc_fxcast_switch& cast_sw, \ + sc_fxnum_fast_observer* observer_ ) \ +: sc_fxnum_fast( a, \ + sc_fxtype_params( a.type_params(), wl_, iwl_ ), \ + SC_US_, \ + cast_sw, \ + observer_ ) \ +{} \ + \ +inline \ +sc_ufix_fast::sc_ufix_fast( tp a, \ + sc_q_mode qm, sc_o_mode om, \ + const sc_fxcast_switch& cast_sw, \ + sc_fxnum_fast_observer* observer_ ) \ +: sc_fxnum_fast( a, \ + sc_fxtype_params( a.type_params(), qm, om ), \ + SC_US_, \ + cast_sw, \ + observer_ ) \ +{} \ + \ +inline \ +sc_ufix_fast::sc_ufix_fast( tp a, \ + sc_q_mode qm, sc_o_mode om, int nb, \ + const sc_fxcast_switch& cast_sw, \ + sc_fxnum_fast_observer* observer_ ) \ +: sc_fxnum_fast( a, \ + sc_fxtype_params( a.type_params(), qm, om, nb ), \ + SC_US_, \ + cast_sw, \ + observer_ ) \ +{} \ + \ +inline \ +sc_ufix_fast::sc_ufix_fast( tp a, \ + int wl_, int iwl_, sc_q_mode qm, sc_o_mode om, \ + const sc_fxcast_switch& cast_sw, \ + sc_fxnum_fast_observer* observer_ ) \ +: sc_fxnum_fast( a, \ + sc_fxtype_params( wl_, iwl_, qm, om ), \ + SC_US_, \ + cast_sw, \ + observer_ ) \ +{} \ + \ +inline \ +sc_ufix_fast::sc_ufix_fast( tp a, \ + int wl_, int iwl_, \ + sc_q_mode qm, sc_o_mode om, int nb, \ + const sc_fxcast_switch& cast_sw, \ + sc_fxnum_fast_observer* observer_ ) \ +: sc_fxnum_fast( a, \ + sc_fxtype_params( wl_, iwl_, qm, om, nb ), \ + SC_US_, \ + cast_sw, \ + observer_ ) \ +{} \ + \ +inline \ +sc_ufix_fast::sc_ufix_fast( tp a, \ + const sc_fxtype_params& type_params, \ + sc_fxnum_fast_observer* observer_ ) \ +: sc_fxnum_fast( a, \ + type_params, \ + SC_US_, \ + sc_fxcast_switch(), \ + observer_ ) \ +{} \ + \ +inline \ +sc_ufix_fast::sc_ufix_fast( tp a, \ + const sc_fxtype_params& type_params, \ + const sc_fxcast_switch& cast_sw, \ + sc_fxnum_fast_observer* observer_ ) \ +: sc_fxnum_fast( a, \ + type_params, \ + SC_US_, \ + cast_sw, \ + observer_ ) \ +{} + +DEFN_CTORS_T_A(int) +DEFN_CTORS_T_A(unsigned int) +DEFN_CTORS_T_A(long) +DEFN_CTORS_T_A(unsigned long) +DEFN_CTORS_T_A(float) +DEFN_CTORS_T_A(double) +DEFN_CTORS_T_A(const char*) +DEFN_CTORS_T_A(const sc_fxval&) +DEFN_CTORS_T_A(const sc_fxval_fast&) +DEFN_CTORS_T_B(const sc_fxnum&) +DEFN_CTORS_T_B(const sc_fxnum_fast&) +#ifndef SC_FX_EXCLUDE_OTHER +DEFN_CTORS_T_A(int64) +DEFN_CTORS_T_A(uint64) +DEFN_CTORS_T_A(const sc_int_base&) +DEFN_CTORS_T_A(const sc_uint_base&) +DEFN_CTORS_T_A(const sc_signed&) +DEFN_CTORS_T_A(const sc_unsigned&) +#endif + +#undef DEFN_CTORS_T_A +#undef DEFN_CTORS_T_B + +// copy constructor + +inline +sc_ufix_fast::sc_ufix_fast( const sc_ufix_fast& a ) +: sc_fxnum_fast( a, + a.type_params(), + SC_US_, + sc_fxcast_switch(), + 0 ) +{} + + +// unary bitwise operators + +inline +const sc_ufix_fast +sc_ufix_fast::operator ~ () const +{ + SC_FXNUM_FAST_OBSERVER_READ_( *this ) + int iwl_c = iwl(); + int wl_c = wl(); + sc_ufix_fast c( wl_c, iwl_c ); + for( int i = iwl_c - wl_c; i < iwl_c; ++ i ) + c.set_bit( i, ! get_bit( i ) ); + return sc_ufix_fast( c, wl_c, iwl_c ); +} + + +// unary bitwise functions + +inline +void +b_not( sc_ufix_fast& c, const sc_ufix_fast& a ) +{ + SC_FXNUM_FAST_OBSERVER_READ_( a ) + int iwl_c = c.iwl(); + for( int i = iwl_c - c.wl(); i < iwl_c; ++ i ) + c.set_bit( i, ! a.get_bit( i ) ); + c.cast(); + SC_FXNUM_FAST_OBSERVER_WRITE_( c ) +} + + +// binary bitwise operators + +#define DEFN_BIN_OP_T(op,op2,tp1,tp2) \ +inline \ +const sc_ufix_fast \ +operator op ( const tp1& a, const tp2& b ) \ +{ \ + a.observer_read(); \ + b.observer_read(); \ + int iwl_a = a.iwl(); \ + int iwl_b = b.iwl(); \ + int iwl_c = sc_max( iwl_a, iwl_b ); \ + int fwl_c = sc_max( a.wl() - iwl_a, b.wl() - iwl_b ); \ + sc_ufix_fast c( iwl_c + fwl_c, iwl_c ); \ + for( int i = -fwl_c; i < iwl_c; ++ i ) \ + c.set_bit( i, a.get_bit( i ) op2 b.get_bit( i ) ); \ + return sc_ufix_fast( c, iwl_c + fwl_c, iwl_c ); \ +} + +DEFN_BIN_OP_T(&,&&,sc_ufix_fast,sc_ufix_fast) +DEFN_BIN_OP_T(|,||,sc_ufix_fast,sc_ufix_fast) +DEFN_BIN_OP_T(^,!=,sc_ufix_fast,sc_ufix_fast) + +#undef DEFN_BIN_OP_T + + +// binary bitwise functions + +#define DEFN_BIN_FNC_T(fnc,op2,tp1,tp2) \ +inline \ +void \ +fnc ( sc_ufix_fast& c, const tp1& a, const tp2& b ) \ +{ \ + a.observer_read(); \ + b.observer_read(); \ + int iwl_c = c.iwl(); \ + for( int i = iwl_c - c.wl(); i < iwl_c; ++ i ) \ + c.set_bit( i, a.get_bit( i ) op2 b.get_bit( i ) ); \ + c.cast(); \ + SC_FXNUM_FAST_OBSERVER_WRITE_( c ) \ +} + +DEFN_BIN_FNC_T(b_and,&&,sc_ufix_fast,sc_ufix_fast) +DEFN_BIN_FNC_T(b_or,||,sc_ufix_fast,sc_ufix_fast) +DEFN_BIN_FNC_T(b_xor,!=,sc_ufix_fast,sc_ufix_fast) + +#undef DEFN_BIN_FNC_T + + +// assignment operators + +inline +sc_ufix_fast& +sc_ufix_fast::operator = ( const sc_ufix_fast& a ) +{ + sc_fxnum_fast::operator = ( a ); + return *this; +} + +#define DEFN_ASN_OP_T(op,tp) \ +inline \ +sc_ufix_fast& \ +sc_ufix_fast::operator op ( tp a ) \ +{ \ + sc_fxnum_fast::operator op( a ); \ + return *this; \ +} + +#ifndef SC_FX_EXCLUDE_OTHER +#define DEFN_ASN_OP_OTHER(op) \ +DEFN_ASN_OP_T(op,int64) \ +DEFN_ASN_OP_T(op,uint64) \ +DEFN_ASN_OP_T(op,const sc_int_base&) \ +DEFN_ASN_OP_T(op,const sc_uint_base&) \ +DEFN_ASN_OP_T(op,const sc_signed&) \ +DEFN_ASN_OP_T(op,const sc_unsigned&) +#else +#define DEFN_ASN_OP_OTHER(op) +#endif + +#define DEFN_ASN_OP(op) \ +DEFN_ASN_OP_T(op,int) \ +DEFN_ASN_OP_T(op,unsigned int) \ +DEFN_ASN_OP_T(op,long) \ +DEFN_ASN_OP_T(op,unsigned long) \ +DEFN_ASN_OP_T(op,float) \ +DEFN_ASN_OP_T(op,double) \ +DEFN_ASN_OP_T(op,const char*) \ +DEFN_ASN_OP_T(op,const sc_fxval&) \ +DEFN_ASN_OP_T(op,const sc_fxval_fast&) \ +DEFN_ASN_OP_T(op,const sc_fxnum&) \ +DEFN_ASN_OP_T(op,const sc_fxnum_fast&) \ +DEFN_ASN_OP_OTHER(op) + +DEFN_ASN_OP(=) + +DEFN_ASN_OP(*=) +DEFN_ASN_OP(/=) +DEFN_ASN_OP(+=) +DEFN_ASN_OP(-=) + +DEFN_ASN_OP_T(<<=,int) +DEFN_ASN_OP_T(>>=,int) + +#undef DEFN_ASN_OP_T +#undef DEFN_ASN_OP_OTHER +#undef DEFN_ASN_OP + + +#define DEFN_ASN_OP_T(op,op2,tp) \ +inline \ +sc_ufix_fast& \ +sc_ufix_fast::operator op ( const tp& b ) \ +{ \ + SC_FXNUM_FAST_OBSERVER_READ_( *this ) \ + b.observer_read(); \ + int iwl_c = iwl(); \ + for( int i = iwl_c - wl(); i < iwl_c; ++ i ) \ + set_bit( i, get_bit( i ) op2 b.get_bit( i ) ); \ + cast(); \ + SC_FXNUM_FAST_OBSERVER_WRITE_( *this ) \ + return *this; \ +} + +DEFN_ASN_OP_T(&=,&&,sc_ufix) +DEFN_ASN_OP_T(&=,&&,sc_ufix_fast) +DEFN_ASN_OP_T(|=,||,sc_ufix) +DEFN_ASN_OP_T(|=,||,sc_ufix_fast) +DEFN_ASN_OP_T(^=,!=,sc_ufix) +DEFN_ASN_OP_T(^=,!=,sc_ufix_fast) + +#undef DEFN_ASN_OP_T + + +// auto-increment and auto-decrement + +inline +const sc_fxval_fast +sc_ufix_fast::operator ++ ( int ) +{ + return sc_fxval_fast( sc_fxnum_fast::operator ++ ( 0 ) ); +} + +inline +const sc_fxval_fast +sc_ufix_fast::operator -- ( int ) +{ + return sc_fxval_fast( sc_fxnum_fast::operator -- ( 0 ) ); +} + +inline +sc_ufix_fast& +sc_ufix_fast::operator ++ () +{ + sc_fxnum_fast::operator ++ (); + return *this; +} + +inline +sc_ufix_fast& +sc_ufix_fast::operator -- () +{ + sc_fxnum_fast::operator -- (); + return *this; +} + +} // namespace sc_dt + + +#endif + +// Taf! diff --git a/ext/systemc/src/sysc/datatypes/fx/sc_ufixed.h b/ext/systemc/src/sysc/datatypes/fx/sc_ufixed.h new file mode 100644 index 000000000..266e4b7bb --- /dev/null +++ b/ext/systemc/src/sysc/datatypes/fx/sc_ufixed.h @@ -0,0 +1,660 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_ufixed.h - + + Original Author: Martin Janssen, Synopsys, Inc. + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + +// $Log: sc_ufixed.h,v $ +// Revision 1.2 2011/01/19 18:57:40 acg +// Andy Goodrich: changes for IEEE_1666_2011. +// +// Revision 1.1.1.1 2006/12/15 20:20:04 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:53:58 acg +// Andy Goodrich: added $Log command so that CVS comments are reproduced in +// the source. +// + +#ifndef SC_UFIXED_H +#define SC_UFIXED_H + + +#include "sysc/datatypes/fx/sc_ufix.h" + + +namespace sc_dt +{ + +// classes defined in this module +template <int W, int I, sc_q_mode Q, sc_o_mode O, int N> class sc_ufixed; +template <int W, int I, sc_q_mode Q, sc_o_mode O, int N> class sc_ufixed_fast; + + +// ---------------------------------------------------------------------------- +// TEMPLATE CLASS : sc_ufixed +// +// "Constrained" unsigned fixed-point class; arbitrary precision. +// ---------------------------------------------------------------------------- + +template <int W, int I, + sc_q_mode Q = SC_DEFAULT_Q_MODE_, + sc_o_mode O = SC_DEFAULT_O_MODE_, int N = SC_DEFAULT_N_BITS_> +class sc_ufixed : public sc_ufix +{ + +public: + + // constructors + + explicit sc_ufixed( sc_fxnum_observer* = 0 ); + explicit sc_ufixed( const sc_fxcast_switch&, sc_fxnum_observer* = 0 ); + +#define DECL_CTORS_T_A(tp) \ + sc_ufixed( tp, sc_fxnum_observer* = 0 ); \ + sc_ufixed( tp, const sc_fxcast_switch&, sc_fxnum_observer* = 0 ); + +#define DECL_CTORS_T_B(tp) \ + explicit sc_ufixed( tp, sc_fxnum_observer* = 0 ); \ + sc_ufixed( tp, const sc_fxcast_switch&, sc_fxnum_observer* = 0 ); + + DECL_CTORS_T_A(int) + DECL_CTORS_T_A(unsigned int) + DECL_CTORS_T_A(long) + DECL_CTORS_T_A(unsigned long) + DECL_CTORS_T_A(float) + DECL_CTORS_T_A(double) + DECL_CTORS_T_A(const char*) + DECL_CTORS_T_A(const sc_fxval&) + DECL_CTORS_T_A(const sc_fxval_fast&) + DECL_CTORS_T_A(const sc_fxnum&) + DECL_CTORS_T_A(const sc_fxnum_fast&) +#ifndef SC_FX_EXCLUDE_OTHER + DECL_CTORS_T_B(int64) + DECL_CTORS_T_B(uint64) + DECL_CTORS_T_B(const sc_int_base&) + DECL_CTORS_T_B(const sc_uint_base&) + DECL_CTORS_T_B(const sc_signed&) + DECL_CTORS_T_B(const sc_unsigned&) +#endif + +#undef DECL_CTORS_T_A +#undef DECL_CTORS_T_B + + // copy constructor + + sc_ufixed( const sc_ufixed<W,I,Q,O,N>& ); + + + // assignment operators + + sc_ufixed& operator = ( const sc_ufixed<W,I,Q,O,N>& ); + +#define DECL_ASN_OP_T(op,tp) \ + sc_ufixed& operator op ( tp ); + +#ifndef SC_FX_EXCLUDE_OTHER +#define DECL_ASN_OP_OTHER(op) \ + DECL_ASN_OP_T(op,int64) \ + DECL_ASN_OP_T(op,uint64) \ + DECL_ASN_OP_T(op,const sc_int_base&) \ + DECL_ASN_OP_T(op,const sc_uint_base&) \ + DECL_ASN_OP_T(op,const sc_signed&) \ + DECL_ASN_OP_T(op,const sc_unsigned&) +#else +#define DECL_ASN_OP_OTHER(op) +#endif + +#define DECL_ASN_OP(op) \ + DECL_ASN_OP_T(op,int) \ + DECL_ASN_OP_T(op,unsigned int) \ + DECL_ASN_OP_T(op,long) \ + DECL_ASN_OP_T(op,unsigned long) \ + DECL_ASN_OP_T(op,float) \ + DECL_ASN_OP_T(op,double) \ + DECL_ASN_OP_T(op,const char*) \ + DECL_ASN_OP_T(op,const sc_fxval&) \ + DECL_ASN_OP_T(op,const sc_fxval_fast&) \ + DECL_ASN_OP_T(op,const sc_fxnum&) \ + DECL_ASN_OP_T(op,const sc_fxnum_fast&) \ + DECL_ASN_OP_OTHER(op) + + DECL_ASN_OP(=) + + DECL_ASN_OP(*=) + DECL_ASN_OP(/=) + DECL_ASN_OP(+=) + DECL_ASN_OP(-=) + + DECL_ASN_OP_T(<<=,int) + DECL_ASN_OP_T(>>=,int) + + DECL_ASN_OP_T(&=,const sc_ufix&) + DECL_ASN_OP_T(&=,const sc_ufix_fast&) + DECL_ASN_OP_T(|=,const sc_ufix&) + DECL_ASN_OP_T(|=,const sc_ufix_fast&) + DECL_ASN_OP_T(^=,const sc_ufix&) + DECL_ASN_OP_T(^=,const sc_ufix_fast&) + +#undef DECL_ASN_OP_T +#undef DECL_ASN_OP_OTHER +#undef DECL_ASN_OP + + + // auto-increment and auto-decrement + + const sc_fxval operator ++ ( int ); + const sc_fxval operator -- ( int ); + + sc_ufixed& operator ++ (); + sc_ufixed& operator -- (); + +}; + + +// ---------------------------------------------------------------------------- +// TEMPLATE CLASS : sc_ufixed_fast +// +// "Constrained" unsigned fixed-point class; limited precision. +// ---------------------------------------------------------------------------- + +template <int W, int I, + sc_q_mode Q = SC_DEFAULT_Q_MODE_, + sc_o_mode O = SC_DEFAULT_O_MODE_, int N = SC_DEFAULT_N_BITS_> +class sc_ufixed_fast : public sc_ufix_fast +{ + +public: + + // constructors + + explicit sc_ufixed_fast( sc_fxnum_fast_observer* = 0 ); + explicit sc_ufixed_fast( const sc_fxcast_switch&, + sc_fxnum_fast_observer* = 0 ); + +#define DECL_CTORS_T_A(tp) \ + sc_ufixed_fast( tp, sc_fxnum_fast_observer* = 0 ); \ + sc_ufixed_fast( tp, const sc_fxcast_switch&, \ + sc_fxnum_fast_observer* = 0 ); + +#define DECL_CTORS_T_B(tp) \ + explicit sc_ufixed_fast( tp, sc_fxnum_fast_observer* = 0 ); \ + sc_ufixed_fast( tp, const sc_fxcast_switch&, \ + sc_fxnum_fast_observer* = 0 ); + + DECL_CTORS_T_A(int) + DECL_CTORS_T_A(unsigned int) + DECL_CTORS_T_A(long) + DECL_CTORS_T_A(unsigned long) + DECL_CTORS_T_A(float) + DECL_CTORS_T_A(double) + DECL_CTORS_T_A(const char*) + DECL_CTORS_T_A(const sc_fxval&) + DECL_CTORS_T_A(const sc_fxval_fast&) + DECL_CTORS_T_A(const sc_fxnum&) + DECL_CTORS_T_A(const sc_fxnum_fast&) +#ifndef SC_FX_EXCLUDE_OTHER + DECL_CTORS_T_B(int64) + DECL_CTORS_T_B(uint64) + DECL_CTORS_T_B(const sc_int_base&) + DECL_CTORS_T_B(const sc_uint_base&) + DECL_CTORS_T_B(const sc_signed&) + DECL_CTORS_T_B(const sc_unsigned&) +#endif + +#undef DECL_CTORS_T_A +#undef DECL_CTORS_T_B + + // copy constructor + + sc_ufixed_fast( const sc_ufixed_fast<W,I,Q,O,N>& ); + + + // assignment operators + + sc_ufixed_fast& operator = ( const sc_ufixed_fast<W,I,Q,O,N>& ); + +#define DECL_ASN_OP_T(op,tp) \ + sc_ufixed_fast& operator op ( tp ); + +#ifndef SC_FX_EXCLUDE_OTHER +#define DECL_ASN_OP_OTHER(op) \ + DECL_ASN_OP_T(op,int64) \ + DECL_ASN_OP_T(op,uint64) \ + DECL_ASN_OP_T(op,const sc_int_base&) \ + DECL_ASN_OP_T(op,const sc_uint_base&) \ + DECL_ASN_OP_T(op,const sc_signed&) \ + DECL_ASN_OP_T(op,const sc_unsigned&) +#else +#define DECL_ASN_OP_OTHER(op) +#endif + +#define DECL_ASN_OP(op) \ + DECL_ASN_OP_T(op,int) \ + DECL_ASN_OP_T(op,unsigned int) \ + DECL_ASN_OP_T(op,long) \ + DECL_ASN_OP_T(op,unsigned long) \ + DECL_ASN_OP_T(op,float) \ + DECL_ASN_OP_T(op,double) \ + DECL_ASN_OP_T(op,const char*) \ + DECL_ASN_OP_T(op,const sc_fxval&) \ + DECL_ASN_OP_T(op,const sc_fxval_fast&) \ + DECL_ASN_OP_T(op,const sc_fxnum&) \ + DECL_ASN_OP_T(op,const sc_fxnum_fast&) \ + DECL_ASN_OP_OTHER(op) + + DECL_ASN_OP(=) + + DECL_ASN_OP(*=) + DECL_ASN_OP(/=) + DECL_ASN_OP(+=) + DECL_ASN_OP(-=) + + DECL_ASN_OP_T(<<=,int) + DECL_ASN_OP_T(>>=,int) + + DECL_ASN_OP_T(&=,const sc_ufix&) + DECL_ASN_OP_T(&=,const sc_ufix_fast&) + DECL_ASN_OP_T(|=,const sc_ufix&) + DECL_ASN_OP_T(|=,const sc_ufix_fast&) + DECL_ASN_OP_T(^=,const sc_ufix&) + DECL_ASN_OP_T(^=,const sc_ufix_fast&) + +#undef DECL_ASN_OP_T +#undef DECL_ASN_OP_OTHER +#undef DECL_ASN_OP + + + // auto-increment and auto-decrement + + const sc_fxval_fast operator ++ ( int ); + const sc_fxval_fast operator -- ( int ); + + sc_ufixed_fast& operator ++ (); + sc_ufixed_fast& operator -- (); + +}; + + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + +// ---------------------------------------------------------------------------- +// TEMPLATE CLASS : sc_ufixed +// +// "Constrained" unsigned fixed-point class; arbitrary precision. +// ---------------------------------------------------------------------------- + +template<int W, int I, sc_q_mode Q, sc_o_mode O, int N> +inline +sc_ufixed<W,I,Q,O,N>::sc_ufixed( sc_fxnum_observer* observer_ ) +: sc_ufix( W, I, Q, O, N, observer_ ) +{} + +template<int W, int I, sc_q_mode Q, sc_o_mode O, int N> +inline +sc_ufixed<W,I,Q,O,N>::sc_ufixed( const sc_fxcast_switch& cast_sw, + sc_fxnum_observer* observer_ ) +: sc_ufix( W, I, Q, O, N, cast_sw, observer_ ) +{} + +#define DEFN_CTORS_T(tp) \ +template<int W, int I, sc_q_mode Q, sc_o_mode O, int N> \ +inline \ +sc_ufixed<W,I,Q,O,N>::sc_ufixed( tp a, \ + sc_fxnum_observer* observer_ ) \ +: sc_ufix( a, W, I, Q, O, N, observer_ ) \ +{} \ + \ +template<int W, int I, sc_q_mode Q, sc_o_mode O, int N> \ +inline \ +sc_ufixed<W,I,Q,O,N>::sc_ufixed( tp a, \ + const sc_fxcast_switch& cast_sw, \ + sc_fxnum_observer* observer_ ) \ +: sc_ufix( a, W, I, Q, O, N, cast_sw, observer_ ) \ +{} + +DEFN_CTORS_T(int) +DEFN_CTORS_T(unsigned int) +DEFN_CTORS_T(long) +DEFN_CTORS_T(unsigned long) +DEFN_CTORS_T(float) +DEFN_CTORS_T(double) +DEFN_CTORS_T(const char*) +DEFN_CTORS_T(const sc_fxval&) +DEFN_CTORS_T(const sc_fxval_fast&) +DEFN_CTORS_T(const sc_fxnum&) +DEFN_CTORS_T(const sc_fxnum_fast&) +#ifndef SC_FX_EXCLUDE_OTHER +DEFN_CTORS_T(int64) +DEFN_CTORS_T(uint64) +DEFN_CTORS_T(const sc_int_base&) +DEFN_CTORS_T(const sc_uint_base&) +DEFN_CTORS_T(const sc_signed&) +DEFN_CTORS_T(const sc_unsigned&) +#endif + +#undef DEFN_CTORS_T + +// copy constructor + +template<int W, int I, sc_q_mode Q, sc_o_mode O, int N> +inline +sc_ufixed<W,I,Q,O,N>::sc_ufixed( const sc_ufixed<W,I,Q,O,N>& a ) +: sc_ufix( a, W, I, Q, O, N ) +{} + + +// assignment operators + +template<int W, int I, sc_q_mode Q, sc_o_mode O, int N> +inline +sc_ufixed<W,I,Q,O,N>& +sc_ufixed<W,I,Q,O,N>::operator = ( const sc_ufixed<W,I,Q,O,N>& a ) +{ + sc_ufix::operator = ( a ); + return *this; +} + +#define DEFN_ASN_OP_T(op,tp) \ +template<int W, int I, sc_q_mode Q, sc_o_mode O, int N> \ +inline \ +sc_ufixed<W,I,Q,O,N>& \ +sc_ufixed<W,I,Q,O,N>::operator op ( tp a ) \ +{ \ + sc_ufix::operator op ( a ); \ + return *this; \ +} + +#ifndef SC_FX_EXCLUDE_OTHER +#define DEFN_ASN_OP_OTHER(op) \ +DEFN_ASN_OP_T(op,int64) \ +DEFN_ASN_OP_T(op,uint64) \ +DEFN_ASN_OP_T(op,const sc_int_base&) \ +DEFN_ASN_OP_T(op,const sc_uint_base&) \ +DEFN_ASN_OP_T(op,const sc_signed&) \ +DEFN_ASN_OP_T(op,const sc_unsigned&) +#else +#define DEFN_ASN_OP_OTHER(op) +#endif + +#define DEFN_ASN_OP(op) \ +DEFN_ASN_OP_T(op,int) \ +DEFN_ASN_OP_T(op,unsigned int) \ +DEFN_ASN_OP_T(op,long) \ +DEFN_ASN_OP_T(op,unsigned long) \ +DEFN_ASN_OP_T(op,float) \ +DEFN_ASN_OP_T(op,double) \ +DEFN_ASN_OP_T(op,const char*) \ +DEFN_ASN_OP_T(op,const sc_fxval&) \ +DEFN_ASN_OP_T(op,const sc_fxval_fast&) \ +DEFN_ASN_OP_T(op,const sc_fxnum&) \ +DEFN_ASN_OP_T(op,const sc_fxnum_fast&) \ +DEFN_ASN_OP_OTHER(op) + +DEFN_ASN_OP(=) + +DEFN_ASN_OP(*=) +DEFN_ASN_OP(/=) +DEFN_ASN_OP(+=) +DEFN_ASN_OP(-=) + +DEFN_ASN_OP_T(<<=,int) +DEFN_ASN_OP_T(>>=,int) + +DEFN_ASN_OP_T(&=,const sc_ufix&) +DEFN_ASN_OP_T(&=,const sc_ufix_fast&) +DEFN_ASN_OP_T(|=,const sc_ufix&) +DEFN_ASN_OP_T(|=,const sc_ufix_fast&) +DEFN_ASN_OP_T(^=,const sc_ufix&) +DEFN_ASN_OP_T(^=,const sc_ufix_fast&) + +#undef DEFN_ASN_OP_T +#undef DEFN_ASN_OP_OTHER +#undef DEFN_ASN_OP + + +// auto-increment and auto-decrement + +template<int W, int I, sc_q_mode Q, sc_o_mode O, int N> +inline +const sc_fxval +sc_ufixed<W,I,Q,O,N>::operator ++ ( int ) +{ + return sc_fxval( sc_ufix::operator ++ ( 0 ) ); +} + +template<int W, int I, sc_q_mode Q, sc_o_mode O, int N> +inline +const sc_fxval +sc_ufixed<W,I,Q,O,N>::operator -- ( int ) +{ + return sc_fxval( sc_ufix::operator -- ( 0 ) ); +} + +template<int W, int I, sc_q_mode Q, sc_o_mode O, int N> +inline +sc_ufixed<W,I,Q,O,N>& +sc_ufixed<W,I,Q,O,N>::operator ++ () +{ + sc_ufix::operator ++ (); + return *this; +} + +template<int W, int I, sc_q_mode Q, sc_o_mode O, int N> +inline +sc_ufixed<W,I,Q,O,N>& +sc_ufixed<W,I,Q,O,N>::operator -- () +{ + sc_ufix::operator -- (); + return *this; +} + + +// ---------------------------------------------------------------------------- +// TEMPLATE CLASS : sc_ufixed_fast +// +// "Constrained" unsigned fixed-point class; limited precision. +// ---------------------------------------------------------------------------- + +template<int W, int I, sc_q_mode Q, sc_o_mode O, int N> +inline +sc_ufixed_fast<W,I,Q,O,N>::sc_ufixed_fast( sc_fxnum_fast_observer* observer_ ) +: sc_ufix_fast( W, I, Q, O, N, observer_ ) +{} + +template<int W, int I, sc_q_mode Q, sc_o_mode O, int N> +inline +sc_ufixed_fast<W,I,Q,O,N>::sc_ufixed_fast( const sc_fxcast_switch& cast_sw, + sc_fxnum_fast_observer* observer_ ) +: sc_ufix_fast( W, I, Q, O, N, cast_sw, observer_ ) +{} + +#define DEFN_CTORS_T(tp) \ +template<int W, int I, sc_q_mode Q, sc_o_mode O, int N> \ +inline \ +sc_ufixed_fast<W,I,Q,O,N>::sc_ufixed_fast( tp a, \ + sc_fxnum_fast_observer* observer_ )\ +: sc_ufix_fast( a, W, I, Q, O, N, observer_ ) \ +{} \ + \ +template<int W, int I, sc_q_mode Q, sc_o_mode O, int N> \ +inline \ +sc_ufixed_fast<W,I,Q,O,N>::sc_ufixed_fast( tp a, \ + const sc_fxcast_switch& cast_sw, \ + sc_fxnum_fast_observer* observer_ )\ +: sc_ufix_fast( a, W, I, Q, O, N, cast_sw, observer_ ) \ +{} + +DEFN_CTORS_T(int) +DEFN_CTORS_T(unsigned int) +DEFN_CTORS_T(long) +DEFN_CTORS_T(unsigned long) +DEFN_CTORS_T(float) +DEFN_CTORS_T(double) +DEFN_CTORS_T(const char*) +DEFN_CTORS_T(const sc_fxval&) +DEFN_CTORS_T(const sc_fxval_fast&) +DEFN_CTORS_T(const sc_fxnum&) +DEFN_CTORS_T(const sc_fxnum_fast&) +#ifndef SC_FX_EXCLUDE_OTHER +DEFN_CTORS_T(int64) +DEFN_CTORS_T(uint64) +DEFN_CTORS_T(const sc_int_base&) +DEFN_CTORS_T(const sc_uint_base&) +DEFN_CTORS_T(const sc_signed&) +DEFN_CTORS_T(const sc_unsigned&) +#endif + +#undef DEFN_CTORS_T + +// copy constructor + +template<int W, int I, sc_q_mode Q, sc_o_mode O, int N> +inline +sc_ufixed_fast<W,I,Q,O,N>::sc_ufixed_fast( const sc_ufixed_fast<W,I,Q,O,N>& a ) +: sc_ufix_fast( a, W, I, Q, O, N ) +{} + + +// assignment operators + +template<int W, int I, sc_q_mode Q, sc_o_mode O, int N> +inline +sc_ufixed_fast<W,I,Q,O,N>& +sc_ufixed_fast<W,I,Q,O,N>::operator = ( const sc_ufixed_fast<W,I,Q,O,N>& a ) +{ + sc_ufix_fast::operator = ( a ); + return *this; +} + +#define DEFN_ASN_OP_T(op,tp) \ +template<int W, int I, sc_q_mode Q, sc_o_mode O, int N> \ +inline \ +sc_ufixed_fast<W,I,Q,O,N>& \ +sc_ufixed_fast<W,I,Q,O,N>::operator op ( tp a ) \ +{ \ + sc_ufix_fast::operator op ( a ); \ + return *this; \ +} + +#ifndef SC_FX_EXCLUDE_OTHER +#define DEFN_ASN_OP_OTHER(op) \ +DEFN_ASN_OP_T(op,int64) \ +DEFN_ASN_OP_T(op,uint64) \ +DEFN_ASN_OP_T(op,const sc_int_base&) \ +DEFN_ASN_OP_T(op,const sc_uint_base&) \ +DEFN_ASN_OP_T(op,const sc_signed&) \ +DEFN_ASN_OP_T(op,const sc_unsigned&) +#else +#define DEFN_ASN_OP_OTHER(op) +#endif + +#define DEFN_ASN_OP(op) \ +DEFN_ASN_OP_T(op,int) \ +DEFN_ASN_OP_T(op,unsigned int) \ +DEFN_ASN_OP_T(op,long) \ +DEFN_ASN_OP_T(op,unsigned long) \ +DEFN_ASN_OP_T(op,float) \ +DEFN_ASN_OP_T(op,double) \ +DEFN_ASN_OP_T(op,const char*) \ +DEFN_ASN_OP_T(op,const sc_fxval&) \ +DEFN_ASN_OP_T(op,const sc_fxval_fast&) \ +DEFN_ASN_OP_T(op,const sc_fxnum&) \ +DEFN_ASN_OP_T(op,const sc_fxnum_fast&) \ +DEFN_ASN_OP_OTHER(op) + +DEFN_ASN_OP(=) + +DEFN_ASN_OP(*=) +DEFN_ASN_OP(/=) +DEFN_ASN_OP(+=) +DEFN_ASN_OP(-=) + +DEFN_ASN_OP_T(<<=,int) +DEFN_ASN_OP_T(>>=,int) + +DEFN_ASN_OP_T(&=,const sc_ufix&) +DEFN_ASN_OP_T(&=,const sc_ufix_fast&) +DEFN_ASN_OP_T(|=,const sc_ufix&) +DEFN_ASN_OP_T(|=,const sc_ufix_fast&) +DEFN_ASN_OP_T(^=,const sc_ufix&) +DEFN_ASN_OP_T(^=,const sc_ufix_fast&) + +#undef DEFN_ASN_OP_T +#undef DEFN_ASN_OP_OTHER +#undef DEFN_ASN_OP + + +// auto-increment and auto-decrement + +template<int W, int I, sc_q_mode Q, sc_o_mode O, int N> +inline +const sc_fxval_fast +sc_ufixed_fast<W,I,Q,O,N>::operator ++ ( int ) +{ + return sc_fxval_fast( sc_ufix_fast::operator ++ ( 0 ) ); +} + +template<int W, int I, sc_q_mode Q, sc_o_mode O, int N> +inline +const sc_fxval_fast +sc_ufixed_fast<W,I,Q,O,N>::operator -- ( int ) +{ + return sc_fxval_fast( sc_ufix_fast::operator -- ( 0 ) ); +} + +template<int W, int I, sc_q_mode Q, sc_o_mode O, int N> +inline +sc_ufixed_fast<W,I,Q,O,N>& +sc_ufixed_fast<W,I,Q,O,N>::operator ++ () +{ + sc_ufix_fast::operator ++ (); + return *this; +} + +template<int W, int I, sc_q_mode Q, sc_o_mode O, int N> +inline +sc_ufixed_fast<W,I,Q,O,N>& +sc_ufixed_fast<W,I,Q,O,N>::operator -- () +{ + sc_ufix_fast::operator -- (); + return *this; +} + +} // namespace sc_dt + + +#endif + +// Taf! diff --git a/ext/systemc/src/sysc/datatypes/fx/scfx_ieee.h b/ext/systemc/src/sysc/datatypes/fx/scfx_ieee.h new file mode 100644 index 000000000..b2da95432 --- /dev/null +++ b/ext/systemc/src/sysc/datatypes/fx/scfx_ieee.h @@ -0,0 +1,701 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + scfx_ieee.h - + + Original Author: Martin Janssen, Synopsys, Inc. + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + +// $Log: scfx_ieee.h,v $ +// Revision 1.3 2011/08/24 22:05:43 acg +// Torsten Maehne: initialization changes to remove warnings. +// +// Revision 1.2 2011/08/07 18:55:24 acg +// Philipp A. Hartmann: added guard for __clang__ to get the clang platform +// working. +// +// Revision 1.1.1.1 2006/12/15 20:20:04 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:53:58 acg +// Andy Goodrich: added $Log command so that CVS comments are reproduced in +// the source. +// + +#ifndef SCFX_IEEE_H +#define SCFX_IEEE_H + + +#include "sysc/datatypes/fx/sc_fxdefs.h" + + +namespace sc_dt +{ + +// classes defined in this module +union ieee_double; +class scfx_ieee_double; +union ieee_float; +class scfx_ieee_float; + +#define SCFX_MASK_(Size) \ + ((1u << (Size))-1u) + +// ---------------------------------------------------------------------------- +// UNION : ieee_double +// +// IEEE 754 double-precision format. +// ---------------------------------------------------------------------------- + +union ieee_double +{ + + double d; + + struct + { +#if defined( SC_BIG_ENDIAN ) + unsigned negative:1; + unsigned exponent:11; + unsigned mantissa0:20; + unsigned mantissa1:32; +#elif defined( SC_LITTLE_ENDIAN ) + unsigned mantissa1:32; + unsigned mantissa0:20; + unsigned exponent:11; + unsigned negative:1; +#endif + } s; + +}; + + +const unsigned int SCFX_IEEE_DOUBLE_BIAS = 1023U; + +const int SCFX_IEEE_DOUBLE_E_MAX = 1023; +const int SCFX_IEEE_DOUBLE_E_MIN = -1022; + +const unsigned int SCFX_IEEE_DOUBLE_M_SIZE = 52; +const unsigned int SCFX_IEEE_DOUBLE_M0_SIZE = 20; +const unsigned int SCFX_IEEE_DOUBLE_M1_SIZE = 32; +const unsigned int SCFX_IEEE_DOUBLE_E_SIZE = 11; + + + +// ---------------------------------------------------------------------------- +// CLASS : scfx_ieee_double +// +// Convenient interface to union ieee_double. +// ---------------------------------------------------------------------------- + +class scfx_ieee_double +{ + + ieee_double m_id; + +public: + + scfx_ieee_double(); + scfx_ieee_double( double ); + scfx_ieee_double( const scfx_ieee_double& ); + + scfx_ieee_double& operator = ( double ); + scfx_ieee_double& operator = ( const scfx_ieee_double& ); + + operator double() const; + + unsigned int negative() const; + void negative( unsigned int ); + int exponent() const; + void exponent( int ); + unsigned int mantissa0() const; + void mantissa0( unsigned int ); + unsigned int mantissa1() const; + void mantissa1( unsigned int ); + + bool is_zero() const; + bool is_subnormal() const; + bool is_normal() const; + bool is_inf() const; + bool is_nan() const; + + void set_inf(); + void set_nan(); + + int msb() const; // most significant non-zero bit + int lsb() const; // least significant non-zero bit + + static const scfx_ieee_double nan(); + static const scfx_ieee_double inf( int ); + +}; + + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + +inline +scfx_ieee_double::scfx_ieee_double() : m_id() +{ + m_id.d = 0.0; +} + +inline +scfx_ieee_double::scfx_ieee_double( double d ) : m_id() +{ + m_id.d = d; +} + +inline +scfx_ieee_double::scfx_ieee_double( const scfx_ieee_double& a ) : m_id(a.m_id) +{ + // m_id.d = a.m_id.d; +} + + +inline +scfx_ieee_double& +scfx_ieee_double::operator = ( double d ) +{ + m_id.d = d; + return *this; +} + +inline +scfx_ieee_double& +scfx_ieee_double::operator = ( const scfx_ieee_double& a ) +{ + m_id.d = a.m_id.d; + return *this; +} + + +inline +scfx_ieee_double::operator double() const +{ + return m_id.d; +} + + +inline +unsigned int +scfx_ieee_double::negative() const +{ + return m_id.s.negative; +} + +inline +void +scfx_ieee_double::negative( unsigned int a ) +{ + m_id.s.negative = a & SCFX_MASK_(1); +} + +inline +int +scfx_ieee_double::exponent() const +{ + return m_id.s.exponent - SCFX_IEEE_DOUBLE_BIAS; +} + +inline +void +scfx_ieee_double::exponent( int a ) +{ + m_id.s.exponent = (SCFX_IEEE_DOUBLE_BIAS + a) + & SCFX_MASK_(SCFX_IEEE_DOUBLE_E_SIZE); +} + +inline +unsigned int +scfx_ieee_double::mantissa0() const +{ + return m_id.s.mantissa0; +} + +inline +void +scfx_ieee_double::mantissa0( unsigned int a ) +{ + m_id.s.mantissa0 = a & SCFX_MASK_(SCFX_IEEE_DOUBLE_M0_SIZE); +} + +inline +unsigned int +scfx_ieee_double::mantissa1() const +{ + return m_id.s.mantissa1; +} + +inline +void +scfx_ieee_double::mantissa1( unsigned int a ) +{ + m_id.s.mantissa1 = a; // & SCFX_MASK_(SCFX_IEEE_DOUBLE_M1_SIZE); +} + + +inline +bool +scfx_ieee_double::is_zero() const +{ + return ( exponent() == SCFX_IEEE_DOUBLE_E_MIN - 1 && + mantissa0() == 0U && mantissa1() == 0U ); +} + +inline +bool +scfx_ieee_double::is_subnormal() const +{ + return ( exponent() == SCFX_IEEE_DOUBLE_E_MIN - 1 && + ( mantissa0() != 0U || mantissa1() != 0U ) ); +} + +inline +bool +scfx_ieee_double::is_normal() const +{ + return ( exponent() >= SCFX_IEEE_DOUBLE_E_MIN && + exponent() <= SCFX_IEEE_DOUBLE_E_MAX ); +} + +inline +bool +scfx_ieee_double::is_inf() const +{ + return ( exponent() == SCFX_IEEE_DOUBLE_E_MAX + 1 && + mantissa0() == 0U && mantissa1() == 0U ); +} + +inline +bool +scfx_ieee_double::is_nan() const +{ + return ( exponent() == SCFX_IEEE_DOUBLE_E_MAX + 1 && + ( mantissa0() != 0U || mantissa1() != 0U ) ); +} + + +inline +void +scfx_ieee_double::set_inf() +{ + exponent( SCFX_IEEE_DOUBLE_E_MAX + 1 ); + mantissa0( 0U ); + mantissa1( 0U ); +} + +inline +void +scfx_ieee_double::set_nan() +{ + exponent( SCFX_IEEE_DOUBLE_E_MAX + 1 ); + mantissa0( (unsigned int) -1 ); + mantissa1( (unsigned int) -1 ); +} + + +#define MSB_STATEMENT(x,n) if( x >> n ) { x >>= n; i += n; } + +inline +int +scfx_ieee_double::msb() const +{ + unsigned int m0 = mantissa0(); + unsigned int m1 = mantissa1(); + if( m0 != 0 ) + { + int i = 0; + MSB_STATEMENT(m0,16); + MSB_STATEMENT(m0,8); + MSB_STATEMENT(m0,4); + MSB_STATEMENT(m0,2); + MSB_STATEMENT(m0,1); + return ( i - 20 ); + } + else if( m1 != 0 ) + { + int i = 0; + MSB_STATEMENT(m1,16); + MSB_STATEMENT(m1,8); + MSB_STATEMENT(m1,4); + MSB_STATEMENT(m1,2); + MSB_STATEMENT(m1,1); + return ( i - 52 ); + } + else + { + return 0; + } +} + +#undef MSB_STATEMENT + +#define LSB_STATEMENT(x,n) if( x << n ) { x <<= n; i -= n; } + +inline +int +scfx_ieee_double::lsb() const +{ + unsigned int m0 = mantissa0(); + unsigned int m1 = mantissa1(); + if( m1 != 0 ) + { + int i = 31; + LSB_STATEMENT(m1,16); + LSB_STATEMENT(m1,8); + LSB_STATEMENT(m1,4); + LSB_STATEMENT(m1,2); + LSB_STATEMENT(m1,1); + return ( i - 52 ); + } + else if( m0 != 0 ) + { + int i = 31; + LSB_STATEMENT(m0,16); + LSB_STATEMENT(m0,8); + LSB_STATEMENT(m0,4); + LSB_STATEMENT(m0,2); + LSB_STATEMENT(m0,1); + return ( i - 20 ); + } + else + { + return 0; + } +} + +#undef LSB_STATEMENT + + +inline +const scfx_ieee_double +scfx_ieee_double::nan() +{ + scfx_ieee_double id; + id.set_nan(); + return id; +} + +inline +const scfx_ieee_double +scfx_ieee_double::inf( int sign ) +{ + scfx_ieee_double id( sign ); + id.set_inf(); + return id; +} + + +// ---------------------------------------------------------------------------- +// UNION : ieee_float +// +// IEEE 754 single-precision format. +// ---------------------------------------------------------------------------- + +union ieee_float +{ + + float f; + + struct + { +#if defined( SC_BIG_ENDIAN ) + unsigned negative:1; + unsigned exponent:8; + unsigned mantissa:23; +#elif defined( SC_LITTLE_ENDIAN ) + unsigned mantissa:23; + unsigned exponent:8; + unsigned negative:1; +#endif + } s; + +}; + + +const unsigned int SCFX_IEEE_FLOAT_BIAS = 127U; + +const int SCFX_IEEE_FLOAT_E_MAX = 127; +const int SCFX_IEEE_FLOAT_E_MIN = -126; + +const unsigned int SCFX_IEEE_FLOAT_M_SIZE = 23; +const unsigned int SCFX_IEEE_FLOAT_E_SIZE = 8; + + +// ---------------------------------------------------------------------------- +// CLASS : scfx_ieee_float +// +// Convenient wrapper to union ieee_float. +// ---------------------------------------------------------------------------- + +class scfx_ieee_float +{ + + ieee_float m_if; + +public: + + scfx_ieee_float(); + scfx_ieee_float( float ); + scfx_ieee_float( const scfx_ieee_float& ); + + scfx_ieee_float& operator = ( float ); + scfx_ieee_float& operator = ( const scfx_ieee_float& ); + + operator float() const; + + unsigned int negative() const; + void negative( unsigned int ); + int exponent() const; + void exponent( int ); + unsigned int mantissa() const; + void mantissa( unsigned int ); + + bool is_zero() const; + bool is_subnormal() const; + bool is_normal() const; + bool is_inf() const; + bool is_nan() const; + + void set_inf(); + void set_nan(); + +}; + + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + +inline +scfx_ieee_float::scfx_ieee_float() : m_if() +{ + m_if.f = 0.0; +} + +inline +scfx_ieee_float::scfx_ieee_float( float f ) : m_if() +{ + m_if.f = f; +} + +inline +scfx_ieee_float::scfx_ieee_float( const scfx_ieee_float& a ) : m_if(a.m_if) +{ + // m_if.f = a.m_if.f; +} + + +inline +scfx_ieee_float& +scfx_ieee_float::operator = ( float f ) +{ + m_if.f = f; + return *this; +} + +inline +scfx_ieee_float& +scfx_ieee_float::operator = ( const scfx_ieee_float& a ) +{ + m_if.f = a.m_if.f; + return *this; +} + + +inline +scfx_ieee_float::operator float() const +{ + return m_if.f; +} + + +inline +unsigned int +scfx_ieee_float::negative() const +{ + return m_if.s.negative; +} + +inline +void +scfx_ieee_float::negative( unsigned int a ) +{ + m_if.s.negative = a & SCFX_MASK_(1); +} + +inline +int +scfx_ieee_float::exponent() const +{ + return m_if.s.exponent - SCFX_IEEE_FLOAT_BIAS; +} + +inline +void +scfx_ieee_float::exponent( int a ) +{ + m_if.s.exponent = (SCFX_IEEE_FLOAT_BIAS + a) + & SCFX_MASK_(SCFX_IEEE_FLOAT_E_SIZE); +} + +inline +unsigned int +scfx_ieee_float::mantissa() const +{ + return m_if.s.mantissa; +} + +inline +void +scfx_ieee_float::mantissa( unsigned int a ) +{ + m_if.s.mantissa = a & SCFX_MASK_(SCFX_IEEE_FLOAT_M_SIZE); +} + + +inline +bool +scfx_ieee_float::is_zero() const +{ + return ( exponent() == SCFX_IEEE_FLOAT_E_MIN - 1 && mantissa() == 0U ); +} + +inline +bool +scfx_ieee_float::is_subnormal() const +{ + return ( exponent() == SCFX_IEEE_FLOAT_E_MIN - 1 && mantissa() != 0U ); +} + +inline +bool +scfx_ieee_float::is_normal() const +{ + return ( exponent() >= SCFX_IEEE_FLOAT_E_MIN && + exponent() <= SCFX_IEEE_FLOAT_E_MAX ); +} + +inline +bool +scfx_ieee_float::is_inf() const +{ + return ( exponent() == SCFX_IEEE_FLOAT_E_MAX + 1 && mantissa() == 0U ); +} + +inline +bool +scfx_ieee_float::is_nan() const +{ + return ( exponent() == SCFX_IEEE_FLOAT_E_MAX + 1 && mantissa() != 0U ); +} + + +inline +void +scfx_ieee_float::set_inf() +{ + exponent( SCFX_IEEE_FLOAT_E_MAX + 1 ); + mantissa( 0U ); +} + +inline +void +scfx_ieee_float::set_nan() +{ + exponent( SCFX_IEEE_FLOAT_E_MAX + 1 ); + mantissa( (unsigned int) -1 ); +} + + +// ---------------------------------------------------------------------------- +// FUNCTION : scfx_pow2 +// +// Computes 2.0**exp in double-precision. +// ---------------------------------------------------------------------------- + +inline +double scfx_pow2( int exp ) +{ + scfx_ieee_double r; + if( exp < SCFX_IEEE_DOUBLE_E_MIN ) + { + r = 0.0; + // handle subnormal case + exp -= SCFX_IEEE_DOUBLE_E_MIN; + if( ( exp += 20 ) >= 0 ) + { + r.mantissa0( 1U << exp ); + } + else if( ( exp += 32 ) >= 0 ) + { + r.mantissa1( 1U << exp ); + } + } + else if( exp > SCFX_IEEE_DOUBLE_E_MAX ) + { + r.set_inf(); + } + else + { + r = 1.0; + r.exponent( exp ); + } + return r; +} + + +// ---------------------------------------------------------------------------- +// FUNCTION : uint64_to_double +// +// Platform independent conversion from double uint64 to double. +// Needed because VC++6 doesn't support this conversion. +// ---------------------------------------------------------------------------- + +inline +double +uint64_to_double( uint64 a ) +{ +#if defined( _MSC_VER ) || defined( __clang__ ) + // conversion from uint64 to double not implemented; use int64 + double tmp = static_cast<double>( static_cast<int64>( a ) ); + return ( tmp >= 0 ) ? tmp : tmp + sc_dt::scfx_pow2( 64 ); +#else + return static_cast<double>( a ); +#endif +} + +} // namespace sc_dt + +#undef SCFX_MASK_ + +#endif + +// Taf! diff --git a/ext/systemc/src/sysc/datatypes/fx/scfx_mant.cpp b/ext/systemc/src/sysc/datatypes/fx/scfx_mant.cpp new file mode 100644 index 000000000..fc29764f6 --- /dev/null +++ b/ext/systemc/src/sysc/datatypes/fx/scfx_mant.cpp @@ -0,0 +1,125 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + scfx_mant.cpp - + + Original Author: Robert Graulich, Synopsys, Inc. + Martin Janssen, Synopsys, Inc. + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + + +// $Log: scfx_mant.cpp,v $ +// Revision 1.1.1.1 2006/12/15 20:20:04 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:53:58 acg +// Andy Goodrich: added $Log command so that CVS comments are reproduced in +// the source. +// + +#include "sysc/datatypes/fx/scfx_mant.h" + + +namespace sc_dt +{ + +// ---------------------------------------------------------------------------- +// word memory management +// ---------------------------------------------------------------------------- + +class word_list { // Entry in free_words bucket. + public: + word_list* m_next_p; +}; + +static inline +int +next_pow2_index( std::size_t size ) +{ + int index = scfx_find_msb( size ); + // If this was a power of 2 we are one bucket too low. + if( ~ (1 << index) & size ) index ++; + // If this is a 64-bit machine and we are using 32-bit words go down + // one slot size, as all the slots are 2x in size. + if ( index != 0 && ( sizeof(word_list) != sizeof(word) ) ) + { + index -= 1; + } + return index; +} + +static word_list* free_words[32] = { 0 }; + +word* +scfx_mant::alloc_word( std::size_t size ) +{ + const int ALLOC_SIZE = 128; + + int slot_index = next_pow2_index( size ); + + int alloc_size = ( 1 << slot_index ); + + word_list*& slot = free_words[slot_index]; + + if( ! slot ) + { + slot = new word_list[ALLOC_SIZE * alloc_size]; + int i; + for( i = 0; i < alloc_size*(ALLOC_SIZE-1) ; i+=alloc_size ) + { + slot[i].m_next_p = &slot[i+alloc_size]; + } + slot[i].m_next_p = 0; + } + + word* result = (word*)slot; + free_words[slot_index] = slot[0].m_next_p; + return result; +} + +void +scfx_mant::free_word( word* array, std::size_t size ) +{ + if( array && size ) + { + int slot_index = next_pow2_index( size ); + word_list* wl_p = (word_list*)array; + + wl_p->m_next_p = free_words[slot_index]; + free_words[slot_index] = wl_p; + } +} + +} // namespace sc_dt + + +// Taf! diff --git a/ext/systemc/src/sysc/datatypes/fx/scfx_mant.h b/ext/systemc/src/sysc/datatypes/fx/scfx_mant.h new file mode 100644 index 000000000..84d9b0bd8 --- /dev/null +++ b/ext/systemc/src/sysc/datatypes/fx/scfx_mant.h @@ -0,0 +1,490 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + scfx_mant.h - + + Original Author: Robert Graulich, Synopsys, Inc. + Martin Janssen, Synopsys, Inc. + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + +// $Log: scfx_mant.h,v $ +// Revision 1.2 2011/08/24 22:05:43 acg +// Torsten Maehne: initialization changes to remove warnings. +// +// Revision 1.1.1.1 2006/12/15 20:20:04 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:53:58 acg +// Andy Goodrich: added $Log command so that CVS comments are reproduced in +// the source. +// + +#ifndef SCFX_MANT_H +#define SCFX_MANT_H + + +#include "sysc/datatypes/fx/scfx_ieee.h" +#include "sysc/datatypes/fx/scfx_utils.h" +#include "sysc/kernel/sc_macros.h" + + +namespace sc_dt +{ + +// classes defined in this module +class scfx_mant; +class scfx_mant_ref; + + +typedef unsigned int word; // Using int because of 64-bit machines. +typedef unsigned short half_word; + + +// ---------------------------------------------------------------------------- +// CLASS : scfx_mant +// +// Mantissa class. +// ---------------------------------------------------------------------------- + +class scfx_mant +{ + + word* m_array; + int m_size; + +public: + + explicit scfx_mant( std::size_t ); + scfx_mant( const scfx_mant& ); + + scfx_mant& operator = ( const scfx_mant& ); + + ~scfx_mant(); + + void clear(); + + void resize_to( int, int = 0 ); + + int size() const; + + word operator [] ( int ) const; + word& operator [] ( int ); + + half_word half_at( int ) const; + half_word& half_at( int ); + + half_word* half_addr( int = 0 ) const; + +private: + + static word* alloc( std::size_t ); + static void free( word*, std::size_t ); + + static word* alloc_word( std::size_t size ); + static void free_word( word* array, std::size_t size ); + +}; + + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + +inline +int +scfx_mant::size() const +{ + return m_size; +} + + +inline +word* +scfx_mant::alloc( std::size_t size ) +{ +#if defined( SC_BIG_ENDIAN ) + return alloc_word( size ) + ( size - 1 ); +#elif defined( SC_LITTLE_ENDIAN ) + return alloc_word( size ); +#endif +} + +inline +void +scfx_mant::free( word* mant, std::size_t size ) +{ +#if defined( SC_BIG_ENDIAN ) + free_word( mant - ( size - 1 ), size ); +#elif defined( SC_LITTLE_ENDIAN ) + free_word( mant, size ); +#endif +} + +inline +word +scfx_mant::operator[]( int i ) const +{ + SC_ASSERT_( i >= 0 && i < m_size, "mantissa index out of range" ); +#if defined( SC_BIG_ENDIAN ) + return m_array[-i]; +#elif defined( SC_LITTLE_ENDIAN ) + return m_array[i]; +#endif +} + +inline +word& +scfx_mant::operator[]( int i ) +{ + SC_ASSERT_( i >= 0 && i < m_size, "mantissa index out of range" ); +#if defined( SC_BIG_ENDIAN ) + return m_array[-i]; +#elif defined( SC_LITTLE_ENDIAN ) + return m_array[i]; +#endif +} + +inline +scfx_mant::scfx_mant( std::size_t size ) +: m_array(0), m_size(size) +{ + m_array = alloc( size ); +} + +inline +scfx_mant::scfx_mant( const scfx_mant& rhs ) +: m_array(0), m_size(rhs.m_size) +{ + m_array = alloc( m_size ); + for( int i = 0; i < m_size; i ++ ) + { + (*this)[i] = rhs[i]; + } +} + +inline +scfx_mant& +scfx_mant::operator = ( const scfx_mant& rhs ) +{ + if( &rhs != this ) + { + if( m_size != rhs.m_size ) + { + free( m_array, m_size ); + m_array = alloc( m_size = rhs.m_size ); + } + + for( int i = 0; i < m_size; i ++ ) + { + (*this)[i] = rhs[i]; + } + } + return *this; +} + +inline +scfx_mant::~scfx_mant() +{ + if( m_array != 0 ) + { + free( m_array, m_size ); + } +} + +inline +void +scfx_mant::clear() +{ + for( int i = 0; i < m_size; i ++ ) + { + (*this)[i] = 0; + } +} + +inline +void +scfx_mant::resize_to( int size, int restore ) +{ + if( size == m_size ) + { + return; + } + + if( ! m_array ) + { + m_array = alloc( m_size = size ); + } + else + { + word* p = alloc( size ); + + if( restore ) + { + int end = sc_min( size, m_size ); + if( restore == 1 ) // msb resized -> align at 0 + { + for( int i = 0; i < size; i ++ ) + { + if( i < end ) + { +#if defined( SC_BIG_ENDIAN ) + p[-i] = m_array[-i]; +#elif defined( SC_LITTLE_ENDIAN ) + p[i] = m_array[i]; +#endif + } + else + { +#if defined( SC_BIG_ENDIAN ) + p[-i] = 0; +#elif defined( SC_LITTLE_ENDIAN ) + p[i] = 0; +#endif + } + } + } + else // lsb resized -> align at size-1 + { + for( int i = 0; i < size; i ++ ) + { + if( i < end ) + { +#if defined( SC_BIG_ENDIAN ) + p[-size+1+i] = m_array[-m_size+1+i]; +#elif defined( SC_LITTLE_ENDIAN ) + p[size-1-i] = m_array[m_size-1-i]; +#endif + } + else + { +#if defined( SC_BIG_ENDIAN ) + p[-size+1+i] = 0; +#elif defined( SC_LITTLE_ENDIAN ) + p[size-1-i] = 0; +#endif + } + } + } + } + + free( m_array, m_size ); + m_array = p; + m_size = size; + } +} + +inline +half_word +scfx_mant::half_at( int i ) const +{ + SC_ASSERT_( ( i >> 1 ) >= 0 && ( i >> 1 ) < m_size, + "mantissa index out of range" ); +#if defined( SC_BIG_ENDIAN ) + return reinterpret_cast<half_word*>( m_array )[-i]; +#elif defined( SC_LITTLE_ENDIAN ) + return reinterpret_cast<half_word*>( m_array )[i]; +#endif +} + +inline +half_word& +scfx_mant::half_at( int i ) +{ + SC_ASSERT_( ( i >> 1 ) >= 0 && ( i >> 1 ) < m_size, + "mantissa index out of range" ); +#if defined( SC_BIG_ENDIAN ) + return reinterpret_cast<half_word*>( m_array )[-i]; +#elif defined( SC_LITTLE_ENDIAN ) + return reinterpret_cast<half_word*>( m_array )[i]; +#endif +} + +inline +half_word* +scfx_mant::half_addr( int i ) const +{ + SC_ASSERT_( i >= 0 && i < m_size, "mantissa index out of range" ); +#if defined( SC_BIG_ENDIAN ) + return reinterpret_cast<half_word*>( m_array - i ) + 1; +#elif defined( SC_LITTLE_ENDIAN ) + return reinterpret_cast<half_word*>( m_array + i ); +#endif +} + + +// ---------------------------------------------------------------------------- +// one's complement of a mantissa +// ---------------------------------------------------------------------------- + +inline +void +complement( scfx_mant& target, const scfx_mant& source, int size ) +{ + for( int i = 0; i < size; i ++ ) + { + target[i] = ~source[i]; + } +} + + +// ---------------------------------------------------------------------------- +// increment mantissa +// ---------------------------------------------------------------------------- + +inline +void +inc( scfx_mant& mant ) +{ + for( int i = 0; i < mant.size(); i ++ ) + { + if( ++ mant[i] ) + { + break; + } + } +} + + +// ---------------------------------------------------------------------------- +// CLASS : scfx_mant_ref +// +// Mantissa reference class. +// ---------------------------------------------------------------------------- + +class scfx_mant_ref +{ + + scfx_mant* m_mant; + bool m_not_const; + +public: + + scfx_mant_ref(); + scfx_mant_ref( const scfx_mant& ); + scfx_mant_ref( scfx_mant* ); + + scfx_mant_ref& operator = ( const scfx_mant& ); + scfx_mant_ref& operator = ( scfx_mant* ); + + ~scfx_mant_ref(); + + operator scfx_mant&(); + + word operator [] ( int ); + +private: + + void remove_it(); + + scfx_mant_ref( const scfx_mant_ref& ); + scfx_mant_ref& operator = ( const scfx_mant_ref& ); + + void* operator new( std::size_t sz ) { return ::operator new( sz ); } + +}; + + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + +inline +void +scfx_mant_ref::remove_it() +{ + if( m_not_const ) + { + delete m_mant; + } +} + +inline +scfx_mant_ref::scfx_mant_ref() +: m_mant( 0 ), m_not_const( false ) +{} + +inline +scfx_mant_ref::scfx_mant_ref( const scfx_mant& mant ) +: m_mant( const_cast<scfx_mant*>( &mant ) ), m_not_const( false ) +{} + +inline +scfx_mant_ref::scfx_mant_ref( scfx_mant* mant ) +: m_mant( mant ), m_not_const( true ) +{} + +inline +scfx_mant_ref& +scfx_mant_ref::operator = ( const scfx_mant& mant ) +{ + remove_it(); + + m_mant = const_cast<scfx_mant*>( &mant ); + m_not_const = false; + + return *this; +} + +inline +scfx_mant_ref& +scfx_mant_ref::operator = ( scfx_mant* mant ) +{ + remove_it(); + + m_mant = mant; + m_not_const = true; + + return *this; +} + +inline +scfx_mant_ref::~scfx_mant_ref() +{ + remove_it(); +} + +inline +scfx_mant_ref::operator scfx_mant&() +{ + // SC_ASSERT_( m_not_const, "not allowed to modify mant" ); + return *m_mant; +} + +inline +word +scfx_mant_ref::operator [] ( int i ) +{ + return (*m_mant)[i]; +} + +} // namespace sc_dt + + +#endif + +// Taf! diff --git a/ext/systemc/src/sysc/datatypes/fx/scfx_other_defs.h b/ext/systemc/src/sysc/datatypes/fx/scfx_other_defs.h new file mode 100644 index 000000000..a52d74b6b --- /dev/null +++ b/ext/systemc/src/sysc/datatypes/fx/scfx_other_defs.h @@ -0,0 +1,433 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + scfx_other_defs.h - + + Original Author: Martin Janssen, Synopsys, Inc. + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + +// $Log: scfx_other_defs.h,v $ +// Revision 1.1.1.1 2006/12/15 20:20:04 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:53:58 acg +// Andy Goodrich: added $Log command so that CVS comments are reproduced in +// the source. +// + +#ifndef SCFX_OTHER_DEFS_H +#define SCFX_OTHER_DEFS_H + + +#include "sysc/datatypes/fx/sc_fx_ids.h" +#include "sysc/datatypes/int/sc_signed.h" +#include "sysc/datatypes/int/sc_unsigned.h" +#include "sysc/datatypes/int/sc_int_base.h" +#include "sysc/datatypes/int/sc_uint_base.h" +#include "sysc/tracing/sc_trace.h" + + +namespace sc_dt +{ + +#ifdef SC_INCLUDE_FX + +// ---------------------------------------------------------------------------- +// CLASS : sc_signed +// ---------------------------------------------------------------------------- + +// assignment operators + +inline +const sc_signed& +sc_signed::operator = ( const sc_fxval& v ) +{ + if( ! v.is_normal() ) /* also triggers OBSERVER_READ call */ + { + SC_REPORT_ERROR( sc_core::SC_ID_INVALID_FX_VALUE_, + "sc_signed::operator = ( const sc_fxval& )" ); + } + + for( int i = 0; i < length(); ++ i ) + (*this)[i] = v.get_bit( i ); + + return *this; +} + +inline +const sc_signed& +sc_signed::operator = ( const sc_fxval_fast& v ) +{ + if( ! v.is_normal() ) /* also triggers OBSERVER_READ call */ + { + SC_REPORT_ERROR( sc_core::SC_ID_INVALID_FX_VALUE_, + "sc_signed::operator = ( const sc_fxval_fast& )" ); + } + + for( int i = 0; i < length(); ++ i ) + (*this)[i] = v.get_bit( i ); + + return *this; +} + +inline +const sc_signed& +sc_signed::operator = ( const sc_fxnum& v ) +{ + if( ! v.is_normal() ) /* also triggers OBSERVER_READ call */ + { + SC_REPORT_ERROR( sc_core::SC_ID_INVALID_FX_VALUE_, + "sc_signed::operator = ( const sc_fxnum& )" ); + } + + for( int i = 0; i < length(); ++ i ) + (*this)[i] = v.get_bit( i ); + + return *this; +} + +inline +const sc_signed& +sc_signed::operator = ( const sc_fxnum_fast& v ) +{ + if( ! v.is_normal() ) /* also triggers OBSERVER_READ call */ + { + SC_REPORT_ERROR( sc_core::SC_ID_INVALID_FX_VALUE_, + "sc_signed::operator = ( const sc_fxnum_fast& )" ); + } + + for( int i = 0; i < length(); ++ i ) + (*this)[i] = v.get_bit( i ); + + return *this; +} + + +// ---------------------------------------------------------------------------- +// CLASS : sc_unsigned +// ---------------------------------------------------------------------------- + +// assignment operators + +inline +const sc_unsigned& +sc_unsigned::operator = ( const sc_fxval& v ) +{ + if( ! v.is_normal() ) /* also triggers OBSERVER_READ call */ + { + SC_REPORT_ERROR( sc_core::SC_ID_INVALID_FX_VALUE_, + "sc_unsigned::operator = ( const sc_fxval& )" ); + } + + for( int i = 0; i < length(); ++ i ) + (*this)[i] = v.get_bit( i ); + + return *this; +} + +inline +const sc_unsigned& +sc_unsigned::operator = ( const sc_fxval_fast& v ) +{ + if( ! v.is_normal() ) /* also triggers OBSERVER_READ call */ + { + SC_REPORT_ERROR( sc_core::SC_ID_INVALID_FX_VALUE_, + "sc_unsigned::operator = ( const sc_fxval_fast& )" ); + } + + for( int i = 0; i < length(); ++ i ) + (*this)[i] = v.get_bit( i ); + + return *this; +} + +inline +const sc_unsigned& +sc_unsigned::operator = ( const sc_fxnum& v ) +{ + if( ! v.is_normal() ) /* also triggers OBSERVER_READ call */ + { + SC_REPORT_ERROR( sc_core::SC_ID_INVALID_FX_VALUE_, + "sc_unsigned::operator = ( const sc_fxnum& )" ); + } + + for( int i = 0; i < length(); ++ i ) + (*this)[i] = v.get_bit( i ); + + return *this; +} + +inline +const sc_unsigned& +sc_unsigned::operator = ( const sc_fxnum_fast& v ) +{ + if( ! v.is_normal() ) /* also triggers OBSERVER_READ call */ + { + SC_REPORT_ERROR( sc_core::SC_ID_INVALID_FX_VALUE_, + "sc_unsigned::operator = ( const sc_fxnum_fast& )" ); + } + + for( int i = 0; i < length(); ++ i ) + (*this)[i] = v.get_bit( i ); + + return *this; +} + + +// ---------------------------------------------------------------------------- +// CLASS : sc_int_base +// ---------------------------------------------------------------------------- + +#ifndef _32BIT_ +#define NUM_WIDTH LLWIDTH +#else +#define NUM_WIDTH INTWIDTH +#endif + + +// assignment operators + +inline +sc_int_base& +sc_int_base::operator = ( const sc_fxval& v ) +{ + if( ! v.is_normal() ) { /* also triggers OBSERVER_READ call */ + SC_REPORT_ERROR( sc_core::SC_ID_INVALID_FX_VALUE_, + "sc_int_base::operator = ( const sc_fxval& )" ); + } + for( int i = 0; i < m_len; ++ i ) { + set( i, v.get_bit( i ) ); + } + extend_sign(); + return *this; +} + +inline +sc_int_base& +sc_int_base::operator = ( const sc_fxval_fast& v ) +{ + if( ! v.is_normal() ) { /* also triggers OBSERVER_READ call */ + SC_REPORT_ERROR( sc_core::SC_ID_INVALID_FX_VALUE_, + "sc_int_base::operator = ( const sc_fxval_fast& )" ); + } + for( int i = 0; i < m_len; ++ i ) { + set( i, v.get_bit( i ) ); + } + extend_sign(); + return *this; +} + +inline +sc_int_base& +sc_int_base::operator = ( const sc_fxnum& v ) +{ + if( ! v.is_normal() ) { /* also triggers OBSERVER_READ call */ + SC_REPORT_ERROR( sc_core::SC_ID_INVALID_FX_VALUE_, + "sc_int_base::operator = ( const sc_fxnum& )" ); + } + for( int i = 0; i < m_len; ++ i ) { + set( i, v.get_bit( i ) ); + } + extend_sign(); + return *this; +} + +inline +sc_int_base& +sc_int_base::operator = ( const sc_fxnum_fast& v ) +{ + if( ! v.is_normal() ) { /* also triggers OBSERVER_READ call */ + SC_REPORT_ERROR( sc_core::SC_ID_INVALID_FX_VALUE_, + "sc_int_base::operator = ( const sc_fxnum_fast& )" ); + } + for( int i = 0; i < m_len; ++ i ) { + set( i, v.get_bit( i ) ); + } + extend_sign(); + return *this; +} + +#undef NUM_WIDTH + + +// ---------------------------------------------------------------------------- +// CLASS : sc_uint_base +// ---------------------------------------------------------------------------- + +// assignment operators + +inline +sc_uint_base& +sc_uint_base::operator = ( const sc_fxval& v ) +{ + if( ! v.is_normal() ) { /* also triggers OBSERVER_READ call */ + SC_REPORT_ERROR( sc_core::SC_ID_INVALID_FX_VALUE_, + "sc_uint_base::operator = ( const sc_fxval& )" ); + } + for( int i = 0; i < m_len; ++ i ) { + set( i, v.get_bit( i ) ); + } + extend_sign(); + return *this; +} + +inline +sc_uint_base& +sc_uint_base::operator = ( const sc_fxval_fast& v ) +{ + if( ! v.is_normal() ) { /* also triggers OBSERVER_READ call */ + SC_REPORT_ERROR( sc_core::SC_ID_INVALID_FX_VALUE_, + "sc_uint_base::operator = ( const sc_fxval_fast& )" ); + } + for( int i = 0; i < m_len; ++ i ) { + set( i, v.get_bit( i ) ); + } + extend_sign(); + return *this; +} + +inline +sc_uint_base& +sc_uint_base::operator = ( const sc_fxnum& v ) +{ + if( ! v.is_normal() ) { /* also triggers OBSERVER_READ call */ + SC_REPORT_ERROR( sc_core::SC_ID_INVALID_FX_VALUE_, + "sc_uint_base::operator = ( const sc_fxnum& )" ); + } + for( int i = 0; i < m_len; ++ i ) { + set( i, v.get_bit( i ) ); + } + extend_sign(); + return *this; +} + +inline +sc_uint_base& +sc_uint_base::operator = ( const sc_fxnum_fast& v ) +{ + if( ! v.is_normal() ) { /* also triggers OBSERVER_READ call */ + SC_REPORT_ERROR( sc_core::SC_ID_INVALID_FX_VALUE_, + "sc_uint_base::operator = ( const sc_fxnum_fast& )" ); + } + for( int i = 0; i < m_len; ++ i ) { + set( i, v.get_bit( i ) ); + } + extend_sign(); + return *this; +} + + +#endif + + +// ---------------------------------------------------------------------------- +// FUNCTION : sc_trace +// ---------------------------------------------------------------------------- + +inline +void +sc_trace( sc_core::sc_trace_file* tf, + const sc_fxval& object, const std::string& name ) +{ + if( tf ) + tf->trace( object, name ); +} + +inline +void +sc_trace( sc_core::sc_trace_file* tf, + const sc_fxval* object, const std::string& name ) +{ + if( tf ) + tf->trace( *object, name ); +} + +inline +void +sc_trace( sc_core::sc_trace_file* tf, + const sc_fxval_fast& object, const std::string& name ) +{ + if( tf ) + tf->trace( object, name ); +} + +inline +void +sc_trace( sc_core::sc_trace_file* tf, + const sc_fxval_fast* object, const std::string& name ) +{ + if( tf ) + tf->trace( *object, name ); +} + +inline +void +sc_trace( sc_core::sc_trace_file* tf, + const sc_fxnum& object, const std::string& name ) +{ + if( tf ) + tf->trace( object, name ); +} + +inline +void +sc_trace( sc_core::sc_trace_file* tf, + const sc_fxnum* object, const std::string& name ) +{ + if( tf ) + tf->trace( *object, name ); +} + +inline +void +sc_trace( sc_core::sc_trace_file* tf, + const sc_fxnum_fast& object, const std::string& name ) +{ + if( tf ) + tf->trace( object, name ); +} + +inline +void +sc_trace( sc_core::sc_trace_file* tf, + const sc_fxnum_fast* object, const std::string& name ) +{ + if( tf ) + tf->trace( *object, name ); +} + +} // namespace sc_dt + + +#endif + +// Taf! diff --git a/ext/systemc/src/sysc/datatypes/fx/scfx_params.h b/ext/systemc/src/sysc/datatypes/fx/scfx_params.h new file mode 100644 index 000000000..8cd646651 --- /dev/null +++ b/ext/systemc/src/sysc/datatypes/fx/scfx_params.h @@ -0,0 +1,222 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + scfx_params.h - + + Original Author: Martin Janssen, Synopsys, Inc. + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + +// $Log: scfx_params.h,v $ +// Revision 1.1.1.1 2006/12/15 20:20:04 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:53:58 acg +// Andy Goodrich: added $Log command so that CVS comments are reproduced in +// the source. +// + +#ifndef SCFX_PARAMS_H +#define SCFX_PARAMS_H + + +#include "sysc/datatypes/fx/sc_fx_ids.h" +#include "sysc/datatypes/fx/sc_fxcast_switch.h" +#include "sysc/datatypes/fx/sc_fxtype_params.h" + + +namespace sc_dt +{ + +// classes defined in this module +class scfx_params; + + +// ---------------------------------------------------------------------------- +// CLASS : scfx_params +// +// ... +// ---------------------------------------------------------------------------- + +class scfx_params +{ + +public: + + // constructor + + scfx_params( const sc_fxtype_params&, + sc_enc, + const sc_fxcast_switch& ); + + + // query functions + + const sc_fxtype_params& type_params() const; + sc_enc enc() const; + const sc_fxcast_switch& cast_switch() const; + + + // shortcuts + + int wl() const; + int iwl() const; + int fwl() const; + sc_q_mode q_mode() const; + sc_o_mode o_mode() const; + int n_bits() const; + + + // dump content + + void dump( ::std::ostream& ) const; + +private: + + sc_fxtype_params m_type_params; + sc_enc m_enc; + sc_fxcast_switch m_cast_switch; + +}; + + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + +// constructor + +inline +scfx_params::scfx_params( const sc_fxtype_params& type_params_, + sc_enc enc_, + const sc_fxcast_switch& cast_sw ) +: m_type_params( type_params_ ), + m_enc( enc_ ), + m_cast_switch( cast_sw ) +{ + if( m_enc == SC_US_ && m_type_params.o_mode() == SC_WRAP_SM ) + { + SC_REPORT_ERROR( sc_core::SC_ID_INVALID_O_MODE_, + "SC_WRAP_SM not defined for unsigned numbers" ); + } + +} + + +// query functions + +inline +const sc_fxtype_params& +scfx_params::type_params() const +{ + return m_type_params; +} + +inline +sc_enc +scfx_params::enc() const +{ + return m_enc; +} + +inline +const sc_fxcast_switch& +scfx_params::cast_switch() const +{ + return m_cast_switch; +} + + +// shortcuts + +inline +int +scfx_params::wl() const +{ + return m_type_params.wl(); +} + +inline +int +scfx_params::iwl() const +{ + return m_type_params.iwl(); +} + +inline +int +scfx_params::fwl() const +{ + return ( m_type_params.wl() - m_type_params.iwl() ); +} + +inline +sc_q_mode +scfx_params::q_mode() const +{ + return m_type_params.q_mode(); +} + +inline +sc_o_mode +scfx_params::o_mode() const +{ + return m_type_params.o_mode(); +} + +inline +int +scfx_params::n_bits() const +{ + return m_type_params.n_bits(); +} + + +// dump content + +inline +void +scfx_params::dump( ::std::ostream& os ) const +{ + os << "scfx_params" << ::std::endl; + os << "(" << ::std::endl; + os << "type_params = "; + m_type_params.dump( os ); + os << "enc = " << m_enc << ::std::endl; + os << "cast_switch = "; + m_cast_switch.dump( os ); + os << ")" << ::std::endl; +} + +} // namespace sc_dt + + +#endif + +// Taf! diff --git a/ext/systemc/src/sysc/datatypes/fx/scfx_pow10.cpp b/ext/systemc/src/sysc/datatypes/fx/scfx_pow10.cpp new file mode 100644 index 000000000..ac931763b --- /dev/null +++ b/ext/systemc/src/sysc/datatypes/fx/scfx_pow10.cpp @@ -0,0 +1,147 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + scfx_pow10.cpp - + + Original Author: Robert Graulich, Synopsys, Inc. + Martin Janssen, Synopsys, Inc. + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + + +// $Log: scfx_pow10.cpp,v $ +// Revision 1.1.1.1 2006/12/15 20:20:04 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:53:58 acg +// Andy Goodrich: added $Log command so that CVS comments are reproduced in +// the source. +// + +#include "sysc/datatypes/fx/scfx_pow10.h" + + +namespace sc_dt +{ + +// ---------------------------------------------------------------------------- +// CLASS : scfx_pow10 +// +// Class to compute (and cache) powers of 10 in arbitrary precision. +// ---------------------------------------------------------------------------- + +scfx_pow10::scfx_pow10() +{ + m_pos[0] = scfx_rep( 10.0 ); + m_neg[0] = scfx_rep( 0.1 ); + + for( int i = 1; i < SCFX_POW10_TABLE_SIZE; i ++ ) + { + m_pos[i].set_nan(); + m_neg[i].set_nan(); + } +} + +scfx_pow10::~scfx_pow10() +{} + + +const scfx_rep +scfx_pow10::operator() ( int i ) +{ + if( i == 0 ) { + return scfx_rep( 1.0 ); + } + + if( i > 0 ) + { + int bit = scfx_find_msb( i ); + scfx_rep result = *pos( bit ); + if( bit ) + { + while( -- bit >= 0 ) + { + if( ( 1 << bit ) & i ) + { + scfx_rep* tmp = mult_scfx_rep( result, *pos( bit ) ); + result = *tmp; + delete tmp; + } + } + } + return result; + } + else + { + i = -i; + int bit = scfx_find_msb( i ); + scfx_rep result = *neg( bit ); + if( bit ) + { + while( -- bit >= 0 ) + { + if( ( 1 << bit ) & i ) + { + scfx_rep* tmp = mult_scfx_rep( result, *neg( bit ) ); + result = *tmp; + delete tmp; + } + } + } + return result; + } +} + + +scfx_rep* +scfx_pow10::pos( int i ) +{ + if( ! m_pos[i].is_normal() ) + { + multiply( m_pos[i], *pos( i - 1 ), *pos( i - 1 ) ); + } + return &m_pos[i]; +} + +scfx_rep* +scfx_pow10::neg( int i ) +{ + if( ! m_neg[i].is_normal() ) + { + multiply( m_neg[i], *neg( i - 1 ), *neg( i - 1 ) ); + } + return &m_neg[i]; +} + +} // namespace sc_dt + + +// Taf! diff --git a/ext/systemc/src/sysc/datatypes/fx/scfx_pow10.h b/ext/systemc/src/sysc/datatypes/fx/scfx_pow10.h new file mode 100644 index 000000000..c9b278561 --- /dev/null +++ b/ext/systemc/src/sysc/datatypes/fx/scfx_pow10.h @@ -0,0 +1,95 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + scfx_pow10.h - + + Original Author: Robert Graulich, Synopsys, Inc. + Martin Janssen, Synopsys, Inc. + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + +// $Log: scfx_pow10.h,v $ +// Revision 1.1.1.1 2006/12/15 20:20:04 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:53:58 acg +// Andy Goodrich: added $Log command so that CVS comments are reproduced in +// the source. +// + +#ifndef SCFX_POW10_H +#define SCFX_POW10_H + + +#include "sysc/datatypes/fx/scfx_rep.h" + + +namespace sc_dt +{ + +// classes defined in this module +class scfx_pow10; + + +// ---------------------------------------------------------------------------- +// CLASS : scfx_pow10 +// +// Class to compute (and cache) powers of 10 in arbitrary precision. +// ---------------------------------------------------------------------------- + +const int SCFX_POW10_TABLE_SIZE = 32; + + +class scfx_pow10 +{ + +public: + + scfx_pow10(); + ~scfx_pow10(); + + const scfx_rep operator() ( int ); + +private: + + scfx_rep* pos( int ); + scfx_rep* neg( int ); + + scfx_rep m_pos[SCFX_POW10_TABLE_SIZE]; + scfx_rep m_neg[SCFX_POW10_TABLE_SIZE]; +}; + +} // namespace sc_dt + + +#endif + +// Taf! diff --git a/ext/systemc/src/sysc/datatypes/fx/scfx_rep.cpp b/ext/systemc/src/sysc/datatypes/fx/scfx_rep.cpp new file mode 100644 index 000000000..772835e6d --- /dev/null +++ b/ext/systemc/src/sysc/datatypes/fx/scfx_rep.cpp @@ -0,0 +1,2926 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + scfx_rep.cpp - + + Original Author: Robert Graulich, Synopsys, Inc. + Martin Janssen, Synopsys, Inc. + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + + +// $Log: scfx_rep.cpp,v $ +// Revision 1.4 2011/08/24 22:05:43 acg +// Torsten Maehne: initialization changes to remove warnings. +// +// Revision 1.3 2011/08/15 16:43:24 acg +// Torsten Maehne: changes to remove unused argument warnings. +// +// Revision 1.2 2009/02/28 00:26:20 acg +// Andy Goodrich: bug fixes. +// +// Revision 1.2 2008/11/06 17:22:47 acg +// Andy Goodrich: bug fixes for 2.2.1. +// +// Revision 1.1.1.1 2006/12/15 20:31:36 acg +// SystemC 2.2 +// +// Revision 1.3 2006/01/13 18:53:58 acg +// Andy Goodrich: added $Log command so that CVS comments are reproduced in +// the source. +// + +#include "sysc/utils/sc_machine.h" +#include "sysc/datatypes/fx/scfx_rep.h" + +#include "sysc/datatypes/fx/scfx_ieee.h" +#include "sysc/datatypes/fx/scfx_pow10.h" +#include "sysc/datatypes/fx/scfx_utils.h" + +#include "sysc/datatypes/bit/sc_bv_base.h" + +#include <ctype.h> +#include <cstdio> +#include <stdlib.h> +#include <math.h> + + +namespace sc_dt +{ + +// ---------------------------------------------------------------------------- +// some utilities +// ---------------------------------------------------------------------------- + +static scfx_pow10 pow10_fx; + +static const int mantissa0_size = SCFX_IEEE_DOUBLE_M_SIZE - bits_in_int; + +static inline +int +n_word( int x ) +{ + return ( x + bits_in_word - 1 ) / bits_in_word; +} + + +// ---------------------------------------------------------------------------- +// CONSTRUCTORS +// ---------------------------------------------------------------------------- + +scfx_rep::scfx_rep() +: m_mant( min_mant ), m_wp(), m_sign(), m_state(), m_msw(), m_lsw(), + m_r_flag( false ) +{ + set_zero(); +} + +scfx_rep::scfx_rep( int a ) +: m_mant( min_mant ), m_wp(), m_sign(), m_state(), m_msw(), m_lsw(), + m_r_flag( false ) +{ + if( a != 0 ) + { + m_mant.clear(); + m_wp = m_msw = m_lsw = 2; + m_state = normal; + if( a > 0 ) + { + m_mant[2] = a; + m_sign = 1; + } + else + { + m_mant[2] = -a; + m_sign = -1; + } + } + else + set_zero(); +} + +scfx_rep::scfx_rep( unsigned int a ) +: m_mant( min_mant ), m_wp(), m_sign(), m_state(), m_msw(), m_lsw(), + m_r_flag( false ) +{ + if( a != 0 ) + { + m_mant.clear(); + m_wp = m_msw = m_lsw = 2; + m_state = normal; + m_mant[2] = a; + m_sign = 1; + } + else + set_zero(); +} + +scfx_rep::scfx_rep( long a ) +: m_mant( min_mant ), m_wp(), m_sign(), m_state(), m_msw(), m_lsw(), + m_r_flag( false ) +{ + if( a != 0 ) + { + m_mant.clear(); + m_state = normal; + if ( a > 0 ) + { + m_sign = 1; + } + else + { + a = -a; + m_sign = -1; + } +# if defined(SC_LONG_64) + m_wp = 1; + m_mant[1] = static_cast<word>( a ); + m_mant[2] = static_cast<word>( a >> bits_in_word ); + find_sw(); +# else + m_wp = 2; + m_msw = 2; + m_lsw = 2; + m_mant[2] = a; +# endif + + } + else + set_zero(); +} + +scfx_rep::scfx_rep( unsigned long a ) +: m_mant( min_mant ), m_wp(), m_sign(), m_state(), m_msw(), m_lsw(), + m_r_flag( false ) +{ + if( a != 0 ) + { + m_mant.clear(); + m_wp = m_msw = m_lsw = 2; + m_state = normal; +# if defined(SC_LONG_64) + m_wp = 1; + m_mant[1] = static_cast<word>( a ); + m_mant[2] = static_cast<word>( a >> bits_in_word ); + find_sw(); +# else + m_wp = 2; + m_msw = 2; + m_lsw = 2; + m_mant[2] = a; +# endif + m_sign = 1; + } + else + set_zero(); +} + +scfx_rep::scfx_rep( double a ) +: m_mant( min_mant ), m_wp( 0 ), m_sign(), m_state( normal ), m_msw( 0 ), + m_lsw( 0 ), m_r_flag( false ) +{ + m_mant.clear(); + + scfx_ieee_double id( a ); + + m_sign = id.negative() ? -1 : 1; + + if( id.is_nan() ) + m_state = not_a_number; + else if( id.is_inf() ) + m_state = infinity; + else if( id.is_subnormal() ) + { + m_mant[0] = id.mantissa1(); + m_mant[1] = id.mantissa0(); + normalize( id.exponent() + 1 - SCFX_IEEE_DOUBLE_M_SIZE ); + } + else if( id.is_normal() ) + { + m_mant[0] = id.mantissa1(); + m_mant[1] = id.mantissa0() | ( 1 << mantissa0_size ); + normalize( id.exponent() - SCFX_IEEE_DOUBLE_M_SIZE ); + } +} + +scfx_rep::scfx_rep( int64 a ) +: m_mant( min_mant ), m_wp(), m_sign(), m_state(), m_msw(), m_lsw(), + m_r_flag( false ) +{ + if( a != 0 ) + { + m_mant.clear(); + m_wp = 1; + m_state = normal; + if( a > 0 ) + { + m_mant[1] = static_cast<word>( a ); + m_mant[2] = static_cast<word>( a >> bits_in_word ); + m_sign = 1; + } + else + { + m_mant[1] = static_cast<word>( -a ); + m_mant[2] = static_cast<word>( (-a) >> bits_in_word ); + m_sign = -1; + } + find_sw(); + } + else + set_zero(); +} + +scfx_rep::scfx_rep( uint64 a ) +: m_mant( min_mant ), m_wp(), m_sign(), m_state(), m_msw(), m_lsw(), + m_r_flag( false ) +{ + if( a != 0 ) + { + m_mant.clear(); + m_wp = 1; + m_state = normal; + m_mant[1] = static_cast<word>( a ); + m_mant[2] = static_cast<word>( a >> bits_in_word ); + m_sign = 1; + find_sw(); + } + else + set_zero(); +} + +scfx_rep::scfx_rep( const sc_signed& a ) +: m_mant( min_mant ), m_wp(), m_sign(), m_state(), m_msw(), m_lsw(), + m_r_flag( false ) +{ + if( a.iszero() ) + set_zero(); + else + { + int words = n_word( a.length() ); + if( words > size() ) + resize_to( words ); + m_mant.clear(); + m_wp = 0; + m_state = normal; + if( a.sign() ) + { + sc_signed a2 = -a; + for( int i = 0; i < a2.length(); ++ i ) + { + if( a2[i] ) + { + scfx_index x = calc_indices( i ); + m_mant[x.wi()] |= 1 << x.bi(); + } + } + m_sign = -1; + } + else + { + for( int i = 0; i < a.length(); ++ i ) + { + if( a[i] ) + { + scfx_index x = calc_indices( i ); + m_mant[x.wi()] |= 1 << x.bi(); + } + } + m_sign = 1; + } + find_sw(); + } +} + +scfx_rep::scfx_rep( const sc_unsigned& a ) +: m_mant( min_mant ), m_wp(), m_sign(), m_state(), m_msw(), m_lsw(), + m_r_flag( false ) +{ + if( a.iszero() ) + set_zero(); + else + { + int words = n_word( a.length() ); + if( words > size() ) + resize_to( words ); + m_mant.clear(); + m_wp = 0; + m_state = normal; + for( int i = 0; i < a.length(); ++ i ) + { + if( a[i] ) + { + scfx_index x = calc_indices( i ); + m_mant[x.wi()] |= 1 << x.bi(); + } + } + m_sign = 1; + find_sw(); + } +} + + +// copy constructor + +scfx_rep::scfx_rep( const scfx_rep& a ) +: m_mant( a.m_mant ), m_wp( a.m_wp ), m_sign( a.m_sign ), m_state( a.m_state ), + m_msw( a.m_msw ), m_lsw( a.m_lsw ), m_r_flag( false ) +{} + + +// ---------------------------------------------------------------------------- +// OPERATORS : new, delete +// +// Memory management for class scfx_rep. +// ---------------------------------------------------------------------------- + +union scfx_rep_node +{ + char data[sizeof( scfx_rep )]; + scfx_rep_node* next; +}; + + +static scfx_rep_node* list = 0; + + +void* +scfx_rep::operator new( std::size_t size ) +{ + const int ALLOC_SIZE = 1024; + + if( size != sizeof( scfx_rep ) ) + return ::operator new( size ); + + if( ! list ) + { + list = new scfx_rep_node[ALLOC_SIZE]; + for( int i = 0; i < ALLOC_SIZE - 1; i ++ ) + list[i].next = list + i + 1; + list[ALLOC_SIZE - 1].next = 0; + } + + scfx_rep* ptr = reinterpret_cast<scfx_rep*>( list->data ); + list = list->next; + + return ptr; +} + + +void scfx_rep::operator delete( void* ptr, std::size_t size ) +{ + if( size != sizeof( scfx_rep ) ) + { + ::operator delete( ptr ); + return; + } + + scfx_rep_node* node = static_cast<scfx_rep_node*>( ptr ); + node->next = list; + list = node; +} + + +// ---------------------------------------------------------------------------- +// METHOD : from_string +// +// Convert from character string to sc_fxrep. +// ---------------------------------------------------------------------------- + +#define SCFX_FAIL_IF_(cnd) \ +{ \ + if( ( cnd ) ) \ + { \ + m_state = not_a_number; \ + m_mant.clear(); /* to avoid Purify UMRs during assignment */ \ + return; \ + } \ +} + + +void +scfx_rep::from_string( const char* s, int cte_wl ) +{ + SCFX_FAIL_IF_( s == 0 || *s == 0 ); + + scfx_string s2; + s2 += s; + s2 += '\0'; + + bool sign_char; + m_sign = scfx_parse_sign( s, sign_char ); + + sc_numrep numrep = scfx_parse_prefix( s ); + + int base = 0; + + switch( numrep ) + { + case SC_DEC: + { + base = 10; + if( scfx_is_nan( s ) ) + { // special case: NaN + m_state = not_a_number; + m_mant.clear(); /* to avoid Purify UMRs during assignment */ + return; + } + if( scfx_is_inf( s ) ) + { // special case: Infinity + m_state = infinity; + m_mant.clear(); /* to avoid Purify UMRs during assignment */ + return; + } + break; + } + case SC_BIN: + case SC_BIN_US: + { + SCFX_FAIL_IF_( sign_char ); + base = 2; + break; + } + + case SC_BIN_SM: + { + base = 2; + break; + } + case SC_OCT: + case SC_OCT_US: + { + SCFX_FAIL_IF_( sign_char ); + base = 8; + break; + } + case SC_OCT_SM: + { + base = 8; + break; + } + case SC_HEX: + case SC_HEX_US: + { + SCFX_FAIL_IF_( sign_char ); + base = 16; + break; + } + case SC_HEX_SM: + { + base = 16; + break; + } + case SC_CSD: + { + SCFX_FAIL_IF_( sign_char ); + base = 2; + scfx_csd2tc( s2 ); + s = (const char*) s2 + 4; + numrep = SC_BIN; + break; + } + default:; + } + + // + // find end of mantissa and count the digits and points + // + + const char *end = s; + bool based_point = false; + int int_digits = 0; + int frac_digits = 0; + + while( *end ) + { + if( scfx_exp_start( end ) ) + break; + + if( *end == '.' ) + { + SCFX_FAIL_IF_( based_point ); + based_point = true; + } + else + { + SCFX_FAIL_IF_( ! scfx_is_digit( *end, numrep ) ); + if( based_point ) + frac_digits ++; + else + int_digits ++; + } + + ++ end; + } + + SCFX_FAIL_IF_( int_digits == 0 && frac_digits == 0 ); + + // [ exponent ] + + int exponent = 0; + + if( *end ) + { + for( const char *e = end + 2; *e; ++ e ) + SCFX_FAIL_IF_( ! scfx_is_digit( *e, SC_DEC ) ); + exponent = atoi( end + 1 ); + } + + // + // check if the mantissa is negative + // + + bool mant_is_neg = false; + + switch( numrep ) + { + case SC_BIN: + case SC_OCT: + case SC_HEX: + { + const char* p = s; + if( *p == '.' ) + ++ p; + + mant_is_neg = ( scfx_to_digit( *p, numrep ) >= ( base >> 1 ) ); + + break; + } + default: + ; + } + + // + // convert the mantissa + // + + switch( base ) + { + case 2: + { + int bit_offset = exponent % bits_in_word; + int word_offset = exponent / bits_in_word; + + int_digits += bit_offset; + frac_digits -= bit_offset; + + int words = n_word( int_digits ) + n_word( frac_digits ); + if( words > size() ) + resize_to( words ); + m_mant.clear(); + + int j = n_word( frac_digits ) * bits_in_word + int_digits - 1; + + for( ; s < end; s ++ ) + { + switch( *s ) + { + case '1': + set_bin( j ); + case '0': + j --; + case '.': + break; + default: + SCFX_FAIL_IF_( true ); // should not happen + } + } + + m_wp = n_word( frac_digits ) - word_offset; + break; + } + case 8: + { + exponent *= 3; + int_digits *= 3; + frac_digits *= 3; + + int bit_offset = exponent % bits_in_word; + int word_offset = exponent / bits_in_word; + + int_digits += bit_offset; + frac_digits -= bit_offset; + + int words = n_word( int_digits ) + n_word( frac_digits ); + if( words > size() ) + resize_to( words ); + m_mant.clear(); + + int j = n_word( frac_digits ) * bits_in_word + int_digits - 3; + + for( ; s < end; s ++ ) + { + switch( *s ) + { + case '7': case '6': case '5': case '4': + case '3': case '2': case '1': + set_oct( j, *s - '0' ); + case '0': + j -= 3; + case '.': + break; + default: + SCFX_FAIL_IF_( true ); // should not happen + } + } + + m_wp = n_word( frac_digits ) - word_offset; + break; + } + case 10: + { + word carry, temp; + int length = int_digits + frac_digits; + resize_to( sc_max( min_mant, n_word( 4 * length ) ) ); + + m_mant.clear(); + m_msw = m_lsw = 0; + + for( ; s < end; s ++ ) + { + switch( *s ) + { + case '9': case '8': case '7': case '6': case '5': + case '4': case '3': case '2': case '1': case '0': + multiply_by_ten(); + carry = *s - '0'; + for ( int i = 0; carry && i < m_mant.size(); i++ ) + { + temp = m_mant[i]; + temp += carry; + carry = temp < m_mant[i]; + m_mant[i] = temp; + } + case '.': + break; + default: + SCFX_FAIL_IF_( true ); // should not happen + } + } + + m_wp = 0; + find_sw(); + + int denominator = frac_digits - exponent; + + if( denominator ) + { + scfx_rep frac_num = pow10_fx( denominator ); + scfx_rep* temp_num = + div_scfx_rep( const_cast<const scfx_rep&>( *this ), + frac_num, cte_wl ); + *this = *temp_num; + delete temp_num; + } + + break; + } + case 16: + { + exponent *= 4; + int_digits *= 4; + frac_digits *= 4; + + int bit_offset = exponent % bits_in_word; + int word_offset = exponent / bits_in_word; + + int_digits += bit_offset; + frac_digits -= bit_offset; + + int words = n_word( int_digits ) + n_word( frac_digits ); + if( words > size() ) + resize_to( words ); + m_mant.clear(); + + int j = n_word( frac_digits ) * bits_in_word + int_digits - 4; + + for( ; s < end; s ++ ) + { + switch( *s ) + { + case 'f': case 'e': case 'd': case 'c': case 'b': case 'a': + set_hex( j, *s - 'a' + 10 ); + j -= 4; + break; + case 'F': case 'E': case 'D': case 'C': case 'B': case 'A': + set_hex( j, *s - 'A' + 10 ); + j -= 4; + break; + case '9': case '8': case '7': case '6': case '5': + case '4': case '3': case '2': case '1': + set_hex( j, *s - '0' ); + case '0': + j -= 4; + case '.': + break; + default: + SCFX_FAIL_IF_( true ); // should not happen + } + } + + m_wp = n_word( frac_digits ) - word_offset; + break; + } + } + + m_state = normal; + find_sw(); + + // + // two's complement of mantissa if it is negative + // + + if( mant_is_neg ) + { + m_mant[m_msw] |= -1 << scfx_find_msb( m_mant[m_msw] ); + for( int i = m_msw + 1; i < m_mant.size(); ++ i ) + m_mant[i] = static_cast<word>( -1 ); + complement( m_mant, m_mant, m_mant.size() ); + inc( m_mant ); + m_sign *= -1; + find_sw(); + } +} + + +#undef SCFX_FAIL_IF_ + + +// ---------------------------------------------------------------------------- +// METHOD : to_double +// +// Convert from scfx_rep to double. +// ---------------------------------------------------------------------------- + +double +scfx_rep::to_double() const +{ + scfx_ieee_double id; + + // handle special cases + + if( is_nan() ) + { + id.set_nan(); + return id; + } + + if( is_inf() ) + { + id.set_inf(); + id.negative( m_sign < 0 ); + return id; + } + + if( is_zero() ) + { + id = 0.; + id.negative( m_sign < 0 ); + return id; + } + + int msb = scfx_find_msb( m_mant[m_msw] ); + + int exp = (m_msw - m_wp) * bits_in_word + msb; + + if( exp > SCFX_IEEE_DOUBLE_E_MAX ) + { + id.set_inf(); + id.negative( m_sign < 0 ); + return id; + } + + if( exp < SCFX_IEEE_DOUBLE_E_MIN + - static_cast<int>( SCFX_IEEE_DOUBLE_M_SIZE ) ) + { + id = 0.; + return id; + } + + int shift = mantissa0_size - msb; + + unsigned int m0; + unsigned int m1 = 0; + unsigned int guard = 0; + + if( shift == 0 ) + { + m0 = m_mant[m_msw] & ~( 1 << mantissa0_size ); + if( m_msw > m_lsw ) + { + m1 = m_mant[m_msw - 1]; + if( m_msw - 1 > m_lsw ) + guard = m_mant[m_msw - 2] >> ( bits_in_word - 1 ); + } + } + else if( shift < 0 ) + { + m0 = ( m_mant[m_msw] >> -shift ) & ~( 1 << mantissa0_size ); + m1 = m_mant[m_msw] << ( bits_in_word + shift ); + if( m_msw > m_lsw ) + { + m1 |= m_mant[m_msw - 1] >> -shift; + guard = ( m_mant[m_msw - 1] >> ( -shift - 1 ) ) & 1; + } + } + else + { + m0 = ( m_mant[m_msw] << shift ) & ~( 1 << mantissa0_size ); + if( m_msw > m_lsw ) + { + m0 |= m_mant[m_msw - 1] >> ( bits_in_word - shift ); + m1 = m_mant[m_msw - 1] << shift; + if( m_msw - 1 > m_lsw ) + { + m1 |= m_mant[m_msw - 2] >> ( bits_in_word - shift ); + guard = ( m_mant[m_msw - 2] >> (bits_in_word - shift - 1) ) + & 1; + } + } + } + + if( exp < SCFX_IEEE_DOUBLE_E_MIN ) + { + m0 |= ( 1 << mantissa0_size ); + + int subnormal_shift = SCFX_IEEE_DOUBLE_E_MIN - exp; + + if( subnormal_shift < bits_in_word ) + { + m1 = m1 >> subnormal_shift + | m0 << ( bits_in_word - subnormal_shift ); + m0 = m0 >> subnormal_shift; + } + else + { + m1 = m0 >> ( subnormal_shift - bits_in_word ); + m0 = 0; + } + + guard = 0; + + exp = SCFX_IEEE_DOUBLE_E_MIN - 1; + } + + id.mantissa0( m0 ); + id.mantissa1( m1 ); + id.exponent( exp ); + id.negative( m_sign < 0 ); + + double result = id; + + if( guard != 0 ) + result += m_sign * scfx_pow2( exp - SCFX_IEEE_DOUBLE_M_SIZE ); + + return result; +} + + +// ---------------------------------------------------------------------------- +// METHOD : to_string +// +// Convert from scfx_rep to character string. +// ---------------------------------------------------------------------------- + +void +print_dec( scfx_string& s, const scfx_rep& num, int w_prefix, sc_fmt fmt ) +{ + if( num.is_neg() ) + s += '-'; + + if( w_prefix == 1 ) { + scfx_print_prefix( s, SC_DEC ); + } + + if( num.is_zero() ) + { + s += '0'; + return; + } + + // split 'num' into its integer and fractional part + + scfx_rep int_part = num; + scfx_rep frac_part = num; + + int i; + + for( i = int_part.m_lsw; i <= int_part.m_msw && i < int_part.m_wp; i ++ ) + int_part.m_mant[i] = 0; + int_part.find_sw(); + if( int_part.m_wp < int_part.m_lsw ) + int_part.resize_to( int_part.size() - int_part.m_wp, -1 ); + + for( i = frac_part.m_msw; + i >= frac_part.m_lsw && i >= frac_part.m_wp; + i -- ) + frac_part.m_mant[i] = 0; + frac_part.find_sw(); + if( frac_part.m_msw == frac_part.size() - 1 ) + frac_part.resize_to( frac_part.size() + 1, 1 ); + + // print integer part + + int int_digits = 0; + int int_zeros = 0; + + if( ! int_part.is_zero() ) + { + double int_wl = ( int_part.m_msw - int_part.m_wp ) * bits_in_word + + scfx_find_msb( int_part.m_mant[int_part.m_msw] ) + 1; + int_digits = (int) ceil( int_wl * log10( 2. ) ); + + int len = s.length(); + s.append( int_digits ); + + bool zero_digits = ( frac_part.is_zero() && fmt != SC_F ); + + for( i = int_digits + len - 1; i >= len; i-- ) + { + unsigned int remainder = int_part.divide_by_ten(); + s[i] = static_cast<char>( '0' + remainder ); + + if( zero_digits ) + { + if( remainder == 0 ) + int_zeros ++; + else + zero_digits = false; + } + } + + // discard trailing zeros from int_part + s.discard( int_zeros ); + + if( s[len] == '0' ) + { + // int_digits was overestimated by one + s.remove( len ); + -- int_digits; + } + } + + // print fractional part + + int frac_digits = 0; + int frac_zeros = 0; + + if( ! frac_part.is_zero() ) + { + s += '.'; + + bool zero_digits = ( int_digits == 0 && fmt != SC_F ); + + double frac_wl = ( frac_part.m_wp - frac_part.m_msw ) * bits_in_word + - scfx_find_msb( frac_part.m_mant[frac_part.m_msw] ) + - 1; + frac_zeros = (int) floor( frac_wl * log10( 2. ) ); + + scfx_rep temp; + sc_dt::multiply( temp, frac_part, pow10_fx( frac_zeros ) ); + frac_part = temp; + if( frac_part.m_msw == frac_part.size() - 1 ) + frac_part.resize_to( frac_part.size() + 1, 1 ); + + frac_digits = frac_zeros; + if( ! zero_digits ) + { + for( i = 0; i < frac_zeros; i ++ ) + s += '0'; + frac_zeros = 0; + } + + while( ! frac_part.is_zero() ) + { + frac_part.multiply_by_ten(); + int n = frac_part.m_mant[frac_part.m_msw + 1]; + + if( zero_digits ) + { + if( n == 0 ) + frac_zeros ++; + else + zero_digits = false; + } + + if( ! zero_digits ) + s += static_cast<char>( '0' + n ); + + frac_part.m_mant[frac_part.m_msw + 1] = 0; + frac_digits ++; + } + } + + // print exponent + + if( fmt != SC_F ) + { + if( frac_digits == 0 ) + scfx_print_exp( s, int_zeros ); + else if( int_digits == 0 ) + scfx_print_exp( s, - frac_zeros ); + } +} + +void +print_other( scfx_string& s, const scfx_rep& a, sc_numrep numrep, int w_prefix, + sc_fmt fmt, const scfx_params* params ) +{ + scfx_rep b = a; + + sc_numrep numrep2 = numrep; + + bool numrep_is_sm = ( numrep == SC_BIN_SM || + numrep == SC_OCT_SM || + numrep == SC_HEX_SM ); + + if( numrep_is_sm ) + { + if( b.is_neg() ) + { + s += '-'; + b = *neg_scfx_rep( a ); + } + switch( numrep ) + { + case SC_BIN_SM: + numrep2 = SC_BIN_US; + break; + case SC_OCT_SM: + numrep2 = SC_OCT_US; + break; + case SC_HEX_SM: + numrep2 = SC_HEX_US; + break; + default: + ; + } + } + + if( w_prefix != 0 ) { + scfx_print_prefix( s, numrep ); + } + + numrep = numrep2; + + int msb, lsb; + + if( params != 0 ) + { + msb = params->iwl() - 1; + lsb = params->iwl() - params->wl(); + + if( params->enc() == SC_TC_ && + ( numrep == SC_BIN_US || + numrep == SC_OCT_US || + numrep == SC_HEX_US ) && + ! numrep_is_sm && + params->wl() > 1 ) + -- msb; + else if( params->enc() == SC_US_ && + ( numrep == SC_BIN || + numrep == SC_OCT || + numrep == SC_HEX || + numrep == SC_CSD ) ) + ++ msb; + } + else + { + if( b.is_zero() ) + { + msb = 0; + lsb = 0; + } + else + { + msb = ( b.m_msw - b.m_wp ) * bits_in_word + + scfx_find_msb( b.m_mant[ b.m_msw ] ) + 1; + while( b.get_bit( msb ) == b.get_bit( msb - 1 ) ) + -- msb; + + if( numrep == SC_BIN_US || + numrep == SC_OCT_US || + numrep == SC_HEX_US ) + -- msb; + + lsb = ( b.m_lsw - b.m_wp ) * bits_in_word + + scfx_find_lsb( b.m_mant[ b.m_lsw ] ); + } + } + + int step; + + switch( numrep ) + { + case SC_BIN: + case SC_BIN_US: + case SC_CSD: + step = 1; + break; + case SC_OCT: + case SC_OCT_US: + step = 3; + break; + case SC_HEX: + case SC_HEX_US: + step = 4; + break; + default: + step = 0; + } + + msb = (int) ceil( double( msb + 1 ) / step ) * step - 1; + + lsb = (int) floor( double( lsb ) / step ) * step; + + if( msb < 0 ) + { + s += '.'; + if( fmt == SC_F ) + { + int sign = ( b.is_neg() ) ? ( 1 << step ) - 1 : 0; + for( int i = ( msb + 1 ) / step; i < 0; i ++ ) + { + if( sign < 10 ) + s += static_cast<char>( sign + '0' ); + else + s += static_cast<char>( sign + 'a' - 10 ); + } + } + } + + int i = msb; + while( i >= lsb ) + { + int value = 0; + for( int j = step - 1; j >= 0; -- j ) + { + value += static_cast<int>( b.get_bit( i ) ) << j; + -- i; + } + if( value < 10 ) + s += static_cast<char>( value + '0' ); + else + s += static_cast<char>( value + 'a' - 10 ); + if( i == -1 ) + s += '.'; + } + + if( lsb > 0 && fmt == SC_F ) + { + for( int i = lsb / step; i > 0; i -- ) + s += '0'; + } + + if( s[s.length() - 1] == '.' ) + s.discard( 1 ); + + if( fmt != SC_F ) + { + if( msb < 0 ) + scfx_print_exp( s, ( msb + 1 ) / step ); + else if( lsb > 0 ) + scfx_print_exp( s, lsb / step ); + } + + if( numrep == SC_CSD ) + scfx_tc2csd( s, w_prefix ); +} + +const char* +scfx_rep::to_string( sc_numrep numrep, int w_prefix, + sc_fmt fmt, const scfx_params* params ) const +{ + static scfx_string s; + + s.clear(); + + if( is_nan() ) + scfx_print_nan( s ); + else if( is_inf() ) + scfx_print_inf( s, is_neg() ); + else if( is_neg() && ! is_zero() && + ( numrep == SC_BIN_US || + numrep == SC_OCT_US || + numrep == SC_HEX_US ) ) + s += "negative"; + else if( numrep == SC_DEC || numrep == SC_NOBASE ) + sc_dt::print_dec( s, *this, w_prefix, fmt ); + else + sc_dt::print_other( s, *this, numrep, w_prefix, fmt, params ); + + return s; +} + + +// ---------------------------------------------------------------------------- +// ADD +// +// add two mantissas of the same size +// result has the same size +// returns carry of operation +// ---------------------------------------------------------------------------- + +static inline +int +add_mants( int size, scfx_mant& result, + const scfx_mant& a, const scfx_mant& b ) +{ + unsigned int carry = 0; + + int index = 0; + + do + { + word x = a[index]; + word y = b[index]; + + y += carry; + carry = y < carry; + y += x; + carry += y < x; + result[index] = y; + } + while( ++ index < size ); + + return ( carry ? 1 : 0 ); +} + + +static inline +int +sub_mants( int size, scfx_mant& result, + const scfx_mant& a, const scfx_mant& b ) +{ + unsigned carry = 0; + + int index = 0; + + do + { + word x = a[index]; + word y = b[index]; + + y += carry; + carry = y < carry; + y = x - y; + carry += y > x; + result[index] = y; + } + while( ++ index < size ); + + return ( carry ? 1 : 0 ); +} + + +scfx_rep* +add_scfx_rep( const scfx_rep& lhs, const scfx_rep& rhs, int max_wl ) +{ + scfx_rep& result = *new scfx_rep; + + // + // check for special cases + // + + if( lhs.is_nan() || rhs.is_nan() + || ( lhs.is_inf() && rhs.is_inf() && lhs.m_sign != rhs.m_sign ) ) + { + result.set_nan(); + return &result; + } + + if( lhs.is_inf() ) + { + result.set_inf( lhs.m_sign ); + return &result; + } + + if( rhs.is_inf() ) + { + result.set_inf( rhs.m_sign ); + return &result; + } + + // + // align operands if needed + // + + scfx_mant_ref lhs_mant; + scfx_mant_ref rhs_mant; + + int len_mant = lhs.size(); + int new_wp = lhs.m_wp; + + align( lhs, rhs, new_wp, len_mant, lhs_mant, rhs_mant ); + + // + // size the result mantissa + // + + result.resize_to( len_mant ); + result.m_wp = new_wp; + + // + // do it + // + + if( lhs.m_sign == rhs.m_sign ) + { + add_mants( len_mant, result.m_mant, lhs_mant, rhs_mant ); + result.m_sign = lhs.m_sign; + } + else + { + int cmp = compare_abs( lhs, rhs ); + + if( cmp == 1 ) + { + sub_mants( len_mant, result.m_mant, lhs_mant, rhs_mant ); + result.m_sign = lhs.m_sign; + } + else if ( cmp == -1 ) + { + sub_mants( len_mant, result.m_mant, rhs_mant, lhs_mant ); + result.m_sign = rhs.m_sign; + } + else + { + result.m_mant.clear(); + result.m_sign = 1; + } + } + + result.find_sw(); + result.round( max_wl ); + + return &result; +} + + +// ---------------------------------------------------------------------------- +// SUB +// +// sub two word's of the same size +// result has the same size +// returns carry of operation +// ---------------------------------------------------------------------------- + +static inline +int +sub_with_index( scfx_mant& a, int a_msw, int /*a_lsw*/, + const scfx_mant& b, int b_msw, int b_lsw ) +{ + unsigned carry = 0; + + int size = b_msw - b_lsw; + int a_index = a_msw - size; + int b_index = b_msw - size; + + do + { + word x = a[a_index]; + word y = b[b_index]; + + y += carry; + carry = y < carry; + y = x - y; + carry += y > x; + a[a_index] = y; + + a_index ++; + b_index ++; + } + while( size -- ); + + if( carry ) + { + // special case: a[a_msw + 1 ] == 1 + a[a_msw + 1] = 0; + } + + return ( carry ? 1 : 0 ); +} + + +scfx_rep* +sub_scfx_rep( const scfx_rep& lhs, const scfx_rep& rhs, int max_wl ) +{ + scfx_rep& result = *new scfx_rep; + + // + // check for special cases + // + + if( lhs.is_nan() || rhs.is_nan() + || ( lhs.is_inf() && rhs.is_inf() && lhs.m_sign == rhs.m_sign ) ) + { + result.set_nan(); + return &result; + } + + if( lhs.is_inf() ) + { + result.set_inf( lhs.m_sign ); + return &result; + } + + if( rhs.is_inf() ) + { + result.set_inf( -1 * rhs.m_sign ); + return &result; + } + + // + // align operands if needed + // + + scfx_mant_ref lhs_mant; + scfx_mant_ref rhs_mant; + + int len_mant = lhs.size(); + int new_wp = lhs.m_wp; + + align( lhs, rhs, new_wp, len_mant, lhs_mant, rhs_mant ); + + // + // size the result mantissa + // + + result.resize_to( len_mant ); + result.m_wp = new_wp; + + // + // do it + // + + if( lhs.m_sign != rhs.m_sign ) + { + add_mants( len_mant, result.m_mant, lhs_mant, rhs_mant ); + result.m_sign = lhs.m_sign; + } + else + { + int cmp = compare_abs( lhs, rhs ); + + if( cmp == 1 ) + { + sub_mants( len_mant, result.m_mant, lhs_mant, rhs_mant ); + result.m_sign = lhs.m_sign; + } + else if ( cmp == -1 ) + { + sub_mants( len_mant, result.m_mant, rhs_mant, lhs_mant ); + result.m_sign = -rhs.m_sign; + } else { + result.m_mant.clear(); + result.m_sign = 1; + } + } + + result.find_sw(); + result.round( max_wl ); + + return &result; +} + + +// ---------------------------------------------------------------------------- +// MUL +// ---------------------------------------------------------------------------- + +union word_short +{ + word l; + struct + { +#if defined( SC_BIG_ENDIAN ) + half_word u; + half_word l; +#elif defined( SC_LITTLE_ENDIAN ) + half_word l; + half_word u; +#endif + } s; +}; + + +#if defined( SC_BIG_ENDIAN ) +static const int half_word_incr = -1; +#elif defined( SC_LITTLE_ENDIAN ) +static const int half_word_incr = 1; +#endif + + +void +multiply( scfx_rep& result, const scfx_rep& lhs, const scfx_rep& rhs, + int max_wl ) +{ + // + // check for special cases + // + + if( lhs.is_nan() || rhs.is_nan() + || (lhs.is_inf() && rhs.is_zero()) + || (lhs.is_zero() && rhs.is_inf()) ) + { + result.set_nan(); + return; + } + + if( lhs.is_inf() || rhs.is_inf() ) + { + result.set_inf( lhs.m_sign * rhs.m_sign ); + return; + } + + if( lhs.is_zero() || rhs.is_zero() ) { + result.set_zero( lhs.m_sign * rhs.m_sign ); + return; + } + + // + // do it + // + + int len_lhs = lhs.m_msw - lhs.m_lsw + 1; + int len_rhs = rhs.m_msw - rhs.m_lsw + 1; + + int new_size = sc_max( min_mant, len_lhs + len_rhs ); + int new_wp = ( lhs.m_wp - lhs.m_lsw ) + ( rhs.m_wp - rhs.m_lsw ); + int new_sign = lhs.m_sign * rhs.m_sign; + + result.resize_to( new_size ); + result.m_mant.clear(); + result.m_wp = new_wp; + result.m_sign = new_sign; + result.m_state = scfx_rep::normal; + + half_word *s1 = lhs.m_mant.half_addr( lhs.m_lsw ); + half_word *s2 = rhs.m_mant.half_addr( rhs.m_lsw ); + + half_word *t = result.m_mant.half_addr(); + + len_lhs <<= 1; + len_rhs <<= 1; + + int i1, i2; + + for( i1 = 0; i1 * half_word_incr < len_lhs; i1 += half_word_incr ) + { + word_short ls; + ls.l = 0; + + half_word v1 = s1[i1]; + + for( i2 = 0; i2 * half_word_incr < len_rhs; i2 += half_word_incr ) + { + ls.l += v1 * s2[i2]; + ls.s.l = ls.s.u + ( ( t[i2] += ls.s.l ) < ls.s.l ); + ls.s.u = 0; + } + + t[i2] = ls.s.l; + t += half_word_incr; + } + + result.find_sw(); + result.round( max_wl ); +} + + +// ---------------------------------------------------------------------------- +// DIV +// ---------------------------------------------------------------------------- + +scfx_rep* +div_scfx_rep( const scfx_rep& lhs, const scfx_rep& rhs, int div_wl ) +{ + scfx_rep& result = *new scfx_rep; + + // + // check for special cases + // + + if( lhs.is_nan() || rhs.is_nan() || (lhs.is_inf() && rhs.is_inf()) || + (lhs.is_zero() && rhs.is_zero()) ) + { + result.set_nan(); + return &result; + } + + if( lhs.is_inf() || rhs.is_zero() ) + { + result.set_inf( lhs.m_sign * rhs.m_sign ); + return &result; + } + + if( lhs.is_zero() || rhs.is_inf() ) + { + result.set_zero( lhs.m_sign * rhs.m_sign ); + return &result; + } + + // + // do it + // + + // compute one bit more for rounding + div_wl ++; + + result.resize_to( sc_max( n_word( div_wl ) + 1, min_mant ) ); + result.m_mant.clear(); + result.m_sign = lhs.m_sign * rhs.m_sign; + + int msb_lhs = scfx_find_msb( lhs.m_mant[lhs.m_msw] ) + + ( lhs.m_msw - lhs.m_wp ) * bits_in_word; + int msb_rhs = scfx_find_msb( rhs.m_mant[rhs.m_msw] ) + + ( rhs.m_msw - rhs.m_wp ) * bits_in_word; + + int msb_res = msb_lhs - msb_rhs; + int to_shift = -msb_res % bits_in_word; + int result_index; + + int c = ( msb_res % bits_in_word >= 0 ) ? 1 : 0; + + result_index = (result.size() - c) * bits_in_word + msb_res % bits_in_word; + result.m_wp = (result.size() - c) - msb_res / bits_in_word; + + scfx_rep remainder = lhs; + + // align msb from remainder to msb from rhs + remainder.lshift( to_shift ); + + // make sure msw( remainder ) < size - 1 + if( remainder.m_msw == remainder.size() - 1 ) + remainder.resize_to( remainder.size() + 1, 1 ); + + // make sure msw( remainder ) >= msw( rhs )! + int msw_diff = rhs.m_msw - remainder.m_msw; + if (msw_diff > 0) + remainder.resize_to( remainder.size() + msw_diff, -1 ); + + int counter; + + for( counter = div_wl; counter && ! remainder.is_zero(); counter -- ) + { + if( compare_msw_ff( rhs, remainder ) <= 0 ) + { + result.set_bin( result_index ); + sub_with_index( remainder.m_mant, remainder.m_msw, remainder.m_lsw, + rhs.m_mant, rhs.m_msw, rhs.m_lsw ); + } + result_index --; + remainder.shift_left( 1 ); + remainder.m_lsw = remainder.find_lsw(); + } + + // perform convergent rounding, if needed + if( counter == 0 ) + { + int index = result_index + 1 - result.m_wp * bits_in_word; + + scfx_index x = result.calc_indices( index ); + scfx_index x1 = result.calc_indices( index + 1 ); + + if( result.o_bit_at( x ) && result.o_bit_at( x1 ) ) + result.q_incr( x ); + + result.m_r_flag = true; + } + + result.find_sw(); + + return &result; +} + + +// ---------------------------------------------------------------------------- +// destructive shift mantissa to the left +// ---------------------------------------------------------------------------- + +void +scfx_rep::lshift( int n ) +{ + if( n == 0 ) + return; + + if( n < 0 ) + { + rshift( -n ); + return; + } + + if( is_normal() ) + { + int shift_bits = n % bits_in_word; + int shift_words = n / bits_in_word; + + // resize if needed + if( m_msw == size() - 1 && + scfx_find_msb( m_mant[m_msw] ) >= bits_in_word - shift_bits ) + resize_to( size() + 1, 1 ); + + // do it + m_wp -= shift_words; + shift_left( shift_bits ); + find_sw(); + } +} + + +// ---------------------------------------------------------------------------- +// destructive shift mantissa to the right +// ---------------------------------------------------------------------------- + +void +scfx_rep::rshift( int n ) +{ + if( n == 0 ) + return; + + if( n < 0 ) + { + lshift( -n ); + return; + } + + if( is_normal() ) + { + int shift_bits = n % bits_in_word; + int shift_words = n / bits_in_word; + + // resize if needed + if( m_lsw == 0 && scfx_find_lsb( m_mant[m_lsw] ) < shift_bits ) + resize_to( size() + 1, -1 ); + + // do it + m_wp += shift_words; + shift_right( shift_bits ); + find_sw(); + } +} + + +// ---------------------------------------------------------------------------- +// FRIEND FUNCTION : compare_abs +// +// Compares the absolute values of two scfx_reps, excluding the special cases. +// ---------------------------------------------------------------------------- + +int +compare_abs( const scfx_rep& a, const scfx_rep& b ) +{ + // check for zero + + word a_word = a.m_mant[a.m_msw]; + word b_word = b.m_mant[b.m_msw]; + + if( a_word == 0 || b_word == 0 ) + { + if( a_word != 0 ) + return 1; + if( b_word != 0 ) + return -1; + return 0; + } + + // compare msw index + + int a_msw = a.m_msw - a.m_wp; + int b_msw = b.m_msw - b.m_wp; + + if( a_msw > b_msw ) + return 1; + + if( a_msw < b_msw ) + return -1; + + // compare content + + int a_i = a.m_msw; + int b_i = b.m_msw; + + while( a_i >= a.m_lsw && b_i >= b.m_lsw ) + { + a_word = a.m_mant[a_i]; + b_word = b.m_mant[b_i]; + if( a_word > b_word ) + return 1; + if( a_word < b_word ) + return -1; + -- a_i; + -- b_i; + } + + bool a_zero = true; + while( a_i >= a.m_lsw ) + { + a_zero = a_zero && ( a.m_mant[a_i] == 0 ); + -- a_i; + } + + bool b_zero = true; + while( b_i >= b.m_lsw ) + { + b_zero = b_zero && ( b.m_mant[b_i] == 0 ); + -- b_i; + } + + // assertion: a_zero || b_zero == true + + if( ! a_zero && b_zero ) + return 1; + + if( a_zero && ! b_zero ) + return -1; + + return 0; +} + + +// ---------------------------------------------------------------------------- +// FRIEND FUNCTION : cmp_scfx_rep +// +// Compares the values of two scfx_reps, including the special cases. +// ---------------------------------------------------------------------------- + +int +cmp_scfx_rep( const scfx_rep& a, const scfx_rep& b ) +{ + // handle special cases + + if( a.is_nan() || b.is_nan() ) + { +#if 0 + if( a.is_nan() && b.is_nan() ) + { + return 0; + } +#endif + return 2; + } + + if( a.is_inf() || b.is_inf() ) + { + if( a.is_inf() ) + { + if( ! a.is_neg() ) + { + if( b.is_inf() && ! b.is_neg() ) + { + return 0; + } + else + { + return 1; + } + } + else + { + if( b.is_inf() && b.is_neg() ) + { + return 0; + } + else + { + return -1; + } + } + } + if( b.is_inf() ) + { + if( ! b.is_neg() ) + { + return -1; + } + else + { + return 1; + } + } + } + + if( a.is_zero() && b.is_zero() ) + { + return 0; + } + + // compare sign + + if( a.m_sign != b.m_sign ) + { + return a.m_sign; + } + + return ( a.m_sign * compare_abs( a, b ) ); +} + + +// ---------------------------------------------------------------------------- +// PRIVATE METHOD : quantization +// +// Performs destructive quantization. +// ---------------------------------------------------------------------------- + +void +scfx_rep::quantization( const scfx_params& params, bool& q_flag ) +{ + scfx_index x = calc_indices( params.iwl() - params.wl() ); + + if( x.wi() < 0 ) + return; + + if( x.wi() >= size() ) + resize_to( x.wi() + 1, 1 ); + + bool qb = q_bit( x ); + bool qz = q_zero( x ); + + q_flag = ( qb || ! qz ); + + if( q_flag ) + { + switch( params.q_mode() ) + { + case SC_TRN: // truncation + { + if( is_neg() ) + q_incr( x ); + break; + } + case SC_RND: // rounding to plus infinity + { + if( ! is_neg() ) + { + if( qb ) + q_incr( x ); + } + else + { + if( qb && ! qz ) + q_incr( x ); + } + break; + } + case SC_TRN_ZERO: // truncation to zero + { + break; + } + case SC_RND_INF: // rounding to infinity + { + if( qb ) + q_incr( x ); + break; + } + case SC_RND_CONV: // convergent rounding + { + if( (qb && ! qz) || (qb && qz && q_odd( x )) ) + q_incr( x ); + break; + } + case SC_RND_ZERO: // rounding to zero + { + if( qb && ! qz ) + q_incr( x ); + break; + } + case SC_RND_MIN_INF: // rounding to minus infinity + { + if( ! is_neg() ) + { + if( qb && ! qz ) + q_incr( x ); + } + else + { + if( qb ) + q_incr( x ); + } + break; + } + default: + ; + } + q_clear( x ); + + find_sw(); + } +} + + +// ---------------------------------------------------------------------------- +// PRIVATE METHOD : overflow +// +// Performs destructive overflow handling. +// ---------------------------------------------------------------------------- + +void +scfx_rep::overflow( const scfx_params& params, bool& o_flag ) +{ + scfx_index x = calc_indices( params.iwl() - 1 ); + + if( x.wi() >= size() ) + resize_to( x.wi() + 1, 1 ); + + if( x.wi() < 0 ) + { + resize_to( size() - x.wi(), -1 ); + x.wi( 0 ); + } + + bool zero_left = o_zero_left( x ); + bool bit_at = o_bit_at( x ); + bool zero_right = o_zero_right( x ); + + bool under = false; + bool over = false; + + sc_enc enc = params.enc(); + + if( enc == SC_TC_ ) + { + if( is_neg() ) + { + if( params.o_mode() == SC_SAT_SYM ) + under = ( ! zero_left || bit_at ); + else + under = (! zero_left || (zero_left && bit_at && ! zero_right)); + } + else + over = ( ! zero_left || bit_at ); + } + else + { + if( is_neg() ) + under = ( ! is_zero() ); + else + over = ( ! zero_left ); + } + + o_flag = ( under || over ); + + if( o_flag ) + { + scfx_index x2 = calc_indices( params.iwl() - params.wl() ); + + if( x2.wi() < 0 ) + { + resize_to( size() - x2.wi(), -1 ); + x.wi( x.wi() - x2.wi() ); + x2.wi( 0 ); + } + + switch( params.o_mode() ) + { + case SC_WRAP: // wrap-around + { + int n_bits = params.n_bits(); + + if( n_bits == 0 ) + { + // wrap-around all 'wl' bits + toggle_tc(); + o_extend( x, enc ); + toggle_tc(); + } + else if( n_bits < params.wl() ) + { + scfx_index x3 = calc_indices( params.iwl() - 1 - n_bits ); + + // wrap-around least significant 'wl - n_bits' bits; + // saturate most significant 'n_bits' bits + toggle_tc(); + o_set( x, x3, enc, under ); + o_extend( x, enc ); + toggle_tc(); + } + else + { + // saturate all 'wl' bits + if( under ) + o_set_low( x, enc ); + else + o_set_high( x, x2, enc ); + } + break; + } + case SC_SAT: // saturation + { + if( under ) + o_set_low( x, enc ); + else + o_set_high( x, x2, enc ); + break; + } + case SC_SAT_SYM: // symmetrical saturation + { + if( under ) + { + if( enc == SC_TC_ ) + o_set_high( x, x2, SC_TC_, -1 ); + else + o_set_low( x, SC_US_ ); + } + else + o_set_high( x, x2, enc ); + break; + } + case SC_SAT_ZERO: // saturation to zero + { + set_zero(); + break; + } + case SC_WRAP_SM: // sign magnitude wrap-around + { + SC_ERROR_IF_( enc == SC_US_, + sc_core::SC_ID_WRAP_SM_NOT_DEFINED_ ); + + int n_bits = params.n_bits(); + + if( n_bits == 0 ) + { + scfx_index x4 = calc_indices( params.iwl() ); + + if( x4.wi() >= size() ) + resize_to( x4.wi() + 1, 1 ); + + toggle_tc(); + if( o_bit_at( x4 ) != o_bit_at( x ) ) + o_invert( x2 ); + o_extend( x, SC_TC_ ); + toggle_tc(); + } + else if( n_bits == 1 ) + { + toggle_tc(); + if( is_neg() != o_bit_at( x ) ) + o_invert( x2 ); + o_extend( x, SC_TC_ ); + toggle_tc(); + } + else if( n_bits < params.wl() ) + { + scfx_index x3 = calc_indices( params.iwl() - 1 - n_bits ); + scfx_index x4 = calc_indices( params.iwl() - n_bits ); + + // wrap-around least significant 'wl - n_bits' bits; + // saturate most significant 'n_bits' bits + toggle_tc(); + if( is_neg() == o_bit_at( x4 ) ) + o_invert( x2 ); + o_set( x, x3, SC_TC_, under ); + o_extend( x, SC_TC_ ); + toggle_tc(); + } + else + { + if( under ) + o_set_low( x, SC_TC_ ); + else + o_set_high( x, x2, SC_TC_ ); + } + break; + } + default: + ; + } + + find_sw(); + } +} + + +// ---------------------------------------------------------------------------- +// PUBLIC METHOD : cast +// +// Performs a destructive cast operation on a scfx_rep. +// ---------------------------------------------------------------------------- + +void +scfx_rep::cast( const scfx_params& params, bool& q_flag, bool& o_flag ) +{ + q_flag = false; + o_flag = false; + + // check for special cases + + if( is_zero() ) + { + if( is_neg() ) + m_sign = 1; + return; + } + + // perform casting + + quantization( params, q_flag ); + overflow( params, o_flag ); + + // check for special case: -0 + + if( is_zero() && is_neg() ) + m_sign = 1; +} + + +// ---------------------------------------------------------------------------- +// make sure, the two mantissas are aligned +// ---------------------------------------------------------------------------- + +void +align( const scfx_rep& lhs, const scfx_rep& rhs, int& new_wp, + int& len_mant, scfx_mant_ref& lhs_mant, scfx_mant_ref& rhs_mant ) +{ + bool need_lhs = true; + bool need_rhs = true; + + if( lhs.m_wp != rhs.m_wp || lhs.size() != rhs.size() ) + { + int lower_bound_lhs = lhs.m_lsw - lhs.m_wp; + int upper_bound_lhs = lhs.m_msw - lhs.m_wp; + int lower_bound_rhs = rhs.m_lsw - rhs.m_wp; + int upper_bound_rhs = rhs.m_msw - rhs.m_wp; + + int lower_bound = sc_min( lower_bound_lhs, lower_bound_rhs ); + int upper_bound = sc_max( upper_bound_lhs, upper_bound_rhs ); + + new_wp = -lower_bound; + len_mant = sc_max( min_mant, upper_bound - lower_bound + 1 ); + + if( new_wp != lhs.m_wp || len_mant != lhs.size() ) + { + lhs_mant = lhs.resize( len_mant, new_wp ); + need_lhs = false; + } + + if( new_wp != rhs.m_wp || len_mant != rhs.size() ) + { + rhs_mant = rhs.resize( len_mant, new_wp ); + need_rhs = false; + } + } + + if( need_lhs ) + { + lhs_mant = lhs.m_mant; + } + + if( need_rhs ) + { + rhs_mant = rhs.m_mant; + } +} + + +// ---------------------------------------------------------------------------- +// compare two mantissas +// ---------------------------------------------------------------------------- + +int +compare_msw_ff( const scfx_rep& lhs, const scfx_rep& rhs ) +{ + // special case: rhs.m_mant[rhs.m_msw + 1] == 1 + if( rhs.m_msw < rhs.size() - 1 && rhs.m_mant[rhs.m_msw + 1 ] != 0 ) + { + return -1; + } + + int lhs_size = lhs.m_msw - lhs.m_lsw + 1; + int rhs_size = rhs.m_msw - rhs.m_lsw + 1; + + int size = sc_min( lhs_size, rhs_size ); + + int lhs_index = lhs.m_msw; + int rhs_index = rhs.m_msw; + + int i; + + for( i = 0; + i < size && lhs.m_mant[lhs_index] == rhs.m_mant[rhs_index]; + i ++ ) + { + lhs_index --; + rhs_index --; + } + + if( i == size ) + { + if( lhs_size == rhs_size ) + { + return 0; + } + + if( lhs_size < rhs_size ) + { + return -1; + } + else + { + return 1; + } + } + + if( lhs.m_mant[lhs_index] < rhs.m_mant[rhs_index] ) + { + return -1; + } else { + return 1; + } +} + + +// ---------------------------------------------------------------------------- +// divide the mantissa by ten +// ---------------------------------------------------------------------------- + +unsigned int +scfx_rep::divide_by_ten() +{ +#if defined( SC_BIG_ENDIAN ) + half_word* hw = (half_word*) &m_mant[m_msw]; +#elif defined( SC_LITTLE_ENDIAN ) + half_word* hw = ( (half_word*) &m_mant[m_msw] ) + 1; +#endif + + unsigned int remainder = 0; + + word_short ls; + ls.l = 0; + +#if defined( SC_BIG_ENDIAN ) + for( int i = 0, end = ( m_msw - m_wp + 1 ) * 2; i < end; i ++ ) +#elif defined( SC_LITTLE_ENDIAN ) + for( int i = 0, end = -( m_msw - m_wp + 1 ) * 2; i > end; i -- ) +#endif + { + ls.s.u = static_cast<half_word>( remainder ); + ls.s.l = hw[i]; + remainder = ls.l % 10; + ls.l /= 10; + hw[i] = ls.s.l; + } + + return remainder; +} + + +// ---------------------------------------------------------------------------- +// multiply the mantissa by ten +// ---------------------------------------------------------------------------- + +void +scfx_rep::multiply_by_ten() +{ + int size = m_mant.size() + 1; + + scfx_mant mant8( size ); + scfx_mant mant2( size ); + + size --; + + mant8[size] = (m_mant[size - 1] >> (bits_in_word - 3)); + mant2[size] = (m_mant[size - 1] >> (bits_in_word - 1)); + + while( -- size ) + { + mant8[size] = ( m_mant[size] << 3 ) | + ( m_mant[size - 1] >> ( bits_in_word - 3 ) ); + mant2[size] = ( m_mant[size] << 1 ) | + ( m_mant[size - 1] >> ( bits_in_word - 1 ) ); + } + + mant8[0] = ( m_mant[0] << 3 ); + mant2[0] = ( m_mant[0] << 1 ); + + add_mants( m_mant.size(), m_mant, mant8, mant2 ); + +#if 0 + for( int i = size() - 1; i > 0; i -- ) + { + m_mant[i] = ( m_mant[i] << 3 ) | + ( m_mant[i-1] >> ( bits_in_word - 3 ) ) + + ( m_mant[i] << 1 ) | + ( m_mant[i-1] >> ( bits_in_word - 1 ) ); + } + m_mant[0] = ( m_mant[0] << 3 ) + ( m_mant[0] << 1 ); +#endif +} + + +// ---------------------------------------------------------------------------- +// normalize +// ---------------------------------------------------------------------------- + +void +scfx_rep::normalize( int exponent ) +{ + int shift = exponent % bits_in_word; + if( shift < 0 ) + { + shift += bits_in_word; + } + + if( shift ) + { + shift_left( shift ); + } + + find_sw(); + + m_wp = (shift - exponent) / bits_in_word; +} + + +// ---------------------------------------------------------------------------- +// return a new mantissa that is aligned and resized +// ---------------------------------------------------------------------------- + +scfx_mant* +scfx_rep::resize( int new_size, int new_wp ) const +{ + scfx_mant *result = new scfx_mant( new_size ); + + result->clear(); + + int shift = new_wp - m_wp; + + for( int j = m_lsw; j <= m_msw; j ++ ) + { + (*result)[j+shift] = m_mant[j]; + } + + return result; +} + + +// ---------------------------------------------------------------------------- +// set a single bit +// ---------------------------------------------------------------------------- + +void +scfx_rep::set_bin( int i ) +{ + m_mant[i >> 5] |= 1 << ( i & 31 ); +} + + +// ---------------------------------------------------------------------------- +// set three bits +// ---------------------------------------------------------------------------- + +void +scfx_rep::set_oct( int i, int n ) +{ + if( n & 1 ) + { + m_mant[i >> 5] |= 1 << ( i & 31 ); + } + i ++; + if( n & 2 ) + { + m_mant[i >> 5] |= 1 << ( i & 31 ); + } + i ++; + if( n & 4 ) + { + m_mant[i >> 5] |= 1 << ( i & 31 ); + } +} + + +// ---------------------------------------------------------------------------- +// set four bits +// ---------------------------------------------------------------------------- + +void +scfx_rep::set_hex( int i, int n ) +{ + if( n & 1 ) + { + m_mant[i >> 5] |= 1 << ( i & 31 ); + } + i ++; + if( n & 2 ) + { + m_mant[i >> 5] |= 1 << ( i & 31 ); + } + i ++; + if( n & 4 ) + { + m_mant[i >> 5] |= 1 << ( i & 31 ); + } + i ++; + if( n & 8 ) + { + m_mant[i >> 5] |= 1 << ( i & 31 ); + } +} + + +// ---------------------------------------------------------------------------- +// PRIVATE METHOD : shift_left +// +// Shifts a scfx_rep to the left by a MAXIMUM of bits_in_word - 1 bits. +// ---------------------------------------------------------------------------- + +void +scfx_rep::shift_left( int n ) +{ + if( n != 0 ) + { + int shift_left = n; + int shift_right = bits_in_word - n; + + SC_ASSERT_( !(m_mant[size()-1] >> shift_right), + "shift_left overflow" ); + + for( int i = size() - 1; i > 0; i -- ) + { + m_mant[i] = ( m_mant[i] << shift_left ) | + ( m_mant[i-1] >> shift_right ); + } + m_mant[0] <<= shift_left; + } +} + + +// ---------------------------------------------------------------------------- +// PRIVATE METHOD : shift_right +// +// Shifts a scfx_rep to the right by a MAXIMUM of bits_in_word - 1 bits. +// ---------------------------------------------------------------------------- + +void +scfx_rep::shift_right( int n ) +{ + if( n != 0 ) + { + int shift_left = bits_in_word - n; + int shift_right = n; + + SC_ASSERT_( !(m_mant[0] << shift_left), "shift_right overflow" ); + + for( int i = 0; i < size() - 1; i ++ ) + { + m_mant[i] = ( m_mant[i] >> shift_right ) | + ( m_mant[i+1] << shift_left ); + } + m_mant[size()-1] >>= shift_right; + } +} + + +// ---------------------------------------------------------------------------- +// METHOD : get_bit +// +// Tests a bit, in two's complement. +// ---------------------------------------------------------------------------- + +bool +scfx_rep::get_bit( int i ) const +{ + if( ! is_normal() ) + return false; + + scfx_index x = calc_indices( i ); + + if( x.wi() >= size() ) + return is_neg(); + + if( x.wi() < 0 ) + return false; + + const_cast<scfx_rep*>( this )->toggle_tc(); + + bool result = ( m_mant[x.wi()] & ( 1 << x.bi() ) ) != 0; + + const_cast<scfx_rep*>( this )->toggle_tc(); + + return result; +} + + +// ---------------------------------------------------------------------------- +// METHOD : set +// +// Sets a bit, in two's complement, between iwl-1 and -fwl. +// ---------------------------------------------------------------------------- + +bool +scfx_rep::set( int i, const scfx_params& params ) +{ + if( ! is_normal() ) + return false; + + scfx_index x = calc_indices( i ); + + if( x.wi() >= size() ) + { + if( is_neg() ) + return true; + else + resize_to( x.wi() + 1, 1 ); + } + else if( x.wi() < 0 ) + { + resize_to( size() - x.wi(), -1 ); + x.wi( 0 ); + } + + toggle_tc(); + + m_mant[x.wi()] |= 1 << x.bi(); + + if( i == params.iwl() - 1 ) + o_extend( x, params.enc() ); // sign extension + + toggle_tc(); + + find_sw(); + + return true; +} + + +// ---------------------------------------------------------------------------- +// METHOD : clear +// +// Clears a bit, in two's complement, between iwl-1 and -fwl. +// ---------------------------------------------------------------------------- + +bool +scfx_rep::clear( int i, const scfx_params& params ) +{ + if( ! is_normal() ) + return false; + + scfx_index x = calc_indices( i ); + + if( x.wi() >= size() ) + { + if( ! is_neg() ) + return true; + else + resize_to( x.wi() + 1, 1 ); + } + else if( x.wi() < 0 ) + return true; + + toggle_tc(); + + m_mant[x.wi()] &= ~( 1 << x.bi() ); + + if( i == params.iwl() - 1 ) + o_extend( x, params.enc() ); // sign extension + + toggle_tc(); + + find_sw(); + + return true; +} + + +// ---------------------------------------------------------------------------- +// METHOD : get_slice +// ---------------------------------------------------------------------------- + +bool +scfx_rep::get_slice( int i, int j, const scfx_params&, + sc_bv_base& bv ) const +{ + if( is_nan() || is_inf() ) + return false; + + // get the bits + + int l = j; + for( int k = 0; k < bv.length(); ++ k ) + { + bv[k] = get_bit( l ); + + if( i >= j ) + ++ l; + else + -- l; + } + + return true; +} + +bool +scfx_rep::set_slice( int i, int j, const scfx_params& params, + const sc_bv_base& bv ) +{ + if( is_nan() || is_inf() ) + return false; + + // set the bits + + int l = j; + for( int k = 0; k < bv.length(); ++ k ) + { + if( bv[k].to_bool() ) + set( l, params ); + else + clear( l, params ); + + if( i >= j ) + ++ l; + else + -- l; + } + + return true; +} + + +// ---------------------------------------------------------------------------- +// METHOD : print +// ---------------------------------------------------------------------------- + +void +scfx_rep::print( ::std::ostream& os ) const +{ + os << to_string( SC_DEC, -1, SC_E ); +} + + +// ---------------------------------------------------------------------------- +// METHOD : dump +// ---------------------------------------------------------------------------- + +void +scfx_rep::dump( ::std::ostream& os ) const +{ + os << "scfx_rep" << ::std::endl; + os << "(" << ::std::endl; + + os << "mant =" << ::std::endl; + for( int i = size() - 1; i >= 0; i -- ) + { + char buf[BUFSIZ]; + std::sprintf( buf, " %d: %10u (%8x)", i, (int) m_mant[i], (int) m_mant[i] ); + os << buf << ::std::endl; + } + + os << "wp = " << m_wp << ::std::endl; + os << "sign = " << m_sign << ::std::endl; + + os << "state = "; + switch( m_state ) + { + case normal: + os << "normal"; + break; + case infinity: + os << "infinity"; + break; + case not_a_number: + os << "not_a_number"; + break; + default: + os << "unknown"; + } + os << ::std::endl; + + os << "msw = " << m_msw << ::std::endl; + os << "lsw = " << m_lsw << ::std::endl; + + os << ")" << ::std::endl; +} + + +// ---------------------------------------------------------------------------- +// METHOD : get_type +// ---------------------------------------------------------------------------- + +void +scfx_rep::get_type( int& wl, int& iwl, sc_enc& enc ) const +{ + if( is_nan() || is_inf() ) + { + wl = 0; + iwl = 0; + enc = SC_TC_; + return; + } + + if( is_zero() ) + { + wl = 1; + iwl = 1; + enc = SC_US_; + return; + } + + int msb = ( m_msw - m_wp ) * bits_in_word + + scfx_find_msb( m_mant[ m_msw ] ) + 1; + while( get_bit( msb ) == get_bit( msb - 1 ) ) + { + -- msb; + } + + int lsb = ( m_lsw - m_wp ) * bits_in_word + + scfx_find_lsb( m_mant[ m_lsw ] ); + + if( is_neg() ) + { + wl = msb - lsb + 1; + iwl = msb + 1; + enc = SC_TC_; + } + else + { + wl = msb - lsb; + iwl = msb; + enc = SC_US_; + } +} + + +// ---------------------------------------------------------------------------- +// PRIVATE METHOD : round +// +// Performs convergent rounding (rounding to even) as in floating-point. +// ---------------------------------------------------------------------------- + +void +scfx_rep::round( int wl ) +{ + // check for special cases + + if( is_nan() || is_inf() || is_zero() ) + return; + + // estimate effective wordlength and compare + + int wl_effective; + + wl_effective = ( m_msw - m_lsw + 1 ) * bits_in_word; + if( wl_effective <= wl ) + return; + + // calculate effective wordlength and compare + + int msb = scfx_find_msb( m_mant[m_msw] ); + int lsb = scfx_find_lsb( m_mant[m_lsw] ); + + wl_effective = ( m_msw * bits_in_word + msb ) - + ( m_lsw * bits_in_word + lsb ) + 1; + if( wl_effective <= wl ) + return; + + // perform rounding + + int wi = m_msw - ( wl - 1 ) / bits_in_word; + int bi = msb - ( wl - 1 ) % bits_in_word; + if( bi < 0 ) + { + -- wi; + bi += bits_in_word; + } + + scfx_index x( wi, bi ); + + if( (q_bit( x ) && ! q_zero( x )) || + (q_bit( x ) && q_zero( x ) && q_odd( x )) ) + q_incr( x ); + q_clear( x ); + + find_sw(); + + m_r_flag = true; +} + +} // namespace sc_dt + + +// Taf! diff --git a/ext/systemc/src/sysc/datatypes/fx/scfx_rep.h b/ext/systemc/src/sysc/datatypes/fx/scfx_rep.h new file mode 100644 index 000000000..c5b76ce54 --- /dev/null +++ b/ext/systemc/src/sysc/datatypes/fx/scfx_rep.h @@ -0,0 +1,842 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + scfx_rep.h - + + Original Author: Robert Graulich, Synopsys, Inc. + Martin Janssen, Synopsys, Inc. + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + +// $Log: scfx_rep.h,v $ +// Revision 1.6 2011/08/24 22:05:43 acg +// Torsten Maehne: initialization changes to remove warnings. +// +// Revision 1.5 2011/07/25 10:20:29 acg +// Andy Goodrich: check in aftermath of call to automake. +// +// Revision 1.4 2010/12/07 20:09:08 acg +// Andy Goodrich: Philipp Hartmann's constructor disambiguation fix +// +// Revision 1.3 2010/08/03 15:54:52 acg +// Andy Goodrich: formatting. +// +// Revision 1.2 2010/03/15 18:29:01 acg +// Andy Goodrich: Moved default argument specifications from friend +// declarations to the actual function signatures. +// +// Revision 1.1.1.1 2006/12/15 20:20:04 acg +// SystemC 2.3 +// +// Revision 1.4 2006/03/13 20:24:27 acg +// Andy Goodrich: Addition of function declarations, e.g., neg_scfx_rep(), +// to keep gcc 4.x happy. +// +// Revision 1.3 2006/01/13 18:53:58 acg +// Andy Goodrich: added $Log command so that CVS comments are reproduced in +// the source. +// + +#ifndef SCFX_REP_H +#define SCFX_REP_H + + +#include <climits> + +#include "sysc/datatypes/fx/scfx_mant.h" +#include "sysc/datatypes/fx/scfx_params.h" +#include "sysc/datatypes/fx/scfx_string.h" + + +namespace sc_dt +{ + +// classes defined in this module +class scfx_index; +class scfx_rep; + +// forward class declarations +class sc_bv_base; +class sc_signed; +class sc_unsigned; + +// function declarations +void multiply( scfx_rep&, const scfx_rep&, const scfx_rep&, + int max_wl = SC_DEFAULT_MAX_WL_ ); +scfx_rep* neg_scfx_rep( const scfx_rep& ); +scfx_rep* mult_scfx_rep( const scfx_rep&, const scfx_rep&, + int max_wl = SC_DEFAULT_MAX_WL_ ); +scfx_rep* div_scfx_rep( const scfx_rep&, const scfx_rep&, + int max_wl = SC_DEFAULT_DIV_WL_ ); +scfx_rep* add_scfx_rep( const scfx_rep&, const scfx_rep&, + int max_wl = SC_DEFAULT_MAX_WL_ ); +scfx_rep* sub_scfx_rep( const scfx_rep&, const scfx_rep&, + int max_wl = SC_DEFAULT_MAX_WL_ ); +scfx_rep* lsh_scfx_rep( const scfx_rep&, int ); +scfx_rep* rsh_scfx_rep( const scfx_rep&, int ); +int cmp_scfx_rep( const scfx_rep&, const scfx_rep& ); + + +const int min_mant = 4; + +const int bits_in_int = sizeof(int) * CHAR_BIT; +const int bits_in_word = sizeof(word) * CHAR_BIT; + + +// ---------------------------------------------------------------------------- +// CLASS : scfx_index +// ---------------------------------------------------------------------------- + +class scfx_index +{ + +public: + + scfx_index( int wi_, int bi_ ) : m_wi( wi_ ), m_bi( bi_ ) {} + + int wi() const { return m_wi; } + int bi() const { return m_bi; } + + void wi( int wi_ ) { m_wi = wi_; } + +private: + + int m_wi; + int m_bi; + +}; + + +// ---------------------------------------------------------------------------- +// CLASS : scfx_rep +// +// Arbitrary-precision fixed-point implementation class. +// ---------------------------------------------------------------------------- + +class scfx_rep +{ + enum state + { + normal, + infinity, + not_a_number + }; + +public: + + // constructors + + scfx_rep(); + explicit scfx_rep( int ); + explicit scfx_rep( unsigned int ); + explicit scfx_rep( long ); + explicit scfx_rep( unsigned long ); + explicit scfx_rep( double ); + explicit scfx_rep( const char* ); + explicit scfx_rep( int64 ); + explicit scfx_rep( uint64 ); + explicit scfx_rep( const sc_signed& ); + explicit scfx_rep( const sc_unsigned& ); + + + // copy constructor + + scfx_rep( const scfx_rep& ); + + + // destructor + + ~scfx_rep(); + + + void* operator new( std::size_t ); + void operator delete( void*, std::size_t ); + + + void from_string( const char*, int ); + + double to_double() const; + + const char* to_string( sc_numrep, + int, + sc_fmt, + const scfx_params* = 0 ) const; + + + // assignment operator + + void operator = ( const scfx_rep& ); + + friend void multiply( scfx_rep&, const scfx_rep&, const scfx_rep&, int ); + + friend scfx_rep* neg_scfx_rep( const scfx_rep& ); + friend scfx_rep* mult_scfx_rep( const scfx_rep&, const scfx_rep&, int ); + friend scfx_rep* div_scfx_rep( const scfx_rep&, const scfx_rep&, int ); + friend scfx_rep* add_scfx_rep( const scfx_rep&, const scfx_rep&, int ); + friend scfx_rep* sub_scfx_rep( const scfx_rep&, const scfx_rep&, int ); + friend scfx_rep* lsh_scfx_rep( const scfx_rep&, int ); + friend scfx_rep* rsh_scfx_rep( const scfx_rep&, int ); + + void lshift( int ); + void rshift( int ); + + friend int cmp_scfx_rep( const scfx_rep&, const scfx_rep& ); + + void cast( const scfx_params&, bool&, bool& ); + + bool is_neg() const; + bool is_zero() const; + bool is_nan() const; + bool is_inf() const; + bool is_normal() const; + + void set_zero( int = 1 ); + void set_nan(); + void set_inf( int ); + + bool get_bit( int ) const; + bool set( int, const scfx_params& ); + bool clear( int, const scfx_params& ); + + bool get_slice( int, int, const scfx_params&, sc_bv_base& ) const; + bool set_slice( int, int, const scfx_params&, const sc_bv_base& ); + + void print( ::std::ostream& ) const; + void dump( ::std::ostream& ) const; + + void get_type( int&, int&, sc_enc& ) const; + + friend scfx_rep* quantization_scfx_rep( const scfx_rep&, + const scfx_params&, + bool& ); + friend scfx_rep* overflow_scfx_rep( const scfx_rep&, + const scfx_params&, + bool& ); + + bool rounding_flag() const; + +private: + + friend void align( const scfx_rep&, const scfx_rep&, int&, int&, + scfx_mant_ref&, scfx_mant_ref& ); + friend int compare_msw( const scfx_rep&, const scfx_rep& ); + friend int compare_msw_ff( const scfx_rep& lhs, const scfx_rep& rhs ); + unsigned int divide_by_ten(); + int find_lsw() const; + int find_msw() const; + void find_sw(); + void multiply_by_ten(); + void normalize( int ); + scfx_mant* resize( int, int ) const; + void set_bin( int ); + void set_oct( int, int ); + void set_hex( int, int ); + void shift_left( int ); + void shift_right( int ); + + const scfx_index calc_indices( int ) const; + + void o_extend( const scfx_index&, sc_enc ); + bool o_bit_at( const scfx_index& ) const; + bool o_zero_left( const scfx_index& ) const; + bool o_zero_right( const scfx_index& ) const; + void o_set_low( const scfx_index&, sc_enc ); + void o_set_high( const scfx_index&, const scfx_index&, sc_enc, int = 1 ); + void o_set( const scfx_index&, const scfx_index&, sc_enc, bool ); + void o_invert( const scfx_index& ); + bool q_bit( const scfx_index& ) const; + void q_clear( const scfx_index& ); + void q_incr( const scfx_index& ); + bool q_odd( const scfx_index& ) const; + bool q_zero( const scfx_index& ) const; + + void resize_to( int, int = 0 ); + int size() const; + void toggle_tc(); + + friend void print_dec( scfx_string&, const scfx_rep&, int, sc_fmt ); + friend void print_other( scfx_string&, const scfx_rep&, sc_numrep, int, + sc_fmt, const scfx_params* ); + + void quantization( const scfx_params&, bool& ); + void overflow( const scfx_params&, bool& ); + + friend int compare_abs( const scfx_rep&, const scfx_rep& ); + + void round( int ); + +private: + + scfx_mant m_mant; // mantissa (bits of the value). + int m_wp; // index of highest order word in value. + int m_sign; // sign of value. + state m_state; // value state, e.g., normal, inf, etc. + int m_msw; // index of most significant non-zero word. + int m_lsw; // index of least significant non-zero word. + bool m_r_flag; // true if founding occurred. + +}; + + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + +inline +void +scfx_rep::set_zero( int sign ) +{ + m_mant.clear(); + m_wp = m_msw = m_lsw = 0; + m_sign = sign; + m_state = normal; +} + +inline +void +scfx_rep::set_nan() +{ + m_mant.resize_to( min_mant ); + m_state = not_a_number; +} + +inline +void +scfx_rep::set_inf( int sign ) +{ + m_mant.resize_to( min_mant ); + m_state = infinity; + m_sign = sign; +} + + +// constructors + +inline +scfx_rep::scfx_rep( const char* s ) +: m_mant( min_mant ), m_wp( 2 ), m_sign( 1 ), m_state( normal ), + m_msw(0), m_lsw(0), m_r_flag( false ) +{ + from_string( s, SC_DEFAULT_CTE_WL_ ); +} + + +// destructor + +inline +scfx_rep::~scfx_rep() +{} + + +// assignment operator + +inline +void +scfx_rep::operator = ( const scfx_rep& f ) +{ + if( &f != this ) + { + m_mant = f.m_mant; + m_wp = f.m_wp; + m_sign = f.m_sign; + m_state = f.m_state; + m_msw = f.m_msw; + m_lsw = f.m_lsw; + round( SC_DEFAULT_MAX_WL_ ); + } +} + +inline +scfx_rep* +neg_scfx_rep( const scfx_rep& a ) +{ + scfx_rep& c = *new scfx_rep( a ); + c.m_sign = - c.m_sign; + return &c; +} + +inline +scfx_rep* +mult_scfx_rep( const scfx_rep& a, const scfx_rep& b, int max_wl ) +{ + scfx_rep& c = *new scfx_rep; + sc_dt::multiply( c, a, b, max_wl ); + return &c; +} + +inline +scfx_rep* +lsh_scfx_rep( const scfx_rep& a, int b ) +{ + scfx_rep& c = *new scfx_rep( a ); + c.lshift( b ); + return &c; +} + +inline +scfx_rep* +rsh_scfx_rep( const scfx_rep& a, int b ) +{ + scfx_rep& c = *new scfx_rep( a ); + c.rshift( b ); + return &c; +} + +inline +int +scfx_rep::size() const +{ + return m_mant.size(); +} + +inline +bool +scfx_rep::is_neg() const +{ + return ( m_sign == -1 ); +} + +inline +bool +scfx_rep::is_zero() const +{ + if( m_state != normal ) + return false; + + for( int i = 0; i < size(); i ++ ) + { + if( m_mant[i] ) + return false; + } + + return true; +} + +inline +bool +scfx_rep::is_nan() const +{ + return ( m_state == not_a_number ); +} + +inline +bool +scfx_rep::is_inf() const +{ + return ( m_state == infinity ); +} + +inline +bool +scfx_rep::is_normal() const +{ + return ( m_state == normal ); +} + +inline +scfx_rep* +quantization_scfx_rep( const scfx_rep& a, + const scfx_params& params, + bool& q_flag ) +{ + scfx_rep& c = *new scfx_rep( a ); + c.quantization( params, q_flag ); + return &c; +} + +inline +scfx_rep* +overflow_scfx_rep( const scfx_rep& a, + const scfx_params& params, + bool& o_flag ) +{ + scfx_rep& c = *new scfx_rep( a ); + c.overflow( params, o_flag ); + return &c; +} + +inline +bool +scfx_rep::rounding_flag() const +{ + return m_r_flag; +} + +inline +void +scfx_rep::resize_to( int new_size, int restore ) +{ + if( restore == -1 ) + { + int size_incr = new_size - size(); + m_wp += size_incr; + m_msw += size_incr; + m_lsw += size_incr; + } + m_mant.resize_to( new_size, restore ); +} + +inline +const scfx_index +scfx_rep::calc_indices( int n ) const +{ + int wi = n / bits_in_word + m_wp; + int bi = n % bits_in_word; + + if( bi < 0 ) + { + bi += bits_in_word; + -- wi; + } + + return scfx_index( wi, bi ); +} + +inline +void +scfx_rep::o_extend( const scfx_index& x, sc_enc enc ) +{ + int wi = x.wi(); + int bi = x.bi(); + + SC_ASSERT_( wi >= 0 && wi < size(), "word index out of range" ); + + if( enc == SC_US_ || ( m_mant[wi] & ( ((word)1) << bi ) ) == 0 ) + { + if( bi != bits_in_word - 1 ) + m_mant[wi] &= ~( ((word)-1) << ( bi + 1 ) ); + for( int i = wi + 1; i < size(); ++ i ) + m_mant[i] = 0; + m_sign = 1; + } + else + { + if( bi != bits_in_word - 1 ) + m_mant[wi] |= ( ((word)-1) << ( bi + 1 ) ); + for( int i = wi + 1; i < size(); ++ i ) + m_mant[i] = static_cast<word>( -1 ); + m_sign = -1; + } +} + +inline +bool +scfx_rep::o_bit_at( const scfx_index& x ) const +{ + int wi = x.wi(); + int bi = x.bi(); + + SC_ASSERT_( wi >= 0 && wi < size(), "word index out of range" ); + + return ( m_mant[wi] & ( ((word)1) << bi ) ) != 0; +} + +inline +bool +scfx_rep::o_zero_left( const scfx_index& x ) const +{ + int wi = x.wi(); + int bi = x.bi(); + + SC_ASSERT_( wi >= 0 && wi < size(), "word index out of range" ); + + bool zero = true; + if( bi != bits_in_word - 1 ) + zero = ( m_mant[wi] & ( ((word)-1) << ( bi + 1 ) ) ) == 0; + for( int i = wi + 1; i < size(); ++ i ) + zero = zero && m_mant[i] == 0; + + return zero; +} + +inline +bool +scfx_rep::o_zero_right( const scfx_index& x ) const +{ + int wi = x.wi(); + int bi = x.bi(); + + SC_ASSERT_( wi >= 0 && wi < size(), "word index out of range" ); + + bool zero = ( m_mant[wi] & ~( ((word)-1) << bi ) ) == 0; + for( int i = wi - 1; i >= 0; -- i ) + zero = zero && m_mant[i] == 0; + + return zero; +} + +inline +void +scfx_rep::o_set_low( const scfx_index& x, sc_enc enc ) +{ + int wi = x.wi(); + int bi = x.bi(); + + SC_ASSERT_( wi >= 0 && wi < size(), "word index out of range" ); + + m_mant.clear(); + + if( enc == SC_TC_ ) + { + m_mant[wi] |= ( ((word)1) << bi ); + m_sign = -1; + } + else + m_sign = 1; +} + +inline +void +scfx_rep::o_set_high( const scfx_index& x, const scfx_index& x2, + sc_enc enc, int sign ) +{ + int wi = x.wi(); + int bi = x.bi(); + int wi2 = x2.wi(); + int bi2 = x2.bi(); + + SC_ASSERT_( wi >= 0 && wi < size(), "word index out of range" ); + SC_ASSERT_( wi2 >= 0 && wi2 < size(), "word index out of range" ); + + int i; + + for( i = 0; i < size(); ++ i ) + m_mant[i] = static_cast<word>( -1 ); + + m_mant[wi] &= ~( ((word)-1) << bi ); + for( i = wi + 1; i < size(); ++ i ) + m_mant[i] = 0; + + m_mant[wi2] &= ( ((word)-1) << bi2 ); + for( i = wi2 - 1; i >= 0; -- i ) + m_mant[i] = 0; + + if( enc == SC_TC_ ) + m_sign = sign; + else + { + m_mant[wi] |= ( ((word)1) << bi ); + m_sign = 1; + } +} + +inline +void +scfx_rep::o_set( const scfx_index& x, const scfx_index& x3, + sc_enc enc, bool under ) +{ + int wi = x.wi(); + int bi = x.bi(); + int wi3 = x3.wi(); + int bi3 = x3.bi(); + + SC_ASSERT_( wi >= 0 && wi < size(), "word index out of range" ); + SC_ASSERT_( wi3 >= 0 && wi3 < size(), "word index out of range" ); + + if( bi3 != bits_in_word - 1 ) + { + if( under ) + m_mant[wi3] &= ~( ((word)-1) << ( bi3 + 1 ) ); + else + m_mant[wi3] |= ( ((word)-1) << ( bi3 + 1 ) ); + } + for( int i = wi3 + 1; i < size(); ++ i ) + { + if( under ) + m_mant[i] = 0; + else + m_mant[i] = static_cast<word>( -1 ); + } + + if( enc == SC_TC_ ) + { + if( under ) + m_mant[wi] |= ( ((word)1) << bi ); + else + m_mant[wi] &= ~( ((word)1) << bi ); + } +} + +inline +void +scfx_rep::o_invert( const scfx_index& x2 ) +{ + int wi2 = x2.wi(); + int bi2 = x2.bi(); + + m_mant[wi2] ^= ( ((word)-1) << bi2 ); + for( int i = wi2 + 1; i < size(); ++ i ) + m_mant[i] = ~ m_mant[i]; +} + +inline +bool +scfx_rep::q_bit( const scfx_index& x ) const +{ + int wi = x.wi(); + int bi = x.bi(); + + SC_ASSERT_( wi >= 0 && wi < size(), "word index out of range" ); + + if( bi != 0 ) + return ( m_mant[wi] & ( ((word)1) << ( bi - 1 ) ) ) != 0; + else if( wi != 0 ) + return ( m_mant[wi - 1] & ( ((word)1) << ( bits_in_word - 1 ) ) ) != 0; + else + return false; +} + +inline +void +scfx_rep::q_clear( const scfx_index& x ) +{ + int wi = x.wi(); + int bi = x.bi(); + + SC_ASSERT_( wi >= 0 && wi < size(), "word index out of range" ); + + m_mant[wi] &= ( ((word)-1) << bi ); + for( int i = wi - 1; i >= 0; -- i ) + m_mant[i] = 0; +} + +inline +void +scfx_rep::q_incr( const scfx_index& x ) +{ + int wi = x.wi(); + int bi = x.bi(); + + SC_ASSERT_( wi >= 0 && wi < size(), "word index out of range" ); + + word old_val = m_mant[wi]; + m_mant[wi] += ( ((word)1) << bi ); + if( m_mant[wi] <= old_val ) + { + if( wi + 1 == size() ) + resize_to( size() + 1, 1 ); + + for( int i = wi + 1; i < size(); ++ i ) + { + if( ++ m_mant[i] != 0 ) + break; + } + } +} + +inline +bool +scfx_rep::q_odd( const scfx_index& x ) const +{ + int wi = x.wi(); + int bi = x.bi(); + + SC_ASSERT_( wi >= 0 && wi < size(), "word index out of range" ); + + return ( m_mant[wi] & ( ((word)1) << bi ) ) != 0; +} + +inline +bool +scfx_rep::q_zero( const scfx_index& x ) const +{ + int wi = x.wi(); + int bi = x.bi(); + + SC_ASSERT_( wi >= 0 && wi < size(), "word index out of range" ); + + bool zero; + + if( bi != 0 ) + { + zero = ( m_mant[wi] & ~( ((word)-1) << (bi - 1) ) ) == 0; + for( int i = wi - 1; i >= 0; -- i ) + zero = zero && m_mant[i] == 0; + } + else if( wi != 0 ) + { + zero = ( m_mant[wi - 1] & ~( ((word)-1) << (bits_in_word - 1) ) ) == 0; + for( int i = wi - 2; i >= 0; -- i ) + zero = zero && m_mant[i] == 0; + } + else + zero = true; + + return zero; +} + +inline +int +scfx_rep::find_lsw() const +{ + for( int i = 0; i < size(); i ++ ) + { + if( m_mant[i] ) + return i; + } + return 0; +} + +inline +int +scfx_rep::find_msw() const +{ + for( int i = size() - 1; i >= 0; i -- ) + { + if( m_mant[i] ) + return i; + } + return 0; +} + +inline +void +scfx_rep::find_sw() +{ + m_lsw = find_lsw(); + m_msw = find_msw(); +} + +inline +void +scfx_rep::toggle_tc() +{ + if( is_neg() ) + { + complement( m_mant, m_mant, m_mant.size() ); + inc( m_mant ); + } +} + +} // namespace sc_dt + + +#endif + +// Taf! diff --git a/ext/systemc/src/sysc/datatypes/fx/scfx_string.h b/ext/systemc/src/sysc/datatypes/fx/scfx_string.h new file mode 100644 index 000000000..338031ccc --- /dev/null +++ b/ext/systemc/src/sysc/datatypes/fx/scfx_string.h @@ -0,0 +1,232 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + scfx_string.h - + + Original Author: Robert Graulich, Synopsys, Inc. + Martin Janssen, Synopsys, Inc. + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ +// $Log: scfx_string.h,v $ +// Revision 1.1.1.1 2006/12/15 20:20:04 acg +// SystemC 2.3 +// +// Revision 1.2 2006/01/03 23:18:34 acg +// Changed copyright to include 2006. +// +// Revision 1.1.1.1 2005/12/19 23:16:43 acg +// First check in of SystemC 2.1 into its own archive. +// +// Revision 1.9 2005/09/15 23:02:03 acg +// Added std:: prefix to appropriate methods and types to get around +// issues with the Edison Front End. +// +// Revision 1.8 2005/06/07 17:27:02 acg +// Fixed bug in scfx_string::operator += where an array reference was used +// rather than the [] operator. This meant that the buffer may have been +// accessed beyond its allocated storage. +// + +#ifndef SCFX_STRING_H +#define SCFX_STRING_H + +#include <cstdio> + + +namespace sc_dt +{ + +// classes defined in this module +class scfx_string; + + +// ---------------------------------------------------------------------------- +// CLASS : scfx_string +// +// Simple string class for internal use. +// ---------------------------------------------------------------------------- + +class scfx_string +{ + void resize( std::size_t ); + +public: + + scfx_string(); + + ~scfx_string(); + + int length() const; + + void clear(); + + char& operator [] ( int ); + + void append( int ); + void discard( int ); + void remove( int ); + + void operator += ( char ); + void operator += ( const char* ); + + operator const char* (); + +private: + + std::size_t m_len; + std::size_t m_alloc; + char* m_buffer; +}; + + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + +inline +void +scfx_string::resize( std::size_t i ) +{ + do { + m_alloc *= 2; + } while( i >= m_alloc ); + + char* temp = new char[m_alloc]; + + for( int j = 0; j < (int) m_len; ++ j ) { + temp[j] = m_buffer[j]; + } + temp[m_len] = 0; + + delete [] m_buffer; + m_buffer = temp; +} + + +inline +scfx_string::scfx_string() +: m_len( 0 ), m_alloc( BUFSIZ ), m_buffer( new char[m_alloc] ) +{ + m_buffer[m_len] = 0; +} + + +inline +scfx_string::~scfx_string() +{ + delete [] m_buffer; +} + + +inline +int +scfx_string::length() const +{ + return m_len; +} + + +inline +void +scfx_string::clear() +{ + m_len = 0; + m_buffer[m_len] = 0; +} + + +inline +char& +scfx_string::operator [] ( int i ) +{ + if( i >= (int) m_alloc ) { + resize( i ); + } + return m_buffer[i]; +} + + +inline +void +scfx_string::append( int n ) +{ + m_len += n; + m_buffer[m_len] = 0; +} + +inline +void +scfx_string::discard( int n ) +{ + m_len -= n; + m_buffer[m_len] = 0; +} + +inline +void +scfx_string::remove( int i ) +{ + for( int j = i + 1; j < (int) m_len; ++ j ) + m_buffer[j - 1] = m_buffer[j]; + -- m_len; + m_buffer[m_len] = 0; +} + + +inline +void +scfx_string::operator += ( char c ) +{ + this->operator [] ( m_len ) = c; + m_len ++; + this->operator [] ( m_len ) = 0; +} + +inline +void +scfx_string::operator += ( const char* s ) +{ + while( *s ) + (*this) += *s ++; +} + + +inline +scfx_string::operator const char*() +{ + m_buffer[m_len] = 0; + return m_buffer; +} + +} // namespace sc_dt + + +#endif + +// Taf! diff --git a/ext/systemc/src/sysc/datatypes/fx/scfx_utils.cpp b/ext/systemc/src/sysc/datatypes/fx/scfx_utils.cpp new file mode 100644 index 000000000..0735a6c25 --- /dev/null +++ b/ext/systemc/src/sysc/datatypes/fx/scfx_utils.cpp @@ -0,0 +1,176 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + scfx_utils.cpp - + + Original Author: Martin Janssen, Synopsys, Inc. + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + + +// $Log: scfx_utils.cpp,v $ +// Revision 1.1.1.1 2006/12/15 20:20:04 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:53:58 acg +// Andy Goodrich: added $Log command so that CVS comments are reproduced in +// the source. +// + +#include "sysc/datatypes/fx/scfx_utils.h" + + +namespace sc_dt +{ + +void +scfx_tc2csd( scfx_string& s, int w_prefix ) +{ + if( w_prefix != 0 ) { + SC_ASSERT_( s[0] == '0' && s[1] == 'c' && + s[2] == 's' && s[3] == 'd', "invalid prefix" ); + } + + scfx_string csd; + + // copy bits from 's' into 'csd'; skip prefix, point, and exponent + int i = 0; + int j = (w_prefix != 0 ? 4 : 0); + while( s[j] ) + { + if( s[j] == '0' || s[j] == '1' ) + csd[i ++] = s[j]; + else if( s[j] != '.' ) + break; + ++ j; + } + csd[i] = '\0'; + + // convert 'csd' from two's complement to csd + -- i; + while( i >= 0 ) + { + if( csd[i] == '0' ) + -- i; + else + { + if( i > 0 && csd[i - 1] == '0' ) + -- i; + else if( i == 0 ) + csd[i --] = '-'; + else + { // i > 0 && csd[i - 1] == '1' + csd[i --] = '-'; + while( i >= 0 && csd[i] == '1' ) + csd[i --] = '0'; + if( i > 0 ) + csd[i] = '1'; + else if( i == 0 ) + csd[i --] = '1'; + } + } + } + + // copy bits from 'csd' back into 's' + i = 0; + j = (w_prefix != 0 ? 4 : 0); + while( csd[i] ) + { + if( s[j] == '.' ) + ++ j; + s[j ++] = csd[i ++]; + } +} + + +void +scfx_csd2tc( scfx_string& csd ) +{ + SC_ASSERT_( csd[0] == '0' && csd[1] == 'c' && + csd[2] == 's' && csd[3] == 'd', "invalid prefix" ); + + scfx_string s; + + // copy bits from 'csd' into 's'; skip prefix, point, and exponent + int i = 0; + s[i ++] = '0'; + int j = 4; + while( csd[j] ) + { + if( csd[j] == '-' || csd[j] == '0' || csd[j] == '1' ) + s[i ++] = csd[j]; + else if( csd[j] != '.' ) + break; + ++ j; + } + s[i] = '\0'; + + // convert 's' from csd to two's complement + int len = i; + i = 1; + while( i < len ) + { + while( i < len && s[i] != '-' ) + i ++; + if( i < len ) + { + j = i ++; + s[j --] = '1'; + while( j >= 0 && s[j] == '0' ) + s[j --] = '1'; + if( j >= 0 ) + s[j] = '0'; + } + } + + // copy bits from 's' back into 'csd' + j = csd.length(); + csd[j + 1] = '\0'; + while( j > 4 ) + { + csd[j] = csd[j - 1]; + -- j; + } + + i = 0; + j = 4; + while( s[i] ) + { + if( csd[j] == '.' ) + ++ j; + csd[j ++] = s[i ++]; + } +} + +} // namespace sc_dt + + +// Taf! diff --git a/ext/systemc/src/sysc/datatypes/fx/scfx_utils.h b/ext/systemc/src/sysc/datatypes/fx/scfx_utils.h new file mode 100644 index 000000000..55fabe045 --- /dev/null +++ b/ext/systemc/src/sysc/datatypes/fx/scfx_utils.h @@ -0,0 +1,534 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + scfx_utils.h - + + Original Author: Martin Janssen, Synopsys, Inc. + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + +// $Log: scfx_utils.h,v $ +// Revision 1.2 2009/02/28 00:26:20 acg +// Andy Goodrich: bug fixes. +// +// Revision 1.1.1.1 2006/12/15 20:31:36 acg +// SystemC 2.2 +// +// Revision 1.3 2006/01/13 18:53:58 acg +// Andy Goodrich: added $Log command so that CVS comments are reproduced in +// the source. +// + +#ifndef SCFX_UTILS_H +#define SCFX_UTILS_H + + +#include "sysc/datatypes/fx/sc_fxdefs.h" +#include "sysc/datatypes/fx/scfx_params.h" +#include "sysc/datatypes/fx/scfx_string.h" + + +namespace sc_dt +{ + +// ---------------------------------------------------------------------------- +// Find the most and least significant non-zero bits in a unsigned long +// ---------------------------------------------------------------------------- + +#define MSB_STATEMENT(n) if( x >> n ) { x >>= n; i += n; } + +inline +int +scfx_find_msb( unsigned long x ) +{ + int i = 0; +# if defined(SC_LONG_64) + MSB_STATEMENT( 32 ); +# endif // defined(SC_LONG_64) + MSB_STATEMENT( 16 ); + MSB_STATEMENT( 8 ); + MSB_STATEMENT( 4 ); + MSB_STATEMENT( 2 ); + MSB_STATEMENT( 1 ); + return i; +} + +#undef MSB_STATEMENT + +#define LSB_STATEMENT(n) if( x << n ) { x <<= n; i -= n; } + +inline +int +scfx_find_lsb( unsigned long x ) +{ + int i; +# if defined(SC_LONG_64) + i = 63; + LSB_STATEMENT( 32 ); +# else + i = 31; +# endif // defined(SC_LONG_64) + LSB_STATEMENT( 16 ); + LSB_STATEMENT( 8 ); + LSB_STATEMENT( 4 ); + LSB_STATEMENT( 2 ); + LSB_STATEMENT( 1 ); + return i; +} + +#undef LSB_STATEMENT + + +// ---------------------------------------------------------------------------- +// Utilities for parsing a character string number +// ---------------------------------------------------------------------------- + +inline +int +scfx_parse_sign( const char*& s, bool& sign_char ) +{ + int sign = 1; + + if( *s == '+' ) + { + ++ s; + sign_char = true; + } + else if( *s == '-' ) + { + sign = -1; + ++ s; + sign_char = true; + } + else + sign_char = false; + + return sign; +} + +inline +sc_numrep +scfx_parse_prefix( const char*& s ) +{ + if( s[0] == '0' ) { + switch( s[1] ) + { + case 'b': + case 'B': + { + if( (s[2] == 'u' || s[2] == 'U') && (s[3] == 's' || s[3] == 'S') ) { + s += 4; + return SC_BIN_US; + } + if( (s[2] == 's' || s[2] == 'S') && (s[3] == 'm' || s[3] == 'M') ) { + s += 4; + return SC_BIN_SM; + } + s += 2; + return SC_BIN; + } + case 'o': + case 'O': + { + if( (s[2] == 'u' || s[2] == 'U') && (s[3] == 's' || s[3] == 'S') ) { + s += 4; + return SC_OCT_US; + } + if( (s[2] == 's' || s[2] == 'S') && (s[3] == 'm' || s[3] == 'M') ) { + s += 4; + return SC_OCT_SM; + } + s += 2; + return SC_OCT; + } + case 'x': + case 'X': + { + if( (s[2] == 'u' || s[2] == 'U') && (s[3] == 's' || s[3] == 'S') ) { + s += 4; + return SC_HEX_US; + } + if( (s[2] == 's' || s[2] == 'S') && (s[3] == 'm' || s[3] == 'M') ) { + s += 4; + return SC_HEX_SM; + } + s += 2; + return SC_HEX; + } + case 'd': + case 'D': + { + s += 2; + return SC_DEC; + } + case 'c': + case 'C': + { + if( (s[2] == 's' || s[2] == 'S') && (s[3] == 'd' || s[3] == 'D') ) { + s += 4; + return SC_CSD; + } + break; + } + default: + break; + } + } + + return SC_DEC; +} + + +inline +int +scfx_parse_base( const char*& s ) +{ + const char* s1 = s + 1; + + int base = 10; + + if( *s == '0' ) + { + switch( *s1 ) + { + case 'b': + case 'B': base = 2; s += 2; break; + case 'o': + case 'O': base = 8; s += 2; break; + case 'd': + case 'D': base = 10; s += 2; break; + case 'x': + case 'X': base = 16; s += 2; break; + } + } + + return base; +} + +inline +bool +scfx_is_equal( const char* a, const char* b ) +{ + while( *a != 0 && *b != 0 && *a == *b ) + { + ++ a; + ++ b; + } + return ( *a == 0 && *b == 0 ); +} + +inline +bool +scfx_is_nan( const char* s ) +{ + return scfx_is_equal( s, "NaN" ); +} + +inline +bool +scfx_is_inf( const char* s ) +{ + return ( scfx_is_equal( s, "Inf" ) || scfx_is_equal( s, "Infinity" ) ); +} + +inline +bool +scfx_exp_start( const char* s ) +{ + if( *s == 'e' || *s == 'E' ) + { + ++ s; + if( *s == '+' || *s == '-' ) + return true; + } + return false; +} + +inline +bool +scfx_is_digit( char c, sc_numrep numrep ) +{ + bool is_digit; + + switch( numrep ) + { + case SC_DEC: + { + switch( c ) + { + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + { + is_digit = true; + break; + } + default: + is_digit = false; + } + break; + } + case SC_BIN: + case SC_BIN_US: + case SC_BIN_SM: + { + switch( c ) + { + case '0': case '1': + { + is_digit = true; + break; + } + default: + is_digit = false; + } + break; + } + case SC_OCT: + case SC_OCT_US: + case SC_OCT_SM: + { + switch( c ) + { + case '0': case '1': case '2': case '3': + case '4': case '5': case '6': case '7': + { + is_digit = true; + break; + } + default: + is_digit = false; + } + break; + } + case SC_HEX: + case SC_HEX_US: + case SC_HEX_SM: + { + switch( c ) + { + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': + case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': + { + is_digit = true; + break; + } + default: + is_digit = false; + } + break; + } + case SC_CSD: + { + switch( c ) + { + case '0': case '1': case '-': + { + is_digit = true; + break; + } + default: + is_digit = false; + } + break; + } + default: + is_digit = false; + } + + return is_digit; +} + +inline +int +scfx_to_digit( char c, sc_numrep numrep ) +{ + int to_digit; + + switch( numrep ) + { + case SC_DEC: + case SC_BIN: + case SC_BIN_US: + case SC_BIN_SM: + case SC_OCT: + case SC_OCT_US: + case SC_OCT_SM: + { + to_digit = c - '0'; + break; + } + case SC_HEX: + case SC_HEX_US: + case SC_HEX_SM: + { + switch( c ) + { + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + to_digit = c - '0'; + break; + case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': + to_digit = c - 'a' + 10; + break; + case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': + to_digit = c - 'A' + 10; + break; + default: + to_digit = -2; + } + break; + } + case SC_CSD: + { + if( c == '-' ) + to_digit = -1; + else + to_digit = c - '0'; + break; + } + default: + to_digit = -2; + } + + return to_digit; +} + + +// ---------------------------------------------------------------------------- +// Utilities for printing a character string number +// ---------------------------------------------------------------------------- + +inline +void +scfx_print_nan( scfx_string& s ) +{ + s += "NaN"; +} + +inline +void +scfx_print_inf( scfx_string& s, bool negative ) +{ + if( negative ) + s += "-Inf"; + else + s += "Inf"; +} + +inline +void +scfx_print_prefix( scfx_string& s, sc_numrep numrep ) +{ + switch( numrep ) + { + case SC_DEC: + s += "0d"; + break; + case SC_BIN: + s += "0b"; + break; + case SC_BIN_US: + s += "0bus"; + break; + case SC_BIN_SM: + s += "0bsm"; + break; + case SC_OCT: + s += "0o"; + break; + case SC_OCT_US: + s += "0ous"; + break; + case SC_OCT_SM: + s += "0osm"; + break; + case SC_HEX: + s += "0x"; + break; + case SC_HEX_US: + s += "0xus"; + break; + case SC_HEX_SM: + s += "0xsm"; + break; + case SC_CSD: + s += "0csd"; + break; + default: + s += "unknown"; + } +} + +inline +void +scfx_print_exp( scfx_string& s, int exp ) +{ + if( exp != 0 ) + { + s += 'e'; + + if( exp < 0 ) + { + exp = - exp; + s += '-'; + } + else + s += '+'; + + bool first = true; + int scale = 1000000000; + do + { + int digit = exp / scale; + exp = exp % scale; + if( digit != 0 || ! first ) + { + s += static_cast<char>( digit + '0' ); + first = false; + } + scale /= 10; + } + while( scale > 0 ); + } +} + + +void scfx_tc2csd( scfx_string&, int ); +void scfx_csd2tc( scfx_string& ); + +} // namespace sc_dt + + +#endif + +// Taf! diff --git a/ext/systemc/src/sysc/datatypes/int/sc_bigint.h b/ext/systemc/src/sysc/datatypes/int/sc_bigint.h new file mode 100644 index 000000000..d5445fc84 --- /dev/null +++ b/ext/systemc/src/sysc/datatypes/int/sc_bigint.h @@ -0,0 +1,271 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_bigint.h -- Template version of sc_signed. This class enables + compile-time bit widths for sc_signed numbers. + + Original Author: Ali Dasdan, Synopsys, Inc. + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: Gene Bushayev, Synopsys, Inc. + Description of Modification: - Interface between sc_bigint and sc_bv/sc_lv. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + +// $Log: sc_bigint.h,v $ +// Revision 1.2 2011/02/18 20:19:14 acg +// Andy Goodrich: updating Copyright notice. +// +// Revision 1.1.1.1 2006/12/15 20:20:05 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:49:31 acg +// Added $Log command so that CVS check in comments are reproduced in the +// source. +// + +#ifndef SC_BIGINT_H +#define SC_BIGINT_H + + +#include "sysc/datatypes/int/sc_signed.h" +#include "sysc/datatypes/int/sc_unsigned.h" + +namespace sc_dt +{ + +// classes defined in this module +template <int W> class sc_bigint; + +// forward class declarations +class sc_bv_base; +class sc_lv_base; +class sc_fxval; +class sc_fxval_fast; +class sc_fxnum; +class sc_fxnum_fast; + + +// ---------------------------------------------------------------------------- +// CLASS TEMPLATE : sc_bigint<W> +// +// Arbitrary size signed integer type. +// ---------------------------------------------------------------------------- + +#ifdef SC_MAX_NBITS +template< int W = SC_MAX_NBITS > +#else +template< int W > +#endif +class sc_bigint + : public sc_signed +{ +public: + + // constructors + + sc_bigint() + : sc_signed( W ) + {} + + sc_bigint( const sc_bigint<W>& v ) + : sc_signed( W ) + { *this = v; } + + sc_bigint( const sc_signed& v ) + : sc_signed( W ) + { *this = v; } + + sc_bigint( const sc_signed_subref& v ) + : sc_signed( W ) + { *this = v; } + + template< class T > + sc_bigint( const sc_generic_base<T>& a ) + : sc_signed( W ) + { a->to_sc_signed(*this); } + + sc_bigint( const sc_unsigned& v ) + : sc_signed( W ) + { *this = v; } + + sc_bigint( const sc_unsigned_subref& v ) + : sc_signed( W ) + { *this = v; } + + sc_bigint( const char* v ) + : sc_signed( W ) + { *this = v; } + + sc_bigint( int64 v ) + : sc_signed( W ) + { *this = v; } + + sc_bigint( uint64 v ) + : sc_signed( W ) + { *this = v; } + + sc_bigint( long v ) + : sc_signed( W ) + { *this = v; } + + sc_bigint( unsigned long v ) + : sc_signed( W ) + { *this = v; } + + sc_bigint( int v ) + : sc_signed( W ) + { *this = v; } + + sc_bigint( unsigned int v ) + : sc_signed( W ) + { *this = v; } + + sc_bigint( double v ) + : sc_signed( W ) + { *this = v; } + + sc_bigint( const sc_bv_base& v ) + : sc_signed( W ) + { *this = v; } + + sc_bigint( const sc_lv_base& v ) + : sc_signed( W ) + { *this = v; } + +#ifdef SC_INCLUDE_FX + + explicit sc_bigint( const sc_fxval& v ) + : sc_signed( W ) + { *this = v; } + + explicit sc_bigint( const sc_fxval_fast& v ) + : sc_signed( W ) + { *this = v; } + + explicit sc_bigint( const sc_fxnum& v ) + : sc_signed( W ) + { *this = v; } + + explicit sc_bigint( const sc_fxnum_fast& v ) + : sc_signed( W ) + { *this = v; } + +#endif + + +#ifndef SC_MAX_NBITS + + // destructor + + ~sc_bigint() + {} + +#endif + + // assignment operators + + sc_bigint<W>& operator = ( const sc_bigint<W>& v ) + { sc_signed::operator = ( v ); return *this; } + + sc_bigint<W>& operator = ( const sc_signed& v ) + { sc_signed::operator = ( v ); return *this; } + + sc_bigint<W>& operator = (const sc_signed_subref& v ) + { sc_signed::operator = ( v ); return *this; } + + template< class T > + sc_bigint<W>& operator = ( const sc_generic_base<T>& a ) + { a->to_sc_signed(*this); return *this;} + + sc_bigint<W>& operator = ( const sc_unsigned& v ) + { sc_signed::operator = ( v ); return *this; } + + sc_bigint<W>& operator = ( const sc_unsigned_subref& v ) + { sc_signed::operator = ( v ); return *this; } + + sc_bigint<W>& operator = ( const char* v ) + { sc_signed::operator = ( v ); return *this; } + + sc_bigint<W>& operator = ( int64 v ) + { sc_signed::operator = ( v ); return *this; } + + sc_bigint<W>& operator = ( uint64 v ) + { sc_signed::operator = ( v ); return *this; } + + sc_bigint<W>& operator = ( long v ) + { sc_signed::operator = ( v ); return *this; } + + sc_bigint<W>& operator = ( unsigned long v ) + { sc_signed::operator = ( v ); return *this; } + + sc_bigint<W>& operator = ( int v ) + { sc_signed::operator = ( v ); return *this; } + + sc_bigint<W>& operator = ( unsigned int v ) + { sc_signed::operator = ( v ); return *this; } + + sc_bigint<W>& operator = ( double v ) + { sc_signed::operator = ( v ); return *this; } + + + sc_bigint<W>& operator = ( const sc_bv_base& v ) + { sc_signed::operator = ( v ); return *this; } + + sc_bigint<W>& operator = ( const sc_lv_base& v ) + { sc_signed::operator = ( v ); return *this; } + + sc_bigint<W>& operator = ( const sc_int_base& v ) + { sc_signed::operator = ( v ); return *this; } + + sc_bigint<W>& operator = ( const sc_uint_base& v ) + { sc_signed::operator = ( v ); return *this; } + +#ifdef SC_INCLUDE_FX + + sc_bigint<W>& operator = ( const sc_fxval& v ) + { sc_signed::operator = ( v ); return *this; } + + sc_bigint<W>& operator = ( const sc_fxval_fast& v ) + { sc_signed::operator = ( v ); return *this; } + + sc_bigint<W>& operator = ( const sc_fxnum& v ) + { sc_signed::operator = ( v ); return *this; } + + sc_bigint<W>& operator = ( const sc_fxnum_fast& v ) + { sc_signed::operator = ( v ); return *this; } + +#endif +}; + +} // namespace sc_dt + + +#endif diff --git a/ext/systemc/src/sysc/datatypes/int/sc_biguint.h b/ext/systemc/src/sysc/datatypes/int/sc_biguint.h new file mode 100644 index 000000000..689f41e63 --- /dev/null +++ b/ext/systemc/src/sysc/datatypes/int/sc_biguint.h @@ -0,0 +1,272 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_biguint.h -- Template version of sc_unsigned. This class + enables compile-time bit widths for sc_unsigned numbers. + + Original Author: Ali Dasdan, Synopsys, Inc. + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: Gene Bushayev, Synopsys, Inc. + Description of Modification: - Interface between sc_bigint and sc_bv/sc_lv. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + +// $Log: sc_biguint.h,v $ +// Revision 1.2 2011/02/18 20:19:14 acg +// Andy Goodrich: updating Copyright notice. +// +// Revision 1.1.1.1 2006/12/15 20:20:05 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:49:31 acg +// Added $Log command so that CVS check in comments are reproduced in the +// source. +// + +#ifndef SC_BIGUINT_H +#define SC_BIGUINT_H + + +#include "sysc/datatypes/int/sc_signed.h" +#include "sysc/datatypes/int/sc_unsigned.h" + +namespace sc_dt +{ + +// classes defined in this module +template <int W> class sc_biguint; + +// forward class declarations +class sc_bv_base; +class sc_lv_base; +class sc_fxval; +class sc_fxval_fast; +class sc_fxnum; +class sc_fxnum_fast; + + +// ---------------------------------------------------------------------------- +// CLASS TEMPLATE : sc_biguint<W> +// +// Arbitrary size unsigned integer type. +// ---------------------------------------------------------------------------- + +#ifdef SC_MAX_NBITS +template< int W = SC_MAX_NBITS > +#else +template< int W > +#endif +class sc_biguint + : public sc_unsigned +{ +public: + + // constructors + + sc_biguint() + : sc_unsigned( W ) + {} + + sc_biguint( const sc_biguint<W>& v ) + : sc_unsigned( W ) + { *this = v; } + + sc_biguint( const sc_unsigned& v ) + : sc_unsigned( W ) + { *this = v; } + + sc_biguint( const sc_unsigned_subref& v ) + : sc_unsigned( W ) + { *this = v; } + + template< class T > + sc_biguint( const sc_generic_base<T>& a ) + : sc_unsigned( W ) + { a->to_sc_unsigned(*this); } + + sc_biguint( const sc_signed& v ) + : sc_unsigned( W ) + { *this = v; } + + sc_biguint( const sc_signed_subref& v ) + : sc_unsigned( W ) + { *this = v; } + + sc_biguint( const char* v ) + : sc_unsigned( W ) + { *this = v; } + + sc_biguint( int64 v ) + : sc_unsigned( W ) + { *this = v; } + + sc_biguint( uint64 v ) + : sc_unsigned( W ) + { *this = v; } + + sc_biguint( long v ) + : sc_unsigned( W ) + { *this = v; } + + sc_biguint( unsigned long v ) + : sc_unsigned( W ) + { *this = v; } + + sc_biguint( int v ) + : sc_unsigned( W ) + { *this = v; } + + sc_biguint( unsigned int v ) + : sc_unsigned( W ) + { *this = v; } + + sc_biguint( double v ) + : sc_unsigned( W ) + { *this = v; } + + sc_biguint( const sc_bv_base& v ) + : sc_unsigned( W ) + { *this = v; } + + sc_biguint( const sc_lv_base& v ) + : sc_unsigned( W ) + { *this = v; } + +#ifdef SC_INCLUDE_FX + + explicit sc_biguint( const sc_fxval& v ) + : sc_unsigned( W ) + { *this = v; } + + explicit sc_biguint( const sc_fxval_fast& v ) + : sc_unsigned( W ) + { *this = v; } + + explicit sc_biguint( const sc_fxnum& v ) + : sc_unsigned( W ) + { *this = v; } + + explicit sc_biguint( const sc_fxnum_fast& v ) + : sc_unsigned( W ) + { *this = v; } + +#endif + + +#ifndef SC_MAX_NBITS + + // destructor + + ~sc_biguint() + {} + +#endif + + + // assignment operators + + sc_biguint<W>& operator = ( const sc_biguint<W>& v ) + { sc_unsigned::operator = ( v ); return *this; } + + sc_biguint<W>& operator = ( const sc_unsigned& v ) + { sc_unsigned::operator = ( v ); return *this; } + + sc_biguint<W>& operator = ( const sc_unsigned_subref& v ) + { sc_unsigned::operator = ( v ); return *this; } + + template< class T > + sc_biguint<W>& operator = ( const sc_generic_base<T>& a ) + { a->to_sc_unsigned(*this); return *this; } + + sc_biguint<W>& operator = ( const sc_signed& v ) + { sc_unsigned::operator = ( v ); return *this; } + + sc_biguint<W>& operator = ( const sc_signed_subref& v ) + { sc_unsigned::operator = ( v ); return *this; } + + sc_biguint<W>& operator = ( const char* v ) + { sc_unsigned::operator = ( v ); return *this; } + + sc_biguint<W>& operator = ( int64 v ) + { sc_unsigned::operator = ( v ); return *this; } + + sc_biguint<W>& operator = ( uint64 v ) + { sc_unsigned::operator = ( v ); return *this; } + + sc_biguint<W>& operator = ( long v ) + { sc_unsigned::operator = ( v ); return *this; } + + sc_biguint<W>& operator = ( unsigned long v ) + { sc_unsigned::operator = ( v ); return *this; } + + sc_biguint<W>& operator = ( int v ) + { sc_unsigned::operator = ( v ); return *this; } + + sc_biguint<W>& operator = ( unsigned int v ) + { sc_unsigned::operator = ( v ); return *this; } + + sc_biguint<W>& operator = ( double v ) + { sc_unsigned::operator = ( v ); return *this; } + + + sc_biguint<W>& operator = ( const sc_bv_base& v ) + { sc_unsigned::operator = ( v ); return *this; } + + sc_biguint<W>& operator = ( const sc_lv_base& v ) + { sc_unsigned::operator = ( v ); return *this; } + + sc_biguint<W>& operator = ( const sc_int_base& v ) + { sc_unsigned::operator = ( v ); return *this; } + + sc_biguint<W>& operator = ( const sc_uint_base& v ) + { sc_unsigned::operator = ( v ); return *this; } + +#ifdef SC_INCLUDE_FX + + sc_biguint<W>& operator = ( const sc_fxval& v ) + { sc_unsigned::operator = ( v ); return *this; } + + sc_biguint<W>& operator = ( const sc_fxval_fast& v ) + { sc_unsigned::operator = ( v ); return *this; } + + sc_biguint<W>& operator = ( const sc_fxnum& v ) + { sc_unsigned::operator = ( v ); return *this; } + + sc_biguint<W>& operator = ( const sc_fxnum_fast& v ) + { sc_unsigned::operator = ( v ); return *this; } + +#endif +}; + +} // namespace sc_dt + + +#endif diff --git a/ext/systemc/src/sysc/datatypes/int/sc_int.h b/ext/systemc/src/sysc/datatypes/int/sc_int.h new file mode 100644 index 000000000..adcb6b321 --- /dev/null +++ b/ext/systemc/src/sysc/datatypes/int/sc_int.h @@ -0,0 +1,312 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_int.h -- A sc_int is a signed integer whose length is less than the + machine's native integer length. We provide two implementations + (i) sc_int with length between 1 - 64, and (ii) sc_int with + length between 1 - 32. Implementation (i) is the default + implementation, while implementation (ii) can be used only if + the class library is compiled with -D_32BIT_. Unlike arbitrary + precision, arithmetic and bitwise operations are performed + using the native types (hence capped at 32/64 bits). The sc_int + integer is useful when the user does not need arbitrary + precision and the performance is superior to + sc_bigint/sc_biguint. + + Original Author: Amit Rao, Synopsys, Inc. + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: Ali Dasdan, Synopsys, Inc. + Description of Modification: - Resolved ambiguity with sc_(un)signed. + - Merged the code for 64- and 32-bit versions + via the constants in sc_nbdefs.h. + - Eliminated redundant file inclusions. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + +// $Log: sc_int.h,v $ +// Revision 1.2 2011/02/18 20:19:14 acg +// Andy Goodrich: updating Copyright notice. +// +// Revision 1.1.1.1 2006/12/15 20:20:05 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:49:31 acg +// Added $Log command so that CVS check in comments are reproduced in the +// source. +// + +#ifndef SC_INT_H +#define SC_INT_H + + +#include "sysc/datatypes/int/sc_int_base.h" + + +namespace sc_dt +{ + +// classes defined in this module +template <int W> class sc_int; + + +// ---------------------------------------------------------------------------- +// CLASS TEMPLATE : sc_int<W> +// +// Template class sc_int<W> is the interface that the user sees. It is +// derived from sc_int_base and most of its methods are just wrappers +// that call the corresponding method in the parent class. Note that +// the length of sc_int datatype is specified as a template parameter. +// ---------------------------------------------------------------------------- + +template <int W> +class sc_int + : public sc_int_base +{ +public: + + // constructors + + sc_int() + : sc_int_base( W ) + {} + + sc_int( int_type v ) + : sc_int_base( v, W ) + {} + + sc_int( const sc_int<W>& a ) + : sc_int_base( a ) + {} + + sc_int( const sc_int_base& a ) + : sc_int_base( W ) + { sc_int_base::operator = ( a ); } + + sc_int( const sc_int_subref_r& a ) + : sc_int_base( W ) + { sc_int_base::operator = ( a ); } + + template< class T > + sc_int( const sc_generic_base<T>& a ) + : sc_int_base( W ) + { sc_int_base::operator = ( a->to_int64() ); } + + sc_int( const sc_signed& a ) + : sc_int_base( W ) + { sc_int_base::operator = ( a ); } + + sc_int( const sc_unsigned& a ) + : sc_int_base( W ) + { sc_int_base::operator = ( a ); } + +#ifdef SC_INCLUDE_FX + + explicit sc_int( const sc_fxval& a ) + : sc_int_base( W ) + { sc_int_base::operator = ( a ); } + + explicit sc_int( const sc_fxval_fast& a ) + : sc_int_base( W ) + { sc_int_base::operator = ( a ); } + + explicit sc_int( const sc_fxnum& a ) + : sc_int_base( W ) + { sc_int_base::operator = ( a ); } + + explicit sc_int( const sc_fxnum_fast& a ) + : sc_int_base( W ) + { sc_int_base::operator = ( a ); } + +#endif + + sc_int( const sc_bv_base& a ) + : sc_int_base( W ) + { sc_int_base::operator = ( a ); } + + sc_int( const sc_lv_base& a ) + : sc_int_base( W ) + { sc_int_base::operator = ( a ); } + + sc_int( const char* a ) + : sc_int_base( W ) + { sc_int_base::operator = ( a ); } + + sc_int( unsigned long a ) + : sc_int_base( W ) + { sc_int_base::operator = ( a ); } + + sc_int( long a ) + : sc_int_base( W ) + { sc_int_base::operator = ( a ); } + + sc_int( unsigned int a ) + : sc_int_base( W ) + { sc_int_base::operator = ( a ); } + + sc_int( int a ) + : sc_int_base( W ) + { sc_int_base::operator = ( a ); } + + sc_int( uint64 a ) + : sc_int_base( W ) + { sc_int_base::operator = ( a ); } + + sc_int( double a ) + : sc_int_base( W ) + { sc_int_base::operator = ( a ); } + + + // assignment operators + + sc_int<W>& operator = ( int_type v ) + { sc_int_base::operator = ( v ); return *this; } + + sc_int<W>& operator = ( const sc_int_base& a ) + { sc_int_base::operator = ( a ); return *this; } + + sc_int<W>& operator = ( const sc_int_subref_r& a ) + { sc_int_base::operator = ( a ); return *this; } + + sc_int<W>& operator = ( const sc_int<W>& a ) + { m_val = a.m_val; return *this; } + + template< class T > + sc_int<W>& operator = ( const sc_generic_base<T>& a ) + { sc_int_base::operator = ( a->to_int64() ); return *this; } + + sc_int<W>& operator = ( const sc_signed& a ) + { sc_int_base::operator = ( a ); return *this; } + + sc_int<W>& operator = ( const sc_unsigned& a ) + { sc_int_base::operator = ( a ); return *this; } + +#ifdef SC_INCLUDE_FX + + sc_int<W>& operator = ( const sc_fxval& a ) + { sc_int_base::operator = ( a ); return *this; } + + sc_int<W>& operator = ( const sc_fxval_fast& a ) + { sc_int_base::operator = ( a ); return *this; } + + sc_int<W>& operator = ( const sc_fxnum& a ) + { sc_int_base::operator = ( a ); return *this; } + + sc_int<W>& operator = ( const sc_fxnum_fast& a ) + { sc_int_base::operator = ( a ); return *this; } + +#endif + + sc_int<W>& operator = ( const sc_bv_base& a ) + { sc_int_base::operator = ( a ); return *this; } + + sc_int<W>& operator = ( const sc_lv_base& a ) + { sc_int_base::operator = ( a ); return *this; } + + sc_int<W>& operator = ( const char* a ) + { sc_int_base::operator = ( a ); return *this; } + + sc_int<W>& operator = ( unsigned long a ) + { sc_int_base::operator = ( a ); return *this; } + + sc_int<W>& operator = ( long a ) + { sc_int_base::operator = ( a ); return *this; } + + sc_int<W>& operator = ( unsigned int a ) + { sc_int_base::operator = ( a ); return *this; } + + sc_int<W>& operator = ( int a ) + { sc_int_base::operator = ( a ); return *this; } + + sc_int<W>& operator = ( uint64 a ) + { sc_int_base::operator = ( a ); return *this; } + + sc_int<W>& operator = ( double a ) + { sc_int_base::operator = ( a ); return *this; } + + + // arithmetic assignment operators + + sc_int<W>& operator += ( int_type v ) + { sc_int_base::operator += ( v ); return *this; } + + sc_int<W>& operator -= ( int_type v ) + { sc_int_base::operator -= ( v ); return *this; } + + sc_int<W>& operator *= ( int_type v ) + { sc_int_base::operator *= ( v ); return *this; } + + sc_int<W>& operator /= ( int_type v ) + { sc_int_base::operator /= ( v ); return *this; } + + sc_int<W>& operator %= ( int_type v ) + { sc_int_base::operator %= ( v ); return *this; } + + + // bitwise assignment operators + + sc_int<W>& operator &= ( int_type v ) + { sc_int_base::operator &= ( v ); return *this; } + + sc_int<W>& operator |= ( int_type v ) + { sc_int_base::operator |= ( v ); return *this; } + + sc_int<W>& operator ^= ( int_type v ) + { sc_int_base::operator ^= ( v ); return *this; } + + + sc_int<W>& operator <<= ( int_type v ) + { sc_int_base::operator <<= ( v ); return *this; } + + sc_int<W>& operator >>= ( int_type v ) + { sc_int_base::operator >>= ( v ); return *this; } + + + // prefix and postfix increment and decrement operators + + sc_int<W>& operator ++ () // prefix + { sc_int_base::operator ++ (); return *this; } + + const sc_int<W> operator ++ ( int ) // postfix + { return sc_int<W>( sc_int_base::operator ++ ( 0 ) ); } + + sc_int<W>& operator -- () // prefix + { sc_int_base::operator -- (); return *this; } + + const sc_int<W> operator -- ( int ) // postfix + { return sc_int<W>( sc_int_base::operator -- ( 0 ) ); } +}; + +} // namespace sc_dt + + +#endif + +// Taf! diff --git a/ext/systemc/src/sysc/datatypes/int/sc_int32_mask.cpp b/ext/systemc/src/sysc/datatypes/int/sc_int32_mask.cpp new file mode 100644 index 000000000..5e55dfb87 --- /dev/null +++ b/ext/systemc/src/sysc/datatypes/int/sc_int32_mask.cpp @@ -0,0 +1,665 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_int32_mask.cpp -- Fills the mask_int lookup table to enable efficient + part-selection on 32-bit sc_ints and sc_uints. + + Original Author: Amit Rao, Synopsys, Inc. + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: Ali Dasdan, Synopsys, Inc. + Description of Modification: - Resolved ambiguity with sc_(un)signed. + - Merged the code for 64- and 32-bit versions + via the constants in sc_nbdefs.h. + - Eliminated redundant file inclusions. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + + +// $Log: sc_int32_mask.cpp,v $ +// Revision 1.2 2011/02/18 20:19:14 acg +// Andy Goodrich: updating Copyright notice. +// +// Revision 1.1.1.1 2006/12/15 20:20:05 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:49:31 acg +// Added $Log command so that CVS check in comments are reproduced in the +// source. +// + +#ifdef _32BIT_ + +#include "sysc/datatypes/int/sc_int_base.h" +#include "sysc/datatypes/int/sc_uint_base.h" + + +namespace sc_dt +{ + +const uint_type mask_int[SC_INTWIDTH][SC_INTWIDTH] = +{ +{ +0xfffffffeU +}, +{ +0xfffffffcU, +0xfffffffdU +}, +{ +0xfffffff8U, +0xfffffff9U, +0xfffffffbU +}, +{ +0xfffffff0U, +0xfffffff1U, +0xfffffff3U, +0xfffffff7U +}, +{ +0xffffffe0U, +0xffffffe1U, +0xffffffe3U, +0xffffffe7U, +0xffffffefU +}, +{ +0xffffffc0U, +0xffffffc1U, +0xffffffc3U, +0xffffffc7U, +0xffffffcfU, +0xffffffdfU +}, +{ +0xffffff80U, +0xffffff81U, +0xffffff83U, +0xffffff87U, +0xffffff8fU, +0xffffff9fU, +0xffffffbfU +}, +{ +0xffffff00U, +0xffffff01U, +0xffffff03U, +0xffffff07U, +0xffffff0fU, +0xffffff1fU, +0xffffff3fU, +0xffffff7fU +}, +{ +0xfffffe00U, +0xfffffe01U, +0xfffffe03U, +0xfffffe07U, +0xfffffe0fU, +0xfffffe1fU, +0xfffffe3fU, +0xfffffe7fU, +0xfffffeffU +}, +{ +0xfffffc00U, +0xfffffc01U, +0xfffffc03U, +0xfffffc07U, +0xfffffc0fU, +0xfffffc1fU, +0xfffffc3fU, +0xfffffc7fU, +0xfffffcffU, +0xfffffdffU +}, +{ +0xfffff800U, +0xfffff801U, +0xfffff803U, +0xfffff807U, +0xfffff80fU, +0xfffff81fU, +0xfffff83fU, +0xfffff87fU, +0xfffff8ffU, +0xfffff9ffU, +0xfffffbffU +}, +{ +0xfffff000U, +0xfffff001U, +0xfffff003U, +0xfffff007U, +0xfffff00fU, +0xfffff01fU, +0xfffff03fU, +0xfffff07fU, +0xfffff0ffU, +0xfffff1ffU, +0xfffff3ffU, +0xfffff7ffU +}, +{ +0xffffe000U, +0xffffe001U, +0xffffe003U, +0xffffe007U, +0xffffe00fU, +0xffffe01fU, +0xffffe03fU, +0xffffe07fU, +0xffffe0ffU, +0xffffe1ffU, +0xffffe3ffU, +0xffffe7ffU, +0xffffefffU +}, +{ +0xffffc000U, +0xffffc001U, +0xffffc003U, +0xffffc007U, +0xffffc00fU, +0xffffc01fU, +0xffffc03fU, +0xffffc07fU, +0xffffc0ffU, +0xffffc1ffU, +0xffffc3ffU, +0xffffc7ffU, +0xffffcfffU, +0xffffdfffU +}, +{ +0xffff8000U, +0xffff8001U, +0xffff8003U, +0xffff8007U, +0xffff800fU, +0xffff801fU, +0xffff803fU, +0xffff807fU, +0xffff80ffU, +0xffff81ffU, +0xffff83ffU, +0xffff87ffU, +0xffff8fffU, +0xffff9fffU, +0xffffbfffU +}, +{ +0xffff0000U, +0xffff0001U, +0xffff0003U, +0xffff0007U, +0xffff000fU, +0xffff001fU, +0xffff003fU, +0xffff007fU, +0xffff00ffU, +0xffff01ffU, +0xffff03ffU, +0xffff07ffU, +0xffff0fffU, +0xffff1fffU, +0xffff3fffU, +0xffff7fffU +}, +{ +0xfffe0000U, +0xfffe0001U, +0xfffe0003U, +0xfffe0007U, +0xfffe000fU, +0xfffe001fU, +0xfffe003fU, +0xfffe007fU, +0xfffe00ffU, +0xfffe01ffU, +0xfffe03ffU, +0xfffe07ffU, +0xfffe0fffU, +0xfffe1fffU, +0xfffe3fffU, +0xfffe7fffU, +0xfffeffffU +}, +{ +0xfffc0000U, +0xfffc0001U, +0xfffc0003U, +0xfffc0007U, +0xfffc000fU, +0xfffc001fU, +0xfffc003fU, +0xfffc007fU, +0xfffc00ffU, +0xfffc01ffU, +0xfffc03ffU, +0xfffc07ffU, +0xfffc0fffU, +0xfffc1fffU, +0xfffc3fffU, +0xfffc7fffU, +0xfffcffffU, +0xfffdffffU +}, +{ +0xfff80000U, +0xfff80001U, +0xfff80003U, +0xfff80007U, +0xfff8000fU, +0xfff8001fU, +0xfff8003fU, +0xfff8007fU, +0xfff800ffU, +0xfff801ffU, +0xfff803ffU, +0xfff807ffU, +0xfff80fffU, +0xfff81fffU, +0xfff83fffU, +0xfff87fffU, +0xfff8ffffU, +0xfff9ffffU, +0xfffbffffU +}, +{ +0xfff00000U, +0xfff00001U, +0xfff00003U, +0xfff00007U, +0xfff0000fU, +0xfff0001fU, +0xfff0003fU, +0xfff0007fU, +0xfff000ffU, +0xfff001ffU, +0xfff003ffU, +0xfff007ffU, +0xfff00fffU, +0xfff01fffU, +0xfff03fffU, +0xfff07fffU, +0xfff0ffffU, +0xfff1ffffU, +0xfff3ffffU, +0xfff7ffffU +}, +{ +0xffe00000U, +0xffe00001U, +0xffe00003U, +0xffe00007U, +0xffe0000fU, +0xffe0001fU, +0xffe0003fU, +0xffe0007fU, +0xffe000ffU, +0xffe001ffU, +0xffe003ffU, +0xffe007ffU, +0xffe00fffU, +0xffe01fffU, +0xffe03fffU, +0xffe07fffU, +0xffe0ffffU, +0xffe1ffffU, +0xffe3ffffU, +0xffe7ffffU, +0xffefffffU +}, +{ +0xffc00000U, +0xffc00001U, +0xffc00003U, +0xffc00007U, +0xffc0000fU, +0xffc0001fU, +0xffc0003fU, +0xffc0007fU, +0xffc000ffU, +0xffc001ffU, +0xffc003ffU, +0xffc007ffU, +0xffc00fffU, +0xffc01fffU, +0xffc03fffU, +0xffc07fffU, +0xffc0ffffU, +0xffc1ffffU, +0xffc3ffffU, +0xffc7ffffU, +0xffcfffffU, +0xffdfffffU +}, +{ +0xff800000U, +0xff800001U, +0xff800003U, +0xff800007U, +0xff80000fU, +0xff80001fU, +0xff80003fU, +0xff80007fU, +0xff8000ffU, +0xff8001ffU, +0xff8003ffU, +0xff8007ffU, +0xff800fffU, +0xff801fffU, +0xff803fffU, +0xff807fffU, +0xff80ffffU, +0xff81ffffU, +0xff83ffffU, +0xff87ffffU, +0xff8fffffU, +0xff9fffffU, +0xffbfffffU +}, +{ +0xff000000U, +0xff000001U, +0xff000003U, +0xff000007U, +0xff00000fU, +0xff00001fU, +0xff00003fU, +0xff00007fU, +0xff0000ffU, +0xff0001ffU, +0xff0003ffU, +0xff0007ffU, +0xff000fffU, +0xff001fffU, +0xff003fffU, +0xff007fffU, +0xff00ffffU, +0xff01ffffU, +0xff03ffffU, +0xff07ffffU, +0xff0fffffU, +0xff1fffffU, +0xff3fffffU, +0xff7fffffU +}, +{ +0xfe000000U, +0xfe000001U, +0xfe000003U, +0xfe000007U, +0xfe00000fU, +0xfe00001fU, +0xfe00003fU, +0xfe00007fU, +0xfe0000ffU, +0xfe0001ffU, +0xfe0003ffU, +0xfe0007ffU, +0xfe000fffU, +0xfe001fffU, +0xfe003fffU, +0xfe007fffU, +0xfe00ffffU, +0xfe01ffffU, +0xfe03ffffU, +0xfe07ffffU, +0xfe0fffffU, +0xfe1fffffU, +0xfe3fffffU, +0xfe7fffffU, +0xfeffffffU +}, +{ +0xfc000000U, +0xfc000001U, +0xfc000003U, +0xfc000007U, +0xfc00000fU, +0xfc00001fU, +0xfc00003fU, +0xfc00007fU, +0xfc0000ffU, +0xfc0001ffU, +0xfc0003ffU, +0xfc0007ffU, +0xfc000fffU, +0xfc001fffU, +0xfc003fffU, +0xfc007fffU, +0xfc00ffffU, +0xfc01ffffU, +0xfc03ffffU, +0xfc07ffffU, +0xfc0fffffU, +0xfc1fffffU, +0xfc3fffffU, +0xfc7fffffU, +0xfcffffffU, +0xfdffffffU +}, +{ +0xf8000000U, +0xf8000001U, +0xf8000003U, +0xf8000007U, +0xf800000fU, +0xf800001fU, +0xf800003fU, +0xf800007fU, +0xf80000ffU, +0xf80001ffU, +0xf80003ffU, +0xf80007ffU, +0xf8000fffU, +0xf8001fffU, +0xf8003fffU, +0xf8007fffU, +0xf800ffffU, +0xf801ffffU, +0xf803ffffU, +0xf807ffffU, +0xf80fffffU, +0xf81fffffU, +0xf83fffffU, +0xf87fffffU, +0xf8ffffffU, +0xf9ffffffU, +0xfbffffffU +}, +{ +0xf0000000U, +0xf0000001U, +0xf0000003U, +0xf0000007U, +0xf000000fU, +0xf000001fU, +0xf000003fU, +0xf000007fU, +0xf00000ffU, +0xf00001ffU, +0xf00003ffU, +0xf00007ffU, +0xf0000fffU, +0xf0001fffU, +0xf0003fffU, +0xf0007fffU, +0xf000ffffU, +0xf001ffffU, +0xf003ffffU, +0xf007ffffU, +0xf00fffffU, +0xf01fffffU, +0xf03fffffU, +0xf07fffffU, +0xf0ffffffU, +0xf1ffffffU, +0xf3ffffffU, +0xf7ffffffU +}, +{ +0xe0000000U, +0xe0000001U, +0xe0000003U, +0xe0000007U, +0xe000000fU, +0xe000001fU, +0xe000003fU, +0xe000007fU, +0xe00000ffU, +0xe00001ffU, +0xe00003ffU, +0xe00007ffU, +0xe0000fffU, +0xe0001fffU, +0xe0003fffU, +0xe0007fffU, +0xe000ffffU, +0xe001ffffU, +0xe003ffffU, +0xe007ffffU, +0xe00fffffU, +0xe01fffffU, +0xe03fffffU, +0xe07fffffU, +0xe0ffffffU, +0xe1ffffffU, +0xe3ffffffU, +0xe7ffffffU, +0xefffffffU +}, +{ +0xc0000000U, +0xc0000001U, +0xc0000003U, +0xc0000007U, +0xc000000fU, +0xc000001fU, +0xc000003fU, +0xc000007fU, +0xc00000ffU, +0xc00001ffU, +0xc00003ffU, +0xc00007ffU, +0xc0000fffU, +0xc0001fffU, +0xc0003fffU, +0xc0007fffU, +0xc000ffffU, +0xc001ffffU, +0xc003ffffU, +0xc007ffffU, +0xc00fffffU, +0xc01fffffU, +0xc03fffffU, +0xc07fffffU, +0xc0ffffffU, +0xc1ffffffU, +0xc3ffffffU, +0xc7ffffffU, +0xcfffffffU, +0xdfffffffU +}, +{ +0x80000000U, +0x80000001U, +0x80000003U, +0x80000007U, +0x8000000fU, +0x8000001fU, +0x8000003fU, +0x8000007fU, +0x800000ffU, +0x800001ffU, +0x800003ffU, +0x800007ffU, +0x80000fffU, +0x80001fffU, +0x80003fffU, +0x80007fffU, +0x8000ffffU, +0x8001ffffU, +0x8003ffffU, +0x8007ffffU, +0x800fffffU, +0x801fffffU, +0x803fffffU, +0x807fffffU, +0x80ffffffU, +0x81ffffffU, +0x83ffffffU, +0x87ffffffU, +0x8fffffffU, +0x9fffffffU, +0xbfffffffU +}, +{ +0x0U, +0x1U, +0x3U, +0x7U, +0xfU, +0x1fU, +0x3fU, +0x7fU, +0xffU, +0x1ffU, +0x3ffU, +0x7ffU, +0xfffU, +0x1fffU, +0x3fffU, +0x7fffU, +0xffffU, +0x1ffffU, +0x3ffffU, +0x7ffffU, +0xfffffU, +0x1fffffU, +0x3fffffU, +0x7fffffU, +0xffffffU, +0x1ffffffU, +0x3ffffffU, +0x7ffffffU, +0xfffffffU, +0x1fffffffU, +0x3fffffffU, +0x7fffffffU +} +}; + +} // namespace sc_dt + +#endif diff --git a/ext/systemc/src/sysc/datatypes/int/sc_int64_io.cpp b/ext/systemc/src/sysc/datatypes/int/sc_int64_io.cpp new file mode 100644 index 000000000..b43bc6ed8 --- /dev/null +++ b/ext/systemc/src/sysc/datatypes/int/sc_int64_io.cpp @@ -0,0 +1,182 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_int64_io.cpp -- + + Original Author: Amit Rao, Synopsys, Inc. + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + + +// $Log: sc_int64_io.cpp,v $ +// Revision 1.2 2011/02/18 20:19:14 acg +// Andy Goodrich: updating Copyright notice. +// +// Revision 1.1.1.1 2006/12/15 20:20:05 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:49:31 acg +// Added $Log command so that CVS check in comments are reproduced in the +// source. +// + +#include "sysc/utils/sc_iostream.h" +#include "sysc/datatypes/int/sc_unsigned.h" +#include "sysc/datatypes/int/sc_signed.h" +#include "sysc/datatypes/int/sc_int_base.h" +#include "sysc/datatypes/int/sc_uint_base.h" + + +#if defined( _MSC_VER ) + +namespace sc_dt +{ + +static void +write_uint64(::std::ostream& os, uint64 val, int sign) +{ + const int WRITE_BUF_SIZE = 10 + sizeof(uint64)*3; + char buf[WRITE_BUF_SIZE]; + char* buf_ptr = buf + WRITE_BUF_SIZE; + const char* show_base = ""; + int show_base_len = 0; + int show_pos = 0; + fmtflags flags = os.flags(); + + if ((flags & ::std::ios::basefield) == ::std::ios::oct) { + do { + *--buf_ptr = (char)((val & 7) + '0'); + val = val >> 3; + } while (val != 0); + if ((flags & ::std::ios::showbase) && (*buf_ptr != '0')) + *--buf_ptr = '0'; + } else if ((flags & ::std::ios::basefield) == ::std::ios::hex) { + const char* xdigs = (flags & ::std::ios::uppercase) ? + "0123456789ABCDEF0X" : + "0123456789abcdef0x"; + do { + *--buf_ptr = xdigs[val & 15]; + val = val >> 4; + } while (val != 0); + if ((flags & ::std::ios::showbase)) { + show_base = xdigs + 16; + show_base_len = 2; + } + } else { + while (val > UINT_MAX) { + *--buf_ptr = (char)((val % 10) + '0'); + val /= 10; + } + unsigned ival = (unsigned) val; + do { + *--buf_ptr = (ival % 10) + '0'; + ival /= 10; + } while (ival != 0); + if (sign > 0 && (flags & ::std::ios::showpos)) + show_pos = 1; + } + + int buf_len = buf + WRITE_BUF_SIZE - buf_ptr; + int w = os.width(0); + + int len = buf_len + show_pos; + if (sign < 0) len++; + len += show_base_len; + + int padding = len > w ? 0 : w - len; + fmtflags pad_kind = flags & ::std::ios::adjustfield; + char fill_char = os.fill(); + + if (padding > 0 && + ::std::ios::left != pad_kind && + ::std::ios::internal != pad_kind) { + for (int i = padding - 1; i >= 0; --i) { + if (! os.put(fill_char)) + goto fail; + } + } + if (sign < 0 || show_pos) { + if (! os.put(sign < 0 ? '-' : '+')) + goto fail; + } + if (show_base_len) { + if (! os.write(show_base, show_base_len)) + goto fail; + } + if ((fmtflags)::std::ios::internal == pad_kind && padding > 0) { + for (int i = padding - 1; i >= 0; --i) { + if (! os.put(fill_char)) + goto fail; + } + } + if (! os.write(buf_ptr, buf_len)) + goto fail; + if ((fmtflags)::std::ios::left == pad_kind && padding > 0) { + for (int i = padding - 1; i >= 0; --i) { + if (! os.put(fill_char)) + goto fail; + } + } + os.osfx(); + return; +fail: + //os.set(::std::ios::badbit); + os.osfx(); +} + +::std::ostream& +operator << ( ::std::ostream& os, int64 n ) +{ + if (os.opfx()) { + int sign = 1; + uint64 abs_n = (uint64) n; + if (n < 0 && (os.flags() & (::std::ios::oct|::std::ios::hex)) == 0) { + abs_n = -1*((uint64) n); + sign = -1; + } + sc_dt::write_uint64(os, abs_n, sign); + } + return os; +} + +::std::ostream& +operator << ( ::std::ostream& os, uint64 n ) +{ + if (os.opfx()) { + sc_dt::write_uint64(os, n, 0); + } + return os; +} + +} // namespace sc_dt + + +#endif diff --git a/ext/systemc/src/sysc/datatypes/int/sc_int64_mask.cpp b/ext/systemc/src/sysc/datatypes/int/sc_int64_mask.cpp new file mode 100644 index 000000000..df69a6dda --- /dev/null +++ b/ext/systemc/src/sysc/datatypes/int/sc_int64_mask.cpp @@ -0,0 +1,4502 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_int64_mask.cpp -- Fills the mask_int lookup table to enable efficient + part-selection on 64-bit sc_ints and sc_uints. + + Original Author: Amit Rao, Synopsys, Inc. + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: Ali Dasdan, Synopsys, Inc. + Description of Modification: - Resolved ambiguity with sc_(un)signed. + - Merged the code for 64- and 32-bit versions + via the constants in sc_nbdefs.h. + - Eliminated redundant file inclusions. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + + +// $Log: sc_int64_mask.cpp,v $ +// Revision 1.3 2011/02/18 20:19:14 acg +// Andy Goodrich: updating Copyright notice. +// +// Revision 1.2 2009/05/22 16:06:29 acg +// Andy Goodrich: process control updates. +// +// Revision 1.1.1.1 2006/12/15 20:20:05 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:49:31 acg +// Added $Log command so that CVS check in comments are reproduced in the +// source. +// + +#ifndef _32BIT_ + +#include "sysc/datatypes/int/sc_int_base.h" +#include "sysc/datatypes/int/sc_uint_base.h" + + +namespace sc_dt +{ + +#if !defined(_WIN32) || defined(__MINGW32__) + +const uint_type mask_int[SC_INTWIDTH][SC_INTWIDTH] = +{ +{ +0xfffffffffffffffeULL +}, +{ +0xfffffffffffffffcULL, +0xfffffffffffffffdULL +}, +{ +0xfffffffffffffff8ULL, +0xfffffffffffffff9ULL, +0xfffffffffffffffbULL +}, +{ +0xfffffffffffffff0ULL, +0xfffffffffffffff1ULL, +0xfffffffffffffff3ULL, +0xfffffffffffffff7ULL +}, +{ +0xffffffffffffffe0ULL, +0xffffffffffffffe1ULL, +0xffffffffffffffe3ULL, +0xffffffffffffffe7ULL, +0xffffffffffffffefULL +}, +{ +0xffffffffffffffc0ULL, +0xffffffffffffffc1ULL, +0xffffffffffffffc3ULL, +0xffffffffffffffc7ULL, +0xffffffffffffffcfULL, +0xffffffffffffffdfULL +}, +{ +0xffffffffffffff80ULL, +0xffffffffffffff81ULL, +0xffffffffffffff83ULL, +0xffffffffffffff87ULL, +0xffffffffffffff8fULL, +0xffffffffffffff9fULL, +0xffffffffffffffbfULL +}, +{ +0xffffffffffffff00ULL, +0xffffffffffffff01ULL, +0xffffffffffffff03ULL, +0xffffffffffffff07ULL, +0xffffffffffffff0fULL, +0xffffffffffffff1fULL, +0xffffffffffffff3fULL, +0xffffffffffffff7fULL +}, +{ +0xfffffffffffffe00ULL, +0xfffffffffffffe01ULL, +0xfffffffffffffe03ULL, +0xfffffffffffffe07ULL, +0xfffffffffffffe0fULL, +0xfffffffffffffe1fULL, +0xfffffffffffffe3fULL, +0xfffffffffffffe7fULL, +0xfffffffffffffeffULL +}, +{ +0xfffffffffffffc00ULL, +0xfffffffffffffc01ULL, +0xfffffffffffffc03ULL, +0xfffffffffffffc07ULL, +0xfffffffffffffc0fULL, +0xfffffffffffffc1fULL, +0xfffffffffffffc3fULL, +0xfffffffffffffc7fULL, +0xfffffffffffffcffULL, +0xfffffffffffffdffULL +}, +{ +0xfffffffffffff800ULL, +0xfffffffffffff801ULL, +0xfffffffffffff803ULL, +0xfffffffffffff807ULL, +0xfffffffffffff80fULL, +0xfffffffffffff81fULL, +0xfffffffffffff83fULL, +0xfffffffffffff87fULL, +0xfffffffffffff8ffULL, +0xfffffffffffff9ffULL, +0xfffffffffffffbffULL +}, +{ +0xfffffffffffff000ULL, +0xfffffffffffff001ULL, +0xfffffffffffff003ULL, +0xfffffffffffff007ULL, +0xfffffffffffff00fULL, +0xfffffffffffff01fULL, +0xfffffffffffff03fULL, +0xfffffffffffff07fULL, +0xfffffffffffff0ffULL, +0xfffffffffffff1ffULL, +0xfffffffffffff3ffULL, +0xfffffffffffff7ffULL +}, +{ +0xffffffffffffe000ULL, +0xffffffffffffe001ULL, +0xffffffffffffe003ULL, +0xffffffffffffe007ULL, +0xffffffffffffe00fULL, +0xffffffffffffe01fULL, +0xffffffffffffe03fULL, +0xffffffffffffe07fULL, +0xffffffffffffe0ffULL, +0xffffffffffffe1ffULL, +0xffffffffffffe3ffULL, +0xffffffffffffe7ffULL, +0xffffffffffffefffULL +}, +{ +0xffffffffffffc000ULL, +0xffffffffffffc001ULL, +0xffffffffffffc003ULL, +0xffffffffffffc007ULL, +0xffffffffffffc00fULL, +0xffffffffffffc01fULL, +0xffffffffffffc03fULL, +0xffffffffffffc07fULL, +0xffffffffffffc0ffULL, +0xffffffffffffc1ffULL, +0xffffffffffffc3ffULL, +0xffffffffffffc7ffULL, +0xffffffffffffcfffULL, +0xffffffffffffdfffULL +}, +{ +0xffffffffffff8000ULL, +0xffffffffffff8001ULL, +0xffffffffffff8003ULL, +0xffffffffffff8007ULL, +0xffffffffffff800fULL, +0xffffffffffff801fULL, +0xffffffffffff803fULL, +0xffffffffffff807fULL, +0xffffffffffff80ffULL, +0xffffffffffff81ffULL, +0xffffffffffff83ffULL, +0xffffffffffff87ffULL, +0xffffffffffff8fffULL, +0xffffffffffff9fffULL, +0xffffffffffffbfffULL +}, +{ +0xffffffffffff0000ULL, +0xffffffffffff0001ULL, +0xffffffffffff0003ULL, +0xffffffffffff0007ULL, +0xffffffffffff000fULL, +0xffffffffffff001fULL, +0xffffffffffff003fULL, +0xffffffffffff007fULL, +0xffffffffffff00ffULL, +0xffffffffffff01ffULL, +0xffffffffffff03ffULL, +0xffffffffffff07ffULL, +0xffffffffffff0fffULL, +0xffffffffffff1fffULL, +0xffffffffffff3fffULL, +0xffffffffffff7fffULL +}, +{ +0xfffffffffffe0000ULL, +0xfffffffffffe0001ULL, +0xfffffffffffe0003ULL, +0xfffffffffffe0007ULL, +0xfffffffffffe000fULL, +0xfffffffffffe001fULL, +0xfffffffffffe003fULL, +0xfffffffffffe007fULL, +0xfffffffffffe00ffULL, +0xfffffffffffe01ffULL, +0xfffffffffffe03ffULL, +0xfffffffffffe07ffULL, +0xfffffffffffe0fffULL, +0xfffffffffffe1fffULL, +0xfffffffffffe3fffULL, +0xfffffffffffe7fffULL, +0xfffffffffffeffffULL +}, +{ +0xfffffffffffc0000ULL, +0xfffffffffffc0001ULL, +0xfffffffffffc0003ULL, +0xfffffffffffc0007ULL, +0xfffffffffffc000fULL, +0xfffffffffffc001fULL, +0xfffffffffffc003fULL, +0xfffffffffffc007fULL, +0xfffffffffffc00ffULL, +0xfffffffffffc01ffULL, +0xfffffffffffc03ffULL, +0xfffffffffffc07ffULL, +0xfffffffffffc0fffULL, +0xfffffffffffc1fffULL, +0xfffffffffffc3fffULL, +0xfffffffffffc7fffULL, +0xfffffffffffcffffULL, +0xfffffffffffdffffULL +}, +{ +0xfffffffffff80000ULL, +0xfffffffffff80001ULL, +0xfffffffffff80003ULL, +0xfffffffffff80007ULL, +0xfffffffffff8000fULL, +0xfffffffffff8001fULL, +0xfffffffffff8003fULL, +0xfffffffffff8007fULL, +0xfffffffffff800ffULL, +0xfffffffffff801ffULL, +0xfffffffffff803ffULL, +0xfffffffffff807ffULL, +0xfffffffffff80fffULL, +0xfffffffffff81fffULL, +0xfffffffffff83fffULL, +0xfffffffffff87fffULL, +0xfffffffffff8ffffULL, +0xfffffffffff9ffffULL, +0xfffffffffffbffffULL +}, +{ +0xfffffffffff00000ULL, +0xfffffffffff00001ULL, +0xfffffffffff00003ULL, +0xfffffffffff00007ULL, +0xfffffffffff0000fULL, +0xfffffffffff0001fULL, +0xfffffffffff0003fULL, +0xfffffffffff0007fULL, +0xfffffffffff000ffULL, +0xfffffffffff001ffULL, +0xfffffffffff003ffULL, +0xfffffffffff007ffULL, +0xfffffffffff00fffULL, +0xfffffffffff01fffULL, +0xfffffffffff03fffULL, +0xfffffffffff07fffULL, +0xfffffffffff0ffffULL, +0xfffffffffff1ffffULL, +0xfffffffffff3ffffULL, +0xfffffffffff7ffffULL +}, +{ +0xffffffffffe00000ULL, +0xffffffffffe00001ULL, +0xffffffffffe00003ULL, +0xffffffffffe00007ULL, +0xffffffffffe0000fULL, +0xffffffffffe0001fULL, +0xffffffffffe0003fULL, +0xffffffffffe0007fULL, +0xffffffffffe000ffULL, +0xffffffffffe001ffULL, +0xffffffffffe003ffULL, +0xffffffffffe007ffULL, +0xffffffffffe00fffULL, +0xffffffffffe01fffULL, +0xffffffffffe03fffULL, +0xffffffffffe07fffULL, +0xffffffffffe0ffffULL, +0xffffffffffe1ffffULL, +0xffffffffffe3ffffULL, +0xffffffffffe7ffffULL, +0xffffffffffefffffULL +}, +{ +0xffffffffffc00000ULL, +0xffffffffffc00001ULL, +0xffffffffffc00003ULL, +0xffffffffffc00007ULL, +0xffffffffffc0000fULL, +0xffffffffffc0001fULL, +0xffffffffffc0003fULL, +0xffffffffffc0007fULL, +0xffffffffffc000ffULL, +0xffffffffffc001ffULL, +0xffffffffffc003ffULL, +0xffffffffffc007ffULL, +0xffffffffffc00fffULL, +0xffffffffffc01fffULL, +0xffffffffffc03fffULL, +0xffffffffffc07fffULL, +0xffffffffffc0ffffULL, +0xffffffffffc1ffffULL, +0xffffffffffc3ffffULL, +0xffffffffffc7ffffULL, +0xffffffffffcfffffULL, +0xffffffffffdfffffULL +}, +{ +0xffffffffff800000ULL, +0xffffffffff800001ULL, +0xffffffffff800003ULL, +0xffffffffff800007ULL, +0xffffffffff80000fULL, +0xffffffffff80001fULL, +0xffffffffff80003fULL, +0xffffffffff80007fULL, +0xffffffffff8000ffULL, +0xffffffffff8001ffULL, +0xffffffffff8003ffULL, +0xffffffffff8007ffULL, +0xffffffffff800fffULL, +0xffffffffff801fffULL, +0xffffffffff803fffULL, +0xffffffffff807fffULL, +0xffffffffff80ffffULL, +0xffffffffff81ffffULL, +0xffffffffff83ffffULL, +0xffffffffff87ffffULL, +0xffffffffff8fffffULL, +0xffffffffff9fffffULL, +0xffffffffffbfffffULL +}, +{ +0xffffffffff000000ULL, +0xffffffffff000001ULL, +0xffffffffff000003ULL, +0xffffffffff000007ULL, +0xffffffffff00000fULL, +0xffffffffff00001fULL, +0xffffffffff00003fULL, +0xffffffffff00007fULL, +0xffffffffff0000ffULL, +0xffffffffff0001ffULL, +0xffffffffff0003ffULL, +0xffffffffff0007ffULL, +0xffffffffff000fffULL, +0xffffffffff001fffULL, +0xffffffffff003fffULL, +0xffffffffff007fffULL, +0xffffffffff00ffffULL, +0xffffffffff01ffffULL, +0xffffffffff03ffffULL, +0xffffffffff07ffffULL, +0xffffffffff0fffffULL, +0xffffffffff1fffffULL, +0xffffffffff3fffffULL, +0xffffffffff7fffffULL +}, +{ +0xfffffffffe000000ULL, +0xfffffffffe000001ULL, +0xfffffffffe000003ULL, +0xfffffffffe000007ULL, +0xfffffffffe00000fULL, +0xfffffffffe00001fULL, +0xfffffffffe00003fULL, +0xfffffffffe00007fULL, +0xfffffffffe0000ffULL, +0xfffffffffe0001ffULL, +0xfffffffffe0003ffULL, +0xfffffffffe0007ffULL, +0xfffffffffe000fffULL, +0xfffffffffe001fffULL, +0xfffffffffe003fffULL, +0xfffffffffe007fffULL, +0xfffffffffe00ffffULL, +0xfffffffffe01ffffULL, +0xfffffffffe03ffffULL, +0xfffffffffe07ffffULL, +0xfffffffffe0fffffULL, +0xfffffffffe1fffffULL, +0xfffffffffe3fffffULL, +0xfffffffffe7fffffULL, +0xfffffffffeffffffULL +}, +{ +0xfffffffffc000000ULL, +0xfffffffffc000001ULL, +0xfffffffffc000003ULL, +0xfffffffffc000007ULL, +0xfffffffffc00000fULL, +0xfffffffffc00001fULL, +0xfffffffffc00003fULL, +0xfffffffffc00007fULL, +0xfffffffffc0000ffULL, +0xfffffffffc0001ffULL, +0xfffffffffc0003ffULL, +0xfffffffffc0007ffULL, +0xfffffffffc000fffULL, +0xfffffffffc001fffULL, +0xfffffffffc003fffULL, +0xfffffffffc007fffULL, +0xfffffffffc00ffffULL, +0xfffffffffc01ffffULL, +0xfffffffffc03ffffULL, +0xfffffffffc07ffffULL, +0xfffffffffc0fffffULL, +0xfffffffffc1fffffULL, +0xfffffffffc3fffffULL, +0xfffffffffc7fffffULL, +0xfffffffffcffffffULL, +0xfffffffffdffffffULL +}, +{ +0xfffffffff8000000ULL, +0xfffffffff8000001ULL, +0xfffffffff8000003ULL, +0xfffffffff8000007ULL, +0xfffffffff800000fULL, +0xfffffffff800001fULL, +0xfffffffff800003fULL, +0xfffffffff800007fULL, +0xfffffffff80000ffULL, +0xfffffffff80001ffULL, +0xfffffffff80003ffULL, +0xfffffffff80007ffULL, +0xfffffffff8000fffULL, +0xfffffffff8001fffULL, +0xfffffffff8003fffULL, +0xfffffffff8007fffULL, +0xfffffffff800ffffULL, +0xfffffffff801ffffULL, +0xfffffffff803ffffULL, +0xfffffffff807ffffULL, +0xfffffffff80fffffULL, +0xfffffffff81fffffULL, +0xfffffffff83fffffULL, +0xfffffffff87fffffULL, +0xfffffffff8ffffffULL, +0xfffffffff9ffffffULL, +0xfffffffffbffffffULL +}, +{ +0xfffffffff0000000ULL, +0xfffffffff0000001ULL, +0xfffffffff0000003ULL, +0xfffffffff0000007ULL, +0xfffffffff000000fULL, +0xfffffffff000001fULL, +0xfffffffff000003fULL, +0xfffffffff000007fULL, +0xfffffffff00000ffULL, +0xfffffffff00001ffULL, +0xfffffffff00003ffULL, +0xfffffffff00007ffULL, +0xfffffffff0000fffULL, +0xfffffffff0001fffULL, +0xfffffffff0003fffULL, +0xfffffffff0007fffULL, +0xfffffffff000ffffULL, +0xfffffffff001ffffULL, +0xfffffffff003ffffULL, +0xfffffffff007ffffULL, +0xfffffffff00fffffULL, +0xfffffffff01fffffULL, +0xfffffffff03fffffULL, +0xfffffffff07fffffULL, +0xfffffffff0ffffffULL, +0xfffffffff1ffffffULL, +0xfffffffff3ffffffULL, +0xfffffffff7ffffffULL +}, +{ +0xffffffffe0000000ULL, +0xffffffffe0000001ULL, +0xffffffffe0000003ULL, +0xffffffffe0000007ULL, +0xffffffffe000000fULL, +0xffffffffe000001fULL, +0xffffffffe000003fULL, +0xffffffffe000007fULL, +0xffffffffe00000ffULL, +0xffffffffe00001ffULL, +0xffffffffe00003ffULL, +0xffffffffe00007ffULL, +0xffffffffe0000fffULL, +0xffffffffe0001fffULL, +0xffffffffe0003fffULL, +0xffffffffe0007fffULL, +0xffffffffe000ffffULL, +0xffffffffe001ffffULL, +0xffffffffe003ffffULL, +0xffffffffe007ffffULL, +0xffffffffe00fffffULL, +0xffffffffe01fffffULL, +0xffffffffe03fffffULL, +0xffffffffe07fffffULL, +0xffffffffe0ffffffULL, +0xffffffffe1ffffffULL, +0xffffffffe3ffffffULL, +0xffffffffe7ffffffULL, +0xffffffffefffffffULL +}, +{ +0xffffffffc0000000ULL, +0xffffffffc0000001ULL, +0xffffffffc0000003ULL, +0xffffffffc0000007ULL, +0xffffffffc000000fULL, +0xffffffffc000001fULL, +0xffffffffc000003fULL, +0xffffffffc000007fULL, +0xffffffffc00000ffULL, +0xffffffffc00001ffULL, +0xffffffffc00003ffULL, +0xffffffffc00007ffULL, +0xffffffffc0000fffULL, +0xffffffffc0001fffULL, +0xffffffffc0003fffULL, +0xffffffffc0007fffULL, +0xffffffffc000ffffULL, +0xffffffffc001ffffULL, +0xffffffffc003ffffULL, +0xffffffffc007ffffULL, +0xffffffffc00fffffULL, +0xffffffffc01fffffULL, +0xffffffffc03fffffULL, +0xffffffffc07fffffULL, +0xffffffffc0ffffffULL, +0xffffffffc1ffffffULL, +0xffffffffc3ffffffULL, +0xffffffffc7ffffffULL, +0xffffffffcfffffffULL, +0xffffffffdfffffffULL +}, +{ +0xffffffff80000000ULL, +0xffffffff80000001ULL, +0xffffffff80000003ULL, +0xffffffff80000007ULL, +0xffffffff8000000fULL, +0xffffffff8000001fULL, +0xffffffff8000003fULL, +0xffffffff8000007fULL, +0xffffffff800000ffULL, +0xffffffff800001ffULL, +0xffffffff800003ffULL, +0xffffffff800007ffULL, +0xffffffff80000fffULL, +0xffffffff80001fffULL, +0xffffffff80003fffULL, +0xffffffff80007fffULL, +0xffffffff8000ffffULL, +0xffffffff8001ffffULL, +0xffffffff8003ffffULL, +0xffffffff8007ffffULL, +0xffffffff800fffffULL, +0xffffffff801fffffULL, +0xffffffff803fffffULL, +0xffffffff807fffffULL, +0xffffffff80ffffffULL, +0xffffffff81ffffffULL, +0xffffffff83ffffffULL, +0xffffffff87ffffffULL, +0xffffffff8fffffffULL, +0xffffffff9fffffffULL, +0xffffffffbfffffffULL +}, +{ +0xffffffff00000000ULL, +0xffffffff00000001ULL, +0xffffffff00000003ULL, +0xffffffff00000007ULL, +0xffffffff0000000fULL, +0xffffffff0000001fULL, +0xffffffff0000003fULL, +0xffffffff0000007fULL, +0xffffffff000000ffULL, +0xffffffff000001ffULL, +0xffffffff000003ffULL, +0xffffffff000007ffULL, +0xffffffff00000fffULL, +0xffffffff00001fffULL, +0xffffffff00003fffULL, +0xffffffff00007fffULL, +0xffffffff0000ffffULL, +0xffffffff0001ffffULL, +0xffffffff0003ffffULL, +0xffffffff0007ffffULL, +0xffffffff000fffffULL, +0xffffffff001fffffULL, +0xffffffff003fffffULL, +0xffffffff007fffffULL, +0xffffffff00ffffffULL, +0xffffffff01ffffffULL, +0xffffffff03ffffffULL, +0xffffffff07ffffffULL, +0xffffffff0fffffffULL, +0xffffffff1fffffffULL, +0xffffffff3fffffffULL, +0xffffffff7fffffffULL +}, +{ +0xfffffffe00000000ULL, +0xfffffffe00000001ULL, +0xfffffffe00000003ULL, +0xfffffffe00000007ULL, +0xfffffffe0000000fULL, +0xfffffffe0000001fULL, +0xfffffffe0000003fULL, +0xfffffffe0000007fULL, +0xfffffffe000000ffULL, +0xfffffffe000001ffULL, +0xfffffffe000003ffULL, +0xfffffffe000007ffULL, +0xfffffffe00000fffULL, +0xfffffffe00001fffULL, +0xfffffffe00003fffULL, +0xfffffffe00007fffULL, +0xfffffffe0000ffffULL, +0xfffffffe0001ffffULL, +0xfffffffe0003ffffULL, +0xfffffffe0007ffffULL, +0xfffffffe000fffffULL, +0xfffffffe001fffffULL, +0xfffffffe003fffffULL, +0xfffffffe007fffffULL, +0xfffffffe00ffffffULL, +0xfffffffe01ffffffULL, +0xfffffffe03ffffffULL, +0xfffffffe07ffffffULL, +0xfffffffe0fffffffULL, +0xfffffffe1fffffffULL, +0xfffffffe3fffffffULL, +0xfffffffe7fffffffULL, +0xfffffffeffffffffULL +}, +{ +0xfffffffc00000000ULL, +0xfffffffc00000001ULL, +0xfffffffc00000003ULL, +0xfffffffc00000007ULL, +0xfffffffc0000000fULL, +0xfffffffc0000001fULL, +0xfffffffc0000003fULL, +0xfffffffc0000007fULL, +0xfffffffc000000ffULL, +0xfffffffc000001ffULL, +0xfffffffc000003ffULL, +0xfffffffc000007ffULL, +0xfffffffc00000fffULL, +0xfffffffc00001fffULL, +0xfffffffc00003fffULL, +0xfffffffc00007fffULL, +0xfffffffc0000ffffULL, +0xfffffffc0001ffffULL, +0xfffffffc0003ffffULL, +0xfffffffc0007ffffULL, +0xfffffffc000fffffULL, +0xfffffffc001fffffULL, +0xfffffffc003fffffULL, +0xfffffffc007fffffULL, +0xfffffffc00ffffffULL, +0xfffffffc01ffffffULL, +0xfffffffc03ffffffULL, +0xfffffffc07ffffffULL, +0xfffffffc0fffffffULL, +0xfffffffc1fffffffULL, +0xfffffffc3fffffffULL, +0xfffffffc7fffffffULL, +0xfffffffcffffffffULL, +0xfffffffdffffffffULL +}, +{ +0xfffffff800000000ULL, +0xfffffff800000001ULL, +0xfffffff800000003ULL, +0xfffffff800000007ULL, +0xfffffff80000000fULL, +0xfffffff80000001fULL, +0xfffffff80000003fULL, +0xfffffff80000007fULL, +0xfffffff8000000ffULL, +0xfffffff8000001ffULL, +0xfffffff8000003ffULL, +0xfffffff8000007ffULL, +0xfffffff800000fffULL, +0xfffffff800001fffULL, +0xfffffff800003fffULL, +0xfffffff800007fffULL, +0xfffffff80000ffffULL, +0xfffffff80001ffffULL, +0xfffffff80003ffffULL, +0xfffffff80007ffffULL, +0xfffffff8000fffffULL, +0xfffffff8001fffffULL, +0xfffffff8003fffffULL, +0xfffffff8007fffffULL, +0xfffffff800ffffffULL, +0xfffffff801ffffffULL, +0xfffffff803ffffffULL, +0xfffffff807ffffffULL, +0xfffffff80fffffffULL, +0xfffffff81fffffffULL, +0xfffffff83fffffffULL, +0xfffffff87fffffffULL, +0xfffffff8ffffffffULL, +0xfffffff9ffffffffULL, +0xfffffffbffffffffULL +}, +{ +0xfffffff000000000ULL, +0xfffffff000000001ULL, +0xfffffff000000003ULL, +0xfffffff000000007ULL, +0xfffffff00000000fULL, +0xfffffff00000001fULL, +0xfffffff00000003fULL, +0xfffffff00000007fULL, +0xfffffff0000000ffULL, +0xfffffff0000001ffULL, +0xfffffff0000003ffULL, +0xfffffff0000007ffULL, +0xfffffff000000fffULL, +0xfffffff000001fffULL, +0xfffffff000003fffULL, +0xfffffff000007fffULL, +0xfffffff00000ffffULL, +0xfffffff00001ffffULL, +0xfffffff00003ffffULL, +0xfffffff00007ffffULL, +0xfffffff0000fffffULL, +0xfffffff0001fffffULL, +0xfffffff0003fffffULL, +0xfffffff0007fffffULL, +0xfffffff000ffffffULL, +0xfffffff001ffffffULL, +0xfffffff003ffffffULL, +0xfffffff007ffffffULL, +0xfffffff00fffffffULL, +0xfffffff01fffffffULL, +0xfffffff03fffffffULL, +0xfffffff07fffffffULL, +0xfffffff0ffffffffULL, +0xfffffff1ffffffffULL, +0xfffffff3ffffffffULL, +0xfffffff7ffffffffULL +}, +{ +0xffffffe000000000ULL, +0xffffffe000000001ULL, +0xffffffe000000003ULL, +0xffffffe000000007ULL, +0xffffffe00000000fULL, +0xffffffe00000001fULL, +0xffffffe00000003fULL, +0xffffffe00000007fULL, +0xffffffe0000000ffULL, +0xffffffe0000001ffULL, +0xffffffe0000003ffULL, +0xffffffe0000007ffULL, +0xffffffe000000fffULL, +0xffffffe000001fffULL, +0xffffffe000003fffULL, +0xffffffe000007fffULL, +0xffffffe00000ffffULL, +0xffffffe00001ffffULL, +0xffffffe00003ffffULL, +0xffffffe00007ffffULL, +0xffffffe0000fffffULL, +0xffffffe0001fffffULL, +0xffffffe0003fffffULL, +0xffffffe0007fffffULL, +0xffffffe000ffffffULL, +0xffffffe001ffffffULL, +0xffffffe003ffffffULL, +0xffffffe007ffffffULL, +0xffffffe00fffffffULL, +0xffffffe01fffffffULL, +0xffffffe03fffffffULL, +0xffffffe07fffffffULL, +0xffffffe0ffffffffULL, +0xffffffe1ffffffffULL, +0xffffffe3ffffffffULL, +0xffffffe7ffffffffULL, +0xffffffefffffffffULL +}, +{ +0xffffffc000000000ULL, +0xffffffc000000001ULL, +0xffffffc000000003ULL, +0xffffffc000000007ULL, +0xffffffc00000000fULL, +0xffffffc00000001fULL, +0xffffffc00000003fULL, +0xffffffc00000007fULL, +0xffffffc0000000ffULL, +0xffffffc0000001ffULL, +0xffffffc0000003ffULL, +0xffffffc0000007ffULL, +0xffffffc000000fffULL, +0xffffffc000001fffULL, +0xffffffc000003fffULL, +0xffffffc000007fffULL, +0xffffffc00000ffffULL, +0xffffffc00001ffffULL, +0xffffffc00003ffffULL, +0xffffffc00007ffffULL, +0xffffffc0000fffffULL, +0xffffffc0001fffffULL, +0xffffffc0003fffffULL, +0xffffffc0007fffffULL, +0xffffffc000ffffffULL, +0xffffffc001ffffffULL, +0xffffffc003ffffffULL, +0xffffffc007ffffffULL, +0xffffffc00fffffffULL, +0xffffffc01fffffffULL, +0xffffffc03fffffffULL, +0xffffffc07fffffffULL, +0xffffffc0ffffffffULL, +0xffffffc1ffffffffULL, +0xffffffc3ffffffffULL, +0xffffffc7ffffffffULL, +0xffffffcfffffffffULL, +0xffffffdfffffffffULL +}, +{ +0xffffff8000000000ULL, +0xffffff8000000001ULL, +0xffffff8000000003ULL, +0xffffff8000000007ULL, +0xffffff800000000fULL, +0xffffff800000001fULL, +0xffffff800000003fULL, +0xffffff800000007fULL, +0xffffff80000000ffULL, +0xffffff80000001ffULL, +0xffffff80000003ffULL, +0xffffff80000007ffULL, +0xffffff8000000fffULL, +0xffffff8000001fffULL, +0xffffff8000003fffULL, +0xffffff8000007fffULL, +0xffffff800000ffffULL, +0xffffff800001ffffULL, +0xffffff800003ffffULL, +0xffffff800007ffffULL, +0xffffff80000fffffULL, +0xffffff80001fffffULL, +0xffffff80003fffffULL, +0xffffff80007fffffULL, +0xffffff8000ffffffULL, +0xffffff8001ffffffULL, +0xffffff8003ffffffULL, +0xffffff8007ffffffULL, +0xffffff800fffffffULL, +0xffffff801fffffffULL, +0xffffff803fffffffULL, +0xffffff807fffffffULL, +0xffffff80ffffffffULL, +0xffffff81ffffffffULL, +0xffffff83ffffffffULL, +0xffffff87ffffffffULL, +0xffffff8fffffffffULL, +0xffffff9fffffffffULL, +0xffffffbfffffffffULL +}, +{ +0xffffff0000000000ULL, +0xffffff0000000001ULL, +0xffffff0000000003ULL, +0xffffff0000000007ULL, +0xffffff000000000fULL, +0xffffff000000001fULL, +0xffffff000000003fULL, +0xffffff000000007fULL, +0xffffff00000000ffULL, +0xffffff00000001ffULL, +0xffffff00000003ffULL, +0xffffff00000007ffULL, +0xffffff0000000fffULL, +0xffffff0000001fffULL, +0xffffff0000003fffULL, +0xffffff0000007fffULL, +0xffffff000000ffffULL, +0xffffff000001ffffULL, +0xffffff000003ffffULL, +0xffffff000007ffffULL, +0xffffff00000fffffULL, +0xffffff00001fffffULL, +0xffffff00003fffffULL, +0xffffff00007fffffULL, +0xffffff0000ffffffULL, +0xffffff0001ffffffULL, +0xffffff0003ffffffULL, +0xffffff0007ffffffULL, +0xffffff000fffffffULL, +0xffffff001fffffffULL, +0xffffff003fffffffULL, +0xffffff007fffffffULL, +0xffffff00ffffffffULL, +0xffffff01ffffffffULL, +0xffffff03ffffffffULL, +0xffffff07ffffffffULL, +0xffffff0fffffffffULL, +0xffffff1fffffffffULL, +0xffffff3fffffffffULL, +0xffffff7fffffffffULL +}, +{ +0xfffffe0000000000ULL, +0xfffffe0000000001ULL, +0xfffffe0000000003ULL, +0xfffffe0000000007ULL, +0xfffffe000000000fULL, +0xfffffe000000001fULL, +0xfffffe000000003fULL, +0xfffffe000000007fULL, +0xfffffe00000000ffULL, +0xfffffe00000001ffULL, +0xfffffe00000003ffULL, +0xfffffe00000007ffULL, +0xfffffe0000000fffULL, +0xfffffe0000001fffULL, +0xfffffe0000003fffULL, +0xfffffe0000007fffULL, +0xfffffe000000ffffULL, +0xfffffe000001ffffULL, +0xfffffe000003ffffULL, +0xfffffe000007ffffULL, +0xfffffe00000fffffULL, +0xfffffe00001fffffULL, +0xfffffe00003fffffULL, +0xfffffe00007fffffULL, +0xfffffe0000ffffffULL, +0xfffffe0001ffffffULL, +0xfffffe0003ffffffULL, +0xfffffe0007ffffffULL, +0xfffffe000fffffffULL, +0xfffffe001fffffffULL, +0xfffffe003fffffffULL, +0xfffffe007fffffffULL, +0xfffffe00ffffffffULL, +0xfffffe01ffffffffULL, +0xfffffe03ffffffffULL, +0xfffffe07ffffffffULL, +0xfffffe0fffffffffULL, +0xfffffe1fffffffffULL, +0xfffffe3fffffffffULL, +0xfffffe7fffffffffULL, +0xfffffeffffffffffULL +}, +{ +0xfffffc0000000000ULL, +0xfffffc0000000001ULL, +0xfffffc0000000003ULL, +0xfffffc0000000007ULL, +0xfffffc000000000fULL, +0xfffffc000000001fULL, +0xfffffc000000003fULL, +0xfffffc000000007fULL, +0xfffffc00000000ffULL, +0xfffffc00000001ffULL, +0xfffffc00000003ffULL, +0xfffffc00000007ffULL, +0xfffffc0000000fffULL, +0xfffffc0000001fffULL, +0xfffffc0000003fffULL, +0xfffffc0000007fffULL, +0xfffffc000000ffffULL, +0xfffffc000001ffffULL, +0xfffffc000003ffffULL, +0xfffffc000007ffffULL, +0xfffffc00000fffffULL, +0xfffffc00001fffffULL, +0xfffffc00003fffffULL, +0xfffffc00007fffffULL, +0xfffffc0000ffffffULL, +0xfffffc0001ffffffULL, +0xfffffc0003ffffffULL, +0xfffffc0007ffffffULL, +0xfffffc000fffffffULL, +0xfffffc001fffffffULL, +0xfffffc003fffffffULL, +0xfffffc007fffffffULL, +0xfffffc00ffffffffULL, +0xfffffc01ffffffffULL, +0xfffffc03ffffffffULL, +0xfffffc07ffffffffULL, +0xfffffc0fffffffffULL, +0xfffffc1fffffffffULL, +0xfffffc3fffffffffULL, +0xfffffc7fffffffffULL, +0xfffffcffffffffffULL, +0xfffffdffffffffffULL +}, +{ +0xfffff80000000000ULL, +0xfffff80000000001ULL, +0xfffff80000000003ULL, +0xfffff80000000007ULL, +0xfffff8000000000fULL, +0xfffff8000000001fULL, +0xfffff8000000003fULL, +0xfffff8000000007fULL, +0xfffff800000000ffULL, +0xfffff800000001ffULL, +0xfffff800000003ffULL, +0xfffff800000007ffULL, +0xfffff80000000fffULL, +0xfffff80000001fffULL, +0xfffff80000003fffULL, +0xfffff80000007fffULL, +0xfffff8000000ffffULL, +0xfffff8000001ffffULL, +0xfffff8000003ffffULL, +0xfffff8000007ffffULL, +0xfffff800000fffffULL, +0xfffff800001fffffULL, +0xfffff800003fffffULL, +0xfffff800007fffffULL, +0xfffff80000ffffffULL, +0xfffff80001ffffffULL, +0xfffff80003ffffffULL, +0xfffff80007ffffffULL, +0xfffff8000fffffffULL, +0xfffff8001fffffffULL, +0xfffff8003fffffffULL, +0xfffff8007fffffffULL, +0xfffff800ffffffffULL, +0xfffff801ffffffffULL, +0xfffff803ffffffffULL, +0xfffff807ffffffffULL, +0xfffff80fffffffffULL, +0xfffff81fffffffffULL, +0xfffff83fffffffffULL, +0xfffff87fffffffffULL, +0xfffff8ffffffffffULL, +0xfffff9ffffffffffULL, +0xfffffbffffffffffULL +}, +{ +0xfffff00000000000ULL, +0xfffff00000000001ULL, +0xfffff00000000003ULL, +0xfffff00000000007ULL, +0xfffff0000000000fULL, +0xfffff0000000001fULL, +0xfffff0000000003fULL, +0xfffff0000000007fULL, +0xfffff000000000ffULL, +0xfffff000000001ffULL, +0xfffff000000003ffULL, +0xfffff000000007ffULL, +0xfffff00000000fffULL, +0xfffff00000001fffULL, +0xfffff00000003fffULL, +0xfffff00000007fffULL, +0xfffff0000000ffffULL, +0xfffff0000001ffffULL, +0xfffff0000003ffffULL, +0xfffff0000007ffffULL, +0xfffff000000fffffULL, +0xfffff000001fffffULL, +0xfffff000003fffffULL, +0xfffff000007fffffULL, +0xfffff00000ffffffULL, +0xfffff00001ffffffULL, +0xfffff00003ffffffULL, +0xfffff00007ffffffULL, +0xfffff0000fffffffULL, +0xfffff0001fffffffULL, +0xfffff0003fffffffULL, +0xfffff0007fffffffULL, +0xfffff000ffffffffULL, +0xfffff001ffffffffULL, +0xfffff003ffffffffULL, +0xfffff007ffffffffULL, +0xfffff00fffffffffULL, +0xfffff01fffffffffULL, +0xfffff03fffffffffULL, +0xfffff07fffffffffULL, +0xfffff0ffffffffffULL, +0xfffff1ffffffffffULL, +0xfffff3ffffffffffULL, +0xfffff7ffffffffffULL +}, +{ +0xffffe00000000000ULL, +0xffffe00000000001ULL, +0xffffe00000000003ULL, +0xffffe00000000007ULL, +0xffffe0000000000fULL, +0xffffe0000000001fULL, +0xffffe0000000003fULL, +0xffffe0000000007fULL, +0xffffe000000000ffULL, +0xffffe000000001ffULL, +0xffffe000000003ffULL, +0xffffe000000007ffULL, +0xffffe00000000fffULL, +0xffffe00000001fffULL, +0xffffe00000003fffULL, +0xffffe00000007fffULL, +0xffffe0000000ffffULL, +0xffffe0000001ffffULL, +0xffffe0000003ffffULL, +0xffffe0000007ffffULL, +0xffffe000000fffffULL, +0xffffe000001fffffULL, +0xffffe000003fffffULL, +0xffffe000007fffffULL, +0xffffe00000ffffffULL, +0xffffe00001ffffffULL, +0xffffe00003ffffffULL, +0xffffe00007ffffffULL, +0xffffe0000fffffffULL, +0xffffe0001fffffffULL, +0xffffe0003fffffffULL, +0xffffe0007fffffffULL, +0xffffe000ffffffffULL, +0xffffe001ffffffffULL, +0xffffe003ffffffffULL, +0xffffe007ffffffffULL, +0xffffe00fffffffffULL, +0xffffe01fffffffffULL, +0xffffe03fffffffffULL, +0xffffe07fffffffffULL, +0xffffe0ffffffffffULL, +0xffffe1ffffffffffULL, +0xffffe3ffffffffffULL, +0xffffe7ffffffffffULL, +0xffffefffffffffffULL +}, +{ +0xffffc00000000000ULL, +0xffffc00000000001ULL, +0xffffc00000000003ULL, +0xffffc00000000007ULL, +0xffffc0000000000fULL, +0xffffc0000000001fULL, +0xffffc0000000003fULL, +0xffffc0000000007fULL, +0xffffc000000000ffULL, +0xffffc000000001ffULL, +0xffffc000000003ffULL, +0xffffc000000007ffULL, +0xffffc00000000fffULL, +0xffffc00000001fffULL, +0xffffc00000003fffULL, +0xffffc00000007fffULL, +0xffffc0000000ffffULL, +0xffffc0000001ffffULL, +0xffffc0000003ffffULL, +0xffffc0000007ffffULL, +0xffffc000000fffffULL, +0xffffc000001fffffULL, +0xffffc000003fffffULL, +0xffffc000007fffffULL, +0xffffc00000ffffffULL, +0xffffc00001ffffffULL, +0xffffc00003ffffffULL, +0xffffc00007ffffffULL, +0xffffc0000fffffffULL, +0xffffc0001fffffffULL, +0xffffc0003fffffffULL, +0xffffc0007fffffffULL, +0xffffc000ffffffffULL, +0xffffc001ffffffffULL, +0xffffc003ffffffffULL, +0xffffc007ffffffffULL, +0xffffc00fffffffffULL, +0xffffc01fffffffffULL, +0xffffc03fffffffffULL, +0xffffc07fffffffffULL, +0xffffc0ffffffffffULL, +0xffffc1ffffffffffULL, +0xffffc3ffffffffffULL, +0xffffc7ffffffffffULL, +0xffffcfffffffffffULL, +0xffffdfffffffffffULL +}, +{ +0xffff800000000000ULL, +0xffff800000000001ULL, +0xffff800000000003ULL, +0xffff800000000007ULL, +0xffff80000000000fULL, +0xffff80000000001fULL, +0xffff80000000003fULL, +0xffff80000000007fULL, +0xffff8000000000ffULL, +0xffff8000000001ffULL, +0xffff8000000003ffULL, +0xffff8000000007ffULL, +0xffff800000000fffULL, +0xffff800000001fffULL, +0xffff800000003fffULL, +0xffff800000007fffULL, +0xffff80000000ffffULL, +0xffff80000001ffffULL, +0xffff80000003ffffULL, +0xffff80000007ffffULL, +0xffff8000000fffffULL, +0xffff8000001fffffULL, +0xffff8000003fffffULL, +0xffff8000007fffffULL, +0xffff800000ffffffULL, +0xffff800001ffffffULL, +0xffff800003ffffffULL, +0xffff800007ffffffULL, +0xffff80000fffffffULL, +0xffff80001fffffffULL, +0xffff80003fffffffULL, +0xffff80007fffffffULL, +0xffff8000ffffffffULL, +0xffff8001ffffffffULL, +0xffff8003ffffffffULL, +0xffff8007ffffffffULL, +0xffff800fffffffffULL, +0xffff801fffffffffULL, +0xffff803fffffffffULL, +0xffff807fffffffffULL, +0xffff80ffffffffffULL, +0xffff81ffffffffffULL, +0xffff83ffffffffffULL, +0xffff87ffffffffffULL, +0xffff8fffffffffffULL, +0xffff9fffffffffffULL, +0xffffbfffffffffffULL +}, +{ +0xffff000000000000ULL, +0xffff000000000001ULL, +0xffff000000000003ULL, +0xffff000000000007ULL, +0xffff00000000000fULL, +0xffff00000000001fULL, +0xffff00000000003fULL, +0xffff00000000007fULL, +0xffff0000000000ffULL, +0xffff0000000001ffULL, +0xffff0000000003ffULL, +0xffff0000000007ffULL, +0xffff000000000fffULL, +0xffff000000001fffULL, +0xffff000000003fffULL, +0xffff000000007fffULL, +0xffff00000000ffffULL, +0xffff00000001ffffULL, +0xffff00000003ffffULL, +0xffff00000007ffffULL, +0xffff0000000fffffULL, +0xffff0000001fffffULL, +0xffff0000003fffffULL, +0xffff0000007fffffULL, +0xffff000000ffffffULL, +0xffff000001ffffffULL, +0xffff000003ffffffULL, +0xffff000007ffffffULL, +0xffff00000fffffffULL, +0xffff00001fffffffULL, +0xffff00003fffffffULL, +0xffff00007fffffffULL, +0xffff0000ffffffffULL, +0xffff0001ffffffffULL, +0xffff0003ffffffffULL, +0xffff0007ffffffffULL, +0xffff000fffffffffULL, +0xffff001fffffffffULL, +0xffff003fffffffffULL, +0xffff007fffffffffULL, +0xffff00ffffffffffULL, +0xffff01ffffffffffULL, +0xffff03ffffffffffULL, +0xffff07ffffffffffULL, +0xffff0fffffffffffULL, +0xffff1fffffffffffULL, +0xffff3fffffffffffULL, +0xffff7fffffffffffULL +}, +{ +0xfffe000000000000ULL, +0xfffe000000000001ULL, +0xfffe000000000003ULL, +0xfffe000000000007ULL, +0xfffe00000000000fULL, +0xfffe00000000001fULL, +0xfffe00000000003fULL, +0xfffe00000000007fULL, +0xfffe0000000000ffULL, +0xfffe0000000001ffULL, +0xfffe0000000003ffULL, +0xfffe0000000007ffULL, +0xfffe000000000fffULL, +0xfffe000000001fffULL, +0xfffe000000003fffULL, +0xfffe000000007fffULL, +0xfffe00000000ffffULL, +0xfffe00000001ffffULL, +0xfffe00000003ffffULL, +0xfffe00000007ffffULL, +0xfffe0000000fffffULL, +0xfffe0000001fffffULL, +0xfffe0000003fffffULL, +0xfffe0000007fffffULL, +0xfffe000000ffffffULL, +0xfffe000001ffffffULL, +0xfffe000003ffffffULL, +0xfffe000007ffffffULL, +0xfffe00000fffffffULL, +0xfffe00001fffffffULL, +0xfffe00003fffffffULL, +0xfffe00007fffffffULL, +0xfffe0000ffffffffULL, +0xfffe0001ffffffffULL, +0xfffe0003ffffffffULL, +0xfffe0007ffffffffULL, +0xfffe000fffffffffULL, +0xfffe001fffffffffULL, +0xfffe003fffffffffULL, +0xfffe007fffffffffULL, +0xfffe00ffffffffffULL, +0xfffe01ffffffffffULL, +0xfffe03ffffffffffULL, +0xfffe07ffffffffffULL, +0xfffe0fffffffffffULL, +0xfffe1fffffffffffULL, +0xfffe3fffffffffffULL, +0xfffe7fffffffffffULL, +0xfffeffffffffffffULL +}, +{ +0xfffc000000000000ULL, +0xfffc000000000001ULL, +0xfffc000000000003ULL, +0xfffc000000000007ULL, +0xfffc00000000000fULL, +0xfffc00000000001fULL, +0xfffc00000000003fULL, +0xfffc00000000007fULL, +0xfffc0000000000ffULL, +0xfffc0000000001ffULL, +0xfffc0000000003ffULL, +0xfffc0000000007ffULL, +0xfffc000000000fffULL, +0xfffc000000001fffULL, +0xfffc000000003fffULL, +0xfffc000000007fffULL, +0xfffc00000000ffffULL, +0xfffc00000001ffffULL, +0xfffc00000003ffffULL, +0xfffc00000007ffffULL, +0xfffc0000000fffffULL, +0xfffc0000001fffffULL, +0xfffc0000003fffffULL, +0xfffc0000007fffffULL, +0xfffc000000ffffffULL, +0xfffc000001ffffffULL, +0xfffc000003ffffffULL, +0xfffc000007ffffffULL, +0xfffc00000fffffffULL, +0xfffc00001fffffffULL, +0xfffc00003fffffffULL, +0xfffc00007fffffffULL, +0xfffc0000ffffffffULL, +0xfffc0001ffffffffULL, +0xfffc0003ffffffffULL, +0xfffc0007ffffffffULL, +0xfffc000fffffffffULL, +0xfffc001fffffffffULL, +0xfffc003fffffffffULL, +0xfffc007fffffffffULL, +0xfffc00ffffffffffULL, +0xfffc01ffffffffffULL, +0xfffc03ffffffffffULL, +0xfffc07ffffffffffULL, +0xfffc0fffffffffffULL, +0xfffc1fffffffffffULL, +0xfffc3fffffffffffULL, +0xfffc7fffffffffffULL, +0xfffcffffffffffffULL, +0xfffdffffffffffffULL +}, +{ +0xfff8000000000000ULL, +0xfff8000000000001ULL, +0xfff8000000000003ULL, +0xfff8000000000007ULL, +0xfff800000000000fULL, +0xfff800000000001fULL, +0xfff800000000003fULL, +0xfff800000000007fULL, +0xfff80000000000ffULL, +0xfff80000000001ffULL, +0xfff80000000003ffULL, +0xfff80000000007ffULL, +0xfff8000000000fffULL, +0xfff8000000001fffULL, +0xfff8000000003fffULL, +0xfff8000000007fffULL, +0xfff800000000ffffULL, +0xfff800000001ffffULL, +0xfff800000003ffffULL, +0xfff800000007ffffULL, +0xfff80000000fffffULL, +0xfff80000001fffffULL, +0xfff80000003fffffULL, +0xfff80000007fffffULL, +0xfff8000000ffffffULL, +0xfff8000001ffffffULL, +0xfff8000003ffffffULL, +0xfff8000007ffffffULL, +0xfff800000fffffffULL, +0xfff800001fffffffULL, +0xfff800003fffffffULL, +0xfff800007fffffffULL, +0xfff80000ffffffffULL, +0xfff80001ffffffffULL, +0xfff80003ffffffffULL, +0xfff80007ffffffffULL, +0xfff8000fffffffffULL, +0xfff8001fffffffffULL, +0xfff8003fffffffffULL, +0xfff8007fffffffffULL, +0xfff800ffffffffffULL, +0xfff801ffffffffffULL, +0xfff803ffffffffffULL, +0xfff807ffffffffffULL, +0xfff80fffffffffffULL, +0xfff81fffffffffffULL, +0xfff83fffffffffffULL, +0xfff87fffffffffffULL, +0xfff8ffffffffffffULL, +0xfff9ffffffffffffULL, +0xfffbffffffffffffULL +}, +{ +0xfff0000000000000ULL, +0xfff0000000000001ULL, +0xfff0000000000003ULL, +0xfff0000000000007ULL, +0xfff000000000000fULL, +0xfff000000000001fULL, +0xfff000000000003fULL, +0xfff000000000007fULL, +0xfff00000000000ffULL, +0xfff00000000001ffULL, +0xfff00000000003ffULL, +0xfff00000000007ffULL, +0xfff0000000000fffULL, +0xfff0000000001fffULL, +0xfff0000000003fffULL, +0xfff0000000007fffULL, +0xfff000000000ffffULL, +0xfff000000001ffffULL, +0xfff000000003ffffULL, +0xfff000000007ffffULL, +0xfff00000000fffffULL, +0xfff00000001fffffULL, +0xfff00000003fffffULL, +0xfff00000007fffffULL, +0xfff0000000ffffffULL, +0xfff0000001ffffffULL, +0xfff0000003ffffffULL, +0xfff0000007ffffffULL, +0xfff000000fffffffULL, +0xfff000001fffffffULL, +0xfff000003fffffffULL, +0xfff000007fffffffULL, +0xfff00000ffffffffULL, +0xfff00001ffffffffULL, +0xfff00003ffffffffULL, +0xfff00007ffffffffULL, +0xfff0000fffffffffULL, +0xfff0001fffffffffULL, +0xfff0003fffffffffULL, +0xfff0007fffffffffULL, +0xfff000ffffffffffULL, +0xfff001ffffffffffULL, +0xfff003ffffffffffULL, +0xfff007ffffffffffULL, +0xfff00fffffffffffULL, +0xfff01fffffffffffULL, +0xfff03fffffffffffULL, +0xfff07fffffffffffULL, +0xfff0ffffffffffffULL, +0xfff1ffffffffffffULL, +0xfff3ffffffffffffULL, +0xfff7ffffffffffffULL +}, +{ +0xffe0000000000000ULL, +0xffe0000000000001ULL, +0xffe0000000000003ULL, +0xffe0000000000007ULL, +0xffe000000000000fULL, +0xffe000000000001fULL, +0xffe000000000003fULL, +0xffe000000000007fULL, +0xffe00000000000ffULL, +0xffe00000000001ffULL, +0xffe00000000003ffULL, +0xffe00000000007ffULL, +0xffe0000000000fffULL, +0xffe0000000001fffULL, +0xffe0000000003fffULL, +0xffe0000000007fffULL, +0xffe000000000ffffULL, +0xffe000000001ffffULL, +0xffe000000003ffffULL, +0xffe000000007ffffULL, +0xffe00000000fffffULL, +0xffe00000001fffffULL, +0xffe00000003fffffULL, +0xffe00000007fffffULL, +0xffe0000000ffffffULL, +0xffe0000001ffffffULL, +0xffe0000003ffffffULL, +0xffe0000007ffffffULL, +0xffe000000fffffffULL, +0xffe000001fffffffULL, +0xffe000003fffffffULL, +0xffe000007fffffffULL, +0xffe00000ffffffffULL, +0xffe00001ffffffffULL, +0xffe00003ffffffffULL, +0xffe00007ffffffffULL, +0xffe0000fffffffffULL, +0xffe0001fffffffffULL, +0xffe0003fffffffffULL, +0xffe0007fffffffffULL, +0xffe000ffffffffffULL, +0xffe001ffffffffffULL, +0xffe003ffffffffffULL, +0xffe007ffffffffffULL, +0xffe00fffffffffffULL, +0xffe01fffffffffffULL, +0xffe03fffffffffffULL, +0xffe07fffffffffffULL, +0xffe0ffffffffffffULL, +0xffe1ffffffffffffULL, +0xffe3ffffffffffffULL, +0xffe7ffffffffffffULL, +0xffefffffffffffffULL +}, +{ +0xffc0000000000000ULL, +0xffc0000000000001ULL, +0xffc0000000000003ULL, +0xffc0000000000007ULL, +0xffc000000000000fULL, +0xffc000000000001fULL, +0xffc000000000003fULL, +0xffc000000000007fULL, +0xffc00000000000ffULL, +0xffc00000000001ffULL, +0xffc00000000003ffULL, +0xffc00000000007ffULL, +0xffc0000000000fffULL, +0xffc0000000001fffULL, +0xffc0000000003fffULL, +0xffc0000000007fffULL, +0xffc000000000ffffULL, +0xffc000000001ffffULL, +0xffc000000003ffffULL, +0xffc000000007ffffULL, +0xffc00000000fffffULL, +0xffc00000001fffffULL, +0xffc00000003fffffULL, +0xffc00000007fffffULL, +0xffc0000000ffffffULL, +0xffc0000001ffffffULL, +0xffc0000003ffffffULL, +0xffc0000007ffffffULL, +0xffc000000fffffffULL, +0xffc000001fffffffULL, +0xffc000003fffffffULL, +0xffc000007fffffffULL, +0xffc00000ffffffffULL, +0xffc00001ffffffffULL, +0xffc00003ffffffffULL, +0xffc00007ffffffffULL, +0xffc0000fffffffffULL, +0xffc0001fffffffffULL, +0xffc0003fffffffffULL, +0xffc0007fffffffffULL, +0xffc000ffffffffffULL, +0xffc001ffffffffffULL, +0xffc003ffffffffffULL, +0xffc007ffffffffffULL, +0xffc00fffffffffffULL, +0xffc01fffffffffffULL, +0xffc03fffffffffffULL, +0xffc07fffffffffffULL, +0xffc0ffffffffffffULL, +0xffc1ffffffffffffULL, +0xffc3ffffffffffffULL, +0xffc7ffffffffffffULL, +0xffcfffffffffffffULL, +0xffdfffffffffffffULL +}, +{ +0xff80000000000000ULL, +0xff80000000000001ULL, +0xff80000000000003ULL, +0xff80000000000007ULL, +0xff8000000000000fULL, +0xff8000000000001fULL, +0xff8000000000003fULL, +0xff8000000000007fULL, +0xff800000000000ffULL, +0xff800000000001ffULL, +0xff800000000003ffULL, +0xff800000000007ffULL, +0xff80000000000fffULL, +0xff80000000001fffULL, +0xff80000000003fffULL, +0xff80000000007fffULL, +0xff8000000000ffffULL, +0xff8000000001ffffULL, +0xff8000000003ffffULL, +0xff8000000007ffffULL, +0xff800000000fffffULL, +0xff800000001fffffULL, +0xff800000003fffffULL, +0xff800000007fffffULL, +0xff80000000ffffffULL, +0xff80000001ffffffULL, +0xff80000003ffffffULL, +0xff80000007ffffffULL, +0xff8000000fffffffULL, +0xff8000001fffffffULL, +0xff8000003fffffffULL, +0xff8000007fffffffULL, +0xff800000ffffffffULL, +0xff800001ffffffffULL, +0xff800003ffffffffULL, +0xff800007ffffffffULL, +0xff80000fffffffffULL, +0xff80001fffffffffULL, +0xff80003fffffffffULL, +0xff80007fffffffffULL, +0xff8000ffffffffffULL, +0xff8001ffffffffffULL, +0xff8003ffffffffffULL, +0xff8007ffffffffffULL, +0xff800fffffffffffULL, +0xff801fffffffffffULL, +0xff803fffffffffffULL, +0xff807fffffffffffULL, +0xff80ffffffffffffULL, +0xff81ffffffffffffULL, +0xff83ffffffffffffULL, +0xff87ffffffffffffULL, +0xff8fffffffffffffULL, +0xff9fffffffffffffULL, +0xffbfffffffffffffULL +}, +{ +0xff00000000000000ULL, +0xff00000000000001ULL, +0xff00000000000003ULL, +0xff00000000000007ULL, +0xff0000000000000fULL, +0xff0000000000001fULL, +0xff0000000000003fULL, +0xff0000000000007fULL, +0xff000000000000ffULL, +0xff000000000001ffULL, +0xff000000000003ffULL, +0xff000000000007ffULL, +0xff00000000000fffULL, +0xff00000000001fffULL, +0xff00000000003fffULL, +0xff00000000007fffULL, +0xff0000000000ffffULL, +0xff0000000001ffffULL, +0xff0000000003ffffULL, +0xff0000000007ffffULL, +0xff000000000fffffULL, +0xff000000001fffffULL, +0xff000000003fffffULL, +0xff000000007fffffULL, +0xff00000000ffffffULL, +0xff00000001ffffffULL, +0xff00000003ffffffULL, +0xff00000007ffffffULL, +0xff0000000fffffffULL, +0xff0000001fffffffULL, +0xff0000003fffffffULL, +0xff0000007fffffffULL, +0xff000000ffffffffULL, +0xff000001ffffffffULL, +0xff000003ffffffffULL, +0xff000007ffffffffULL, +0xff00000fffffffffULL, +0xff00001fffffffffULL, +0xff00003fffffffffULL, +0xff00007fffffffffULL, +0xff0000ffffffffffULL, +0xff0001ffffffffffULL, +0xff0003ffffffffffULL, +0xff0007ffffffffffULL, +0xff000fffffffffffULL, +0xff001fffffffffffULL, +0xff003fffffffffffULL, +0xff007fffffffffffULL, +0xff00ffffffffffffULL, +0xff01ffffffffffffULL, +0xff03ffffffffffffULL, +0xff07ffffffffffffULL, +0xff0fffffffffffffULL, +0xff1fffffffffffffULL, +0xff3fffffffffffffULL, +0xff7fffffffffffffULL +}, +{ +0xfe00000000000000ULL, +0xfe00000000000001ULL, +0xfe00000000000003ULL, +0xfe00000000000007ULL, +0xfe0000000000000fULL, +0xfe0000000000001fULL, +0xfe0000000000003fULL, +0xfe0000000000007fULL, +0xfe000000000000ffULL, +0xfe000000000001ffULL, +0xfe000000000003ffULL, +0xfe000000000007ffULL, +0xfe00000000000fffULL, +0xfe00000000001fffULL, +0xfe00000000003fffULL, +0xfe00000000007fffULL, +0xfe0000000000ffffULL, +0xfe0000000001ffffULL, +0xfe0000000003ffffULL, +0xfe0000000007ffffULL, +0xfe000000000fffffULL, +0xfe000000001fffffULL, +0xfe000000003fffffULL, +0xfe000000007fffffULL, +0xfe00000000ffffffULL, +0xfe00000001ffffffULL, +0xfe00000003ffffffULL, +0xfe00000007ffffffULL, +0xfe0000000fffffffULL, +0xfe0000001fffffffULL, +0xfe0000003fffffffULL, +0xfe0000007fffffffULL, +0xfe000000ffffffffULL, +0xfe000001ffffffffULL, +0xfe000003ffffffffULL, +0xfe000007ffffffffULL, +0xfe00000fffffffffULL, +0xfe00001fffffffffULL, +0xfe00003fffffffffULL, +0xfe00007fffffffffULL, +0xfe0000ffffffffffULL, +0xfe0001ffffffffffULL, +0xfe0003ffffffffffULL, +0xfe0007ffffffffffULL, +0xfe000fffffffffffULL, +0xfe001fffffffffffULL, +0xfe003fffffffffffULL, +0xfe007fffffffffffULL, +0xfe00ffffffffffffULL, +0xfe01ffffffffffffULL, +0xfe03ffffffffffffULL, +0xfe07ffffffffffffULL, +0xfe0fffffffffffffULL, +0xfe1fffffffffffffULL, +0xfe3fffffffffffffULL, +0xfe7fffffffffffffULL, +0xfeffffffffffffffULL +}, +{ +0xfc00000000000000ULL, +0xfc00000000000001ULL, +0xfc00000000000003ULL, +0xfc00000000000007ULL, +0xfc0000000000000fULL, +0xfc0000000000001fULL, +0xfc0000000000003fULL, +0xfc0000000000007fULL, +0xfc000000000000ffULL, +0xfc000000000001ffULL, +0xfc000000000003ffULL, +0xfc000000000007ffULL, +0xfc00000000000fffULL, +0xfc00000000001fffULL, +0xfc00000000003fffULL, +0xfc00000000007fffULL, +0xfc0000000000ffffULL, +0xfc0000000001ffffULL, +0xfc0000000003ffffULL, +0xfc0000000007ffffULL, +0xfc000000000fffffULL, +0xfc000000001fffffULL, +0xfc000000003fffffULL, +0xfc000000007fffffULL, +0xfc00000000ffffffULL, +0xfc00000001ffffffULL, +0xfc00000003ffffffULL, +0xfc00000007ffffffULL, +0xfc0000000fffffffULL, +0xfc0000001fffffffULL, +0xfc0000003fffffffULL, +0xfc0000007fffffffULL, +0xfc000000ffffffffULL, +0xfc000001ffffffffULL, +0xfc000003ffffffffULL, +0xfc000007ffffffffULL, +0xfc00000fffffffffULL, +0xfc00001fffffffffULL, +0xfc00003fffffffffULL, +0xfc00007fffffffffULL, +0xfc0000ffffffffffULL, +0xfc0001ffffffffffULL, +0xfc0003ffffffffffULL, +0xfc0007ffffffffffULL, +0xfc000fffffffffffULL, +0xfc001fffffffffffULL, +0xfc003fffffffffffULL, +0xfc007fffffffffffULL, +0xfc00ffffffffffffULL, +0xfc01ffffffffffffULL, +0xfc03ffffffffffffULL, +0xfc07ffffffffffffULL, +0xfc0fffffffffffffULL, +0xfc1fffffffffffffULL, +0xfc3fffffffffffffULL, +0xfc7fffffffffffffULL, +0xfcffffffffffffffULL, +0xfdffffffffffffffULL +}, +{ +0xf800000000000000ULL, +0xf800000000000001ULL, +0xf800000000000003ULL, +0xf800000000000007ULL, +0xf80000000000000fULL, +0xf80000000000001fULL, +0xf80000000000003fULL, +0xf80000000000007fULL, +0xf8000000000000ffULL, +0xf8000000000001ffULL, +0xf8000000000003ffULL, +0xf8000000000007ffULL, +0xf800000000000fffULL, +0xf800000000001fffULL, +0xf800000000003fffULL, +0xf800000000007fffULL, +0xf80000000000ffffULL, +0xf80000000001ffffULL, +0xf80000000003ffffULL, +0xf80000000007ffffULL, +0xf8000000000fffffULL, +0xf8000000001fffffULL, +0xf8000000003fffffULL, +0xf8000000007fffffULL, +0xf800000000ffffffULL, +0xf800000001ffffffULL, +0xf800000003ffffffULL, +0xf800000007ffffffULL, +0xf80000000fffffffULL, +0xf80000001fffffffULL, +0xf80000003fffffffULL, +0xf80000007fffffffULL, +0xf8000000ffffffffULL, +0xf8000001ffffffffULL, +0xf8000003ffffffffULL, +0xf8000007ffffffffULL, +0xf800000fffffffffULL, +0xf800001fffffffffULL, +0xf800003fffffffffULL, +0xf800007fffffffffULL, +0xf80000ffffffffffULL, +0xf80001ffffffffffULL, +0xf80003ffffffffffULL, +0xf80007ffffffffffULL, +0xf8000fffffffffffULL, +0xf8001fffffffffffULL, +0xf8003fffffffffffULL, +0xf8007fffffffffffULL, +0xf800ffffffffffffULL, +0xf801ffffffffffffULL, +0xf803ffffffffffffULL, +0xf807ffffffffffffULL, +0xf80fffffffffffffULL, +0xf81fffffffffffffULL, +0xf83fffffffffffffULL, +0xf87fffffffffffffULL, +0xf8ffffffffffffffULL, +0xf9ffffffffffffffULL, +0xfbffffffffffffffULL +}, +{ +0xf000000000000000ULL, +0xf000000000000001ULL, +0xf000000000000003ULL, +0xf000000000000007ULL, +0xf00000000000000fULL, +0xf00000000000001fULL, +0xf00000000000003fULL, +0xf00000000000007fULL, +0xf0000000000000ffULL, +0xf0000000000001ffULL, +0xf0000000000003ffULL, +0xf0000000000007ffULL, +0xf000000000000fffULL, +0xf000000000001fffULL, +0xf000000000003fffULL, +0xf000000000007fffULL, +0xf00000000000ffffULL, +0xf00000000001ffffULL, +0xf00000000003ffffULL, +0xf00000000007ffffULL, +0xf0000000000fffffULL, +0xf0000000001fffffULL, +0xf0000000003fffffULL, +0xf0000000007fffffULL, +0xf000000000ffffffULL, +0xf000000001ffffffULL, +0xf000000003ffffffULL, +0xf000000007ffffffULL, +0xf00000000fffffffULL, +0xf00000001fffffffULL, +0xf00000003fffffffULL, +0xf00000007fffffffULL, +0xf0000000ffffffffULL, +0xf0000001ffffffffULL, +0xf0000003ffffffffULL, +0xf0000007ffffffffULL, +0xf000000fffffffffULL, +0xf000001fffffffffULL, +0xf000003fffffffffULL, +0xf000007fffffffffULL, +0xf00000ffffffffffULL, +0xf00001ffffffffffULL, +0xf00003ffffffffffULL, +0xf00007ffffffffffULL, +0xf0000fffffffffffULL, +0xf0001fffffffffffULL, +0xf0003fffffffffffULL, +0xf0007fffffffffffULL, +0xf000ffffffffffffULL, +0xf001ffffffffffffULL, +0xf003ffffffffffffULL, +0xf007ffffffffffffULL, +0xf00fffffffffffffULL, +0xf01fffffffffffffULL, +0xf03fffffffffffffULL, +0xf07fffffffffffffULL, +0xf0ffffffffffffffULL, +0xf1ffffffffffffffULL, +0xf3ffffffffffffffULL, +0xf7ffffffffffffffULL +}, +{ +0xe000000000000000ULL, +0xe000000000000001ULL, +0xe000000000000003ULL, +0xe000000000000007ULL, +0xe00000000000000fULL, +0xe00000000000001fULL, +0xe00000000000003fULL, +0xe00000000000007fULL, +0xe0000000000000ffULL, +0xe0000000000001ffULL, +0xe0000000000003ffULL, +0xe0000000000007ffULL, +0xe000000000000fffULL, +0xe000000000001fffULL, +0xe000000000003fffULL, +0xe000000000007fffULL, +0xe00000000000ffffULL, +0xe00000000001ffffULL, +0xe00000000003ffffULL, +0xe00000000007ffffULL, +0xe0000000000fffffULL, +0xe0000000001fffffULL, +0xe0000000003fffffULL, +0xe0000000007fffffULL, +0xe000000000ffffffULL, +0xe000000001ffffffULL, +0xe000000003ffffffULL, +0xe000000007ffffffULL, +0xe00000000fffffffULL, +0xe00000001fffffffULL, +0xe00000003fffffffULL, +0xe00000007fffffffULL, +0xe0000000ffffffffULL, +0xe0000001ffffffffULL, +0xe0000003ffffffffULL, +0xe0000007ffffffffULL, +0xe000000fffffffffULL, +0xe000001fffffffffULL, +0xe000003fffffffffULL, +0xe000007fffffffffULL, +0xe00000ffffffffffULL, +0xe00001ffffffffffULL, +0xe00003ffffffffffULL, +0xe00007ffffffffffULL, +0xe0000fffffffffffULL, +0xe0001fffffffffffULL, +0xe0003fffffffffffULL, +0xe0007fffffffffffULL, +0xe000ffffffffffffULL, +0xe001ffffffffffffULL, +0xe003ffffffffffffULL, +0xe007ffffffffffffULL, +0xe00fffffffffffffULL, +0xe01fffffffffffffULL, +0xe03fffffffffffffULL, +0xe07fffffffffffffULL, +0xe0ffffffffffffffULL, +0xe1ffffffffffffffULL, +0xe3ffffffffffffffULL, +0xe7ffffffffffffffULL, +0xefffffffffffffffULL +}, +{ +0xc000000000000000ULL, +0xc000000000000001ULL, +0xc000000000000003ULL, +0xc000000000000007ULL, +0xc00000000000000fULL, +0xc00000000000001fULL, +0xc00000000000003fULL, +0xc00000000000007fULL, +0xc0000000000000ffULL, +0xc0000000000001ffULL, +0xc0000000000003ffULL, +0xc0000000000007ffULL, +0xc000000000000fffULL, +0xc000000000001fffULL, +0xc000000000003fffULL, +0xc000000000007fffULL, +0xc00000000000ffffULL, +0xc00000000001ffffULL, +0xc00000000003ffffULL, +0xc00000000007ffffULL, +0xc0000000000fffffULL, +0xc0000000001fffffULL, +0xc0000000003fffffULL, +0xc0000000007fffffULL, +0xc000000000ffffffULL, +0xc000000001ffffffULL, +0xc000000003ffffffULL, +0xc000000007ffffffULL, +0xc00000000fffffffULL, +0xc00000001fffffffULL, +0xc00000003fffffffULL, +0xc00000007fffffffULL, +0xc0000000ffffffffULL, +0xc0000001ffffffffULL, +0xc0000003ffffffffULL, +0xc0000007ffffffffULL, +0xc000000fffffffffULL, +0xc000001fffffffffULL, +0xc000003fffffffffULL, +0xc000007fffffffffULL, +0xc00000ffffffffffULL, +0xc00001ffffffffffULL, +0xc00003ffffffffffULL, +0xc00007ffffffffffULL, +0xc0000fffffffffffULL, +0xc0001fffffffffffULL, +0xc0003fffffffffffULL, +0xc0007fffffffffffULL, +0xc000ffffffffffffULL, +0xc001ffffffffffffULL, +0xc003ffffffffffffULL, +0xc007ffffffffffffULL, +0xc00fffffffffffffULL, +0xc01fffffffffffffULL, +0xc03fffffffffffffULL, +0xc07fffffffffffffULL, +0xc0ffffffffffffffULL, +0xc1ffffffffffffffULL, +0xc3ffffffffffffffULL, +0xc7ffffffffffffffULL, +0xcfffffffffffffffULL, +0xdfffffffffffffffULL +}, +{ +0x8000000000000000ULL, +0x8000000000000001ULL, +0x8000000000000003ULL, +0x8000000000000007ULL, +0x800000000000000fULL, +0x800000000000001fULL, +0x800000000000003fULL, +0x800000000000007fULL, +0x80000000000000ffULL, +0x80000000000001ffULL, +0x80000000000003ffULL, +0x80000000000007ffULL, +0x8000000000000fffULL, +0x8000000000001fffULL, +0x8000000000003fffULL, +0x8000000000007fffULL, +0x800000000000ffffULL, +0x800000000001ffffULL, +0x800000000003ffffULL, +0x800000000007ffffULL, +0x80000000000fffffULL, +0x80000000001fffffULL, +0x80000000003fffffULL, +0x80000000007fffffULL, +0x8000000000ffffffULL, +0x8000000001ffffffULL, +0x8000000003ffffffULL, +0x8000000007ffffffULL, +0x800000000fffffffULL, +0x800000001fffffffULL, +0x800000003fffffffULL, +0x800000007fffffffULL, +0x80000000ffffffffULL, +0x80000001ffffffffULL, +0x80000003ffffffffULL, +0x80000007ffffffffULL, +0x8000000fffffffffULL, +0x8000001fffffffffULL, +0x8000003fffffffffULL, +0x8000007fffffffffULL, +0x800000ffffffffffULL, +0x800001ffffffffffULL, +0x800003ffffffffffULL, +0x800007ffffffffffULL, +0x80000fffffffffffULL, +0x80001fffffffffffULL, +0x80003fffffffffffULL, +0x80007fffffffffffULL, +0x8000ffffffffffffULL, +0x8001ffffffffffffULL, +0x8003ffffffffffffULL, +0x8007ffffffffffffULL, +0x800fffffffffffffULL, +0x801fffffffffffffULL, +0x803fffffffffffffULL, +0x807fffffffffffffULL, +0x80ffffffffffffffULL, +0x81ffffffffffffffULL, +0x83ffffffffffffffULL, +0x87ffffffffffffffULL, +0x8fffffffffffffffULL, +0x9fffffffffffffffULL, +0xbfffffffffffffffULL +}, +{ +0x0ULL, +0x1ULL, +0x3ULL, +0x7ULL, +0xfULL, +0x1fULL, +0x3fULL, +0x7fULL, +0xffULL, +0x1ffULL, +0x3ffULL, +0x7ffULL, +0xfffULL, +0x1fffULL, +0x3fffULL, +0x7fffULL, +0xffffULL, +0x1ffffULL, +0x3ffffULL, +0x7ffffULL, +0xfffffULL, +0x1fffffULL, +0x3fffffULL, +0x7fffffULL, +0xffffffULL, +0x1ffffffULL, +0x3ffffffULL, +0x7ffffffULL, +0xfffffffULL, +0x1fffffffULL, +0x3fffffffULL, +0x7fffffffULL, +0xffffffffULL, +0x1ffffffffULL, +0x3ffffffffULL, +0x7ffffffffULL, +0xfffffffffULL, +0x1fffffffffULL, +0x3fffffffffULL, +0x7fffffffffULL, +0xffffffffffULL, +0x1ffffffffffULL, +0x3ffffffffffULL, +0x7ffffffffffULL, +0xfffffffffffULL, +0x1fffffffffffULL, +0x3fffffffffffULL, +0x7fffffffffffULL, +0xffffffffffffULL, +0x1ffffffffffffULL, +0x3ffffffffffffULL, +0x7ffffffffffffULL, +0xfffffffffffffULL, +0x1fffffffffffffULL, +0x3fffffffffffffULL, +0x7fffffffffffffULL, +0xffffffffffffffULL, +0x1ffffffffffffffULL, +0x3ffffffffffffffULL, +0x7ffffffffffffffULL, +0xfffffffffffffffULL, +0x1fffffffffffffffULL, +0x3fffffffffffffffULL, +0x7fffffffffffffffULL +} +}; + +#else //end of #ifndef WIN32 + +const uint_type mask_int[SC_INTWIDTH][SC_INTWIDTH] = +{ +{ +0xfffffffffffffffei64 +}, +{ +0xfffffffffffffffci64, +0xfffffffffffffffdi64 +}, +{ +0xfffffffffffffff8i64, +0xfffffffffffffff9i64, +0xfffffffffffffffbi64 +}, +{ +0xfffffffffffffff0i64, +0xfffffffffffffff1i64, +0xfffffffffffffff3i64, +0xfffffffffffffff7i64 +}, +{ +0xffffffffffffffe0i64, +0xffffffffffffffe1i64, +0xffffffffffffffe3i64, +0xffffffffffffffe7i64, +0xffffffffffffffefi64 +}, +{ +0xffffffffffffffc0i64, +0xffffffffffffffc1i64, +0xffffffffffffffc3i64, +0xffffffffffffffc7i64, +0xffffffffffffffcfi64, +0xffffffffffffffdfi64 +}, +{ +0xffffffffffffff80i64, +0xffffffffffffff81i64, +0xffffffffffffff83i64, +0xffffffffffffff87i64, +0xffffffffffffff8fi64, +0xffffffffffffff9fi64, +0xffffffffffffffbfi64 +}, +{ +0xffffffffffffff00i64, +0xffffffffffffff01i64, +0xffffffffffffff03i64, +0xffffffffffffff07i64, +0xffffffffffffff0fi64, +0xffffffffffffff1fi64, +0xffffffffffffff3fi64, +0xffffffffffffff7fi64 +}, +{ +0xfffffffffffffe00i64, +0xfffffffffffffe01i64, +0xfffffffffffffe03i64, +0xfffffffffffffe07i64, +0xfffffffffffffe0fi64, +0xfffffffffffffe1fi64, +0xfffffffffffffe3fi64, +0xfffffffffffffe7fi64, +0xfffffffffffffeffi64 +}, +{ +0xfffffffffffffc00i64, +0xfffffffffffffc01i64, +0xfffffffffffffc03i64, +0xfffffffffffffc07i64, +0xfffffffffffffc0fi64, +0xfffffffffffffc1fi64, +0xfffffffffffffc3fi64, +0xfffffffffffffc7fi64, +0xfffffffffffffcffi64, +0xfffffffffffffdffi64 +}, +{ +0xfffffffffffff800i64, +0xfffffffffffff801i64, +0xfffffffffffff803i64, +0xfffffffffffff807i64, +0xfffffffffffff80fi64, +0xfffffffffffff81fi64, +0xfffffffffffff83fi64, +0xfffffffffffff87fi64, +0xfffffffffffff8ffi64, +0xfffffffffffff9ffi64, +0xfffffffffffffbffi64 +}, +{ +0xfffffffffffff000i64, +0xfffffffffffff001i64, +0xfffffffffffff003i64, +0xfffffffffffff007i64, +0xfffffffffffff00fi64, +0xfffffffffffff01fi64, +0xfffffffffffff03fi64, +0xfffffffffffff07fi64, +0xfffffffffffff0ffi64, +0xfffffffffffff1ffi64, +0xfffffffffffff3ffi64, +0xfffffffffffff7ffi64 +}, +{ +0xffffffffffffe000i64, +0xffffffffffffe001i64, +0xffffffffffffe003i64, +0xffffffffffffe007i64, +0xffffffffffffe00fi64, +0xffffffffffffe01fi64, +0xffffffffffffe03fi64, +0xffffffffffffe07fi64, +0xffffffffffffe0ffi64, +0xffffffffffffe1ffi64, +0xffffffffffffe3ffi64, +0xffffffffffffe7ffi64, +0xffffffffffffefffi64 +}, +{ +0xffffffffffffc000i64, +0xffffffffffffc001i64, +0xffffffffffffc003i64, +0xffffffffffffc007i64, +0xffffffffffffc00fi64, +0xffffffffffffc01fi64, +0xffffffffffffc03fi64, +0xffffffffffffc07fi64, +0xffffffffffffc0ffi64, +0xffffffffffffc1ffi64, +0xffffffffffffc3ffi64, +0xffffffffffffc7ffi64, +0xffffffffffffcfffi64, +0xffffffffffffdfffi64 +}, +{ +0xffffffffffff8000i64, +0xffffffffffff8001i64, +0xffffffffffff8003i64, +0xffffffffffff8007i64, +0xffffffffffff800fi64, +0xffffffffffff801fi64, +0xffffffffffff803fi64, +0xffffffffffff807fi64, +0xffffffffffff80ffi64, +0xffffffffffff81ffi64, +0xffffffffffff83ffi64, +0xffffffffffff87ffi64, +0xffffffffffff8fffi64, +0xffffffffffff9fffi64, +0xffffffffffffbfffi64 +}, +{ +0xffffffffffff0000i64, +0xffffffffffff0001i64, +0xffffffffffff0003i64, +0xffffffffffff0007i64, +0xffffffffffff000fi64, +0xffffffffffff001fi64, +0xffffffffffff003fi64, +0xffffffffffff007fi64, +0xffffffffffff00ffi64, +0xffffffffffff01ffi64, +0xffffffffffff03ffi64, +0xffffffffffff07ffi64, +0xffffffffffff0fffi64, +0xffffffffffff1fffi64, +0xffffffffffff3fffi64, +0xffffffffffff7fffi64 +}, +{ +0xfffffffffffe0000i64, +0xfffffffffffe0001i64, +0xfffffffffffe0003i64, +0xfffffffffffe0007i64, +0xfffffffffffe000fi64, +0xfffffffffffe001fi64, +0xfffffffffffe003fi64, +0xfffffffffffe007fi64, +0xfffffffffffe00ffi64, +0xfffffffffffe01ffi64, +0xfffffffffffe03ffi64, +0xfffffffffffe07ffi64, +0xfffffffffffe0fffi64, +0xfffffffffffe1fffi64, +0xfffffffffffe3fffi64, +0xfffffffffffe7fffi64, +0xfffffffffffeffffi64 +}, +{ +0xfffffffffffc0000i64, +0xfffffffffffc0001i64, +0xfffffffffffc0003i64, +0xfffffffffffc0007i64, +0xfffffffffffc000fi64, +0xfffffffffffc001fi64, +0xfffffffffffc003fi64, +0xfffffffffffc007fi64, +0xfffffffffffc00ffi64, +0xfffffffffffc01ffi64, +0xfffffffffffc03ffi64, +0xfffffffffffc07ffi64, +0xfffffffffffc0fffi64, +0xfffffffffffc1fffi64, +0xfffffffffffc3fffi64, +0xfffffffffffc7fffi64, +0xfffffffffffcffffi64, +0xfffffffffffdffffi64 +}, +{ +0xfffffffffff80000i64, +0xfffffffffff80001i64, +0xfffffffffff80003i64, +0xfffffffffff80007i64, +0xfffffffffff8000fi64, +0xfffffffffff8001fi64, +0xfffffffffff8003fi64, +0xfffffffffff8007fi64, +0xfffffffffff800ffi64, +0xfffffffffff801ffi64, +0xfffffffffff803ffi64, +0xfffffffffff807ffi64, +0xfffffffffff80fffi64, +0xfffffffffff81fffi64, +0xfffffffffff83fffi64, +0xfffffffffff87fffi64, +0xfffffffffff8ffffi64, +0xfffffffffff9ffffi64, +0xfffffffffffbffffi64 +}, +{ +0xfffffffffff00000i64, +0xfffffffffff00001i64, +0xfffffffffff00003i64, +0xfffffffffff00007i64, +0xfffffffffff0000fi64, +0xfffffffffff0001fi64, +0xfffffffffff0003fi64, +0xfffffffffff0007fi64, +0xfffffffffff000ffi64, +0xfffffffffff001ffi64, +0xfffffffffff003ffi64, +0xfffffffffff007ffi64, +0xfffffffffff00fffi64, +0xfffffffffff01fffi64, +0xfffffffffff03fffi64, +0xfffffffffff07fffi64, +0xfffffffffff0ffffi64, +0xfffffffffff1ffffi64, +0xfffffffffff3ffffi64, +0xfffffffffff7ffffi64 +}, +{ +0xffffffffffe00000i64, +0xffffffffffe00001i64, +0xffffffffffe00003i64, +0xffffffffffe00007i64, +0xffffffffffe0000fi64, +0xffffffffffe0001fi64, +0xffffffffffe0003fi64, +0xffffffffffe0007fi64, +0xffffffffffe000ffi64, +0xffffffffffe001ffi64, +0xffffffffffe003ffi64, +0xffffffffffe007ffi64, +0xffffffffffe00fffi64, +0xffffffffffe01fffi64, +0xffffffffffe03fffi64, +0xffffffffffe07fffi64, +0xffffffffffe0ffffi64, +0xffffffffffe1ffffi64, +0xffffffffffe3ffffi64, +0xffffffffffe7ffffi64, +0xffffffffffefffffi64 +}, +{ +0xffffffffffc00000i64, +0xffffffffffc00001i64, +0xffffffffffc00003i64, +0xffffffffffc00007i64, +0xffffffffffc0000fi64, +0xffffffffffc0001fi64, +0xffffffffffc0003fi64, +0xffffffffffc0007fi64, +0xffffffffffc000ffi64, +0xffffffffffc001ffi64, +0xffffffffffc003ffi64, +0xffffffffffc007ffi64, +0xffffffffffc00fffi64, +0xffffffffffc01fffi64, +0xffffffffffc03fffi64, +0xffffffffffc07fffi64, +0xffffffffffc0ffffi64, +0xffffffffffc1ffffi64, +0xffffffffffc3ffffi64, +0xffffffffffc7ffffi64, +0xffffffffffcfffffi64, +0xffffffffffdfffffi64 +}, +{ +0xffffffffff800000i64, +0xffffffffff800001i64, +0xffffffffff800003i64, +0xffffffffff800007i64, +0xffffffffff80000fi64, +0xffffffffff80001fi64, +0xffffffffff80003fi64, +0xffffffffff80007fi64, +0xffffffffff8000ffi64, +0xffffffffff8001ffi64, +0xffffffffff8003ffi64, +0xffffffffff8007ffi64, +0xffffffffff800fffi64, +0xffffffffff801fffi64, +0xffffffffff803fffi64, +0xffffffffff807fffi64, +0xffffffffff80ffffi64, +0xffffffffff81ffffi64, +0xffffffffff83ffffi64, +0xffffffffff87ffffi64, +0xffffffffff8fffffi64, +0xffffffffff9fffffi64, +0xffffffffffbfffffi64 +}, +{ +0xffffffffff000000i64, +0xffffffffff000001i64, +0xffffffffff000003i64, +0xffffffffff000007i64, +0xffffffffff00000fi64, +0xffffffffff00001fi64, +0xffffffffff00003fi64, +0xffffffffff00007fi64, +0xffffffffff0000ffi64, +0xffffffffff0001ffi64, +0xffffffffff0003ffi64, +0xffffffffff0007ffi64, +0xffffffffff000fffi64, +0xffffffffff001fffi64, +0xffffffffff003fffi64, +0xffffffffff007fffi64, +0xffffffffff00ffffi64, +0xffffffffff01ffffi64, +0xffffffffff03ffffi64, +0xffffffffff07ffffi64, +0xffffffffff0fffffi64, +0xffffffffff1fffffi64, +0xffffffffff3fffffi64, +0xffffffffff7fffffi64 +}, +{ +0xfffffffffe000000i64, +0xfffffffffe000001i64, +0xfffffffffe000003i64, +0xfffffffffe000007i64, +0xfffffffffe00000fi64, +0xfffffffffe00001fi64, +0xfffffffffe00003fi64, +0xfffffffffe00007fi64, +0xfffffffffe0000ffi64, +0xfffffffffe0001ffi64, +0xfffffffffe0003ffi64, +0xfffffffffe0007ffi64, +0xfffffffffe000fffi64, +0xfffffffffe001fffi64, +0xfffffffffe003fffi64, +0xfffffffffe007fffi64, +0xfffffffffe00ffffi64, +0xfffffffffe01ffffi64, +0xfffffffffe03ffffi64, +0xfffffffffe07ffffi64, +0xfffffffffe0fffffi64, +0xfffffffffe1fffffi64, +0xfffffffffe3fffffi64, +0xfffffffffe7fffffi64, +0xfffffffffeffffffi64 +}, +{ +0xfffffffffc000000i64, +0xfffffffffc000001i64, +0xfffffffffc000003i64, +0xfffffffffc000007i64, +0xfffffffffc00000fi64, +0xfffffffffc00001fi64, +0xfffffffffc00003fi64, +0xfffffffffc00007fi64, +0xfffffffffc0000ffi64, +0xfffffffffc0001ffi64, +0xfffffffffc0003ffi64, +0xfffffffffc0007ffi64, +0xfffffffffc000fffi64, +0xfffffffffc001fffi64, +0xfffffffffc003fffi64, +0xfffffffffc007fffi64, +0xfffffffffc00ffffi64, +0xfffffffffc01ffffi64, +0xfffffffffc03ffffi64, +0xfffffffffc07ffffi64, +0xfffffffffc0fffffi64, +0xfffffffffc1fffffi64, +0xfffffffffc3fffffi64, +0xfffffffffc7fffffi64, +0xfffffffffcffffffi64, +0xfffffffffdffffffi64 +}, +{ +0xfffffffff8000000i64, +0xfffffffff8000001i64, +0xfffffffff8000003i64, +0xfffffffff8000007i64, +0xfffffffff800000fi64, +0xfffffffff800001fi64, +0xfffffffff800003fi64, +0xfffffffff800007fi64, +0xfffffffff80000ffi64, +0xfffffffff80001ffi64, +0xfffffffff80003ffi64, +0xfffffffff80007ffi64, +0xfffffffff8000fffi64, +0xfffffffff8001fffi64, +0xfffffffff8003fffi64, +0xfffffffff8007fffi64, +0xfffffffff800ffffi64, +0xfffffffff801ffffi64, +0xfffffffff803ffffi64, +0xfffffffff807ffffi64, +0xfffffffff80fffffi64, +0xfffffffff81fffffi64, +0xfffffffff83fffffi64, +0xfffffffff87fffffi64, +0xfffffffff8ffffffi64, +0xfffffffff9ffffffi64, +0xfffffffffbffffffi64 +}, +{ +0xfffffffff0000000i64, +0xfffffffff0000001i64, +0xfffffffff0000003i64, +0xfffffffff0000007i64, +0xfffffffff000000fi64, +0xfffffffff000001fi64, +0xfffffffff000003fi64, +0xfffffffff000007fi64, +0xfffffffff00000ffi64, +0xfffffffff00001ffi64, +0xfffffffff00003ffi64, +0xfffffffff00007ffi64, +0xfffffffff0000fffi64, +0xfffffffff0001fffi64, +0xfffffffff0003fffi64, +0xfffffffff0007fffi64, +0xfffffffff000ffffi64, +0xfffffffff001ffffi64, +0xfffffffff003ffffi64, +0xfffffffff007ffffi64, +0xfffffffff00fffffi64, +0xfffffffff01fffffi64, +0xfffffffff03fffffi64, +0xfffffffff07fffffi64, +0xfffffffff0ffffffi64, +0xfffffffff1ffffffi64, +0xfffffffff3ffffffi64, +0xfffffffff7ffffffi64 +}, +{ +0xffffffffe0000000i64, +0xffffffffe0000001i64, +0xffffffffe0000003i64, +0xffffffffe0000007i64, +0xffffffffe000000fi64, +0xffffffffe000001fi64, +0xffffffffe000003fi64, +0xffffffffe000007fi64, +0xffffffffe00000ffi64, +0xffffffffe00001ffi64, +0xffffffffe00003ffi64, +0xffffffffe00007ffi64, +0xffffffffe0000fffi64, +0xffffffffe0001fffi64, +0xffffffffe0003fffi64, +0xffffffffe0007fffi64, +0xffffffffe000ffffi64, +0xffffffffe001ffffi64, +0xffffffffe003ffffi64, +0xffffffffe007ffffi64, +0xffffffffe00fffffi64, +0xffffffffe01fffffi64, +0xffffffffe03fffffi64, +0xffffffffe07fffffi64, +0xffffffffe0ffffffi64, +0xffffffffe1ffffffi64, +0xffffffffe3ffffffi64, +0xffffffffe7ffffffi64, +0xffffffffefffffffi64 +}, +{ +0xffffffffc0000000i64, +0xffffffffc0000001i64, +0xffffffffc0000003i64, +0xffffffffc0000007i64, +0xffffffffc000000fi64, +0xffffffffc000001fi64, +0xffffffffc000003fi64, +0xffffffffc000007fi64, +0xffffffffc00000ffi64, +0xffffffffc00001ffi64, +0xffffffffc00003ffi64, +0xffffffffc00007ffi64, +0xffffffffc0000fffi64, +0xffffffffc0001fffi64, +0xffffffffc0003fffi64, +0xffffffffc0007fffi64, +0xffffffffc000ffffi64, +0xffffffffc001ffffi64, +0xffffffffc003ffffi64, +0xffffffffc007ffffi64, +0xffffffffc00fffffi64, +0xffffffffc01fffffi64, +0xffffffffc03fffffi64, +0xffffffffc07fffffi64, +0xffffffffc0ffffffi64, +0xffffffffc1ffffffi64, +0xffffffffc3ffffffi64, +0xffffffffc7ffffffi64, +0xffffffffcfffffffi64, +0xffffffffdfffffffi64 +}, +{ +0xffffffff80000000i64, +0xffffffff80000001i64, +0xffffffff80000003i64, +0xffffffff80000007i64, +0xffffffff8000000fi64, +0xffffffff8000001fi64, +0xffffffff8000003fi64, +0xffffffff8000007fi64, +0xffffffff800000ffi64, +0xffffffff800001ffi64, +0xffffffff800003ffi64, +0xffffffff800007ffi64, +0xffffffff80000fffi64, +0xffffffff80001fffi64, +0xffffffff80003fffi64, +0xffffffff80007fffi64, +0xffffffff8000ffffi64, +0xffffffff8001ffffi64, +0xffffffff8003ffffi64, +0xffffffff8007ffffi64, +0xffffffff800fffffi64, +0xffffffff801fffffi64, +0xffffffff803fffffi64, +0xffffffff807fffffi64, +0xffffffff80ffffffi64, +0xffffffff81ffffffi64, +0xffffffff83ffffffi64, +0xffffffff87ffffffi64, +0xffffffff8fffffffi64, +0xffffffff9fffffffi64, +0xffffffffbfffffffi64 +}, +{ +0xffffffff00000000i64, +0xffffffff00000001i64, +0xffffffff00000003i64, +0xffffffff00000007i64, +0xffffffff0000000fi64, +0xffffffff0000001fi64, +0xffffffff0000003fi64, +0xffffffff0000007fi64, +0xffffffff000000ffi64, +0xffffffff000001ffi64, +0xffffffff000003ffi64, +0xffffffff000007ffi64, +0xffffffff00000fffi64, +0xffffffff00001fffi64, +0xffffffff00003fffi64, +0xffffffff00007fffi64, +0xffffffff0000ffffi64, +0xffffffff0001ffffi64, +0xffffffff0003ffffi64, +0xffffffff0007ffffi64, +0xffffffff000fffffi64, +0xffffffff001fffffi64, +0xffffffff003fffffi64, +0xffffffff007fffffi64, +0xffffffff00ffffffi64, +0xffffffff01ffffffi64, +0xffffffff03ffffffi64, +0xffffffff07ffffffi64, +0xffffffff0fffffffi64, +0xffffffff1fffffffi64, +0xffffffff3fffffffi64, +0xffffffff7fffffffi64 +}, +{ +0xfffffffe00000000i64, +0xfffffffe00000001i64, +0xfffffffe00000003i64, +0xfffffffe00000007i64, +0xfffffffe0000000fi64, +0xfffffffe0000001fi64, +0xfffffffe0000003fi64, +0xfffffffe0000007fi64, +0xfffffffe000000ffi64, +0xfffffffe000001ffi64, +0xfffffffe000003ffi64, +0xfffffffe000007ffi64, +0xfffffffe00000fffi64, +0xfffffffe00001fffi64, +0xfffffffe00003fffi64, +0xfffffffe00007fffi64, +0xfffffffe0000ffffi64, +0xfffffffe0001ffffi64, +0xfffffffe0003ffffi64, +0xfffffffe0007ffffi64, +0xfffffffe000fffffi64, +0xfffffffe001fffffi64, +0xfffffffe003fffffi64, +0xfffffffe007fffffi64, +0xfffffffe00ffffffi64, +0xfffffffe01ffffffi64, +0xfffffffe03ffffffi64, +0xfffffffe07ffffffi64, +0xfffffffe0fffffffi64, +0xfffffffe1fffffffi64, +0xfffffffe3fffffffi64, +0xfffffffe7fffffffi64, +0xfffffffeffffffffi64 +}, +{ +0xfffffffc00000000i64, +0xfffffffc00000001i64, +0xfffffffc00000003i64, +0xfffffffc00000007i64, +0xfffffffc0000000fi64, +0xfffffffc0000001fi64, +0xfffffffc0000003fi64, +0xfffffffc0000007fi64, +0xfffffffc000000ffi64, +0xfffffffc000001ffi64, +0xfffffffc000003ffi64, +0xfffffffc000007ffi64, +0xfffffffc00000fffi64, +0xfffffffc00001fffi64, +0xfffffffc00003fffi64, +0xfffffffc00007fffi64, +0xfffffffc0000ffffi64, +0xfffffffc0001ffffi64, +0xfffffffc0003ffffi64, +0xfffffffc0007ffffi64, +0xfffffffc000fffffi64, +0xfffffffc001fffffi64, +0xfffffffc003fffffi64, +0xfffffffc007fffffi64, +0xfffffffc00ffffffi64, +0xfffffffc01ffffffi64, +0xfffffffc03ffffffi64, +0xfffffffc07ffffffi64, +0xfffffffc0fffffffi64, +0xfffffffc1fffffffi64, +0xfffffffc3fffffffi64, +0xfffffffc7fffffffi64, +0xfffffffcffffffffi64, +0xfffffffdffffffffi64 +}, +{ +0xfffffff800000000i64, +0xfffffff800000001i64, +0xfffffff800000003i64, +0xfffffff800000007i64, +0xfffffff80000000fi64, +0xfffffff80000001fi64, +0xfffffff80000003fi64, +0xfffffff80000007fi64, +0xfffffff8000000ffi64, +0xfffffff8000001ffi64, +0xfffffff8000003ffi64, +0xfffffff8000007ffi64, +0xfffffff800000fffi64, +0xfffffff800001fffi64, +0xfffffff800003fffi64, +0xfffffff800007fffi64, +0xfffffff80000ffffi64, +0xfffffff80001ffffi64, +0xfffffff80003ffffi64, +0xfffffff80007ffffi64, +0xfffffff8000fffffi64, +0xfffffff8001fffffi64, +0xfffffff8003fffffi64, +0xfffffff8007fffffi64, +0xfffffff800ffffffi64, +0xfffffff801ffffffi64, +0xfffffff803ffffffi64, +0xfffffff807ffffffi64, +0xfffffff80fffffffi64, +0xfffffff81fffffffi64, +0xfffffff83fffffffi64, +0xfffffff87fffffffi64, +0xfffffff8ffffffffi64, +0xfffffff9ffffffffi64, +0xfffffffbffffffffi64 +}, +{ +0xfffffff000000000i64, +0xfffffff000000001i64, +0xfffffff000000003i64, +0xfffffff000000007i64, +0xfffffff00000000fi64, +0xfffffff00000001fi64, +0xfffffff00000003fi64, +0xfffffff00000007fi64, +0xfffffff0000000ffi64, +0xfffffff0000001ffi64, +0xfffffff0000003ffi64, +0xfffffff0000007ffi64, +0xfffffff000000fffi64, +0xfffffff000001fffi64, +0xfffffff000003fffi64, +0xfffffff000007fffi64, +0xfffffff00000ffffi64, +0xfffffff00001ffffi64, +0xfffffff00003ffffi64, +0xfffffff00007ffffi64, +0xfffffff0000fffffi64, +0xfffffff0001fffffi64, +0xfffffff0003fffffi64, +0xfffffff0007fffffi64, +0xfffffff000ffffffi64, +0xfffffff001ffffffi64, +0xfffffff003ffffffi64, +0xfffffff007ffffffi64, +0xfffffff00fffffffi64, +0xfffffff01fffffffi64, +0xfffffff03fffffffi64, +0xfffffff07fffffffi64, +0xfffffff0ffffffffi64, +0xfffffff1ffffffffi64, +0xfffffff3ffffffffi64, +0xfffffff7ffffffffi64 +}, +{ +0xffffffe000000000i64, +0xffffffe000000001i64, +0xffffffe000000003i64, +0xffffffe000000007i64, +0xffffffe00000000fi64, +0xffffffe00000001fi64, +0xffffffe00000003fi64, +0xffffffe00000007fi64, +0xffffffe0000000ffi64, +0xffffffe0000001ffi64, +0xffffffe0000003ffi64, +0xffffffe0000007ffi64, +0xffffffe000000fffi64, +0xffffffe000001fffi64, +0xffffffe000003fffi64, +0xffffffe000007fffi64, +0xffffffe00000ffffi64, +0xffffffe00001ffffi64, +0xffffffe00003ffffi64, +0xffffffe00007ffffi64, +0xffffffe0000fffffi64, +0xffffffe0001fffffi64, +0xffffffe0003fffffi64, +0xffffffe0007fffffi64, +0xffffffe000ffffffi64, +0xffffffe001ffffffi64, +0xffffffe003ffffffi64, +0xffffffe007ffffffi64, +0xffffffe00fffffffi64, +0xffffffe01fffffffi64, +0xffffffe03fffffffi64, +0xffffffe07fffffffi64, +0xffffffe0ffffffffi64, +0xffffffe1ffffffffi64, +0xffffffe3ffffffffi64, +0xffffffe7ffffffffi64, +0xffffffefffffffffi64 +}, +{ +0xffffffc000000000i64, +0xffffffc000000001i64, +0xffffffc000000003i64, +0xffffffc000000007i64, +0xffffffc00000000fi64, +0xffffffc00000001fi64, +0xffffffc00000003fi64, +0xffffffc00000007fi64, +0xffffffc0000000ffi64, +0xffffffc0000001ffi64, +0xffffffc0000003ffi64, +0xffffffc0000007ffi64, +0xffffffc000000fffi64, +0xffffffc000001fffi64, +0xffffffc000003fffi64, +0xffffffc000007fffi64, +0xffffffc00000ffffi64, +0xffffffc00001ffffi64, +0xffffffc00003ffffi64, +0xffffffc00007ffffi64, +0xffffffc0000fffffi64, +0xffffffc0001fffffi64, +0xffffffc0003fffffi64, +0xffffffc0007fffffi64, +0xffffffc000ffffffi64, +0xffffffc001ffffffi64, +0xffffffc003ffffffi64, +0xffffffc007ffffffi64, +0xffffffc00fffffffi64, +0xffffffc01fffffffi64, +0xffffffc03fffffffi64, +0xffffffc07fffffffi64, +0xffffffc0ffffffffi64, +0xffffffc1ffffffffi64, +0xffffffc3ffffffffi64, +0xffffffc7ffffffffi64, +0xffffffcfffffffffi64, +0xffffffdfffffffffi64 +}, +{ +0xffffff8000000000i64, +0xffffff8000000001i64, +0xffffff8000000003i64, +0xffffff8000000007i64, +0xffffff800000000fi64, +0xffffff800000001fi64, +0xffffff800000003fi64, +0xffffff800000007fi64, +0xffffff80000000ffi64, +0xffffff80000001ffi64, +0xffffff80000003ffi64, +0xffffff80000007ffi64, +0xffffff8000000fffi64, +0xffffff8000001fffi64, +0xffffff8000003fffi64, +0xffffff8000007fffi64, +0xffffff800000ffffi64, +0xffffff800001ffffi64, +0xffffff800003ffffi64, +0xffffff800007ffffi64, +0xffffff80000fffffi64, +0xffffff80001fffffi64, +0xffffff80003fffffi64, +0xffffff80007fffffi64, +0xffffff8000ffffffi64, +0xffffff8001ffffffi64, +0xffffff8003ffffffi64, +0xffffff8007ffffffi64, +0xffffff800fffffffi64, +0xffffff801fffffffi64, +0xffffff803fffffffi64, +0xffffff807fffffffi64, +0xffffff80ffffffffi64, +0xffffff81ffffffffi64, +0xffffff83ffffffffi64, +0xffffff87ffffffffi64, +0xffffff8fffffffffi64, +0xffffff9fffffffffi64, +0xffffffbfffffffffi64 +}, +{ +0xffffff0000000000i64, +0xffffff0000000001i64, +0xffffff0000000003i64, +0xffffff0000000007i64, +0xffffff000000000fi64, +0xffffff000000001fi64, +0xffffff000000003fi64, +0xffffff000000007fi64, +0xffffff00000000ffi64, +0xffffff00000001ffi64, +0xffffff00000003ffi64, +0xffffff00000007ffi64, +0xffffff0000000fffi64, +0xffffff0000001fffi64, +0xffffff0000003fffi64, +0xffffff0000007fffi64, +0xffffff000000ffffi64, +0xffffff000001ffffi64, +0xffffff000003ffffi64, +0xffffff000007ffffi64, +0xffffff00000fffffi64, +0xffffff00001fffffi64, +0xffffff00003fffffi64, +0xffffff00007fffffi64, +0xffffff0000ffffffi64, +0xffffff0001ffffffi64, +0xffffff0003ffffffi64, +0xffffff0007ffffffi64, +0xffffff000fffffffi64, +0xffffff001fffffffi64, +0xffffff003fffffffi64, +0xffffff007fffffffi64, +0xffffff00ffffffffi64, +0xffffff01ffffffffi64, +0xffffff03ffffffffi64, +0xffffff07ffffffffi64, +0xffffff0fffffffffi64, +0xffffff1fffffffffi64, +0xffffff3fffffffffi64, +0xffffff7fffffffffi64 +}, +{ +0xfffffe0000000000i64, +0xfffffe0000000001i64, +0xfffffe0000000003i64, +0xfffffe0000000007i64, +0xfffffe000000000fi64, +0xfffffe000000001fi64, +0xfffffe000000003fi64, +0xfffffe000000007fi64, +0xfffffe00000000ffi64, +0xfffffe00000001ffi64, +0xfffffe00000003ffi64, +0xfffffe00000007ffi64, +0xfffffe0000000fffi64, +0xfffffe0000001fffi64, +0xfffffe0000003fffi64, +0xfffffe0000007fffi64, +0xfffffe000000ffffi64, +0xfffffe000001ffffi64, +0xfffffe000003ffffi64, +0xfffffe000007ffffi64, +0xfffffe00000fffffi64, +0xfffffe00001fffffi64, +0xfffffe00003fffffi64, +0xfffffe00007fffffi64, +0xfffffe0000ffffffi64, +0xfffffe0001ffffffi64, +0xfffffe0003ffffffi64, +0xfffffe0007ffffffi64, +0xfffffe000fffffffi64, +0xfffffe001fffffffi64, +0xfffffe003fffffffi64, +0xfffffe007fffffffi64, +0xfffffe00ffffffffi64, +0xfffffe01ffffffffi64, +0xfffffe03ffffffffi64, +0xfffffe07ffffffffi64, +0xfffffe0fffffffffi64, +0xfffffe1fffffffffi64, +0xfffffe3fffffffffi64, +0xfffffe7fffffffffi64, +0xfffffeffffffffffi64 +}, +{ +0xfffffc0000000000i64, +0xfffffc0000000001i64, +0xfffffc0000000003i64, +0xfffffc0000000007i64, +0xfffffc000000000fi64, +0xfffffc000000001fi64, +0xfffffc000000003fi64, +0xfffffc000000007fi64, +0xfffffc00000000ffi64, +0xfffffc00000001ffi64, +0xfffffc00000003ffi64, +0xfffffc00000007ffi64, +0xfffffc0000000fffi64, +0xfffffc0000001fffi64, +0xfffffc0000003fffi64, +0xfffffc0000007fffi64, +0xfffffc000000ffffi64, +0xfffffc000001ffffi64, +0xfffffc000003ffffi64, +0xfffffc000007ffffi64, +0xfffffc00000fffffi64, +0xfffffc00001fffffi64, +0xfffffc00003fffffi64, +0xfffffc00007fffffi64, +0xfffffc0000ffffffi64, +0xfffffc0001ffffffi64, +0xfffffc0003ffffffi64, +0xfffffc0007ffffffi64, +0xfffffc000fffffffi64, +0xfffffc001fffffffi64, +0xfffffc003fffffffi64, +0xfffffc007fffffffi64, +0xfffffc00ffffffffi64, +0xfffffc01ffffffffi64, +0xfffffc03ffffffffi64, +0xfffffc07ffffffffi64, +0xfffffc0fffffffffi64, +0xfffffc1fffffffffi64, +0xfffffc3fffffffffi64, +0xfffffc7fffffffffi64, +0xfffffcffffffffffi64, +0xfffffdffffffffffi64 +}, +{ +0xfffff80000000000i64, +0xfffff80000000001i64, +0xfffff80000000003i64, +0xfffff80000000007i64, +0xfffff8000000000fi64, +0xfffff8000000001fi64, +0xfffff8000000003fi64, +0xfffff8000000007fi64, +0xfffff800000000ffi64, +0xfffff800000001ffi64, +0xfffff800000003ffi64, +0xfffff800000007ffi64, +0xfffff80000000fffi64, +0xfffff80000001fffi64, +0xfffff80000003fffi64, +0xfffff80000007fffi64, +0xfffff8000000ffffi64, +0xfffff8000001ffffi64, +0xfffff8000003ffffi64, +0xfffff8000007ffffi64, +0xfffff800000fffffi64, +0xfffff800001fffffi64, +0xfffff800003fffffi64, +0xfffff800007fffffi64, +0xfffff80000ffffffi64, +0xfffff80001ffffffi64, +0xfffff80003ffffffi64, +0xfffff80007ffffffi64, +0xfffff8000fffffffi64, +0xfffff8001fffffffi64, +0xfffff8003fffffffi64, +0xfffff8007fffffffi64, +0xfffff800ffffffffi64, +0xfffff801ffffffffi64, +0xfffff803ffffffffi64, +0xfffff807ffffffffi64, +0xfffff80fffffffffi64, +0xfffff81fffffffffi64, +0xfffff83fffffffffi64, +0xfffff87fffffffffi64, +0xfffff8ffffffffffi64, +0xfffff9ffffffffffi64, +0xfffffbffffffffffi64 +}, +{ +0xfffff00000000000i64, +0xfffff00000000001i64, +0xfffff00000000003i64, +0xfffff00000000007i64, +0xfffff0000000000fi64, +0xfffff0000000001fi64, +0xfffff0000000003fi64, +0xfffff0000000007fi64, +0xfffff000000000ffi64, +0xfffff000000001ffi64, +0xfffff000000003ffi64, +0xfffff000000007ffi64, +0xfffff00000000fffi64, +0xfffff00000001fffi64, +0xfffff00000003fffi64, +0xfffff00000007fffi64, +0xfffff0000000ffffi64, +0xfffff0000001ffffi64, +0xfffff0000003ffffi64, +0xfffff0000007ffffi64, +0xfffff000000fffffi64, +0xfffff000001fffffi64, +0xfffff000003fffffi64, +0xfffff000007fffffi64, +0xfffff00000ffffffi64, +0xfffff00001ffffffi64, +0xfffff00003ffffffi64, +0xfffff00007ffffffi64, +0xfffff0000fffffffi64, +0xfffff0001fffffffi64, +0xfffff0003fffffffi64, +0xfffff0007fffffffi64, +0xfffff000ffffffffi64, +0xfffff001ffffffffi64, +0xfffff003ffffffffi64, +0xfffff007ffffffffi64, +0xfffff00fffffffffi64, +0xfffff01fffffffffi64, +0xfffff03fffffffffi64, +0xfffff07fffffffffi64, +0xfffff0ffffffffffi64, +0xfffff1ffffffffffi64, +0xfffff3ffffffffffi64, +0xfffff7ffffffffffi64 +}, +{ +0xffffe00000000000i64, +0xffffe00000000001i64, +0xffffe00000000003i64, +0xffffe00000000007i64, +0xffffe0000000000fi64, +0xffffe0000000001fi64, +0xffffe0000000003fi64, +0xffffe0000000007fi64, +0xffffe000000000ffi64, +0xffffe000000001ffi64, +0xffffe000000003ffi64, +0xffffe000000007ffi64, +0xffffe00000000fffi64, +0xffffe00000001fffi64, +0xffffe00000003fffi64, +0xffffe00000007fffi64, +0xffffe0000000ffffi64, +0xffffe0000001ffffi64, +0xffffe0000003ffffi64, +0xffffe0000007ffffi64, +0xffffe000000fffffi64, +0xffffe000001fffffi64, +0xffffe000003fffffi64, +0xffffe000007fffffi64, +0xffffe00000ffffffi64, +0xffffe00001ffffffi64, +0xffffe00003ffffffi64, +0xffffe00007ffffffi64, +0xffffe0000fffffffi64, +0xffffe0001fffffffi64, +0xffffe0003fffffffi64, +0xffffe0007fffffffi64, +0xffffe000ffffffffi64, +0xffffe001ffffffffi64, +0xffffe003ffffffffi64, +0xffffe007ffffffffi64, +0xffffe00fffffffffi64, +0xffffe01fffffffffi64, +0xffffe03fffffffffi64, +0xffffe07fffffffffi64, +0xffffe0ffffffffffi64, +0xffffe1ffffffffffi64, +0xffffe3ffffffffffi64, +0xffffe7ffffffffffi64, +0xffffefffffffffffi64 +}, +{ +0xffffc00000000000i64, +0xffffc00000000001i64, +0xffffc00000000003i64, +0xffffc00000000007i64, +0xffffc0000000000fi64, +0xffffc0000000001fi64, +0xffffc0000000003fi64, +0xffffc0000000007fi64, +0xffffc000000000ffi64, +0xffffc000000001ffi64, +0xffffc000000003ffi64, +0xffffc000000007ffi64, +0xffffc00000000fffi64, +0xffffc00000001fffi64, +0xffffc00000003fffi64, +0xffffc00000007fffi64, +0xffffc0000000ffffi64, +0xffffc0000001ffffi64, +0xffffc0000003ffffi64, +0xffffc0000007ffffi64, +0xffffc000000fffffi64, +0xffffc000001fffffi64, +0xffffc000003fffffi64, +0xffffc000007fffffi64, +0xffffc00000ffffffi64, +0xffffc00001ffffffi64, +0xffffc00003ffffffi64, +0xffffc00007ffffffi64, +0xffffc0000fffffffi64, +0xffffc0001fffffffi64, +0xffffc0003fffffffi64, +0xffffc0007fffffffi64, +0xffffc000ffffffffi64, +0xffffc001ffffffffi64, +0xffffc003ffffffffi64, +0xffffc007ffffffffi64, +0xffffc00fffffffffi64, +0xffffc01fffffffffi64, +0xffffc03fffffffffi64, +0xffffc07fffffffffi64, +0xffffc0ffffffffffi64, +0xffffc1ffffffffffi64, +0xffffc3ffffffffffi64, +0xffffc7ffffffffffi64, +0xffffcfffffffffffi64, +0xffffdfffffffffffi64 +}, +{ +0xffff800000000000i64, +0xffff800000000001i64, +0xffff800000000003i64, +0xffff800000000007i64, +0xffff80000000000fi64, +0xffff80000000001fi64, +0xffff80000000003fi64, +0xffff80000000007fi64, +0xffff8000000000ffi64, +0xffff8000000001ffi64, +0xffff8000000003ffi64, +0xffff8000000007ffi64, +0xffff800000000fffi64, +0xffff800000001fffi64, +0xffff800000003fffi64, +0xffff800000007fffi64, +0xffff80000000ffffi64, +0xffff80000001ffffi64, +0xffff80000003ffffi64, +0xffff80000007ffffi64, +0xffff8000000fffffi64, +0xffff8000001fffffi64, +0xffff8000003fffffi64, +0xffff8000007fffffi64, +0xffff800000ffffffi64, +0xffff800001ffffffi64, +0xffff800003ffffffi64, +0xffff800007ffffffi64, +0xffff80000fffffffi64, +0xffff80001fffffffi64, +0xffff80003fffffffi64, +0xffff80007fffffffi64, +0xffff8000ffffffffi64, +0xffff8001ffffffffi64, +0xffff8003ffffffffi64, +0xffff8007ffffffffi64, +0xffff800fffffffffi64, +0xffff801fffffffffi64, +0xffff803fffffffffi64, +0xffff807fffffffffi64, +0xffff80ffffffffffi64, +0xffff81ffffffffffi64, +0xffff83ffffffffffi64, +0xffff87ffffffffffi64, +0xffff8fffffffffffi64, +0xffff9fffffffffffi64, +0xffffbfffffffffffi64 +}, +{ +0xffff000000000000i64, +0xffff000000000001i64, +0xffff000000000003i64, +0xffff000000000007i64, +0xffff00000000000fi64, +0xffff00000000001fi64, +0xffff00000000003fi64, +0xffff00000000007fi64, +0xffff0000000000ffi64, +0xffff0000000001ffi64, +0xffff0000000003ffi64, +0xffff0000000007ffi64, +0xffff000000000fffi64, +0xffff000000001fffi64, +0xffff000000003fffi64, +0xffff000000007fffi64, +0xffff00000000ffffi64, +0xffff00000001ffffi64, +0xffff00000003ffffi64, +0xffff00000007ffffi64, +0xffff0000000fffffi64, +0xffff0000001fffffi64, +0xffff0000003fffffi64, +0xffff0000007fffffi64, +0xffff000000ffffffi64, +0xffff000001ffffffi64, +0xffff000003ffffffi64, +0xffff000007ffffffi64, +0xffff00000fffffffi64, +0xffff00001fffffffi64, +0xffff00003fffffffi64, +0xffff00007fffffffi64, +0xffff0000ffffffffi64, +0xffff0001ffffffffi64, +0xffff0003ffffffffi64, +0xffff0007ffffffffi64, +0xffff000fffffffffi64, +0xffff001fffffffffi64, +0xffff003fffffffffi64, +0xffff007fffffffffi64, +0xffff00ffffffffffi64, +0xffff01ffffffffffi64, +0xffff03ffffffffffi64, +0xffff07ffffffffffi64, +0xffff0fffffffffffi64, +0xffff1fffffffffffi64, +0xffff3fffffffffffi64, +0xffff7fffffffffffi64 +}, +{ +0xfffe000000000000i64, +0xfffe000000000001i64, +0xfffe000000000003i64, +0xfffe000000000007i64, +0xfffe00000000000fi64, +0xfffe00000000001fi64, +0xfffe00000000003fi64, +0xfffe00000000007fi64, +0xfffe0000000000ffi64, +0xfffe0000000001ffi64, +0xfffe0000000003ffi64, +0xfffe0000000007ffi64, +0xfffe000000000fffi64, +0xfffe000000001fffi64, +0xfffe000000003fffi64, +0xfffe000000007fffi64, +0xfffe00000000ffffi64, +0xfffe00000001ffffi64, +0xfffe00000003ffffi64, +0xfffe00000007ffffi64, +0xfffe0000000fffffi64, +0xfffe0000001fffffi64, +0xfffe0000003fffffi64, +0xfffe0000007fffffi64, +0xfffe000000ffffffi64, +0xfffe000001ffffffi64, +0xfffe000003ffffffi64, +0xfffe000007ffffffi64, +0xfffe00000fffffffi64, +0xfffe00001fffffffi64, +0xfffe00003fffffffi64, +0xfffe00007fffffffi64, +0xfffe0000ffffffffi64, +0xfffe0001ffffffffi64, +0xfffe0003ffffffffi64, +0xfffe0007ffffffffi64, +0xfffe000fffffffffi64, +0xfffe001fffffffffi64, +0xfffe003fffffffffi64, +0xfffe007fffffffffi64, +0xfffe00ffffffffffi64, +0xfffe01ffffffffffi64, +0xfffe03ffffffffffi64, +0xfffe07ffffffffffi64, +0xfffe0fffffffffffi64, +0xfffe1fffffffffffi64, +0xfffe3fffffffffffi64, +0xfffe7fffffffffffi64, +0xfffeffffffffffffi64 +}, +{ +0xfffc000000000000i64, +0xfffc000000000001i64, +0xfffc000000000003i64, +0xfffc000000000007i64, +0xfffc00000000000fi64, +0xfffc00000000001fi64, +0xfffc00000000003fi64, +0xfffc00000000007fi64, +0xfffc0000000000ffi64, +0xfffc0000000001ffi64, +0xfffc0000000003ffi64, +0xfffc0000000007ffi64, +0xfffc000000000fffi64, +0xfffc000000001fffi64, +0xfffc000000003fffi64, +0xfffc000000007fffi64, +0xfffc00000000ffffi64, +0xfffc00000001ffffi64, +0xfffc00000003ffffi64, +0xfffc00000007ffffi64, +0xfffc0000000fffffi64, +0xfffc0000001fffffi64, +0xfffc0000003fffffi64, +0xfffc0000007fffffi64, +0xfffc000000ffffffi64, +0xfffc000001ffffffi64, +0xfffc000003ffffffi64, +0xfffc000007ffffffi64, +0xfffc00000fffffffi64, +0xfffc00001fffffffi64, +0xfffc00003fffffffi64, +0xfffc00007fffffffi64, +0xfffc0000ffffffffi64, +0xfffc0001ffffffffi64, +0xfffc0003ffffffffi64, +0xfffc0007ffffffffi64, +0xfffc000fffffffffi64, +0xfffc001fffffffffi64, +0xfffc003fffffffffi64, +0xfffc007fffffffffi64, +0xfffc00ffffffffffi64, +0xfffc01ffffffffffi64, +0xfffc03ffffffffffi64, +0xfffc07ffffffffffi64, +0xfffc0fffffffffffi64, +0xfffc1fffffffffffi64, +0xfffc3fffffffffffi64, +0xfffc7fffffffffffi64, +0xfffcffffffffffffi64, +0xfffdffffffffffffi64 +}, +{ +0xfff8000000000000i64, +0xfff8000000000001i64, +0xfff8000000000003i64, +0xfff8000000000007i64, +0xfff800000000000fi64, +0xfff800000000001fi64, +0xfff800000000003fi64, +0xfff800000000007fi64, +0xfff80000000000ffi64, +0xfff80000000001ffi64, +0xfff80000000003ffi64, +0xfff80000000007ffi64, +0xfff8000000000fffi64, +0xfff8000000001fffi64, +0xfff8000000003fffi64, +0xfff8000000007fffi64, +0xfff800000000ffffi64, +0xfff800000001ffffi64, +0xfff800000003ffffi64, +0xfff800000007ffffi64, +0xfff80000000fffffi64, +0xfff80000001fffffi64, +0xfff80000003fffffi64, +0xfff80000007fffffi64, +0xfff8000000ffffffi64, +0xfff8000001ffffffi64, +0xfff8000003ffffffi64, +0xfff8000007ffffffi64, +0xfff800000fffffffi64, +0xfff800001fffffffi64, +0xfff800003fffffffi64, +0xfff800007fffffffi64, +0xfff80000ffffffffi64, +0xfff80001ffffffffi64, +0xfff80003ffffffffi64, +0xfff80007ffffffffi64, +0xfff8000fffffffffi64, +0xfff8001fffffffffi64, +0xfff8003fffffffffi64, +0xfff8007fffffffffi64, +0xfff800ffffffffffi64, +0xfff801ffffffffffi64, +0xfff803ffffffffffi64, +0xfff807ffffffffffi64, +0xfff80fffffffffffi64, +0xfff81fffffffffffi64, +0xfff83fffffffffffi64, +0xfff87fffffffffffi64, +0xfff8ffffffffffffi64, +0xfff9ffffffffffffi64, +0xfffbffffffffffffi64 +}, +{ +0xfff0000000000000i64, +0xfff0000000000001i64, +0xfff0000000000003i64, +0xfff0000000000007i64, +0xfff000000000000fi64, +0xfff000000000001fi64, +0xfff000000000003fi64, +0xfff000000000007fi64, +0xfff00000000000ffi64, +0xfff00000000001ffi64, +0xfff00000000003ffi64, +0xfff00000000007ffi64, +0xfff0000000000fffi64, +0xfff0000000001fffi64, +0xfff0000000003fffi64, +0xfff0000000007fffi64, +0xfff000000000ffffi64, +0xfff000000001ffffi64, +0xfff000000003ffffi64, +0xfff000000007ffffi64, +0xfff00000000fffffi64, +0xfff00000001fffffi64, +0xfff00000003fffffi64, +0xfff00000007fffffi64, +0xfff0000000ffffffi64, +0xfff0000001ffffffi64, +0xfff0000003ffffffi64, +0xfff0000007ffffffi64, +0xfff000000fffffffi64, +0xfff000001fffffffi64, +0xfff000003fffffffi64, +0xfff000007fffffffi64, +0xfff00000ffffffffi64, +0xfff00001ffffffffi64, +0xfff00003ffffffffi64, +0xfff00007ffffffffi64, +0xfff0000fffffffffi64, +0xfff0001fffffffffi64, +0xfff0003fffffffffi64, +0xfff0007fffffffffi64, +0xfff000ffffffffffi64, +0xfff001ffffffffffi64, +0xfff003ffffffffffi64, +0xfff007ffffffffffi64, +0xfff00fffffffffffi64, +0xfff01fffffffffffi64, +0xfff03fffffffffffi64, +0xfff07fffffffffffi64, +0xfff0ffffffffffffi64, +0xfff1ffffffffffffi64, +0xfff3ffffffffffffi64, +0xfff7ffffffffffffi64 +}, +{ +0xffe0000000000000i64, +0xffe0000000000001i64, +0xffe0000000000003i64, +0xffe0000000000007i64, +0xffe000000000000fi64, +0xffe000000000001fi64, +0xffe000000000003fi64, +0xffe000000000007fi64, +0xffe00000000000ffi64, +0xffe00000000001ffi64, +0xffe00000000003ffi64, +0xffe00000000007ffi64, +0xffe0000000000fffi64, +0xffe0000000001fffi64, +0xffe0000000003fffi64, +0xffe0000000007fffi64, +0xffe000000000ffffi64, +0xffe000000001ffffi64, +0xffe000000003ffffi64, +0xffe000000007ffffi64, +0xffe00000000fffffi64, +0xffe00000001fffffi64, +0xffe00000003fffffi64, +0xffe00000007fffffi64, +0xffe0000000ffffffi64, +0xffe0000001ffffffi64, +0xffe0000003ffffffi64, +0xffe0000007ffffffi64, +0xffe000000fffffffi64, +0xffe000001fffffffi64, +0xffe000003fffffffi64, +0xffe000007fffffffi64, +0xffe00000ffffffffi64, +0xffe00001ffffffffi64, +0xffe00003ffffffffi64, +0xffe00007ffffffffi64, +0xffe0000fffffffffi64, +0xffe0001fffffffffi64, +0xffe0003fffffffffi64, +0xffe0007fffffffffi64, +0xffe000ffffffffffi64, +0xffe001ffffffffffi64, +0xffe003ffffffffffi64, +0xffe007ffffffffffi64, +0xffe00fffffffffffi64, +0xffe01fffffffffffi64, +0xffe03fffffffffffi64, +0xffe07fffffffffffi64, +0xffe0ffffffffffffi64, +0xffe1ffffffffffffi64, +0xffe3ffffffffffffi64, +0xffe7ffffffffffffi64, +0xffefffffffffffffi64 +}, +{ +0xffc0000000000000i64, +0xffc0000000000001i64, +0xffc0000000000003i64, +0xffc0000000000007i64, +0xffc000000000000fi64, +0xffc000000000001fi64, +0xffc000000000003fi64, +0xffc000000000007fi64, +0xffc00000000000ffi64, +0xffc00000000001ffi64, +0xffc00000000003ffi64, +0xffc00000000007ffi64, +0xffc0000000000fffi64, +0xffc0000000001fffi64, +0xffc0000000003fffi64, +0xffc0000000007fffi64, +0xffc000000000ffffi64, +0xffc000000001ffffi64, +0xffc000000003ffffi64, +0xffc000000007ffffi64, +0xffc00000000fffffi64, +0xffc00000001fffffi64, +0xffc00000003fffffi64, +0xffc00000007fffffi64, +0xffc0000000ffffffi64, +0xffc0000001ffffffi64, +0xffc0000003ffffffi64, +0xffc0000007ffffffi64, +0xffc000000fffffffi64, +0xffc000001fffffffi64, +0xffc000003fffffffi64, +0xffc000007fffffffi64, +0xffc00000ffffffffi64, +0xffc00001ffffffffi64, +0xffc00003ffffffffi64, +0xffc00007ffffffffi64, +0xffc0000fffffffffi64, +0xffc0001fffffffffi64, +0xffc0003fffffffffi64, +0xffc0007fffffffffi64, +0xffc000ffffffffffi64, +0xffc001ffffffffffi64, +0xffc003ffffffffffi64, +0xffc007ffffffffffi64, +0xffc00fffffffffffi64, +0xffc01fffffffffffi64, +0xffc03fffffffffffi64, +0xffc07fffffffffffi64, +0xffc0ffffffffffffi64, +0xffc1ffffffffffffi64, +0xffc3ffffffffffffi64, +0xffc7ffffffffffffi64, +0xffcfffffffffffffi64, +0xffdfffffffffffffi64 +}, +{ +0xff80000000000000i64, +0xff80000000000001i64, +0xff80000000000003i64, +0xff80000000000007i64, +0xff8000000000000fi64, +0xff8000000000001fi64, +0xff8000000000003fi64, +0xff8000000000007fi64, +0xff800000000000ffi64, +0xff800000000001ffi64, +0xff800000000003ffi64, +0xff800000000007ffi64, +0xff80000000000fffi64, +0xff80000000001fffi64, +0xff80000000003fffi64, +0xff80000000007fffi64, +0xff8000000000ffffi64, +0xff8000000001ffffi64, +0xff8000000003ffffi64, +0xff8000000007ffffi64, +0xff800000000fffffi64, +0xff800000001fffffi64, +0xff800000003fffffi64, +0xff800000007fffffi64, +0xff80000000ffffffi64, +0xff80000001ffffffi64, +0xff80000003ffffffi64, +0xff80000007ffffffi64, +0xff8000000fffffffi64, +0xff8000001fffffffi64, +0xff8000003fffffffi64, +0xff8000007fffffffi64, +0xff800000ffffffffi64, +0xff800001ffffffffi64, +0xff800003ffffffffi64, +0xff800007ffffffffi64, +0xff80000fffffffffi64, +0xff80001fffffffffi64, +0xff80003fffffffffi64, +0xff80007fffffffffi64, +0xff8000ffffffffffi64, +0xff8001ffffffffffi64, +0xff8003ffffffffffi64, +0xff8007ffffffffffi64, +0xff800fffffffffffi64, +0xff801fffffffffffi64, +0xff803fffffffffffi64, +0xff807fffffffffffi64, +0xff80ffffffffffffi64, +0xff81ffffffffffffi64, +0xff83ffffffffffffi64, +0xff87ffffffffffffi64, +0xff8fffffffffffffi64, +0xff9fffffffffffffi64, +0xffbfffffffffffffi64 +}, +{ +0xff00000000000000i64, +0xff00000000000001i64, +0xff00000000000003i64, +0xff00000000000007i64, +0xff0000000000000fi64, +0xff0000000000001fi64, +0xff0000000000003fi64, +0xff0000000000007fi64, +0xff000000000000ffi64, +0xff000000000001ffi64, +0xff000000000003ffi64, +0xff000000000007ffi64, +0xff00000000000fffi64, +0xff00000000001fffi64, +0xff00000000003fffi64, +0xff00000000007fffi64, +0xff0000000000ffffi64, +0xff0000000001ffffi64, +0xff0000000003ffffi64, +0xff0000000007ffffi64, +0xff000000000fffffi64, +0xff000000001fffffi64, +0xff000000003fffffi64, +0xff000000007fffffi64, +0xff00000000ffffffi64, +0xff00000001ffffffi64, +0xff00000003ffffffi64, +0xff00000007ffffffi64, +0xff0000000fffffffi64, +0xff0000001fffffffi64, +0xff0000003fffffffi64, +0xff0000007fffffffi64, +0xff000000ffffffffi64, +0xff000001ffffffffi64, +0xff000003ffffffffi64, +0xff000007ffffffffi64, +0xff00000fffffffffi64, +0xff00001fffffffffi64, +0xff00003fffffffffi64, +0xff00007fffffffffi64, +0xff0000ffffffffffi64, +0xff0001ffffffffffi64, +0xff0003ffffffffffi64, +0xff0007ffffffffffi64, +0xff000fffffffffffi64, +0xff001fffffffffffi64, +0xff003fffffffffffi64, +0xff007fffffffffffi64, +0xff00ffffffffffffi64, +0xff01ffffffffffffi64, +0xff03ffffffffffffi64, +0xff07ffffffffffffi64, +0xff0fffffffffffffi64, +0xff1fffffffffffffi64, +0xff3fffffffffffffi64, +0xff7fffffffffffffi64 +}, +{ +0xfe00000000000000i64, +0xfe00000000000001i64, +0xfe00000000000003i64, +0xfe00000000000007i64, +0xfe0000000000000fi64, +0xfe0000000000001fi64, +0xfe0000000000003fi64, +0xfe0000000000007fi64, +0xfe000000000000ffi64, +0xfe000000000001ffi64, +0xfe000000000003ffi64, +0xfe000000000007ffi64, +0xfe00000000000fffi64, +0xfe00000000001fffi64, +0xfe00000000003fffi64, +0xfe00000000007fffi64, +0xfe0000000000ffffi64, +0xfe0000000001ffffi64, +0xfe0000000003ffffi64, +0xfe0000000007ffffi64, +0xfe000000000fffffi64, +0xfe000000001fffffi64, +0xfe000000003fffffi64, +0xfe000000007fffffi64, +0xfe00000000ffffffi64, +0xfe00000001ffffffi64, +0xfe00000003ffffffi64, +0xfe00000007ffffffi64, +0xfe0000000fffffffi64, +0xfe0000001fffffffi64, +0xfe0000003fffffffi64, +0xfe0000007fffffffi64, +0xfe000000ffffffffi64, +0xfe000001ffffffffi64, +0xfe000003ffffffffi64, +0xfe000007ffffffffi64, +0xfe00000fffffffffi64, +0xfe00001fffffffffi64, +0xfe00003fffffffffi64, +0xfe00007fffffffffi64, +0xfe0000ffffffffffi64, +0xfe0001ffffffffffi64, +0xfe0003ffffffffffi64, +0xfe0007ffffffffffi64, +0xfe000fffffffffffi64, +0xfe001fffffffffffi64, +0xfe003fffffffffffi64, +0xfe007fffffffffffi64, +0xfe00ffffffffffffi64, +0xfe01ffffffffffffi64, +0xfe03ffffffffffffi64, +0xfe07ffffffffffffi64, +0xfe0fffffffffffffi64, +0xfe1fffffffffffffi64, +0xfe3fffffffffffffi64, +0xfe7fffffffffffffi64, +0xfeffffffffffffffi64 +}, +{ +0xfc00000000000000i64, +0xfc00000000000001i64, +0xfc00000000000003i64, +0xfc00000000000007i64, +0xfc0000000000000fi64, +0xfc0000000000001fi64, +0xfc0000000000003fi64, +0xfc0000000000007fi64, +0xfc000000000000ffi64, +0xfc000000000001ffi64, +0xfc000000000003ffi64, +0xfc000000000007ffi64, +0xfc00000000000fffi64, +0xfc00000000001fffi64, +0xfc00000000003fffi64, +0xfc00000000007fffi64, +0xfc0000000000ffffi64, +0xfc0000000001ffffi64, +0xfc0000000003ffffi64, +0xfc0000000007ffffi64, +0xfc000000000fffffi64, +0xfc000000001fffffi64, +0xfc000000003fffffi64, +0xfc000000007fffffi64, +0xfc00000000ffffffi64, +0xfc00000001ffffffi64, +0xfc00000003ffffffi64, +0xfc00000007ffffffi64, +0xfc0000000fffffffi64, +0xfc0000001fffffffi64, +0xfc0000003fffffffi64, +0xfc0000007fffffffi64, +0xfc000000ffffffffi64, +0xfc000001ffffffffi64, +0xfc000003ffffffffi64, +0xfc000007ffffffffi64, +0xfc00000fffffffffi64, +0xfc00001fffffffffi64, +0xfc00003fffffffffi64, +0xfc00007fffffffffi64, +0xfc0000ffffffffffi64, +0xfc0001ffffffffffi64, +0xfc0003ffffffffffi64, +0xfc0007ffffffffffi64, +0xfc000fffffffffffi64, +0xfc001fffffffffffi64, +0xfc003fffffffffffi64, +0xfc007fffffffffffi64, +0xfc00ffffffffffffi64, +0xfc01ffffffffffffi64, +0xfc03ffffffffffffi64, +0xfc07ffffffffffffi64, +0xfc0fffffffffffffi64, +0xfc1fffffffffffffi64, +0xfc3fffffffffffffi64, +0xfc7fffffffffffffi64, +0xfcffffffffffffffi64, +0xfdffffffffffffffi64 +}, +{ +0xf800000000000000i64, +0xf800000000000001i64, +0xf800000000000003i64, +0xf800000000000007i64, +0xf80000000000000fi64, +0xf80000000000001fi64, +0xf80000000000003fi64, +0xf80000000000007fi64, +0xf8000000000000ffi64, +0xf8000000000001ffi64, +0xf8000000000003ffi64, +0xf8000000000007ffi64, +0xf800000000000fffi64, +0xf800000000001fffi64, +0xf800000000003fffi64, +0xf800000000007fffi64, +0xf80000000000ffffi64, +0xf80000000001ffffi64, +0xf80000000003ffffi64, +0xf80000000007ffffi64, +0xf8000000000fffffi64, +0xf8000000001fffffi64, +0xf8000000003fffffi64, +0xf8000000007fffffi64, +0xf800000000ffffffi64, +0xf800000001ffffffi64, +0xf800000003ffffffi64, +0xf800000007ffffffi64, +0xf80000000fffffffi64, +0xf80000001fffffffi64, +0xf80000003fffffffi64, +0xf80000007fffffffi64, +0xf8000000ffffffffi64, +0xf8000001ffffffffi64, +0xf8000003ffffffffi64, +0xf8000007ffffffffi64, +0xf800000fffffffffi64, +0xf800001fffffffffi64, +0xf800003fffffffffi64, +0xf800007fffffffffi64, +0xf80000ffffffffffi64, +0xf80001ffffffffffi64, +0xf80003ffffffffffi64, +0xf80007ffffffffffi64, +0xf8000fffffffffffi64, +0xf8001fffffffffffi64, +0xf8003fffffffffffi64, +0xf8007fffffffffffi64, +0xf800ffffffffffffi64, +0xf801ffffffffffffi64, +0xf803ffffffffffffi64, +0xf807ffffffffffffi64, +0xf80fffffffffffffi64, +0xf81fffffffffffffi64, +0xf83fffffffffffffi64, +0xf87fffffffffffffi64, +0xf8ffffffffffffffi64, +0xf9ffffffffffffffi64, +0xfbffffffffffffffi64 +}, +{ +0xf000000000000000i64, +0xf000000000000001i64, +0xf000000000000003i64, +0xf000000000000007i64, +0xf00000000000000fi64, +0xf00000000000001fi64, +0xf00000000000003fi64, +0xf00000000000007fi64, +0xf0000000000000ffi64, +0xf0000000000001ffi64, +0xf0000000000003ffi64, +0xf0000000000007ffi64, +0xf000000000000fffi64, +0xf000000000001fffi64, +0xf000000000003fffi64, +0xf000000000007fffi64, +0xf00000000000ffffi64, +0xf00000000001ffffi64, +0xf00000000003ffffi64, +0xf00000000007ffffi64, +0xf0000000000fffffi64, +0xf0000000001fffffi64, +0xf0000000003fffffi64, +0xf0000000007fffffi64, +0xf000000000ffffffi64, +0xf000000001ffffffi64, +0xf000000003ffffffi64, +0xf000000007ffffffi64, +0xf00000000fffffffi64, +0xf00000001fffffffi64, +0xf00000003fffffffi64, +0xf00000007fffffffi64, +0xf0000000ffffffffi64, +0xf0000001ffffffffi64, +0xf0000003ffffffffi64, +0xf0000007ffffffffi64, +0xf000000fffffffffi64, +0xf000001fffffffffi64, +0xf000003fffffffffi64, +0xf000007fffffffffi64, +0xf00000ffffffffffi64, +0xf00001ffffffffffi64, +0xf00003ffffffffffi64, +0xf00007ffffffffffi64, +0xf0000fffffffffffi64, +0xf0001fffffffffffi64, +0xf0003fffffffffffi64, +0xf0007fffffffffffi64, +0xf000ffffffffffffi64, +0xf001ffffffffffffi64, +0xf003ffffffffffffi64, +0xf007ffffffffffffi64, +0xf00fffffffffffffi64, +0xf01fffffffffffffi64, +0xf03fffffffffffffi64, +0xf07fffffffffffffi64, +0xf0ffffffffffffffi64, +0xf1ffffffffffffffi64, +0xf3ffffffffffffffi64, +0xf7ffffffffffffffi64 +}, +{ +0xe000000000000000i64, +0xe000000000000001i64, +0xe000000000000003i64, +0xe000000000000007i64, +0xe00000000000000fi64, +0xe00000000000001fi64, +0xe00000000000003fi64, +0xe00000000000007fi64, +0xe0000000000000ffi64, +0xe0000000000001ffi64, +0xe0000000000003ffi64, +0xe0000000000007ffi64, +0xe000000000000fffi64, +0xe000000000001fffi64, +0xe000000000003fffi64, +0xe000000000007fffi64, +0xe00000000000ffffi64, +0xe00000000001ffffi64, +0xe00000000003ffffi64, +0xe00000000007ffffi64, +0xe0000000000fffffi64, +0xe0000000001fffffi64, +0xe0000000003fffffi64, +0xe0000000007fffffi64, +0xe000000000ffffffi64, +0xe000000001ffffffi64, +0xe000000003ffffffi64, +0xe000000007ffffffi64, +0xe00000000fffffffi64, +0xe00000001fffffffi64, +0xe00000003fffffffi64, +0xe00000007fffffffi64, +0xe0000000ffffffffi64, +0xe0000001ffffffffi64, +0xe0000003ffffffffi64, +0xe0000007ffffffffi64, +0xe000000fffffffffi64, +0xe000001fffffffffi64, +0xe000003fffffffffi64, +0xe000007fffffffffi64, +0xe00000ffffffffffi64, +0xe00001ffffffffffi64, +0xe00003ffffffffffi64, +0xe00007ffffffffffi64, +0xe0000fffffffffffi64, +0xe0001fffffffffffi64, +0xe0003fffffffffffi64, +0xe0007fffffffffffi64, +0xe000ffffffffffffi64, +0xe001ffffffffffffi64, +0xe003ffffffffffffi64, +0xe007ffffffffffffi64, +0xe00fffffffffffffi64, +0xe01fffffffffffffi64, +0xe03fffffffffffffi64, +0xe07fffffffffffffi64, +0xe0ffffffffffffffi64, +0xe1ffffffffffffffi64, +0xe3ffffffffffffffi64, +0xe7ffffffffffffffi64, +0xefffffffffffffffi64 +}, +{ +0xc000000000000000i64, +0xc000000000000001i64, +0xc000000000000003i64, +0xc000000000000007i64, +0xc00000000000000fi64, +0xc00000000000001fi64, +0xc00000000000003fi64, +0xc00000000000007fi64, +0xc0000000000000ffi64, +0xc0000000000001ffi64, +0xc0000000000003ffi64, +0xc0000000000007ffi64, +0xc000000000000fffi64, +0xc000000000001fffi64, +0xc000000000003fffi64, +0xc000000000007fffi64, +0xc00000000000ffffi64, +0xc00000000001ffffi64, +0xc00000000003ffffi64, +0xc00000000007ffffi64, +0xc0000000000fffffi64, +0xc0000000001fffffi64, +0xc0000000003fffffi64, +0xc0000000007fffffi64, +0xc000000000ffffffi64, +0xc000000001ffffffi64, +0xc000000003ffffffi64, +0xc000000007ffffffi64, +0xc00000000fffffffi64, +0xc00000001fffffffi64, +0xc00000003fffffffi64, +0xc00000007fffffffi64, +0xc0000000ffffffffi64, +0xc0000001ffffffffi64, +0xc0000003ffffffffi64, +0xc0000007ffffffffi64, +0xc000000fffffffffi64, +0xc000001fffffffffi64, +0xc000003fffffffffi64, +0xc000007fffffffffi64, +0xc00000ffffffffffi64, +0xc00001ffffffffffi64, +0xc00003ffffffffffi64, +0xc00007ffffffffffi64, +0xc0000fffffffffffi64, +0xc0001fffffffffffi64, +0xc0003fffffffffffi64, +0xc0007fffffffffffi64, +0xc000ffffffffffffi64, +0xc001ffffffffffffi64, +0xc003ffffffffffffi64, +0xc007ffffffffffffi64, +0xc00fffffffffffffi64, +0xc01fffffffffffffi64, +0xc03fffffffffffffi64, +0xc07fffffffffffffi64, +0xc0ffffffffffffffi64, +0xc1ffffffffffffffi64, +0xc3ffffffffffffffi64, +0xc7ffffffffffffffi64, +0xcfffffffffffffffi64, +0xdfffffffffffffffi64 +}, +{ +0x8000000000000000i64, +0x8000000000000001i64, +0x8000000000000003i64, +0x8000000000000007i64, +0x800000000000000fi64, +0x800000000000001fi64, +0x800000000000003fi64, +0x800000000000007fi64, +0x80000000000000ffi64, +0x80000000000001ffi64, +0x80000000000003ffi64, +0x80000000000007ffi64, +0x8000000000000fffi64, +0x8000000000001fffi64, +0x8000000000003fffi64, +0x8000000000007fffi64, +0x800000000000ffffi64, +0x800000000001ffffi64, +0x800000000003ffffi64, +0x800000000007ffffi64, +0x80000000000fffffi64, +0x80000000001fffffi64, +0x80000000003fffffi64, +0x80000000007fffffi64, +0x8000000000ffffffi64, +0x8000000001ffffffi64, +0x8000000003ffffffi64, +0x8000000007ffffffi64, +0x800000000fffffffi64, +0x800000001fffffffi64, +0x800000003fffffffi64, +0x800000007fffffffi64, +0x80000000ffffffffi64, +0x80000001ffffffffi64, +0x80000003ffffffffi64, +0x80000007ffffffffi64, +0x8000000fffffffffi64, +0x8000001fffffffffi64, +0x8000003fffffffffi64, +0x8000007fffffffffi64, +0x800000ffffffffffi64, +0x800001ffffffffffi64, +0x800003ffffffffffi64, +0x800007ffffffffffi64, +0x80000fffffffffffi64, +0x80001fffffffffffi64, +0x80003fffffffffffi64, +0x80007fffffffffffi64, +0x8000ffffffffffffi64, +0x8001ffffffffffffi64, +0x8003ffffffffffffi64, +0x8007ffffffffffffi64, +0x800fffffffffffffi64, +0x801fffffffffffffi64, +0x803fffffffffffffi64, +0x807fffffffffffffi64, +0x80ffffffffffffffi64, +0x81ffffffffffffffi64, +0x83ffffffffffffffi64, +0x87ffffffffffffffi64, +0x8fffffffffffffffi64, +0x9fffffffffffffffi64, +0xbfffffffffffffffi64 +}, +{ +0x0i64, +0x1i64, +0x3i64, +0x7i64, +0xfi64, +0x1fi64, +0x3fi64, +0x7fi64, +0xffi64, +0x1ffi64, +0x3ffi64, +0x7ffi64, +0xfffi64, +0x1fffi64, +0x3fffi64, +0x7fffi64, +0xffffi64, +0x1ffffi64, +0x3ffffi64, +0x7ffffi64, +0xfffffi64, +0x1fffffi64, +0x3fffffi64, +0x7fffffi64, +0xffffffi64, +0x1ffffffi64, +0x3ffffffi64, +0x7ffffffi64, +0xfffffffi64, +0x1fffffffi64, +0x3fffffffi64, +0x7fffffffi64, +0xffffffffi64, +0x1ffffffffi64, +0x3ffffffffi64, +0x7ffffffffi64, +0xfffffffffi64, +0x1fffffffffi64, +0x3fffffffffi64, +0x7fffffffffi64, +0xffffffffffi64, +0x1ffffffffffi64, +0x3ffffffffffi64, +0x7ffffffffffi64, +0xfffffffffffi64, +0x1fffffffffffi64, +0x3fffffffffffi64, +0x7fffffffffffi64, +0xffffffffffffi64, +0x1ffffffffffffi64, +0x3ffffffffffffi64, +0x7ffffffffffffi64, +0xfffffffffffffi64, +0x1fffffffffffffi64, +0x3fffffffffffffi64, +0x7fffffffffffffi64, +0xffffffffffffffi64, +0x1ffffffffffffffi64, +0x3ffffffffffffffi64, +0x7ffffffffffffffi64, +0xfffffffffffffffi64, +0x1fffffffffffffffi64, +0x3fffffffffffffffi64, +0x7fffffffffffffffi64 +} +}; + +#endif // end of #ifndef WIN32 + +} // namespace sc_dt + +#endif diff --git a/ext/systemc/src/sysc/datatypes/int/sc_int_base.cpp b/ext/systemc/src/sysc/datatypes/int/sc_int_base.cpp new file mode 100644 index 000000000..fb28d44a2 --- /dev/null +++ b/ext/systemc/src/sysc/datatypes/int/sc_int_base.cpp @@ -0,0 +1,749 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_int_base.cpp -- contains interface definitions between sc_int and + sc_signed, sc_unsigned, and definitions for sc_int_subref. + + Original Author: Ali Dasdan, Synopsys, Inc. + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + + +// $Log: sc_int_base.cpp,v $ +// Revision 1.5 2011/02/18 20:19:14 acg +// Andy Goodrich: updating Copyright notice. +// +// Revision 1.4 2010/02/04 22:23:29 acg +// Andy Goodrich: fixed bug in concatenation reads for part selections, +// the mask being used was 32 bits and should have been 64 bits. +// +// Revision 1.3 2008/06/19 17:47:56 acg +// Andy Goodrich: fixes for bugs. See 2.2.1 RELEASENOTES. +// +// Revision 1.2 2007/11/04 21:27:00 acg +// Andy Goodrich: changes to make sure the proper value is returned from +// concat_get_data(). +// +// Revision 1.1.1.1 2006/12/15 20:20:05 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:49:31 acg +// Added $Log command so that CVS check in comments are reproduced in the +// source. +// + +#include "sysc/kernel/sc_macros.h" +#include "sysc/datatypes/int/sc_signed.h" +#include "sysc/datatypes/int/sc_unsigned.h" +#include "sysc/datatypes/int/sc_int_base.h" +#include "sysc/datatypes/int/sc_uint_base.h" +#include "sysc/datatypes/int/sc_signed.h" +#include "sysc/datatypes/int/sc_int_ids.h" +#include "sysc/datatypes/bit/sc_bv_base.h" +#include "sysc/datatypes/bit/sc_lv_base.h" +#include "sysc/datatypes/misc/sc_concatref.h" +#include "sysc/datatypes/fx/sc_fix.h" +#include "sysc/datatypes/fx/scfx_other_defs.h" + + +namespace sc_dt +{ + +// to avoid code bloat in sc_int_concref<T1,T2> + +void +sc_int_concref_invalid_length( int length ) +{ + char msg[BUFSIZ]; + std::sprintf( msg, + "sc_int_concref<T1,T2> initialization: length = %d " + "violates 1 <= length <= %d", + length, SC_INTWIDTH ); + SC_REPORT_ERROR( sc_core::SC_ID_OUT_OF_BOUNDS_, msg ); +} + + +// ---------------------------------------------------------------------------- +// CLASS : sc_int_bitref +// +// Proxy class for sc_int bit selection (r-value and l-value). +// ---------------------------------------------------------------------------- + +sc_core::sc_vpool<sc_int_bitref> sc_int_bitref::m_pool(9); + +// concatenation methods: + +// #### OPTIMIZE +void sc_int_bitref::concat_set(int64 src, int low_i) +{ + sc_int_base aa( 1 ); + *this = aa = (low_i < 64) ? src >> low_i : src >> 63; +} + +void sc_int_bitref::concat_set(const sc_signed& src, int low_i) +{ + sc_int_base aa( 1 ); + if ( low_i < src.length() ) + *this = aa = 1 & (src >> low_i); + else + *this = aa = (src < 0) ? (int_type)-1 : 0; +} + +void sc_int_bitref::concat_set(const sc_unsigned& src, int low_i) +{ + sc_int_base aa( 1 ); + if ( low_i < src.length() ) + *this = aa = 1 & (src >> low_i); + else + *this = aa = 0; +} + +void sc_int_bitref::concat_set(uint64 src, int low_i) +{ + sc_int_base aa( 1 ); + *this = aa = (low_i < 64) ? src >> low_i : 0; +} + + +// other methods + +void +sc_int_bitref::scan( ::std::istream& is ) +{ + bool b; + is >> b; + *this = b; +} + + +// ---------------------------------------------------------------------------- +// CLASS : sc_int_subref_r +// +// Proxy class for sc_int part selection (l-value). +// ---------------------------------------------------------------------------- + +bool sc_int_subref_r::concat_get_ctrl( sc_digit* dst_p, int low_i ) const +{ + int dst_i; // Word in dst_p now processing. + int end_i; // Highest order word in dst_p to process. + int high_i; // Index of high order bit in dst_p to set. + uint_type mask; // Mask for bits to extract or keep. + + dst_i = low_i / BITS_PER_DIGIT; + high_i = low_i + (m_left-m_right); + end_i = high_i / BITS_PER_DIGIT; + mask = ~mask_int[m_left][m_right]; + + + // PROCESS THE FIRST WORD: + + dst_p[dst_i] = (sc_digit)(dst_p[dst_i] & mask); + switch ( end_i - dst_i ) + { + // BITS ARE ACROSS TWO WORDS: + + case 1: + dst_i++; + dst_p[dst_i] = 0; + break; + + // BITS ARE ACROSS THREE WORDS: + + case 2: + dst_i++; + dst_p[dst_i++] = 0; + dst_p[dst_i] = 0; + break; + + // BITS ARE ACROSS FOUR WORDS: + + case 3: + dst_i++; + dst_p[dst_i++] = 0; + dst_p[dst_i++] = 0; + dst_p[dst_i] = 0; + break; + } + return false; +} + + +bool sc_int_subref_r::concat_get_data( sc_digit* dst_p, int low_i ) const +{ + int dst_i; // Word in dst_p now processing. + int end_i; // Highest order word in dst_p to process. + int high_i; // Index of high order bit in dst_p to set. + int left_shift; // Left shift for val. + uint_type mask; // Mask for bits to extract or keep. + bool non_zero; // True if value inserted is non-zero. + uint_type val; // Selection value extracted from m_obj_p. + + dst_i = low_i / BITS_PER_DIGIT; + left_shift = low_i % BITS_PER_DIGIT; + high_i = low_i + (m_left-m_right); + end_i = high_i / BITS_PER_DIGIT; + mask = ~mask_int[m_left][m_right]; + val = (m_obj_p->m_val & mask) >> m_right; + non_zero = val != 0; + + + // PROCESS THE FIRST WORD: + + mask = ~(-1 << left_shift); + dst_p[dst_i] = (sc_digit)((dst_p[dst_i] & mask) | + ((val << left_shift) & DIGIT_MASK)); + + switch ( end_i - dst_i ) + { + // BITS ARE ACROSS TWO WORDS: + + case 1: + dst_i++; + val >>= (BITS_PER_DIGIT-left_shift); + dst_p[dst_i] = (sc_digit)(val & DIGIT_MASK); + break; + + // BITS ARE ACROSS THREE WORDS: + + case 2: + dst_i++; + val >>= (BITS_PER_DIGIT-left_shift); + dst_p[dst_i++] = (sc_digit)(val & DIGIT_MASK); + val >>= BITS_PER_DIGIT; + dst_p[dst_i] = (sc_digit)val; + break; + + // BITS ARE ACROSS FOUR WORDS: + + case 3: + dst_i++; + val >>= (BITS_PER_DIGIT-left_shift); + dst_p[dst_i++] = (sc_digit)(val & DIGIT_MASK); + val >>= BITS_PER_DIGIT; + dst_p[dst_i++] = (sc_digit)(val & DIGIT_MASK); + val >>= BITS_PER_DIGIT; + dst_p[dst_i] = (sc_digit)val; + break; + } + return non_zero; +} + +// ---------------------------------------------------------------------------- +// CLASS : sc_int_subref +// +// Proxy class for sc_int part selection (r-value and l-value). +// ---------------------------------------------------------------------------- + +sc_core::sc_vpool<sc_int_subref> sc_int_subref::m_pool(9); + +// assignment operators + +sc_int_subref& +sc_int_subref::operator = ( int_type v ) +{ + int_type val = m_obj_p->m_val; + uint_type mask = mask_int[m_left][m_right]; + val &= mask; + val |= (v << m_right) & ~mask; + m_obj_p->m_val = val; + m_obj_p->extend_sign(); + return *this; +} + +sc_int_subref& +sc_int_subref::operator = ( const sc_signed& a ) +{ + sc_int_base aa( length() ); + return ( *this = aa = a ); +} + +sc_int_subref& +sc_int_subref::operator = ( const sc_unsigned& a ) +{ + sc_int_base aa( length() ); + return ( *this = aa = a ); +} + +sc_int_subref& +sc_int_subref::operator = ( const sc_bv_base& a ) +{ + sc_int_base aa( length() ); + return ( *this = aa = a ); +} + +sc_int_subref& +sc_int_subref::operator = ( const sc_lv_base& a ) +{ + sc_int_base aa( length() ); + return ( *this = aa = a ); +} + + +// concatenation methods: + +// #### OPTIMIZE +void sc_int_subref::concat_set(int64 src, int low_i) +{ + sc_int_base aa ( length() ); + *this = aa = (low_i < 64) ? src >> low_i : src >> 63; +} + +void sc_int_subref::concat_set(const sc_signed& src, int low_i) +{ + sc_int_base aa( length() ); + if ( low_i < src.length() ) + *this = aa = src >> low_i; + else + *this = (src < 0) ? (int_type)-1 : 0; +} + +void sc_int_subref::concat_set(const sc_unsigned& src, int low_i) +{ + sc_int_base aa( length() ); + if ( low_i < src.length() ) + *this = aa = src >> low_i; + else + *this = 0; +} + +void sc_int_subref::concat_set(uint64 src, int low_i) +{ + sc_int_base aa ( length() ); + *this = aa = (low_i < 64) ? src >> low_i : 0; +} + + +// other methods + +void +sc_int_subref::scan( ::std::istream& is ) +{ + std::string s; + is >> s; + *this = s.c_str(); +} + + +// ---------------------------------------------------------------------------- +// CLASS : sc_int_base +// +// Base class for sc_int. +// ---------------------------------------------------------------------------- + +// support methods + +void +sc_int_base::invalid_length() const +{ + char msg[BUFSIZ]; + std::sprintf( msg, + "sc_int[_base] initialization: length = %d violates " + "1 <= length <= %d", + m_len, SC_INTWIDTH ); + SC_REPORT_ERROR( sc_core::SC_ID_OUT_OF_BOUNDS_, msg ); +} + +void +sc_int_base::invalid_index( int i ) const +{ + char msg[BUFSIZ]; + std::sprintf( msg, + "sc_int[_base] bit selection: index = %d violates " + "0 <= index <= %d", + i, m_len - 1 ); + SC_REPORT_ERROR( sc_core::SC_ID_OUT_OF_BOUNDS_, msg ); +} + +void +sc_int_base::invalid_range( int l, int r ) const +{ + char msg[BUFSIZ]; + std::sprintf( msg, + "sc_int[_base] part selection: left = %d, right = %d violates " + "%d >= left >= right >= 0", + l, r, m_len - 1 ); + SC_REPORT_ERROR( sc_core::SC_ID_OUT_OF_BOUNDS_, msg ); +} + + +void +sc_int_base::check_value() const +{ + int_type limit = (int_type) 1 << ( m_len - 1 ); + if( m_val < -limit || m_val >= limit ) { + char msg[BUFSIZ]; + std::sprintf( msg, "sc_int[_base]: value does not fit into a length of %d", + m_len ); + SC_REPORT_WARNING( sc_core::SC_ID_OUT_OF_BOUNDS_, msg ); + } +} + + +// constructors +sc_int_base::sc_int_base( const sc_bv_base& v ) + : m_val(0), m_len( v.length() ), m_ulen( SC_INTWIDTH - m_len ) +{ + check_length(); + *this = v; +} +sc_int_base::sc_int_base( const sc_lv_base& v ) + : m_val(0), m_len( v.length() ), m_ulen( SC_INTWIDTH - m_len ) +{ + check_length(); + *this = v; +} +sc_int_base::sc_int_base( const sc_uint_subref_r& v ) + : m_val(0), m_len( v.length() ), m_ulen( SC_INTWIDTH - m_len ) +{ + check_length(); + *this = v.to_uint64(); +} +sc_int_base::sc_int_base( const sc_signed_subref_r& v ) + : m_val(0), m_len( v.length() ), m_ulen( SC_INTWIDTH - m_len ) +{ + check_length(); + *this = v.to_uint64(); +} +sc_int_base::sc_int_base( const sc_unsigned_subref_r& v ) + : m_val(0), m_len( v.length() ), m_ulen( SC_INTWIDTH - m_len ) +{ + check_length(); + *this = v.to_uint64(); +} + +sc_int_base::sc_int_base( const sc_signed& a ) + : m_val( 0 ), m_len( a.length() ), m_ulen( SC_INTWIDTH - m_len ) +{ + check_length(); +#if 0 + for( int i = m_len - 1; i >= 0; -- i ) { + set( i, a.test( i ) ); + } + extend_sign(); +#else + *this = a.to_int64(); +#endif +} + +sc_int_base::sc_int_base( const sc_unsigned& a ) + : m_val( 0 ), m_len( a.length() ), m_ulen( SC_INTWIDTH - m_len ) +{ + check_length(); +#if 0 + for( int i = m_len - 1; i >= 0; -- i ) { + set( i, a.test( i ) ); + } + extend_sign(); +#else + *this = a.to_int64(); +#endif +} + + +// assignment operators + +sc_int_base& +sc_int_base::operator = ( const sc_signed& a ) +{ + int minlen = sc_min( m_len, a.length() ); + int i = 0; + for( ; i < minlen; ++ i ) { + set( i, a.test( i ) ); + } + bool sgn = a.sign(); + for( ; i < m_len; ++ i ) { + // sign extension + set( i, sgn ); + } + extend_sign(); + return *this; +} + +sc_int_base& +sc_int_base::operator = ( const sc_unsigned& a ) +{ + int minlen = sc_min( m_len, a.length() ); + int i = 0; + for( ; i < minlen; ++ i ) { + set( i, a.test( i ) ); + } + for( ; i < m_len; ++ i ) { + // zero extension + set( i, 0 ); + } + extend_sign(); + return *this; +} + + +sc_int_base& +sc_int_base::operator = ( const sc_bv_base& a ) +{ + int minlen = sc_min( m_len, a.length() ); + int i = 0; + for( ; i < minlen; ++ i ) { + set( i, a.get_bit( i ) ); + } + for( ; i < m_len; ++ i ) { + // zero extension + set( i, 0 ); + } + extend_sign(); + return *this; +} + +sc_int_base& +sc_int_base::operator = ( const sc_lv_base& a ) +{ + int minlen = sc_min( m_len, a.length() ); + int i = 0; + for( ; i < minlen; ++ i ) { + set( i, sc_logic( a.get_bit( i ) ).to_bool() ); + } + for( ; i < m_len; ++ i ) { + // zero extension + set( i, 0 ); + } + extend_sign(); + return *this; +} + +sc_int_base& +sc_int_base::operator = ( const char* a ) +{ + if( a == 0 ) { + SC_REPORT_ERROR( sc_core::SC_ID_CONVERSION_FAILED_, + "character string is zero" ); + } + if( *a == 0 ) { + SC_REPORT_ERROR( sc_core::SC_ID_CONVERSION_FAILED_, + "character string is empty" ); + } + try { + int len = m_len; + sc_fix aa( a, len, len, SC_TRN, SC_WRAP, 0, SC_ON ); + return this->operator = ( aa ); + } catch( sc_core::sc_report ) { + char msg[BUFSIZ]; + std::sprintf( msg, "character string '%s' is not valid", a ); + SC_REPORT_ERROR( sc_core::SC_ID_CONVERSION_FAILED_, msg ); + // never reached + return *this; + } +} + +// explicit conversion to character string + +const std::string +sc_int_base::to_string( sc_numrep numrep ) const +{ + int len = m_len; + sc_fix aa( *this, len, len, SC_TRN, SC_WRAP, 0, SC_ON ); + return aa.to_string( numrep ); +} + +const std::string +sc_int_base::to_string( sc_numrep numrep, bool w_prefix ) const +{ + int len = m_len; + sc_fix aa( *this, len, len, SC_TRN, SC_WRAP, 0, SC_ON ); + return aa.to_string( numrep, w_prefix ); +} + + +// reduce methods + +bool +sc_int_base::and_reduce() const +{ + return ( m_val == int_type( -1 ) ); +} + +bool +sc_int_base::or_reduce() const +{ + return ( m_val != int_type( 0 ) ); +} + +bool +sc_int_base::xor_reduce() const +{ + uint_type mask = ~UINT_ZERO; + uint_type val = m_val & (mask >> m_ulen); + int n = SC_INTWIDTH; + do { + n >>= 1; + mask >>= n; + val = ((val & (mask << n)) >> n) ^ (val & mask); + } while( n != 1 ); + return ( val != uint_type( 0 ) ); +} + + +bool sc_int_base::concat_get_ctrl( sc_digit* dst_p, int low_i ) const +{ + int dst_i; // Word in dst_p now processing. + int end_i; // Highest order word in dst_p to process. + int left_shift; // Left shift for val. + uint_type mask; // Mask for bits to extract or keep. + + dst_i = low_i / BITS_PER_DIGIT; + left_shift = low_i % BITS_PER_DIGIT; + end_i = (low_i + (m_len-1)) / BITS_PER_DIGIT; + + mask = ~(-1 << left_shift); + dst_p[dst_i] = (sc_digit)(dst_p[dst_i] & mask); + dst_i++; + for ( ; dst_i <= end_i; dst_i++ ) dst_p[dst_i] = 0; + return false; +} + +//------------------------------------------------------------------------------ +//"sc_int_base::concat_get_data" +// +// This method transfers the value of this object instance to the supplied +// array of sc_unsigned digits starting with the bit specified by low_i within +// the array of digits. +// +// Notes: +// (1) we don't worry about masking the high order data we transfer since +// concat_get_data() is called from low order bit to high order bit. So +// the bits above where we place ours will be filled in by someone else. +// +// dst_p -> array of sc_unsigned digits to be filled in. +// low_i = first bit within dst_p to be set. +//------------------------------------------------------------------------------ +bool sc_int_base::concat_get_data( sc_digit* dst_p, int low_i ) const +{ + int dst_i; // Word in dst_p now processing. + int end_i; // Highest order word in dst_p to process. + int high_i; // Index of high order bit in dst_p to set. + int left_shift; // Left shift for val. + uint_type mask; // Mask for bits to extract or keep. + bool non_zero; // True if value inserted is non-zero. + uint_type val; // Value for this object. + + dst_i = low_i / BITS_PER_DIGIT; + left_shift = low_i % BITS_PER_DIGIT; + high_i = low_i + (m_len-1); + end_i = high_i / BITS_PER_DIGIT; + val = m_val; + non_zero = val != 0; + + // MASK OFF DATA TO BE TRANSFERRED BASED ON WIDTH: + + if ( m_len < 64 ) + { + mask = ~((uint_type)-1 << m_len); + val &= mask; + } + + // PROCESS THE FIRST WORD: + + mask = (-1 << left_shift); + dst_p[dst_i] = (sc_digit)((dst_p[dst_i] & ~mask) | + ((val <<left_shift) & DIGIT_MASK)); + switch ( end_i - dst_i ) + { + // BITS ARE ACROSS TWO WORDS: + + case 1: + dst_i++; + val >>= (BITS_PER_DIGIT-left_shift); + dst_p[dst_i] = (sc_digit)val; + break; + + // BITS ARE ACROSS THREE WORDS: + + case 2: + dst_i++; + val >>= (BITS_PER_DIGIT-left_shift); + dst_p[dst_i++] = ((sc_digit)val) & DIGIT_MASK; + val >>= BITS_PER_DIGIT; + dst_p[dst_i] = (sc_digit)val; + break; + + // BITS ARE ACROSS FOUR WORDS: + + case 3: + dst_i++; + val >>= (BITS_PER_DIGIT-left_shift); + dst_p[dst_i++] = (sc_digit)(val & DIGIT_MASK); + val >>= BITS_PER_DIGIT; + dst_p[dst_i++] = (sc_digit)(val & DIGIT_MASK); + val >>= BITS_PER_DIGIT; + dst_p[dst_i] = (sc_digit)val; + break; + } + return non_zero; +} + +// #### OPTIMIZE +void sc_int_base::concat_set(int64 src, int low_i) +{ + *this = (low_i < 64) ? src >> low_i : src >> 63; +} + +void sc_int_base::concat_set(const sc_signed& src, int low_i) +{ + if ( low_i < src.length() ) + *this = src >> low_i; + else + *this = (src < 0) ? (int_type)-1 : 0; +} + +void sc_int_base::concat_set(const sc_unsigned& src, int low_i) +{ + if ( low_i < src.length() ) + *this = src >> low_i; + else + *this = 0; +} + +void sc_int_base::concat_set(uint64 src, int low_i) +{ + *this = (low_i < 64) ? src >> low_i : 0; +} + +// other methods + +void +sc_int_base::scan( ::std::istream& is ) +{ + std::string s; + is >> s; + *this = s.c_str(); +} + +} // namespace sc_dt; + + +// Taf! diff --git a/ext/systemc/src/sysc/datatypes/int/sc_int_base.h b/ext/systemc/src/sysc/datatypes/int/sc_int_base.h new file mode 100644 index 000000000..a9b8a6457 --- /dev/null +++ b/ext/systemc/src/sysc/datatypes/int/sc_int_base.h @@ -0,0 +1,1382 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_int_base.h -- A sc_int is a signed integer whose length is less than the + machine's native integer length. We provide two implementations + (i) sc_int with length between 1 - 64, and (ii) sc_int with + length between 1 - 32. Implementation (i) is the default + implementation, while implementation (ii) can be used only if + the class library is compiled with -D_32BIT_. Unlike arbitrary + precision, arithmetic and bitwise operations are performed + using the native types (hence capped at 32/64 bits). The sc_int + integer is useful when the user does not need arbitrary + precision and the performance is superior to + sc_bigint/sc_biguint. + + Original Author: Amit Rao, Synopsys, Inc. + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: Ali Dasdan, Synopsys, Inc. + Description of Modification: - Resolved ambiguity with sc_(un)signed. + - Merged the code for 64- and 32-bit versions + via the constants in sc_nbdefs.h. + - Eliminated redundant file inclusions. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + +// $Log: sc_int_base.h,v $ +// Revision 1.3 2011/08/24 22:05:45 acg +// Torsten Maehne: initialization changes to remove warnings. +// +// Revision 1.2 2011/02/18 20:19:15 acg +// Andy Goodrich: updating Copyright notice. +// +// Revision 1.1.1.1 2006/12/15 20:20:05 acg +// SystemC 2.3 +// +// Revision 1.4 2006/05/08 17:50:01 acg +// Andy Goodrich: Added David Long's declarations for friend operators, +// functions, and methods, to keep the Microsoft compiler happy. +// +// Revision 1.3 2006/01/13 18:49:31 acg +// Added $Log command so that CVS check in comments are reproduced in the +// source. +// + +#ifndef SC_INT_BASE_H +#define SC_INT_BASE_H + +#include "sysc/kernel/sc_object.h" +#include "sysc/datatypes/misc/sc_value_base.h" +#include "sysc/datatypes/int/sc_int_ids.h" +#include "sysc/datatypes/int/sc_length_param.h" +#include "sysc/datatypes/int/sc_nbdefs.h" +#include "sysc/datatypes/int/sc_uint_base.h" +#include "sysc/utils/sc_iostream.h" +#include "sysc/utils/sc_temporary.h" + + +namespace sc_dt +{ + +class sc_concatref; + +// classes defined in this module +class sc_int_bitref_r; +class sc_int_bitref; +class sc_int_subref_r; +class sc_int_subref; +class sc_int_base; +class sc_signed_subref_r; +class sc_unsigned_subref_r; + +// forward class declarations +class sc_bv_base; +class sc_lv_base; +class sc_signed; +class sc_unsigned; +class sc_fxval; +class sc_fxval_fast; +class sc_fxnum; +class sc_fxnum_fast; + + +extern const uint_type mask_int[SC_INTWIDTH][SC_INTWIDTH]; + +// friend operator declarations + // relational operators + + inline bool operator == ( const sc_int_base& a, const sc_int_base& b ); + + inline bool operator != ( const sc_int_base& a, const sc_int_base& b ); + + inline bool operator < ( const sc_int_base& a, const sc_int_base& b ); + + inline bool operator <= ( const sc_int_base& a, const sc_int_base& b ); + + inline bool operator > ( const sc_int_base& a, const sc_int_base& b ); + + inline bool operator >= ( const sc_int_base& a, const sc_int_base& b ); + + +// ---------------------------------------------------------------------------- +// CLASS : sc_int_bitref_r +// +// Proxy class for sc_int bit selection (r-value only). +// ---------------------------------------------------------------------------- + +class sc_int_bitref_r : public sc_value_base +{ + friend class sc_int_base; + +protected: + + // constructor + + sc_int_bitref_r() : sc_value_base(), m_index(), m_obj_p() + {} + + // initializer for sc_core::sc_vpool: + + void initialize( const sc_int_base* obj_p, int index_ ) + { + m_obj_p = (sc_int_base*)obj_p; + m_index = index_; + } + +public: + + // copy constructor + + sc_int_bitref_r( const sc_int_bitref_r& a ) : + sc_value_base(a), m_index(a.m_index), m_obj_p(a.m_obj_p) + {} + + // destructor + + virtual ~sc_int_bitref_r() + {} + + // capacity + + int length() const + { return 1; } + +#ifdef SC_DT_DEPRECATED + int bitwidth() const + { return length(); } +#endif + + // concatenation support + + virtual int concat_length( bool *xz_present_p ) const + { if (xz_present_p) *xz_present_p = false; return 1; } + virtual bool concat_get_ctrl( sc_digit* dst_p, int low_i ) const + { + int bit_mask = 1 << (low_i % BITS_PER_DIGIT); + int word_i = low_i / BITS_PER_DIGIT; + + dst_p[word_i] &= ~bit_mask; + return false; + } + virtual bool concat_get_data( sc_digit* dst_p, int low_i ) const + { + bool non_zero; + int bit_mask = 1 << (low_i % BITS_PER_DIGIT); + int word_i = low_i / BITS_PER_DIGIT; + + if ( operator uint64() ) + { + dst_p[word_i] |= bit_mask; + non_zero = true; + } + else + { + dst_p[word_i] &= ~bit_mask; + non_zero = false; + } + return non_zero; + } + virtual uint64 concat_get_uint64() const + { return operator uint64(); } + + + + + // implicit conversions + + operator uint64 () const; + bool operator ! () const; + bool operator ~ () const; + + + // explicit conversions + + uint64 value() const + { return operator uint64(); } + + bool to_bool() const + { return operator uint64(); } + + + // other methods + + void print( ::std::ostream& os = ::std::cout ) const + { os << to_bool(); } + +protected: + int m_index; + sc_int_base* m_obj_p; + +private: + + // disabled + sc_int_bitref_r& operator = ( const sc_int_bitref_r& ); +}; + + +inline +::std::ostream& +operator << ( ::std::ostream&, const sc_int_bitref_r& ); + + +// ---------------------------------------------------------------------------- +// CLASS : sc_int_bitref +// +// Proxy class for sc_int bit selection (r-value and l-value). +// ---------------------------------------------------------------------------- + +class sc_int_bitref + : public sc_int_bitref_r +{ + friend class sc_int_base; + friend class sc_core::sc_vpool<sc_int_bitref>; + + + // constructor + + sc_int_bitref() : sc_int_bitref_r() + {} + + +public: + + // copy constructor + + sc_int_bitref( const sc_int_bitref& a ) : sc_int_bitref_r( a ) + {} + + // assignment operators + + sc_int_bitref& operator = ( const sc_int_bitref_r& b ); + sc_int_bitref& operator = ( const sc_int_bitref& b ); + sc_int_bitref& operator = ( bool b ); + + sc_int_bitref& operator &= ( bool b ); + sc_int_bitref& operator |= ( bool b ); + sc_int_bitref& operator ^= ( bool b ); + + // concatenation methods + + virtual void concat_set(int64 src, int low_i); + virtual void concat_set(const sc_signed& src, int low_i); + virtual void concat_set(const sc_unsigned& src, int low_i); + virtual void concat_set(uint64 src, int low_i); + + + // other methods + + void scan( ::std::istream& is = ::std::cin ); + +public: + static sc_core::sc_vpool<sc_int_bitref> m_pool; + +}; + + + +inline +::std::istream& +operator >> ( ::std::istream&, sc_int_bitref& ); + + +// ---------------------------------------------------------------------------- +// CLASS : sc_int_subref_r +// +// Proxy class for sc_int part selection (r-value only). +// ---------------------------------------------------------------------------- + +class sc_int_subref_r : public sc_value_base +{ + friend class sc_int_base; + friend class sc_int_signal; + friend class sc_int_subref; + +protected: + + // constructor + + sc_int_subref_r() : sc_value_base(), m_left(0), m_obj_p(0), m_right(0) + {} + + // initializer for sc_core::sc_vpool: + + void initialize( const sc_int_base* obj_p, int left_i, int right_i ) + { + m_obj_p = (sc_int_base*)obj_p; + m_left = left_i; + m_right = right_i; + } + + +public: + // copy constructor + + sc_int_subref_r( const sc_int_subref_r& a ) : + sc_value_base(a), m_left( a.m_left ), m_obj_p( a.m_obj_p ), + m_right( a.m_right ) + {} + + // destructor + + virtual ~sc_int_subref_r() + {} + + // capacity + + int length() const + { return ( m_left - m_right + 1 ); } + +#ifdef SC_DT_DEPRECATED + int bitwidth() const + { return length(); } +#endif + + // concatenation support + + virtual int concat_length(bool* xz_present_p) const + { if ( xz_present_p ) *xz_present_p = false; return length(); } + virtual bool concat_get_ctrl( sc_digit* dst_p, int low_i ) const; + virtual bool concat_get_data( sc_digit* dst_p, int low_i ) const; + virtual uint64 concat_get_uint64() const + { + int len = length(); + uint64 val = operator uint_type(); + if ( len < 64 ) + return (uint64)(val & ~((uint_type)-1 << len)); + else + return (uint64)val; + } + + // reduce methods + + bool and_reduce() const; + + bool nand_reduce() const + { return ( ! and_reduce() ); } + + bool or_reduce() const; + + bool nor_reduce() const + { return ( ! or_reduce() ); } + + bool xor_reduce() const; + + bool xnor_reduce() const + { return ( ! xor_reduce() ); } + + + // implicit conversion to uint_type + + operator uint_type () const; + + + // explicit conversions + + uint_type value() const + { return operator uint_type(); } + + + int to_int() const; + unsigned int to_uint() const; + long to_long() const; + unsigned long to_ulong() const; + int64 to_int64() const; + uint64 to_uint64() const; + double to_double() const; + + + // explicit conversion to character string + + const std::string to_string( sc_numrep numrep = SC_DEC ) const; + const std::string to_string( sc_numrep numrep, bool w_prefix ) const; + + + // other methods + + void print( ::std::ostream& os = ::std::cout ) const + { os << to_string(sc_io_base(os,SC_DEC),sc_io_show_base(os)); } + +protected: + + int m_left; + sc_int_base* m_obj_p; + int m_right; + +private: + const sc_int_subref_r& operator = ( const sc_int_subref_r& ); +}; + + + +inline +::std::ostream& +operator << ( ::std::ostream&, const sc_int_subref_r& ); + + +// ---------------------------------------------------------------------------- +// CLASS : sc_int_subref +// +// Proxy class for sc_int part selection (r-value and l-value). +// ---------------------------------------------------------------------------- + +class sc_int_subref + : public sc_int_subref_r +{ + friend class sc_int_base; + friend class sc_core::sc_vpool<sc_int_subref>; + + +protected: + + // constructor + sc_int_subref() : sc_int_subref_r() + {} + +public: + + // copy constructor + + sc_int_subref( const sc_int_subref& a ) : sc_int_subref_r( a ) + {} + + // assignment operators + + sc_int_subref& operator = ( int_type v ); + sc_int_subref& operator = ( const sc_int_base& a ); + + sc_int_subref& operator = ( const sc_int_subref_r& a ) + { return operator = ( a.operator uint_type() ); } + + sc_int_subref& operator = ( const sc_int_subref& a ) + { return operator = ( a.operator uint_type() ); } + + template< class T > + sc_int_subref& operator = ( const sc_generic_base<T>& a ) + { return operator = ( a->to_int64() ); } + + sc_int_subref& operator = ( const char* a ); + + sc_int_subref& operator = ( unsigned long a ) + { return operator = ( (int_type) a ); } + + sc_int_subref& operator = ( long a ) + { return operator = ( (int_type) a ); } + + sc_int_subref& operator = ( unsigned int a ) + { return operator = ( (int_type) a ); } + + sc_int_subref& operator = ( int a ) + { return operator = ( (int_type) a ); } + + sc_int_subref& operator = ( uint64 a ) + { return operator = ( (int_type) a ); } + + sc_int_subref& operator = ( double a ) + { return operator = ( (int_type) a ); } + + sc_int_subref& operator = ( const sc_signed& ); + sc_int_subref& operator = ( const sc_unsigned& ); + sc_int_subref& operator = ( const sc_bv_base& ); + sc_int_subref& operator = ( const sc_lv_base& ); + + // concatenation methods + + virtual void concat_set(int64 src, int low_i); + virtual void concat_set(const sc_signed& src, int low_i); + virtual void concat_set(const sc_unsigned& src, int low_i); + virtual void concat_set(uint64 src, int low_i); + + // other methods + + void scan( ::std::istream& is = ::std::cin ); + +public: + static sc_core::sc_vpool<sc_int_subref> m_pool; + +}; + + + +inline +::std::istream& +operator >> ( ::std::istream&, sc_int_subref& ); + + +// ---------------------------------------------------------------------------- +// CLASS : sc_int_base +// +// Base class for sc_int. +// ---------------------------------------------------------------------------- + +class sc_int_base : public sc_value_base +{ + friend class sc_int_bitref_r; + friend class sc_int_bitref; + friend class sc_int_subref_r; + friend class sc_int_subref; + + + // support methods + + void invalid_length() const; + void invalid_index( int i ) const; + void invalid_range( int l, int r ) const; + + void check_length() const + { if( m_len <= 0 || m_len > SC_INTWIDTH ) { invalid_length(); } } + + void check_index( int i ) const + { if( i < 0 || i >= m_len ) { invalid_index( i ); } } + + void check_range( int l, int r ) const + { if( r < 0 || l >= m_len || l < r ) { invalid_range( l, r ); } } + + void check_value() const; + + void extend_sign() + { +#ifdef DEBUG_SYSTEMC + check_value(); +#endif + m_val = ( m_val << m_ulen >> m_ulen ); + } + +public: + + // constructors + + explicit sc_int_base( int w = sc_length_param().len() ) + : m_val( 0 ), m_len( w ), m_ulen( SC_INTWIDTH - m_len ) + { check_length(); } + + sc_int_base( int_type v, int w ) + : m_val( v ), m_len( w ), m_ulen( SC_INTWIDTH - m_len ) + { check_length(); extend_sign(); } + + sc_int_base( const sc_int_base& a ) + : sc_value_base(a), m_val( a.m_val ), m_len( a.m_len ), + m_ulen( a.m_ulen ) + {} + + explicit sc_int_base( const sc_int_subref_r& a ) + : m_val( a ), m_len( a.length() ), m_ulen( SC_INTWIDTH - m_len ) + { extend_sign(); } + + template< class T > + explicit sc_int_base( const sc_generic_base<T>& a ) : + m_val( a->to_int64() ), m_len( a->length() ), + m_ulen( SC_INTWIDTH - m_len ) + { check_length(); extend_sign(); } + + explicit sc_int_base( const sc_signed& a ); + explicit sc_int_base( const sc_unsigned& a ); + explicit sc_int_base( const sc_bv_base& v ); + explicit sc_int_base( const sc_lv_base& v ); + explicit sc_int_base( const sc_uint_subref_r& v ); + explicit sc_int_base( const sc_signed_subref_r& v ); + explicit sc_int_base( const sc_unsigned_subref_r& v ); + + + + // destructor + + virtual ~sc_int_base() + {} + + // assignment operators + + sc_int_base& operator = ( int_type v ) + { m_val = v; extend_sign(); return *this; } + + sc_int_base& operator = ( const sc_int_base& a ) + { m_val = a.m_val; extend_sign(); return *this; } + + sc_int_base& operator = ( const sc_int_subref_r& a ) + { m_val = a; extend_sign(); return *this; } + + template<class T> + sc_int_base& operator = ( const sc_generic_base<T>& a ) + { m_val = a->to_int64(); extend_sign(); return *this; } + + sc_int_base& operator = ( const sc_signed& a ); + sc_int_base& operator = ( const sc_unsigned& a ); + +#ifdef SC_INCLUDE_FX + sc_int_base& operator = ( const sc_fxval& a ); + sc_int_base& operator = ( const sc_fxval_fast& a ); + sc_int_base& operator = ( const sc_fxnum& a ); + sc_int_base& operator = ( const sc_fxnum_fast& a ); +#endif + + sc_int_base& operator = ( const sc_bv_base& a ); + sc_int_base& operator = ( const sc_lv_base& a ); + + sc_int_base& operator = ( const char* a ); + + sc_int_base& operator = ( unsigned long a ) + { m_val = a; extend_sign(); return *this; } + + sc_int_base& operator = ( long a ) + { m_val = a; extend_sign(); return *this; } + + sc_int_base& operator = ( unsigned int a ) + { m_val = a; extend_sign(); return *this; } + + sc_int_base& operator = ( int a ) + { m_val = a; extend_sign(); return *this; } + + sc_int_base& operator = ( uint64 a ) + { m_val = a; extend_sign(); return *this; } + + sc_int_base& operator = ( double a ) + { m_val = (int_type) a; extend_sign(); return *this; } + + + // arithmetic assignment operators + + sc_int_base& operator += ( int_type v ) + { m_val += v; extend_sign(); return *this; } + + sc_int_base& operator -= ( int_type v ) + { m_val -= v; extend_sign(); return *this; } + + sc_int_base& operator *= ( int_type v ) + { m_val *= v; extend_sign(); return *this; } + + sc_int_base& operator /= ( int_type v ) + { m_val /= v; extend_sign(); return *this; } + + sc_int_base& operator %= ( int_type v ) + { m_val %= v; extend_sign(); return *this; } + + + // bitwise assignment operators + + sc_int_base& operator &= ( int_type v ) + { m_val &= v; extend_sign(); return *this; } + + sc_int_base& operator |= ( int_type v ) + { m_val |= v; extend_sign(); return *this; } + + sc_int_base& operator ^= ( int_type v ) + { m_val ^= v; extend_sign(); return *this; } + + + sc_int_base& operator <<= ( int_type v ) + { m_val <<= v; extend_sign(); return *this; } + + sc_int_base& operator >>= ( int_type v ) + { m_val >>= v; /* no sign extension needed */ return *this; } + + + // prefix and postfix increment and decrement operators + + sc_int_base& operator ++ () // prefix + { ++ m_val; extend_sign(); return *this; } + + const sc_int_base operator ++ ( int ) // postfix + { sc_int_base tmp( *this ); ++ m_val; extend_sign(); return tmp; } + + sc_int_base& operator -- () // prefix + { -- m_val; extend_sign(); return *this; } + + const sc_int_base operator -- ( int ) // postfix + { sc_int_base tmp( *this ); -- m_val; extend_sign(); return tmp; } + + + // relational operators + + friend bool operator == ( const sc_int_base& a, const sc_int_base& b ) + { return a.m_val == b.m_val; } + + friend bool operator != ( const sc_int_base& a, const sc_int_base& b ) + { return a.m_val != b.m_val; } + + friend bool operator < ( const sc_int_base& a, const sc_int_base& b ) + { return a.m_val < b.m_val; } + + friend bool operator <= ( const sc_int_base& a, const sc_int_base& b ) + { return a.m_val <= b.m_val; } + + friend bool operator > ( const sc_int_base& a, const sc_int_base& b ) + { return a.m_val > b.m_val; } + + friend bool operator >= ( const sc_int_base& a, const sc_int_base& b ) + { return a.m_val >= b.m_val; } + + + // bit selection + + sc_int_bitref& operator [] ( int i ); + const sc_int_bitref_r& operator [] ( int i ) const; + + sc_int_bitref& bit( int i ); + const sc_int_bitref_r& bit( int i ) const; + + + // part selection + + sc_int_subref& operator () ( int left, int right ); + const sc_int_subref_r& operator () ( int left, int right ) const; + + sc_int_subref& range( int left, int right ); + const sc_int_subref_r& range( int left, int right ) const; + + + // bit access, without bounds checking or sign extension + + bool test( int i ) const + { return ( 0 != (m_val & (UINT_ONE << i)) ); } + + void set( int i ) + { m_val |= (UINT_ONE << i); } + + void set( int i, bool v ) + { v ? m_val |= (UINT_ONE << i) : m_val &= ~(UINT_ONE << i); } + + + // capacity + + int length() const + { return m_len; } + +#ifdef SC_DT_DEPRECATED + int bitwidth() const + { return length(); } +#endif + + // concatenation support + + virtual int concat_length(bool* xz_present_p) const + { if ( xz_present_p ) *xz_present_p = false; return length(); } + virtual bool concat_get_ctrl( sc_digit* dst_p, int low_i ) const; + virtual bool concat_get_data( sc_digit* dst_p, int low_i ) const; + virtual uint64 concat_get_uint64() const + { + if ( m_len < 64 ) + return (uint64)(m_val & ~((uint_type)-1 << m_len)); + else + return (uint64)m_val; + } + virtual void concat_set(int64 src, int low_i); + virtual void concat_set(const sc_signed& src, int low_i); + virtual void concat_set(const sc_unsigned& src, int low_i); + virtual void concat_set(uint64 src, int low_i); + + + // reduce methods + + bool and_reduce() const; + + bool nand_reduce() const + { return ( ! and_reduce() ); } + + bool or_reduce() const; + + bool nor_reduce() const + { return ( ! or_reduce() ); } + + bool xor_reduce() const; + + bool xnor_reduce() const + { return ( ! xor_reduce() ); } + + + // implicit conversion to int_type + + operator int_type() const + { return m_val; } + + + // explicit conversions + + int_type value() const + { return operator int_type(); } + + + int to_int() const + { return (int) m_val; } + + unsigned int to_uint() const + { return (unsigned int) m_val; } + + long to_long() const + { return (long) m_val; } + + unsigned long to_ulong() const + { return (unsigned long) m_val; } + + int64 to_int64() const + { return (int64) m_val; } + + uint64 to_uint64() const + { return (uint64) m_val; } + + double to_double() const + { return (double) m_val; } + + +#ifndef _32BIT_ + long long_low() const + { return (long) (m_val & UINT64_32ONES); } + + long long_high() const + { return (long) ((m_val >> 32) & UINT64_32ONES); } +#endif + + + // explicit conversion to character string + + const std::string to_string( sc_numrep numrep = SC_DEC ) const; + const std::string to_string( sc_numrep numrep, bool w_prefix ) const; + + + // other methods + + void print( ::std::ostream& os = ::std::cout ) const + { os << to_string(sc_io_base(os,SC_DEC),sc_io_show_base(os)); } + + void scan( ::std::istream& is = ::std::cin ); + +protected: + + int_type m_val; // value + int m_len; // length + int m_ulen; // unused length +}; + + + +inline +::std::ostream& +operator << ( ::std::ostream&, const sc_int_base& ); + +inline +::std::istream& +operator >> ( ::std::istream&, sc_int_base& ); + + + +// ---------------------------------------------------------------------------- +// CLASS : sc_int_bitref_r +// +// Proxy class for sc_int bit selection (r-value only). +// ---------------------------------------------------------------------------- + +// implicit conversion to uint64 + +inline +sc_int_bitref_r::operator uint64 () const +{ + return m_obj_p->test( m_index ); +} + +inline +bool +sc_int_bitref_r::operator ! () const +{ + return ! m_obj_p->test( m_index ); +} + +inline +bool +sc_int_bitref_r::operator ~ () const +{ + return ! m_obj_p->test( m_index ); +} + + + +inline +::std::ostream& +operator << ( ::std::ostream& os, const sc_int_bitref_r& a ) +{ + a.print( os ); + return os; +} + + +// ---------------------------------------------------------------------------- +// CLASS : sc_int_bitref +// +// Proxy class for sc_int bit selection (r-value and l-value). +// ---------------------------------------------------------------------------- + +// assignment operators + +inline +sc_int_bitref& +sc_int_bitref::operator = ( const sc_int_bitref_r& b ) +{ + m_obj_p->set( m_index, (bool) b ); + m_obj_p->extend_sign(); + return *this; +} + +inline +sc_int_bitref& +sc_int_bitref::operator = ( const sc_int_bitref& b ) +{ + m_obj_p->set( m_index, (bool) b ); + m_obj_p->extend_sign(); + return *this; +} + +inline +sc_int_bitref& +sc_int_bitref::operator = ( bool b ) +{ + m_obj_p->set( m_index, b ); + m_obj_p->extend_sign(); + return *this; +} + + +inline +sc_int_bitref& +sc_int_bitref::operator &= ( bool b ) +{ + if( ! b ) { + m_obj_p->set( m_index, b ); + m_obj_p->extend_sign(); + } + return *this; +} + +inline +sc_int_bitref& +sc_int_bitref::operator |= ( bool b ) +{ + if( b ) { + m_obj_p->set( m_index, b ); + m_obj_p->extend_sign(); + } + return *this; +} + +inline +sc_int_bitref& +sc_int_bitref::operator ^= ( bool b ) +{ + if( b ) { + m_obj_p->m_val ^= (UINT_ONE << m_index); + m_obj_p->extend_sign(); + } + return *this; +} + + + +inline +::std::istream& +operator >> ( ::std::istream& is, sc_int_bitref& a ) +{ + a.scan( is ); + return is; +} + + +// ---------------------------------------------------------------------------- +// CLASS : sc_int_subref_r +// +// Proxy class for sc_int part selection (r-value only). +// ---------------------------------------------------------------------------- + +// implicit conversion to int_type + +inline +sc_int_subref_r::operator uint_type() const +{ + uint_type /*int_type*/ val = m_obj_p->m_val; + int uleft = SC_INTWIDTH - (m_left + 1); + int uright = uleft + m_right; + return ( val << uleft >> uright ); +} + + +// reduce methods + +inline +bool +sc_int_subref_r::and_reduce() const +{ + sc_int_base a( *this ); + return a.and_reduce(); +} + +inline +bool +sc_int_subref_r::or_reduce() const +{ + sc_int_base a( *this ); + return a.or_reduce(); +} + +inline +bool +sc_int_subref_r::xor_reduce() const +{ + sc_int_base a( *this ); + return a.xor_reduce(); +} + + +// explicit conversions + +inline +int +sc_int_subref_r::to_int() const +{ + int result = static_cast<int>(operator uint_type()); + return result; +} + +inline +unsigned int +sc_int_subref_r::to_uint() const +{ + unsigned int result = static_cast<unsigned int>(operator uint_type()); + return result; +} + +inline +long +sc_int_subref_r::to_long() const +{ + long result = static_cast<long>(operator uint_type()); + return result; +} + +inline +unsigned long +sc_int_subref_r::to_ulong() const +{ + unsigned long result = static_cast<unsigned long>(operator uint_type()); + return result; +} + +inline +int64 +sc_int_subref_r::to_int64() const +{ + int64 result = operator uint_type(); + return result; +} + +inline +uint64 +sc_int_subref_r::to_uint64() const +{ + uint64 result = operator uint_type(); + return result; +} + +inline +double +sc_int_subref_r::to_double() const +{ + double result = static_cast<double>(operator uint_type()); + return result; +} + + +// explicit conversion to character string + +inline +const std::string +sc_int_subref_r::to_string( sc_numrep numrep ) const +{ + sc_uint_base a(length()); + a = operator uint_type(); + return a.to_string( numrep ); +} + +inline +const std::string +sc_int_subref_r::to_string( sc_numrep numrep, bool w_prefix ) const +{ + sc_uint_base a(length()); + a = operator uint_type(); + return a.to_string( numrep, w_prefix ); +} + + +// functional notation for the reduce methods + +inline +bool +and_reduce( const sc_int_subref_r& a ) +{ + return a.and_reduce(); +} + +inline +bool +nand_reduce( const sc_int_subref_r& a ) +{ + return a.nand_reduce(); +} + +inline +bool +or_reduce( const sc_int_subref_r& a ) +{ + return a.or_reduce(); +} + +inline +bool +nor_reduce( const sc_int_subref_r& a ) +{ + return a.nor_reduce(); +} + +inline +bool +xor_reduce( const sc_int_subref_r& a ) +{ + return a.xor_reduce(); +} + +inline +bool +xnor_reduce( const sc_int_subref_r& a ) +{ + return a.xnor_reduce(); +} + + + +inline +::std::ostream& +operator << ( ::std::ostream& os, const sc_int_subref_r& a ) +{ + a.print( os ); + return os; +} + + +// ---------------------------------------------------------------------------- +// CLASS : sc_int_subref +// +// Proxy class for sc_int part selection (r-value and l-value). +// ---------------------------------------------------------------------------- + +// assignment operators + +inline +sc_int_subref& +sc_int_subref::operator = ( const sc_int_base& a ) +{ + return operator = ( a.operator int_type() ); +} + +inline +sc_int_subref& +sc_int_subref::operator = ( const char* a ) +{ + sc_int_base aa( length() ); + return ( *this = aa = a ); +} + + + +inline +::std::istream& +operator >> ( ::std::istream& is, sc_int_subref& a ) +{ + a.scan( is ); + return is; +} + + +// ---------------------------------------------------------------------------- +// CLASS : sc_int_base +// +// Base class for sc_int. +// ---------------------------------------------------------------------------- + +// bit selection + +inline +sc_int_bitref& +sc_int_base::operator [] ( int i ) +{ + check_index( i ); + sc_int_bitref* result_p = sc_int_bitref::m_pool.allocate(); + result_p->initialize(this, i); + return *result_p; +} + +inline +const sc_int_bitref_r& +sc_int_base::operator [] ( int i ) const +{ + check_index( i ); + sc_int_bitref* result_p = sc_int_bitref::m_pool.allocate(); + result_p->initialize(this, i); + return *result_p; +} + + +inline +sc_int_bitref& +sc_int_base::bit( int i ) +{ + check_index( i ); + sc_int_bitref* result_p = sc_int_bitref::m_pool.allocate(); + result_p->initialize(this, i); + return *result_p; +} + +inline +const sc_int_bitref_r& +sc_int_base::bit( int i ) const +{ + check_index( i ); + sc_int_bitref* result_p = sc_int_bitref::m_pool.allocate(); + result_p->initialize(this, i); + return *result_p; +} + + +// part selection + +inline +sc_int_subref& +sc_int_base::operator () ( int left, int right ) +{ + check_range( left, right ); + sc_int_subref* result_p = sc_int_subref::m_pool.allocate(); + result_p->initialize(this, left, right); + return *result_p; +} + +inline +const sc_int_subref_r& +sc_int_base::operator () ( int left, int right ) const +{ + check_range( left, right ); + sc_int_subref* result_p = sc_int_subref::m_pool.allocate(); + result_p->initialize(this, left, right); + return *result_p; +} + + +inline +sc_int_subref& +sc_int_base::range( int left, int right ) +{ + check_range( left, right ); + sc_int_subref* result_p = sc_int_subref::m_pool.allocate(); + result_p->initialize(this, left, right); + return *result_p; +} + +inline +const sc_int_subref_r& +sc_int_base::range( int left, int right ) const +{ + check_range( left, right ); + sc_int_subref* result_p = sc_int_subref::m_pool.allocate(); + result_p->initialize(this, left, right); + return *result_p; +} + + +// functional notation for the reduce methods + +inline +bool +and_reduce( const sc_int_base& a ) +{ + return a.and_reduce(); +} + +inline +bool +nand_reduce( const sc_int_base& a ) +{ + return a.nand_reduce(); +} + +inline +bool +or_reduce( const sc_int_base& a ) +{ + return a.or_reduce(); +} + +inline +bool +nor_reduce( const sc_int_base& a ) +{ + return a.nor_reduce(); +} + +inline +bool +xor_reduce( const sc_int_base& a ) +{ + return a.xor_reduce(); +} + +inline +bool +xnor_reduce( const sc_int_base& a ) +{ + return a.xnor_reduce(); +} + + + +inline +::std::ostream& +operator << ( ::std::ostream& os, const sc_int_base& a ) +{ + a.print( os ); + return os; +} + +inline +::std::istream& +operator >> ( ::std::istream& is, sc_int_base& a ) +{ + a.scan( is ); + return is; +} + +} // namespace sc_dt + + +#endif + +// Taf! diff --git a/ext/systemc/src/sysc/datatypes/int/sc_int_ids.h b/ext/systemc/src/sysc/datatypes/int/sc_int_ids.h new file mode 100644 index 000000000..13b269590 --- /dev/null +++ b/ext/systemc/src/sysc/datatypes/int/sc_int_ids.h @@ -0,0 +1,80 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_int_ids.h -- Report ids for the datatypes/int code. + + Original Author: Martin Janssen, Synopsys, Inc., 2002-01-17 + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + +// $Log: sc_int_ids.h,v $ +// Revision 1.2 2011/02/18 20:19:15 acg +// Andy Goodrich: updating Copyright notice. +// +// Revision 1.1.1.1 2006/12/15 20:20:05 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:49:31 acg +// Added $Log command so that CVS check in comments are reproduced in the +// source. +// + +#ifndef SC_INT_IDS_H +#define SC_INT_IDS_H + + +#include "sysc/utils/sc_report.h" + + +// ---------------------------------------------------------------------------- +// Report ids (datatypes/int) +// +// Report ids in the range of 400-499. +// ---------------------------------------------------------------------------- + +#ifndef SC_DEFINE_MESSAGE +#define SC_DEFINE_MESSAGE(id,unused1,unused2) \ + namespace sc_core { extern const char id[]; } +extern const char SC_ID_REGISTER_ID_FAILED_[]; // in sc_report_handler.cpp +#endif + + +SC_DEFINE_MESSAGE( SC_ID_INIT_FAILED_, 400, "initialization failed" ) +SC_DEFINE_MESSAGE( SC_ID_ASSIGNMENT_FAILED_, 401, "assignment failed" ) +SC_DEFINE_MESSAGE( SC_ID_OPERATION_FAILED_, 402, "operation failed" ) +SC_DEFINE_MESSAGE( SC_ID_CONVERSION_FAILED_, 403, "conversion failed" ) + + + + +#endif + +// Taf! diff --git a/ext/systemc/src/sysc/datatypes/int/sc_length_param.cpp b/ext/systemc/src/sysc/datatypes/int/sc_length_param.cpp new file mode 100644 index 000000000..c0ba66b6b --- /dev/null +++ b/ext/systemc/src/sysc/datatypes/int/sc_length_param.cpp @@ -0,0 +1,97 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_length_param.cpp - + + Original Author: Martin Janssen, Synopsys, Inc., 2002-03-19 + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + + +// $Log: sc_length_param.cpp,v $ +// Revision 1.2 2011/02/18 20:19:15 acg +// Andy Goodrich: updating Copyright notice. +// +// Revision 1.1.1.1 2006/12/15 20:20:05 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:49:32 acg +// Added $Log command so that CVS check in comments are reproduced in the +// source. +// + +#include "sysc/datatypes/int/sc_length_param.h" + + +namespace sc_dt +{ + +// ---------------------------------------------------------------------------- +// CLASS : sc_length_param +// +// Length parameter type. +// ---------------------------------------------------------------------------- + +const std::string +sc_length_param::to_string() const +{ + std::string s; + + char buf[BUFSIZ]; + + s += "("; + std::sprintf( buf, "%d", m_len ); + s += buf; + s += ")"; + + return s; +} + + +void +sc_length_param::print( ::std::ostream& os ) const +{ + os << to_string(); +} + +void +sc_length_param::dump( ::std::ostream& os ) const +{ + os << "sc_length_param" << ::std::endl; + os << "(" << ::std::endl; + os << "len = " << m_len << ::std::endl; + os << ")" << ::std::endl; +} + +} // namespace sc_dt + + +// Taf! diff --git a/ext/systemc/src/sysc/datatypes/int/sc_length_param.h b/ext/systemc/src/sysc/datatypes/int/sc_length_param.h new file mode 100644 index 000000000..aadb52bda --- /dev/null +++ b/ext/systemc/src/sysc/datatypes/int/sc_length_param.h @@ -0,0 +1,203 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_length_param.h - + + Original Author: Martin Janssen, Synopsys, Inc., 2002-03-19 + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + +// $Log: sc_length_param.h,v $ +// Revision 1.3 2011/08/24 22:05:46 acg +// Torsten Maehne: initialization changes to remove warnings. +// +// Revision 1.2 2011/02/18 20:19:15 acg +// Andy Goodrich: updating Copyright notice. +// +// Revision 1.1.1.1 2006/12/15 20:20:05 acg +// SystemC 2.3 +// +// Revision 1.4 2006/05/08 17:50:01 acg +// Andy Goodrich: Added David Long's declarations for friend operators, +// functions, and methods, to keep the Microsoft compiler happy. +// +// Revision 1.3 2006/01/13 18:49:32 acg +// Added $Log command so that CVS check in comments are reproduced in the +// source. +// + +#ifndef SC_LENGTH_PARAM_H +#define SC_LENGTH_PARAM_H + + +#include "sysc/datatypes/fx/sc_context.h" + + +namespace sc_dt +{ + +// classes defined in this module +class sc_length_param; + +// friend operator declarations + bool operator == ( const sc_length_param&, + const sc_length_param& ); + bool operator != ( const sc_length_param&, + const sc_length_param& ); + + +// ---------------------------------------------------------------------------- +// CLASS : sc_length_param +// +// Length parameter type. +// ---------------------------------------------------------------------------- + +class sc_length_param +{ +public: + + sc_length_param(); + sc_length_param( int ); + sc_length_param( const sc_length_param& ); + explicit sc_length_param( sc_without_context ); + + sc_length_param& operator = ( const sc_length_param& ); + + friend bool operator == ( const sc_length_param&, + const sc_length_param& ); + friend bool operator != ( const sc_length_param&, + const sc_length_param& ); + + int len() const; + void len( int ); + + const std::string to_string() const; + + void print( ::std::ostream& = ::std::cout ) const; + void dump( ::std::ostream& = ::std::cout ) const; + +private: + + int m_len; +}; + + +// ---------------------------------------------------------------------------- +// TYPEDEF : sc_length_context +// +// Context type for the length parameter type. +// ---------------------------------------------------------------------------- + +typedef sc_context<sc_length_param> sc_length_context; + + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + +inline +sc_length_param::sc_length_param() : m_len() +{ + *this = sc_length_context::default_value(); +} + +inline +sc_length_param::sc_length_param( int len_ ) : m_len(len_) +{ + SC_CHECK_WL_( len_ ); +} + +inline +sc_length_param::sc_length_param( const sc_length_param& a ) + : m_len( a.m_len ) +{} + +inline +sc_length_param::sc_length_param( sc_without_context ) + : m_len( SC_DEFAULT_WL_ ) +{} + + +inline +sc_length_param& +sc_length_param::operator = ( const sc_length_param& a ) +{ + if( &a != this ) + { + m_len = a.m_len; + } + return *this; +} + + +inline +bool +operator == ( const sc_length_param& a, const sc_length_param& b ) +{ + return ( a.m_len == b.m_len ); +} + +inline +bool +operator != ( const sc_length_param& a, const sc_length_param& b ) +{ + return ( a.m_len != b.m_len ); +} + + +inline +int +sc_length_param::len() const +{ + return m_len; +} + +inline +void +sc_length_param::len( int len_ ) +{ + SC_CHECK_WL_( len_ ); + m_len = len_; +} + + +inline +::std::ostream& +operator << ( ::std::ostream& os, const sc_length_param& a ) +{ + a.print( os ); + return os; +} + +} // namespace sc_dt + + +#endif + +// Taf! diff --git a/ext/systemc/src/sysc/datatypes/int/sc_nbcommon.inc b/ext/systemc/src/sysc/datatypes/int/sc_nbcommon.inc new file mode 100644 index 000000000..89fc4ba83 --- /dev/null +++ b/ext/systemc/src/sysc/datatypes/int/sc_nbcommon.inc @@ -0,0 +1,2989 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_nbcommon.cpp -- Functions common to both sc_signed and sc_unsigned. + This file is included in sc_signed.cpp and + sc_unsigned.cpp after the macros are defined accordingly. + For example, sc_signed.cpp will first define CLASS_TYPE + as sc_signed before including this file. This file like + sc_nbfriends.cpp and sc_nbexterns.cpp is created in order + to ensure only one version of each function, regardless + of the class that they interface to. + + Original Author: Ali Dasdan, Synopsys, Inc. + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + + +// ---------------------------------------------------------------------------- +// SECTION : Public members +// ---------------------------------------------------------------------------- + +// Create a CLASS_TYPE number with nb bits. +CLASS_TYPE::CLASS_TYPE( int nb ) : + sc_value_base(), sgn(), nbits(), ndigits(), digit() +{ + sgn = default_sign(); + if( nb > 0 ) { + nbits = num_bits( nb ); + } else { + char msg[BUFSIZ]; + std::sprintf( msg, "%s::%s( int nb ) : nb = %d is not valid", + CLASS_TYPE_STR, CLASS_TYPE_STR, nb ); + SC_REPORT_ERROR( sc_core::SC_ID_INIT_FAILED_, msg ); + } + ndigits = DIV_CEIL(nbits); +#ifdef SC_MAX_NBITS + test_bound(nb); +#else + digit = new sc_digit[ndigits]; +#endif + makezero(); +} + + +// Create a copy of v with sgn s. v is of the same type. +CLASS_TYPE::CLASS_TYPE(const CLASS_TYPE& v) : + sc_value_base(v), sgn(v.sgn), nbits(v.nbits), ndigits(v.ndigits), digit() +{ +#ifndef SC_MAX_NBITS + digit = new sc_digit[ndigits]; +#endif + + vec_copy(ndigits, digit, v.digit); +} + + +// Create a copy of v where v is of the different type. +CLASS_TYPE::CLASS_TYPE(const OTHER_CLASS_TYPE& v) : + sc_value_base(v), sgn(v.sgn), nbits(num_bits(v.nbits)), ndigits(), digit() +{ +#if (IF_SC_SIGNED == 1) + ndigits = v.ndigits; +#else + ndigits = DIV_CEIL(nbits); +#endif + +#ifndef SC_MAX_NBITS + digit = new sc_digit[ndigits]; +#endif + + copy_digits(v.nbits, v.ndigits, v.digit); +} + +// Create a copy of v where v is an sign-less instance. +CLASS_TYPE::CLASS_TYPE(const sc_bv_base& v) : + sc_value_base(), sgn(), nbits(), ndigits(), digit() +{ + int nb = v.length(); + sgn = default_sign(); + if( nb > 0 ) { + nbits = num_bits( nb ); + } else { + char msg[BUFSIZ]; + std::sprintf( msg, "%s::%s( sc_bv_base ) : nb = %d is not valid", + CLASS_TYPE_STR, CLASS_TYPE_STR, nb ); + SC_REPORT_ERROR( sc_core::SC_ID_INIT_FAILED_, msg ); + } + ndigits = DIV_CEIL(nbits); +# ifdef SC_MAX_NBITS + test_bound(nb); +# else + digit = new sc_digit[ndigits]; +# endif + makezero(); + *this = v; +} + +CLASS_TYPE::CLASS_TYPE(const sc_lv_base& v) : + sc_value_base(), sgn(), nbits(), ndigits(), digit() +{ + int nb = v.length(); + sgn = default_sign(); + if( nb > 0 ) { + nbits = num_bits( nb ); + } else { + char msg[BUFSIZ]; + std::sprintf( msg, "%s::%s( sc_lv_base ) : nb = %d is not valid", + CLASS_TYPE_STR, CLASS_TYPE_STR, nb ); + SC_REPORT_ERROR( sc_core::SC_ID_INIT_FAILED_, msg ); + } + ndigits = DIV_CEIL(nbits); +# ifdef SC_MAX_NBITS + test_bound(nb); +# else + digit = new sc_digit[ndigits]; +# endif + makezero(); + *this = v; +} + +CLASS_TYPE::CLASS_TYPE(const sc_int_subref_r& v) : + sc_value_base(v), sgn(), nbits(), ndigits(), digit() +{ + int nb = v.length(); + sgn = default_sign(); + if( nb > 0 ) { + nbits = num_bits( nb ); + } else { + char msg[BUFSIZ]; + std::sprintf( msg, "%s::%s( sc_int_subref ) : nb = %d is not valid", + CLASS_TYPE_STR, CLASS_TYPE_STR, nb ); + SC_REPORT_ERROR( sc_core::SC_ID_INIT_FAILED_, msg ); + } + ndigits = DIV_CEIL(nbits); +# ifdef SC_MAX_NBITS + test_bound(nb); +# else + digit = new sc_digit[ndigits]; +# endif + makezero(); + *this = v.to_uint64(); +} + +CLASS_TYPE::CLASS_TYPE(const sc_uint_subref_r& v) : + sc_value_base(v), sgn(), nbits(), ndigits(), digit() +{ + int nb = v.length(); + sgn = default_sign(); + if( nb > 0 ) { + nbits = num_bits( nb ); + } else { + char msg[BUFSIZ]; + std::sprintf( msg, "%s::%s( sc_uint_subref ) : nb = %d is not valid", + CLASS_TYPE_STR, CLASS_TYPE_STR, nb ); + SC_REPORT_ERROR( sc_core::SC_ID_INIT_FAILED_, msg ); + } + ndigits = DIV_CEIL(nbits); +# ifdef SC_MAX_NBITS + test_bound(nb); +# else + digit = new sc_digit[ndigits]; +# endif + makezero(); + *this = v.to_uint64(); +} + +CLASS_TYPE::CLASS_TYPE(const sc_signed_subref_r& v) : + sc_value_base(v), sgn(), nbits(), ndigits(), digit() +{ + int nb = v.length(); + sgn = default_sign(); + if( nb > 0 ) { + nbits = num_bits( nb ); + } else { + char msg[BUFSIZ]; + std::sprintf( msg, "%s::%s( sc_signed_subref ) : nb = %d is not valid", + CLASS_TYPE_STR, CLASS_TYPE_STR, nb ); + SC_REPORT_ERROR( sc_core::SC_ID_INIT_FAILED_, msg ); + } + ndigits = DIV_CEIL(nbits); +# ifdef SC_MAX_NBITS + test_bound(nb); +# else + digit = new sc_digit[ndigits]; +# endif + makezero(); + *this = sc_unsigned(v.m_obj_p, v.m_left, v.m_right); +} + +CLASS_TYPE::CLASS_TYPE(const sc_unsigned_subref_r& v) : + sc_value_base(v), sgn(), nbits(), ndigits(), digit() +{ + int nb = v.length(); + sgn = default_sign(); + if( nb > 0 ) { + nbits = num_bits( nb ); + } else { + char msg[BUFSIZ]; + std::sprintf( msg, "%s::%s( sc_unsigned_subref ) : nb = %d is not valid", + CLASS_TYPE_STR, CLASS_TYPE_STR, nb ); + SC_REPORT_ERROR( sc_core::SC_ID_INIT_FAILED_, msg ); + } + ndigits = DIV_CEIL(nbits); +# ifdef SC_MAX_NBITS + test_bound(nb); +# else + digit = new sc_digit[ndigits]; +# endif + makezero(); + *this = sc_unsigned(v.m_obj_p, v.m_left, v.m_right); +} + +// ---------------------------------------------------------------------------- +// SECTION: Public members - Concatenation support. +// ---------------------------------------------------------------------------- + + +// ---------------------------------------------------------------------------- +// SECTION: Public members - Assignment operators. +// ---------------------------------------------------------------------------- + +// Assignment from v of the same type. +const CLASS_TYPE& +CLASS_TYPE::operator=(const CLASS_TYPE& v) +{ + if (this != &v) { + + sgn = v.sgn; + + if (sgn == SC_ZERO) + vec_zero(ndigits, digit); + + else + copy_digits(v.nbits, v.ndigits, v.digit); + + } + + return *this; +} + + +// Assignment from v of the different type. +const CLASS_TYPE& +CLASS_TYPE::operator=(const OTHER_CLASS_TYPE& v) +{ + sgn = v.sgn; + + if (sgn == SC_ZERO) + vec_zero(ndigits, digit); + + else + copy_digits(v.nbits, v.ndigits, v.digit); + + return *this; +} + + +// Assignment from an sc_unsigned_subref_r +const CLASS_TYPE& +CLASS_TYPE::operator=(const sc_unsigned_subref_r& v) +{ + return operator=(sc_unsigned(v)); +} + + +// Assignment from an sc_signed_subref_r +const CLASS_TYPE& +CLASS_TYPE::operator=(const sc_signed_subref_r& v) +{ + return operator=(sc_unsigned(v)); +} + + +// ---------------------------------------------------------------------------- +// SECTION: Input and output operators +// ---------------------------------------------------------------------------- + +void +CLASS_TYPE::scan( ::std::istream& is ) +{ + std::string s; + is >> s; + *this = s.c_str(); +} + + +// ---------------------------------------------------------------------------- +// SECTION: PLUS operators: +, +=, ++ +// ---------------------------------------------------------------------------- + +// Cases to consider when computing u + v: +// 1. 0 + v = v +// 2. u + 0 = u +// 3. if sgn(u) == sgn(v) +// 3.1 u + v = +(u + v) = sgn(u) * (u + v) +// 3.2 (-u) + (-v) = -(u + v) = sgn(u) * (u + v) +// 4. if sgn(u) != sgn(v) +// 4.1 u + (-v) = u - v = sgn(u) * (u - v) +// 4.2 (-u) + v = -(u - v) ==> sgn(u) * (u - v) +// +// Specialization of above cases for computing ++u or u++: +// 1. 0 + 1 = 1 +// 3. u + 1 = u + 1 = sgn(u) * (u + 1) +// 4. (-u) + 1 = -(u - 1) = sgn(u) * (u - 1) + +const CLASS_TYPE& +CLASS_TYPE::operator+=(const CLASS_TYPE& v) +{ + // u = *this + + if (sgn == SC_ZERO) // case 1 + return (*this = v); + + if (v.sgn == SC_ZERO) // case 2 + return *this; + + // cases 3 and 4 + add_on_help(sgn, nbits, ndigits, digit, + v.sgn, v.nbits, v.ndigits, v.digit); + + convert_SM_to_2C_to_SM(); + + return *this; +} + + +const CLASS_TYPE& +CLASS_TYPE::operator+=(const OTHER_CLASS_TYPE& v) +{ + // u = *this + + if (sgn == SC_ZERO) // case 1 + return (*this = v); + + if (v.sgn == SC_ZERO) // case 2 + return *this; + + // cases 3 and 4 + add_on_help(sgn, nbits, ndigits, digit, + v.sgn, v.nbits, v.ndigits, v.digit); + + convert_SM_to_2C_to_SM(); + + return *this; +} + + +CLASS_TYPE& +CLASS_TYPE::operator++() // prefix +{ + *this = *this + 1; + return *this; +} + + +const CLASS_TYPE +CLASS_TYPE::operator++(int) // postfix +{ + // Copy digit into d. + +#ifdef SC_MAX_NBITS + sc_digit d[MAX_NDIGITS]; +#else + sc_digit *d = new sc_digit[ndigits]; +#endif + + small_type s = sgn; + + vec_copy(ndigits, d, digit); + + *this = *this + 1; + + return CLASS_TYPE(s, nbits, ndigits, d); +} + + +const CLASS_TYPE& +CLASS_TYPE::operator+=(int64 v) +{ + // u = *this + + if (sgn == SC_ZERO) // case 1 + return (*this = v); + + if (v == 0) // case 2 + return *this; + + CONVERT_INT64(v); + + // cases 3 and 4 + add_on_help(sgn, nbits, ndigits, digit, + vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd); + + convert_SM_to_2C_to_SM(); + + return *this; +} + + +const CLASS_TYPE& +CLASS_TYPE::operator+=(uint64 v) +{ + // u = *this + + if (sgn == SC_ZERO) // case 1 + return (*this = v); + + if (v == 0) // case 2 + return *this; + + CONVERT_INT64(v); + + // cases 3 and 4 + add_on_help(sgn, nbits, ndigits, digit, + vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd); + + convert_SM_to_2C_to_SM(); + + return *this; +} + + +const CLASS_TYPE& +CLASS_TYPE::operator+=(long v) +{ + // u = *this + + if (sgn == SC_ZERO) // case 1 + return (*this = v); + + if (v == 0) // case 2 + return *this; + + CONVERT_LONG(v); + + // cases 3 and 4 + add_on_help(sgn, nbits, ndigits, digit, + vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd); + + convert_SM_to_2C_to_SM(); + + return *this; +} + + +const CLASS_TYPE& +CLASS_TYPE::operator+=(unsigned long v) +{ + // u = *this + + if (sgn == SC_ZERO) // case 1 + return (*this = v); + + if (v == 0) // case 2 + return *this; + + CONVERT_LONG(v); + + // cases 3 and 4 + add_on_help(sgn, nbits, ndigits, digit, + vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd); + + convert_SM_to_2C_to_SM(); + + return *this; +} + + +// ---------------------------------------------------------------------------- +// SECTION: MINUS operators: -, -=, -- +// ---------------------------------------------------------------------------- + +// Cases to consider when computing u + v: +// 1. u - 0 = u +// 2. 0 - v = -v +// 3. if sgn(u) != sgn(v) +// 3.1 u - (-v) = u + v = sgn(u) * (u + v) +// 3.2 (-u) - v = -(u + v) ==> sgn(u) * (u + v) +// 4. if sgn(u) == sgn(v) +// 4.1 u - v = +(u - v) = sgn(u) * (u - v) +// 4.2 (-u) - (-v) = -(u - v) = sgn(u) * (u - v) +// +// Specialization of above cases for computing --u or u--: +// 1. 0 - 1 = -1 +// 3. (-u) - 1 = -(u + 1) = sgn(u) * (u + 1) +// 4. u - 1 = u - 1 = sgn(u) * (u - 1) + +const CLASS_TYPE& +CLASS_TYPE::operator-=(const CLASS_TYPE& v) +{ + // u = *this + + if (v.sgn == SC_ZERO) // case 1 + return *this; + + if (sgn == SC_ZERO) { // case 2 + + sgn = -v.sgn; + copy_digits(v.nbits, v.ndigits, v.digit); + + } + else { + + // cases 3 and 4 + add_on_help(sgn, nbits, ndigits, digit, + -v.sgn, v.nbits, v.ndigits, v.digit); + + convert_SM_to_2C_to_SM(); + + } + + return *this; +} + + +const CLASS_TYPE& +CLASS_TYPE::operator-=(const OTHER_CLASS_TYPE& v) +{ + // u = *this + + if (v.sgn == SC_ZERO) // case 1 + return *this; + + if (sgn == SC_ZERO) { // case 2 + + sgn = -v.sgn; + copy_digits(v.nbits, v.ndigits, v.digit); + + } + else { + + // cases 3 and 4 + add_on_help(sgn, nbits, ndigits, digit, + -v.sgn, v.nbits, v.ndigits, v.digit); + + convert_SM_to_2C_to_SM(); + + } + + return *this; +} + + +CLASS_TYPE& +CLASS_TYPE::operator--() // prefix +{ + *this = *this - 1; + return *this; +} + + +const CLASS_TYPE +CLASS_TYPE::operator--(int) // postfix +{ + // Copy digit into d. + +#ifdef SC_MAX_NBITS + sc_digit d[MAX_NDIGITS]; +#else + sc_digit *d = new sc_digit[ndigits]; +#endif + + small_type s = sgn; + + vec_copy(ndigits, d, digit); + + *this = *this - 1; + + return CLASS_TYPE(s, nbits, ndigits, d); +} + + +const CLASS_TYPE& +CLASS_TYPE::operator-=(int64 v) +{ + // u = *this + + if (v == 0) // case 1 + return *this; + + if (sgn == SC_ZERO) // case 2 + return (*this = -v); + + CONVERT_INT64(v); + + // cases 3 and 4 + add_on_help(sgn, nbits, ndigits, digit, + -vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd); + + convert_SM_to_2C_to_SM(); + + return *this; +} + + +const CLASS_TYPE& +CLASS_TYPE::operator-=(uint64 v) +{ + // u = *this + + if (v == 0) // case 1 + return *this; + + int64 v2 = (int64) v; + + if (sgn == SC_ZERO) // case 2 + return (*this = -v2); + + CONVERT_INT64(v); + + // cases 3 and 4 + add_on_help(sgn, nbits, ndigits, digit, + -vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd); + + convert_SM_to_2C_to_SM(); + + return *this; +} + + +const CLASS_TYPE& +CLASS_TYPE::operator-=(long v) +{ + // u = *this + + if (v == 0) // case 1 + return *this; + + if (sgn == SC_ZERO) // case 2 + return (*this = -v); + + CONVERT_LONG(v); + + // cases 3 and 4 + add_on_help(sgn, nbits, ndigits, digit, + -vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd); + + convert_SM_to_2C_to_SM(); + + return *this; +} + + +const CLASS_TYPE& +CLASS_TYPE::operator-=(unsigned long v) +{ + // u = *this + + if (v == 0) // case 1 + return *this; + + long v2 = (long) v; + + if (sgn == SC_ZERO) // case 2 + return (*this = -v2); + + CONVERT_LONG(v); + + // cases 3 and 4 + add_on_help(sgn, nbits, ndigits, digit, + -vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd); + + convert_SM_to_2C_to_SM(); + + return *this; +} + + +// ---------------------------------------------------------------------------- +// SECTION: MULTIPLICATION operators: *, *= +// ---------------------------------------------------------------------------- + +// Cases to consider when computing u * v: +// 1. u * 0 = 0 * v = 0 +// 2. 1 * v = v and -1 * v = -v +// 3. u * 1 = u and u * -1 = -u +// 4. u * v = u * v + +const CLASS_TYPE& +CLASS_TYPE::operator*=(const CLASS_TYPE& v) +{ + // u = *this + + sgn = mul_signs(sgn, v.sgn); + + if (sgn == SC_ZERO) // case 1 + vec_zero(ndigits, digit); + + else + // cases 2-4 + MUL_ON_HELPER(sgn, nbits, ndigits, digit, + v.nbits, v.ndigits, v.digit); + + return *this; +} + + +const CLASS_TYPE& +CLASS_TYPE::operator*=(const OTHER_CLASS_TYPE& v) +{ + // u = *this + + sgn = mul_signs(sgn, v.sgn); + + if (sgn == SC_ZERO) // case 1 + vec_zero(ndigits, digit); + + else + // cases 2-4 + MUL_ON_HELPER(sgn, nbits, ndigits, digit, + v.nbits, v.ndigits, v.digit); + + return *this; +} + + +const CLASS_TYPE& +CLASS_TYPE::operator*=(int64 v) +{ + // u = *this + + sgn = mul_signs(sgn, get_sign(v)); + + if (sgn == SC_ZERO) // case 1 + vec_zero(ndigits, digit); + + else { // cases 2-4 + + CONVERT_INT64_2(v); + + MUL_ON_HELPER(sgn, nbits, ndigits, digit, + BITS_PER_UINT64, DIGITS_PER_UINT64, vd); + + } + + return *this; +} + + +const CLASS_TYPE& +CLASS_TYPE::operator*=(uint64 v) +{ + // u = *this + + sgn = mul_signs(sgn, get_sign(v)); + + if (sgn == SC_ZERO) // case 1 + vec_zero(ndigits, digit); + + else { // cases 2-4 + + CONVERT_INT64_2(v); + + MUL_ON_HELPER(sgn, nbits, ndigits, digit, + BITS_PER_UINT64, DIGITS_PER_UINT64, vd); + + } + + return *this; +} + + +const CLASS_TYPE& +CLASS_TYPE::operator*=(long v) +{ + // u = *this + + sgn = mul_signs(sgn, get_sign(v)); + + if (sgn == SC_ZERO) // case 1 + vec_zero(ndigits, digit); + + else { // cases 2-4 + + CONVERT_LONG_2(v); + + MUL_ON_HELPER(sgn, nbits, ndigits, digit, + BITS_PER_ULONG, DIGITS_PER_ULONG, vd); + + } + + return *this; +} + + +const CLASS_TYPE& +CLASS_TYPE::operator*=(unsigned long v) +{ + // u = *this + + sgn = mul_signs(sgn, get_sign(v)); + + if (sgn == SC_ZERO) // case 1 + vec_zero(ndigits, digit); + + else { // cases 2-4 + + CONVERT_LONG_2(v); + + MUL_ON_HELPER(sgn, nbits, ndigits, digit, + BITS_PER_ULONG, DIGITS_PER_ULONG, vd); + + } + + return *this; +} + + +// ---------------------------------------------------------------------------- +// SECTION: DIVISION operators: /, /= +// ---------------------------------------------------------------------------- + +// Cases to consider when finding the quotient q = floor(u/v): +// Note that u = q * v + r for r < q. +// 1. 0 / 0 or u / 0 => error +// 2. 0 / v => 0 = 0 * v + 0 +// 3. u / v && u = v => u = 1 * u + 0 - u or v can be 1 or -1 +// 4. u / v && u < v => u = 0 * v + u - u can be 1 or -1 +// 5. u / v && u > v => u = q * v + r - v can be 1 or -1 + +const CLASS_TYPE& +CLASS_TYPE::operator/=(const CLASS_TYPE& v) +{ + sgn = mul_signs(sgn, v.sgn); + + if (sgn == SC_ZERO) { + + div_by_zero(v.sgn); // case 1 + vec_zero(ndigits, digit); // case 2 + + } + else // other cases + DIV_ON_HELPER(sgn, nbits, ndigits, digit, + v.nbits, v.ndigits, v.digit); + + return *this; +} + + +const CLASS_TYPE& +CLASS_TYPE::operator/=(const OTHER_CLASS_TYPE& v) +{ + sgn = mul_signs(sgn, v.sgn); + + if (sgn == SC_ZERO) { + + div_by_zero(v.sgn); // case 1 + vec_zero(ndigits, digit); // case 2 + + } + else // other cases + DIV_ON_HELPER(sgn, nbits, ndigits, digit, + v.nbits, v.ndigits, v.digit); + + return *this; +} + + +const CLASS_TYPE& +CLASS_TYPE::operator/=(int64 v) +{ + // u = *this + + sgn = mul_signs(sgn, get_sign(v)); + + if (sgn == SC_ZERO) { + + div_by_zero(v); // case 1 + vec_zero(ndigits, digit); // case 2 + + } + else { + + CONVERT_INT64_2(v); + + // other cases + DIV_ON_HELPER(sgn, nbits, ndigits, digit, + BITS_PER_UINT64, DIGITS_PER_UINT64, vd); + + } + + return *this; +} + + +const CLASS_TYPE& +CLASS_TYPE::operator/=(uint64 v) +{ + // u = *this + + sgn = mul_signs(sgn, get_sign(v)); + + if (sgn == SC_ZERO) { + + div_by_zero(v); // case 1 + vec_zero(ndigits, digit); // case 2 + + } + else { + + CONVERT_INT64_2(v); + + // other cases + DIV_ON_HELPER(sgn, nbits, ndigits, digit, + BITS_PER_UINT64, DIGITS_PER_UINT64, vd); + + } + + return *this; +} + + +const CLASS_TYPE& +CLASS_TYPE::operator/=(long v) +{ + // u = *this + + sgn = mul_signs(sgn, get_sign(v)); + + if (sgn == SC_ZERO) { + + div_by_zero(v); // case 1 + vec_zero(ndigits, digit); // case 2 + + } + else { + + CONVERT_LONG_2(v); + + // other cases + DIV_ON_HELPER(sgn, nbits, ndigits, digit, + BITS_PER_ULONG, DIGITS_PER_ULONG, vd); + + } + + return *this; +} + + +const CLASS_TYPE& +CLASS_TYPE::operator/=(unsigned long v) +{ + // u = *this + + sgn = mul_signs(sgn, get_sign(v)); + + if (sgn == SC_ZERO) { + + div_by_zero(v); // case 1 + vec_zero(ndigits, digit); // case 2 + + } + else { + + CONVERT_LONG_2(v); + + // other cases + DIV_ON_HELPER(sgn, nbits, ndigits, digit, + BITS_PER_ULONG, DIGITS_PER_ULONG, vd); + + } + + return *this; +} + + +// ---------------------------------------------------------------------------- +// SECTION: MOD operators: %, %=. +// ---------------------------------------------------------------------------- + +// Cases to consider when finding the remainder r = u % v: +// Note that u = q * v + r for r < q. +// 1. 0 % 0 or u % 0 => error +// 2. 0 % v => 0 = 0 * v + 0 +// 3. u % v && u = v => u = 1 * u + 0 - u or v can be 1 or -1 +// 4. u % v && u < v => u = 0 * v + u - u can be 1 or -1 +// 5. u % v && u > v => u = q * v + r - v can be 1 or -1 + +const CLASS_TYPE& +CLASS_TYPE::operator%=(const CLASS_TYPE& v) +{ + if ((sgn == SC_ZERO) || (v.sgn == SC_ZERO)) { + + div_by_zero(v.sgn); // case 1 + vec_zero(ndigits, digit); // case 2 + + } + else // other cases + MOD_ON_HELPER(sgn, nbits, ndigits, digit, + v.nbits, v.ndigits, v.digit); + + return *this; +} + + +const CLASS_TYPE& +CLASS_TYPE::operator%=(const OTHER_CLASS_TYPE& v) +{ + if ((sgn == SC_ZERO) || (v.sgn == SC_ZERO)) { + + div_by_zero(v.sgn); // case 1 + vec_zero(ndigits, digit); // case 2 + + } + else // other cases + MOD_ON_HELPER(sgn, nbits, ndigits, digit, + v.nbits, v.ndigits, v.digit); + + return *this; +} + + +const CLASS_TYPE& +CLASS_TYPE::operator%=(int64 v) +{ + small_type vs = get_sign(v); + + if ((sgn == SC_ZERO) || (vs == SC_ZERO)) { + + div_by_zero(v); // case 1 + vec_zero(ndigits, digit); // case 2 + + } + else { + + CONVERT_INT64_2(v); + + // other cases + MOD_ON_HELPER(sgn, nbits, ndigits, digit, + BITS_PER_UINT64, DIGITS_PER_UINT64, vd); + + } + + return *this; +} + + +const CLASS_TYPE& +CLASS_TYPE::operator%=(uint64 v) +{ + if ((sgn == SC_ZERO) || (v == 0)) { + + div_by_zero(v); // case 1 + vec_zero(ndigits, digit); // case 2 + + } + else { + + CONVERT_INT64_2(v); + + // other cases + MOD_ON_HELPER(sgn, nbits, ndigits, digit, + BITS_PER_UINT64, DIGITS_PER_UINT64, vd); + + } + + return *this; +} + + +const CLASS_TYPE& +CLASS_TYPE::operator%=(long v) +{ + small_type vs = get_sign(v); + + if ((sgn == SC_ZERO) || (vs == SC_ZERO)) { + + div_by_zero(v); // case 1 + vec_zero(ndigits, digit); // case 2 + + } + else { + + CONVERT_LONG_2(v); + + // other cases + MOD_ON_HELPER(sgn, nbits, ndigits, digit, + BITS_PER_ULONG, DIGITS_PER_ULONG, vd); + + } + + return *this; +} + + +const CLASS_TYPE& +CLASS_TYPE::operator%=(unsigned long v) +{ + if ((sgn == SC_ZERO) || (v == 0)) { + + div_by_zero(v); // case 1 + vec_zero(ndigits, digit); // case 2 + + } + else { + + CONVERT_LONG_2(v); + + // other cases + MOD_ON_HELPER(sgn, nbits, ndigits, digit, + BITS_PER_ULONG, DIGITS_PER_ULONG, vd); + + } + + return *this; +} + + +// ---------------------------------------------------------------------------- +// SECTION: Bitwise AND operators: &, &= +// ---------------------------------------------------------------------------- + +// Cases to consider when computing u & v: +// 1. u & 0 = 0 & v = 0 +// 2. u & v => sgn = + +// 3. (-u) & (-v) => sgn = - +// 4. u & (-v) => sgn = + +// 5. (-u) & v => sgn = + + +const CLASS_TYPE& +CLASS_TYPE::operator&=(const CLASS_TYPE& v) +{ + // u = *this + + if ((sgn == SC_ZERO) || (v.sgn == SC_ZERO)) // case 1 + makezero(); + + else { // other cases + + and_on_help(sgn, nbits, ndigits, digit, + v.sgn, v.nbits, v.ndigits, v.digit); + + convert_2C_to_SM(); + + } + + return *this; +} + + +const CLASS_TYPE& +CLASS_TYPE::operator&=(const OTHER_CLASS_TYPE& v) +{ + // u = *this + + if ((sgn == SC_ZERO) || (v.sgn == SC_ZERO)) // case 1 + makezero(); + + else { // other cases + + and_on_help(sgn, nbits, ndigits, digit, + v.sgn, v.nbits, v.ndigits, v.digit); + + convert_2C_to_SM(); + + } + + return *this; +} + + +const CLASS_TYPE& +CLASS_TYPE::operator&=(int64 v) +{ + // u = *this + + if ((sgn == SC_ZERO) || (v == 0)) // case 1 + makezero(); + + else { // other cases + + CONVERT_INT64(v); + + and_on_help(sgn, nbits, ndigits, digit, + vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd); + + convert_2C_to_SM(); + + } + + return *this; +} + + +const CLASS_TYPE& +CLASS_TYPE::operator&=(uint64 v) +{ + // u = *this + + if ((sgn == SC_ZERO) || (v == 0)) // case 1 + makezero(); + + else { // other cases + + CONVERT_INT64(v); + + and_on_help(sgn, nbits, ndigits, digit, + vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd); + + convert_2C_to_SM(); + + } + + return *this; +} + + +const CLASS_TYPE& +CLASS_TYPE::operator&=(long v) +{ + // u = *this + + if ((sgn == SC_ZERO) || (v == 0)) // case 1 + makezero(); + + else { // other cases + + CONVERT_LONG(v); + + and_on_help(sgn, nbits, ndigits, digit, + vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd); + + convert_2C_to_SM(); + + } + + return *this; +} + + +const CLASS_TYPE& +CLASS_TYPE::operator&=(unsigned long v) +{ + // u = *this + + if ((sgn == SC_ZERO) || (v == 0)) // case 1 + makezero(); + + else { // other cases + + CONVERT_LONG(v); + + and_on_help(sgn, nbits, ndigits, digit, + vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd); + + convert_2C_to_SM(); + + } + + return *this; +} + + +// ---------------------------------------------------------------------------- +// SECTION: Bitwise OR operators: |, |= +// ---------------------------------------------------------------------------- + +// Cases to consider when computing u | v: +// 1. u | 0 = u +// 2. 0 | v = v +// 3. u | v => sgn = + +// 4. (-u) | (-v) => sgn = - +// 5. u | (-v) => sgn = - +// 6. (-u) | v => sgn = - + +const CLASS_TYPE& +CLASS_TYPE::operator|=(const CLASS_TYPE& v) +{ + if (v.sgn == SC_ZERO) // case 1 + return *this; + + if (sgn == SC_ZERO) // case 2 + return (*this = v); + + // other cases + or_on_help(sgn, nbits, ndigits, digit, + v.sgn, v.nbits, v.ndigits, v.digit); + + convert_2C_to_SM(); + + return *this; +} + + +const CLASS_TYPE& +CLASS_TYPE::operator|=(const OTHER_CLASS_TYPE& v) +{ + if (v.sgn == SC_ZERO) // case 1 + return *this; + + if (sgn == SC_ZERO) // case 2 + return (*this = v); + + // other cases + or_on_help(sgn, nbits, ndigits, digit, + v.sgn, v.nbits, v.ndigits, v.digit); + + convert_2C_to_SM(); + + return *this; +} + + +const CLASS_TYPE& +CLASS_TYPE::operator|=(int64 v) +{ + if (v == 0) // case 1 + return *this; + + if (sgn == SC_ZERO) // case 2 + return (*this = v); + + // other cases + + CONVERT_INT64(v); + + or_on_help(sgn, nbits, ndigits, digit, + vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd); + + convert_2C_to_SM(); + + return *this; +} + + +const CLASS_TYPE& +CLASS_TYPE::operator|=(uint64 v) +{ + if (v == 0) // case 1 + return *this; + + if (sgn == SC_ZERO) // case 2 + return (*this = v); + + // other cases + + CONVERT_INT64(v); + + or_on_help(sgn, nbits, ndigits, digit, + vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd); + + convert_2C_to_SM(); + + return *this; +} + + +const CLASS_TYPE& +CLASS_TYPE::operator|=(long v) +{ + if (v == 0) // case 1 + return *this; + + if (sgn == SC_ZERO) // case 2 + return (*this = v); + + // other cases + + CONVERT_LONG(v); + + or_on_help(sgn, nbits, ndigits, digit, + vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd); + + convert_2C_to_SM(); + + return *this; +} + + +const CLASS_TYPE& +CLASS_TYPE::operator|=(unsigned long v) +{ + if (v == 0) // case 1 + return *this; + + if (sgn == SC_ZERO) // case 2 + return (*this = v); + + // other cases + + CONVERT_LONG(v); + + or_on_help(sgn, nbits, ndigits, digit, + vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd); + + convert_2C_to_SM(); + + return *this; +} + + +// ---------------------------------------------------------------------------- +// SECTION: Bitwise XOR operators: ^, ^= +// ---------------------------------------------------------------------------- + +// Cases to consider when computing u ^ v: +// Note that u ^ v = (~u & v) | (u & ~v). +// 1. u ^ 0 = u +// 2. 0 ^ v = v +// 3. u ^ v => sgn = + +// 4. (-u) ^ (-v) => sgn = - +// 5. u ^ (-v) => sgn = - +// 6. (-u) ^ v => sgn = + + +const CLASS_TYPE& +CLASS_TYPE::operator^=(const CLASS_TYPE& v) +{ + // u = *this + + if (v.sgn == SC_ZERO) // case 1 + return *this; + + if (sgn == SC_ZERO) // case 2 + return (*this = v); + + // other cases + xor_on_help(sgn, nbits, ndigits, digit, + v.sgn, v.nbits, v.ndigits, v.digit); + + convert_2C_to_SM(); + + return *this; +} + + +const CLASS_TYPE& +CLASS_TYPE::operator^=(const OTHER_CLASS_TYPE& v) +{ + // u = *this + + if (v.sgn == SC_ZERO) // case 1 + return *this; + + if (sgn == SC_ZERO) // case 2 + return (*this = v); + + // other cases + xor_on_help(sgn, nbits, ndigits, digit, + v.sgn, v.nbits, v.ndigits, v.digit); + + convert_2C_to_SM(); + + return *this; +} + + +const CLASS_TYPE& +CLASS_TYPE::operator^=(int64 v) +{ + if (v == 0) // case 1 + return *this; + + if (sgn == SC_ZERO) // case 2 + return (*this = v); + + // other cases + + CONVERT_INT64(v); + + xor_on_help(sgn, nbits, ndigits, digit, + vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd); + + convert_2C_to_SM(); + + return *this; +} + + +const CLASS_TYPE& +CLASS_TYPE::operator^=(uint64 v) +{ + if (v == 0) // case 1 + return *this; + + if (sgn == SC_ZERO) // case 2 + return (*this = v); + + // other cases + + CONVERT_INT64(v); + + xor_on_help(sgn, nbits, ndigits, digit, + vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd); + + convert_2C_to_SM(); + + return *this; +} + + +const CLASS_TYPE& +CLASS_TYPE::operator^=(long v) +{ + if (v == 0) // case 1 + return *this; + + if (sgn == SC_ZERO) // case 2 + return (*this = v); + + // other cases + + CONVERT_LONG(v); + + xor_on_help(sgn, nbits, ndigits, digit, + vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd); + + convert_2C_to_SM(); + + return *this; +} + + +const CLASS_TYPE& +CLASS_TYPE::operator^=(unsigned long v) +{ + if (v == 0) // case 1 + return *this; + + if (sgn == SC_ZERO) // case 2 + return (*this = v); + + // other cases + + CONVERT_LONG(v); + + xor_on_help(sgn, nbits, ndigits, digit, + vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd); + + convert_2C_to_SM(); + + return *this; +} + + +// ---------------------------------------------------------------------------- +// SECTION: Bitwise NOT operator: ~ +// ---------------------------------------------------------------------------- + +CLASS_TYPE +operator~(const CLASS_TYPE& u) +{ + small_type s = u.sgn; + + if (s == SC_ZERO) { + + sc_digit d = 1; + return CLASS_TYPE(SC_NEG, u.nbits, 1, &d, false); + + } + + int nd = u.ndigits; + +#ifdef SC_MAX_NBITS + sc_digit d[MAX_NDIGITS]; +#else + sc_digit *d = new sc_digit[nd]; +#endif + + vec_copy(nd, d, u.digit); + + if (s == SC_POS) { + + s = SC_NEG; + vec_add_small_on(nd, d, 1); + + } + else { + + s = SC_POS; + vec_sub_small_on(nd, d, 1); + + if (check_for_zero(nd, d)) + s = SC_ZERO; + + } + + return CLASS_TYPE(s, u.nbits, nd, d); +} + + +// ---------------------------------------------------------------------------- +// SECTION: LEFT SHIFT operators: <<, <<= +// ---------------------------------------------------------------------------- + +CLASS_TYPE +operator<<(const CLASS_TYPE& u, const CLASS_TYPE& v) +{ + if (v.sgn == SC_ZERO) + return CLASS_TYPE(u); + +#ifdef SC_SIGNED + if (v.sgn == SC_NEG) + return CLASS_TYPE(u); +#endif + + return operator<<(u, v.to_ulong()); +} + + +const CLASS_TYPE& +CLASS_TYPE::operator<<=(const CLASS_TYPE& v) +{ + if (v.sgn == SC_ZERO) + return *this; + +#ifdef SC_SIGNED + if (v.sgn == SC_NEG) + return *this; +#endif + + return operator<<=(v.to_ulong()); +} + + +const CLASS_TYPE& +CLASS_TYPE::operator<<=(const OTHER_CLASS_TYPE& v) +{ + if (v.sgn == SC_ZERO) + return *this; + +#ifdef SC_UNSIGNED + if (v.sgn == SC_NEG) + return *this; +#endif + + return operator<<=(v.to_ulong()); +} + + +CLASS_TYPE +operator<<(const CLASS_TYPE& u, int64 v) +{ + if (v <= 0) + return CLASS_TYPE(u); + + return operator<<(u, (unsigned long) v); +} + + +CLASS_TYPE +operator<<(const CLASS_TYPE& u, uint64 v) +{ + if (v == 0) + return CLASS_TYPE(u); + + return operator<<(u, (unsigned long) v); +} + + +const CLASS_TYPE& +CLASS_TYPE::operator<<=(int64 v) +{ + if (v <= 0) + return *this; + + return operator<<=((unsigned long) v); +} + + +const CLASS_TYPE& +CLASS_TYPE::operator<<=(uint64 v) +{ + if (v == 0) + return *this; + + return operator<<=((unsigned long) v); +} + + +CLASS_TYPE +operator<<(const CLASS_TYPE& u, long v) +{ + if (v <= 0) + return CLASS_TYPE(u); + + return operator<<(u, (unsigned long) v); +} + +CLASS_TYPE +operator<<(const CLASS_TYPE& u, unsigned long v) +{ + if (v == 0) + return CLASS_TYPE(u); + + if (u.sgn == SC_ZERO) + return CLASS_TYPE(u); + + int nb = u.nbits + v; + int nd = DIV_CEIL(nb); + +#ifdef SC_MAX_NBITS + test_bound(nb); + sc_digit d[MAX_NDIGITS]; +#else + sc_digit *d = new sc_digit[nd]; +#endif + + vec_copy_and_zero(nd, d, u.ndigits, u.digit); + + convert_SM_to_2C(u.sgn, nd, d); + + vec_shift_left(nd, d, v); + + small_type s = convert_signed_2C_to_SM(nb, nd, d); + + return CLASS_TYPE(s, nb, nd, d); +} + + +const CLASS_TYPE& +CLASS_TYPE::operator<<=(long v) +{ + if (v <= 0) + return *this; + + return operator<<=((unsigned long) v); +} + + +const CLASS_TYPE& +CLASS_TYPE::operator<<=(unsigned long v) +{ + if (v == 0) + return *this; + + if (sgn == SC_ZERO) + return *this; + + convert_SM_to_2C(); + + vec_shift_left(ndigits, digit, v); + + convert_2C_to_SM(); + + return *this; +} + + +// ---------------------------------------------------------------------------- +// SECTION: RIGHT SHIFT operators: >>, >>= +// ---------------------------------------------------------------------------- + +CLASS_TYPE +operator>>(const CLASS_TYPE& u, const CLASS_TYPE& v) +{ + if (v.sgn == SC_ZERO) + return CLASS_TYPE(u); + +#ifdef SC_SIGNED + if (v.sgn == SC_NEG) + return CLASS_TYPE(u); +#endif + + return operator>>(u, v.to_long()); +} + + +const CLASS_TYPE& +CLASS_TYPE::operator>>=(const CLASS_TYPE& v) +{ + if (v.sgn == SC_ZERO) + return *this; + +#ifdef SC_SIGNED + if (v.sgn == SC_NEG) + return *this; +#endif + + return operator>>=(v.to_long()); +} + + +const CLASS_TYPE& +CLASS_TYPE::operator>>=(const OTHER_CLASS_TYPE& v) +{ + if (v.sgn == SC_ZERO) + return *this; + +#ifdef SC_UNSIGNED + if (v.sgn == SC_NEG) + return *this; +#endif + + return operator>>=(v.to_ulong()); +} + + +CLASS_TYPE +operator>>(const CLASS_TYPE& u, int64 v) +{ + if (v <= 0) + return CLASS_TYPE(u); + + return operator>>(u, (unsigned long) v); +} + + +CLASS_TYPE +operator>>(const CLASS_TYPE& u, uint64 v) +{ + if (v == 0) + return CLASS_TYPE(u); + + return operator>>(u, (unsigned long) v); +} + +const CLASS_TYPE& +CLASS_TYPE::operator>>=(int64 v) +{ + if (v <= 0) + return *this; + + return operator>>=((unsigned long) v); +} + + +const CLASS_TYPE& +CLASS_TYPE::operator>>=(uint64 v) +{ + if (v == 0) + return *this; + + return operator>>=((unsigned long) v); +} + + +CLASS_TYPE +operator>>(const CLASS_TYPE& u, long v) +{ + if (v <= 0) + return CLASS_TYPE(u); + + return operator>>(u, (unsigned long) v); +} + + +CLASS_TYPE +operator>>(const CLASS_TYPE& u, unsigned long v) +{ + if (v == 0) + return CLASS_TYPE(u); + + if (u.sgn == SC_ZERO) + return CLASS_TYPE(u); + + int nb = u.nbits; + int nd = u.ndigits; + +#ifdef SC_MAX_NBITS + sc_digit d[MAX_NDIGITS]; +#else + sc_digit *d = new sc_digit[nd]; +#endif + + vec_copy(nd, d, u.digit); + + convert_SM_to_2C(u.sgn, nd, d); + + if (u.sgn == SC_NEG) + vec_shift_right(nd, d, v, DIGIT_MASK); + else + vec_shift_right(nd, d, v, 0); + + small_type s = convert_signed_2C_to_SM(nb, nd, d); + + return CLASS_TYPE(s, nb, nd, d); +} + + +const CLASS_TYPE& +CLASS_TYPE::operator>>=(long v) +{ + if (v <= 0) + return *this; + + return operator>>=((unsigned long) v); +} + + +const CLASS_TYPE& +CLASS_TYPE::operator>>=(unsigned long v) +{ + if (v == 0) + return *this; + + if (sgn == SC_ZERO) + return *this; + + convert_SM_to_2C(); + + if (sgn == SC_NEG) + vec_shift_right(ndigits, digit, v, DIGIT_MASK); + else + vec_shift_right(ndigits, digit, v, 0); + + convert_2C_to_SM(); + + return *this; +} + + +// ---------------------------------------------------------------------------- +// SECTION: EQUAL TO operator: == +// ---------------------------------------------------------------------------- + +// Defined in the sc_signed.cpp and sc_unsigned.cpp. + + +// ---------------------------------------------------------------------------- +// SECTION: NOT_EQUAL operator: != +// ---------------------------------------------------------------------------- + +bool +operator!=(const CLASS_TYPE& u, const CLASS_TYPE& v) +{ + return (! operator==(u, v)); +} + + +bool +operator!=(const CLASS_TYPE& u, int64 v) +{ + return (! operator==(u, v)); +} + + +bool +operator!=(int64 u, const CLASS_TYPE& v) +{ + return (! operator==(u, v)); +} + + +bool +operator!=(const CLASS_TYPE& u, uint64 v) +{ + return (! operator==(u, v)); +} + + +bool +operator!=(uint64 u, const CLASS_TYPE& v) +{ + return (! operator==(u, v)); +} + + +bool +operator!=(const CLASS_TYPE& u, long v) +{ + return (! operator==(u, v)); +} + + +bool +operator!=(long u, const CLASS_TYPE& v) +{ + return (! operator==(u, v)); +} + + +bool +operator!=(const CLASS_TYPE& u, unsigned long v) +{ + return (! operator==(u, v)); +} + + +bool +operator!=(unsigned long u, const CLASS_TYPE& v) +{ + return (! operator==(u, v)); +} + + +// ---------------------------------------------------------------------------- +// SECTION: LESS THAN operator: < +// ---------------------------------------------------------------------------- + +// Defined in the sc_signed.cpp and sc_unsigned.cpp. + + +// ---------------------------------------------------------------------------- +// SECTION: LESS THAN or EQUAL operator: <= +// ---------------------------------------------------------------------------- + +bool +operator<=(const CLASS_TYPE& u, const CLASS_TYPE& v) +{ + return (operator<(u, v) || operator==(u, v)); +} + + +bool +operator<=(const CLASS_TYPE& u, int64 v) +{ + return (operator<(u, v) || operator==(u, v)); +} + + +bool +operator<=(int64 u, const CLASS_TYPE& v) +{ + return (operator<(u, v) || operator==(u, v)); +} + + +bool +operator<=(const CLASS_TYPE& u, uint64 v) +{ + return (operator<(u, v) || operator==(u, v)); +} + + +bool +operator<=(uint64 u, const CLASS_TYPE& v) +{ + return (operator<(u, v) || operator==(u, v)); +} + + +bool +operator<=(const CLASS_TYPE& u, long v) +{ + return (operator<(u, v) || operator==(u, v)); +} + + +bool +operator<=(long u, const CLASS_TYPE& v) +{ + return (operator<(u, v) || operator==(u, v)); +} + + +bool +operator<=(const CLASS_TYPE& u, unsigned long v) +{ + return (operator<(u, v) || operator==(u, v)); +} + + +bool +operator<=(unsigned long u, const CLASS_TYPE& v) +{ + return (operator<(u, v) || operator==(u, v)); +} + + +// ---------------------------------------------------------------------------- +// SECTION: GREATER THAN operator: > +// ---------------------------------------------------------------------------- + +bool +operator>(const CLASS_TYPE& u, const CLASS_TYPE& v) +{ + return (! (operator<=(u, v))); +} + + +bool +operator>(const CLASS_TYPE& u, int64 v) +{ + return (! (operator<=(u, v))); +} + + +bool +operator>(int64 u, const CLASS_TYPE& v) +{ + return (! (operator<=(u, v))); +} + + +bool +operator>(const CLASS_TYPE& u, uint64 v) +{ + return (! (operator<=(u, v))); +} + + +bool +operator>(uint64 u, const CLASS_TYPE& v) +{ + return (! (operator<=(u, v))); +} + + +bool +operator>(const CLASS_TYPE& u, long v) +{ + return (! (operator<=(u, v))); +} + + +bool +operator>(long u, const CLASS_TYPE& v) +{ + return (! (operator<=(u, v))); +} + + +bool +operator>(const CLASS_TYPE& u, unsigned long v) +{ + return (! (operator<=(u, v))); +} + + +bool +operator>(unsigned long u, const CLASS_TYPE& v) +{ + return (! (operator<=(u, v))); +} + + +// ---------------------------------------------------------------------------- +// SECTION: GREATER THAN or EQUAL operator: >= +// ---------------------------------------------------------------------------- + +bool +operator>=(const CLASS_TYPE& u, const CLASS_TYPE& v) +{ + return (! (operator<(u, v))); +} + + +bool +operator>=(const CLASS_TYPE& u, int64 v) +{ + return (! (operator<(u, v))); +} + + +bool +operator>=(int64 u, const CLASS_TYPE& v) +{ + return (! (operator<(u, v))); +} + + +bool +operator>=(const CLASS_TYPE& u, uint64 v) +{ + return (! (operator<(u, v))); +} + + +bool +operator>=(uint64 u, const CLASS_TYPE& v) +{ + return (! (operator<(u, v))); +} + + +bool +operator>=(const CLASS_TYPE& u, long v) +{ + return (! (operator<(u, v))); +} + + +bool +operator>=(long u, const CLASS_TYPE& v) +{ + return (! (operator<(u, v))); +} + + +bool +operator>=(const CLASS_TYPE& u, unsigned long v) +{ + return (! (operator<(u, v))); +} + + +bool +operator>=(unsigned long u, const CLASS_TYPE& v) +{ + return (! (operator<(u, v))); +} + + +// ---------------------------------------------------------------------------- +// SECTION: Public members - Other utils. +// ---------------------------------------------------------------------------- + +// Convert to int64, long, or int. +#define TO_INTX(RET_TYPE, UP_RET_TYPE) \ + \ +if (sgn == SC_ZERO) \ +return 0; \ + \ +int vnd = sc_min((int)DIGITS_PER_ ## UP_RET_TYPE, ndigits); \ + \ +RET_TYPE v = 0; \ +while (--vnd >= 0) \ +v = (v << BITS_PER_DIGIT) + digit[vnd]; \ + \ +if (sgn == SC_NEG) \ +return -v; \ +else \ +return v; + + +int64 +CLASS_TYPE::to_int64() const +{ + TO_INTX(int64, INT64); +} + + +long +CLASS_TYPE::to_long() const +{ + TO_INTX(long, LONG); +} + + +int +CLASS_TYPE::to_int() const +{ + TO_INTX(int, INT); +} + + +// Convert to unsigned int64, unsigned long or unsigned +// int. to_uint64, to_ulong, and to_uint have the same body except for +// the type of v defined inside. +uint64 +CLASS_TYPE::to_uint64() const +{ + if (sgn == SC_ZERO) + return 0; + + int vnd = sc_min((int)DIGITS_PER_INT64, ndigits); + + uint64 v = 0; + + if (sgn == SC_NEG) { + +#ifdef SC_MAX_NBITS + sc_digit d[MAX_NDIGITS]; +#else + sc_digit *d = new sc_digit[ndigits]; +#endif + + vec_copy(ndigits, d, digit); + + convert_SM_to_2C_trimmed(IF_SC_SIGNED, sgn, nbits, ndigits, d); + + while (--vnd >= 0) + v = (v << BITS_PER_DIGIT) + d[vnd]; + +#ifndef SC_MAX_NBITS + delete [] d; +#endif + + } + else { + + while (--vnd >= 0) + v = (v << BITS_PER_DIGIT) + digit[vnd]; + + } + + return v; +} + + +unsigned long +CLASS_TYPE::to_ulong() const +{ + if (sgn == SC_ZERO) + return 0; + + int vnd = sc_min((int)DIGITS_PER_LONG, ndigits); + + unsigned long v = 0; + + if (sgn == SC_NEG) { + +#ifdef SC_MAX_NBITS + sc_digit d[MAX_NDIGITS]; +#else + sc_digit *d = new sc_digit[ndigits]; +#endif + + vec_copy(ndigits, d, digit); + + convert_SM_to_2C_trimmed(IF_SC_SIGNED, sgn, nbits, ndigits, d); + + while (--vnd >= 0) + v = (v << BITS_PER_DIGIT) + d[vnd]; + +#ifndef SC_MAX_NBITS + delete [] d; +#endif + + } + else { + + while (--vnd >= 0) + v = (v << BITS_PER_DIGIT) + digit[vnd]; + + } + + return v; +} + + +unsigned int +CLASS_TYPE::to_uint() const +{ + if (sgn == SC_ZERO) + return 0; + + int vnd = sc_min((int)DIGITS_PER_INT, ndigits); + + unsigned int v = 0; + + if (sgn == SC_NEG) { + +#ifdef SC_MAX_NBITS + sc_digit d[MAX_NDIGITS]; +#else + sc_digit *d = new sc_digit[ndigits]; +#endif + + vec_copy(ndigits, d, digit); + + convert_SM_to_2C_trimmed(IF_SC_SIGNED, sgn, nbits, ndigits, d); + + while (--vnd >= 0) + v = (v << BITS_PER_DIGIT) + d[vnd]; + +#ifndef SC_MAX_NBITS + delete [] d; +#endif + + } + else { + + while (--vnd >= 0) + v = (v << BITS_PER_DIGIT) + digit[vnd]; + + } + + return v; +} + + +// Convert to double. +double +CLASS_TYPE::to_double() const +{ + if (sgn == SC_ZERO) + return (double) 0.0; + + int vnd = ndigits; + + double v = 0.0; + while (--vnd >= 0) + v = v * DIGIT_RADIX + digit[vnd]; + + if (sgn == SC_NEG) + return -v; + else + return v; +} + + +// Return true if the bit i is 1, false otherwise. If i is outside the +// bounds, return 1/0 according to the sign of the number by assuming +// that the number has infinite length. + +bool +CLASS_TYPE::test(int i) const +{ +#ifdef SC_SIGNED + if (check_if_outside(i)) { + if (sgn == SC_NEG) + return 1; + else + return 0; + } +#else + if (check_if_outside(i)) + return 0; +#endif + + int bit_num = bit_ord(i); + int digit_num = digit_ord(i); + + if (sgn == SC_NEG) { + +#ifdef SC_MAX_NBITS + sc_digit d[MAX_NDIGITS]; +#else + sc_digit *d = new sc_digit[ndigits]; +#endif + + vec_copy(ndigits, d, digit); + vec_complement(ndigits, d); + bool val = ((d[digit_num] & one_and_zeros(bit_num)) != 0); + +#ifndef SC_MAX_NBITS + delete [] d; +#endif + + return val; + + } + else + return ((digit[digit_num] & one_and_zeros(bit_num)) != 0); +} + + +// Set the ith bit with 1. +void +CLASS_TYPE::set(int i) +{ + if (check_if_outside(i)) + return; + + int bit_num = bit_ord(i); + int digit_num = digit_ord(i); + + convert_SM_to_2C(); + digit[digit_num] |= one_and_zeros(bit_num); + digit[digit_num] &= DIGIT_MASK; // Needed to zero the overflow bits. + convert_2C_to_SM(); +} + + +// Set the ith bit with 0, i.e., clear the ith bit. +void +CLASS_TYPE::clear(int i) +{ + if (check_if_outside(i)) + return; + + int bit_num = bit_ord(i); + int digit_num = digit_ord(i); + + convert_SM_to_2C(); + digit[digit_num] &= ~(one_and_zeros(bit_num)); + digit[digit_num] &= DIGIT_MASK; // Needed to zero the overflow bits. + convert_2C_to_SM(); +} + + +// Create a mirror image of the number. +void +CLASS_TYPE::reverse() +{ + convert_SM_to_2C(); + vec_reverse(length(), ndigits, digit, length() - 1); + convert_2C_to_SM(); +} + + +// Get a packed bit representation of the number. +void +CLASS_TYPE::get_packed_rep(sc_digit *buf) const +{ + int buf_ndigits = (length() - 1) / BITS_PER_DIGIT_TYPE + 1; + + // Initialize buf to zero. + vec_zero(buf_ndigits, buf); + + if (sgn == SC_ZERO) + return; + + const sc_digit *digit_or_d; +#ifdef SC_MAX_NBITS + sc_digit d[MAX_NDIGITS]; +#else + sc_digit *d = new sc_digit[ndigits]; +#endif + + if (sgn == SC_POS) + digit_or_d = digit; + + else + { + // If sgn is negative, we have to convert digit to its 2's + // complement. Since this function is const, we can not do it on + // digit. Since buf doesn't have overflow bits, we cannot also do + // it on buf. Thus, we have to do the complementation on a copy of + // digit, i.e., on d. + + vec_copy(ndigits, d, digit); + vec_complement(ndigits, d); + + buf[buf_ndigits - 1] = ~((sc_digit) 0); + + digit_or_d = d; + + } + + // Copy the bits from digit to buf. The division and mod operations + // below can be converted to addition/subtraction and comparison + // operations at the expense of complicating the code. We can do it + // if we see any performance problems. + + for (int i = length() - 1; i >= 0; --i) { + + if ((digit_or_d[digit_ord(i)] & one_and_zeros(bit_ord(i))) != 0) // Test. + + buf[i / BITS_PER_DIGIT_TYPE] |= + one_and_zeros(i % BITS_PER_DIGIT_TYPE); // Set. + + else + + buf[i / BITS_PER_DIGIT_TYPE] &= + ~(one_and_zeros(i % BITS_PER_DIGIT_TYPE)); // Clear. + + } + +#ifndef SC_MAX_NBITS + delete[] d; +#endif +} + + +// Set a packed bit representation of the number. +void +CLASS_TYPE::set_packed_rep(sc_digit *buf) +{ + // Initialize digit to zero. + vec_zero(ndigits, digit); + + // Copy the bits from buf to digit. + for (int i = length() - 1; i >= 0; --i) { + + if ((buf[i / BITS_PER_DIGIT_TYPE] & + one_and_zeros(i % BITS_PER_DIGIT_TYPE)) != 0) // Test. + + digit[digit_ord(i)] |= one_and_zeros(bit_ord(i)); // Set. + + else + + digit[digit_ord(i)] &= ~(one_and_zeros(bit_ord(i))); // Clear + + } + + convert_2C_to_SM(); +} + + +// ---------------------------------------------------------------------------- +// SECTION: Private members. +// ---------------------------------------------------------------------------- + +// Create a copy of v with sgn s. +CLASS_TYPE::CLASS_TYPE(const CLASS_TYPE& v, small_type s) : + sc_value_base(v), sgn(s), nbits(v.nbits), ndigits(v.ndigits), digit() +{ +#ifndef SC_MAX_NBITS + digit = new sc_digit[ndigits]; +#endif + + vec_copy(ndigits, digit, v.digit); +} + + +// Create a copy of v where v is of the different type. +CLASS_TYPE::CLASS_TYPE(const OTHER_CLASS_TYPE& v, small_type s) : + sc_value_base(v), sgn(s), nbits(num_bits(v.nbits)), ndigits(), digit() +{ +#if (IF_SC_SIGNED == 1) + ndigits = v.ndigits; +#else + ndigits = DIV_CEIL(nbits); +#endif + +#ifndef SC_MAX_NBITS + digit = new sc_digit[ndigits]; +#endif + + copy_digits(v.nbits, v.ndigits, v.digit); +} + + +// Create a signed number with (s, nb, nd, d) as its attributes (as +// defined in class CLASS_TYPE). If alloc is set, delete d. +CLASS_TYPE::CLASS_TYPE(small_type s, int nb, + int nd, sc_digit *d, + bool alloc) : + sc_value_base(), sgn(s), nbits(num_bits(nb)), ndigits(), digit() +{ + ndigits = DIV_CEIL(nbits); + +#ifndef SC_MAX_NBITS + digit = new sc_digit[ndigits]; +#endif + + if (ndigits <= nd) + vec_copy(ndigits, digit, d); + else + vec_copy_and_zero(ndigits, digit, nd, d); + +#ifndef SC_MAX_NBITS + if (alloc) + delete [] d; +#endif +} + +// This constructor is mainly used in finding a "range" of bits from a +// number of type CLASS_TYPE. The function range(l, r) can have +// arbitrary precedence between l and r. If l is smaller than r, then +// the output is the reverse of range(r, l). +CLASS_TYPE::CLASS_TYPE(const CLASS_TYPE* u, int l, int r) : + sc_value_base(), sgn(), nbits(), ndigits(), digit() +{ + bool reversed = false; + + if( l < r ) { + reversed = true; + int tmp = l; + l = r; + r = tmp; + } + + // at this point, l >= r + + // make sure that l and r point to the bits of u + r = sc_max( r, 0 ); + l = sc_min( l, u->nbits - 1 ); + + nbits = num_bits( l - r + 1 ); + + // nbits can still be <= 0 because l and r have just been updated + // with the bounds of u. + + // if u == 0 or the range is out of bounds, return 0 + if( u->sgn == SC_ZERO || nbits <= num_bits( 0 ) ) { + sgn = SC_ZERO; + if( nbits <= num_bits( 0 ) ) { + nbits = 1; + } + ndigits = DIV_CEIL( nbits ); +#ifndef SC_MAX_NBITS + digit = new sc_digit[ndigits]; +#endif + vec_zero( ndigits, digit ); + return; + } + + // The rest will be executed if u is not zero. + + ndigits = DIV_CEIL(nbits); + + // The number of bits up to and including l and r, respectively. + int nl = l + 1; + int nr = r + 1; + + // The indices of the digits that have lth and rth bits, respectively. + int left_digit = DIV_CEIL(nl) - 1; + int right_digit = DIV_CEIL(nr) - 1; + + int nd; + + // The range is performed on the 2's complement representation, so + // first get the indices for that. + if (u->sgn == SC_NEG) + nd = left_digit + 1; + else + nd = left_digit - right_digit + 1; + + // Allocate memory for the range. +#ifdef SC_MAX_NBITS + sc_digit d[MAX_NDIGITS]; +#else + digit = new sc_digit[ndigits]; + sc_digit *d = new sc_digit[nd]; +#endif + + // Getting the range on the 2's complement representation. + if (u->sgn == SC_NEG) { + + vec_copy(nd, d, u->digit); + vec_complement(nd, d); // d = -d; + vec_shift_right(nd, d, r, DIGIT_MASK); + + } + else { + + for (int i = right_digit; i <= left_digit; ++i) + d[i - right_digit] = u->digit[i]; + + vec_shift_right(nd, d, r - right_digit * BITS_PER_DIGIT, 0); + + } + + vec_zero(ndigits, digit); + + if (! reversed) + vec_copy(sc_min(nd, ndigits), digit, d); + + else { + + // If l < r, i.e., reversed is set, reverse the bits of digit. d + // will be used as a temporary store. The following code tries to + // minimize the use of bit_ord and digit_ord, which use mod and + // div operators. Since these operators are function calls to + // standard library routines, they are slow. The main idea in + // reversing is "read bits out of d from left to right and push + // them into digit using right shifting." + + // Take care of the last digit. + int nd_less_1 = nd - 1; + + // Deletions will start from the left end and move one position + // after each deletion. + sc_digit del_mask = one_and_zeros(bit_ord(l - r)); + + while (del_mask) { + vec_shift_right(ndigits, digit, 1, ((d[nd_less_1] & del_mask) != 0)); + del_mask >>= 1; + } + + // Take care of the other digits if any. + + // Insertion to digit will always occur at the left end. + sc_digit ins_mask = one_and_zeros(BITS_PER_DIGIT - 1); + + for (int j = nd - 2; j >= 0; --j) { // j = nd - 2 + + // Deletions will start from the left end and move one position + // after each deletion. + del_mask = ins_mask; + + while (del_mask) { + vec_shift_right(ndigits, digit, 1, ((d[j] & del_mask) != 0)); + del_mask >>= 1; + } + } + + if (u->sgn == SC_NEG) + vec_shift_right(ndigits, digit, + ndigits * BITS_PER_DIGIT - length(), DIGIT_MASK); + else + vec_shift_right(ndigits, digit, + ndigits * BITS_PER_DIGIT - length(), 0); + + + } // if reversed. + + convert_2C_to_SM(); + +#ifndef SC_MAX_NBITS + delete [] d; +#endif +} + +// This constructor is mainly used in finding a "range" of bits from a +// number of type OTHER_CLASS_TYPE. The function range(l, r) can have +// arbitrary precedence between l and r. If l is smaller than r, then +// the output is the reverse of range(r, l). +CLASS_TYPE::CLASS_TYPE(const OTHER_CLASS_TYPE* u, int l, int r) : + sc_value_base(), sgn(), nbits(), ndigits(), digit() +{ + bool reversed = false; + + if( l < r ) { + reversed = true; + int tmp = l; + l = r; + r = tmp; + } + + // at this point, l >= r + + // make sure that l and r point to the bits of u + r = sc_max( r, 0 ); + l = sc_min( l, u->nbits - 1 ); + + nbits = num_bits( l - r + 1 ); + + // nbits can still be <= 0 because l and r have just been updated + // with the bounds of u. + + // if u == 0 or the range is out of bounds, return 0 + if( u->sgn == SC_ZERO || nbits <= num_bits( 0 ) ) { + sgn = SC_ZERO; + if( nbits <= num_bits( 0 ) ) { + nbits = 1; + } + ndigits = DIV_CEIL( nbits ); +#ifndef SC_MAX_NBITS + digit = new sc_digit[ndigits]; +#endif + vec_zero( ndigits, digit ); + return; + } + + // The rest will be executed if u is not zero. + + ndigits = DIV_CEIL(nbits); + + // The number of bits up to and including l and r, respectively. + int nl = l + 1; + int nr = r + 1; + + // The indices of the digits that have lth and rth bits, respectively. + int left_digit = DIV_CEIL(nl) - 1; + int right_digit = DIV_CEIL(nr) - 1; + + int nd; + + // The range is performed on the 2's complement representation, so + // first get the indices for that. + if (u->sgn == SC_NEG) + nd = left_digit + 1; + else + nd = left_digit - right_digit + 1; + + // Allocate memory for the range. +#ifdef SC_MAX_NBITS + sc_digit d[MAX_NDIGITS]; +#else + digit = new sc_digit[ndigits]; + sc_digit *d = new sc_digit[nd]; +#endif + + // Getting the range on the 2's complement representation. + if (u->sgn == SC_NEG) { + + vec_copy(nd, d, u->digit); + vec_complement(nd, d); // d = -d; + vec_shift_right(nd, d, r, DIGIT_MASK); + + } + else { + + for (int i = right_digit; i <= left_digit; ++i) + d[i - right_digit] = u->digit[i]; + + vec_shift_right(nd, d, r - right_digit * BITS_PER_DIGIT, 0); + + } + + vec_zero(ndigits, digit); + + if (! reversed) + vec_copy(sc_min(nd, ndigits), digit, d); + + else { + + // If l < r, i.e., reversed is set, reverse the bits of digit. d + // will be used as a temporary store. The following code tries to + // minimize the use of bit_ord and digit_ord, which use mod and + // div operators. Since these operators are function calls to + // standard library routines, they are slow. The main idea in + // reversing is "read bits out of d from left to right and push + // them into digit using right shifting." + + // Take care of the last digit. + int nd_less_1 = nd - 1; + + // Deletions will start from the left end and move one position + // after each deletion. + sc_digit del_mask = one_and_zeros(bit_ord(l - r)); + + while (del_mask) { + vec_shift_right(ndigits, digit, 1, ((d[nd_less_1] & del_mask) != 0)); + del_mask >>= 1; + } + + // Take care of the other digits if any. + + // Insertion to digit will always occur at the left end. + sc_digit ins_mask = one_and_zeros(BITS_PER_DIGIT - 1); + + for (int j = nd - 2; j >= 0; --j) { // j = nd - 2 + + // Deletions will start from the left end and move one position + // after each deletion. + del_mask = ins_mask; + + while (del_mask) { + vec_shift_right(ndigits, digit, 1, ((d[j] & del_mask) != 0)); + del_mask >>= 1; + } + } + + if (u->sgn == SC_NEG) + vec_shift_right(ndigits, digit, + ndigits * BITS_PER_DIGIT - length(), DIGIT_MASK); + else + vec_shift_right(ndigits, digit, + ndigits * BITS_PER_DIGIT - length(), 0); + + + } // if reversed. + + convert_2C_to_SM(); + +#ifndef SC_MAX_NBITS + delete [] d; +#endif +} + + +// Print out all the physical attributes. +void +CLASS_TYPE::dump(::std::ostream& os) const +{ + // Save the current setting, and set the base to decimal. +#if defined(__MINGW32__) + std::_Ios_Fmtflags old_flags = os.setf(::std::ios::dec,::std::ios::basefield); +#else + fmtflags old_flags = os.setf(::std::ios::dec, ::std::ios::basefield); +#endif + + os << "width = " << length() << ::std::endl; + os << "value = " << *this << ::std::endl; + os << "bits = "; + + int len = length(); + + for (int i = len - 1; i >= 0; --i) { + + os << "01"[test(i)]; + if (--len % 4 == 0) + os << " "; + + } + + os << ::std::endl; + + // Restore old_flags. + os.setf(old_flags, ::std::ios::basefield); +} + + +// Checks to see if bit_num is out of bounds. +bool +CLASS_TYPE::check_if_outside(int bit_num) const +{ + if ((bit_num < 0) || (num_bits(bit_num) >= nbits)) { + +#ifdef DEBUG_SYSTEMC + if( bit_num < 0 || bit_num >= nbits ) { + char msg[BUFSIZ]; + std::sprintf( msg, "%s::check_if_outside( int bit_num ) : " + "bit_num = %d is out of bounds", + CLASS_TYPE_STR, bit_num ); + SC_REPORT_WARNING( sc_core::SC_ID_OUT_OF_BOUNDS_, msg ); + } +#endif + + return true; + } + + return false; +} + +// End of file. diff --git a/ext/systemc/src/sysc/datatypes/int/sc_nbdefs.cpp b/ext/systemc/src/sysc/datatypes/int/sc_nbdefs.cpp new file mode 100644 index 000000000..48f2d39de --- /dev/null +++ b/ext/systemc/src/sysc/datatypes/int/sc_nbdefs.cpp @@ -0,0 +1,93 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_nbdefs.h -- Top level header file for arbitrary precision signed/unsigned + arithmetic. This file defines all the constants needed. + + Original Author: Ali Dasdan, Synopsys, Inc. + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + + +// $Log: sc_nbdefs.cpp,v $ +// Revision 1.3 2011/02/18 20:19:15 acg +// Andy Goodrich: updating Copyright notice. +// +// Revision 1.2 2009/05/22 16:06:29 acg +// Andy Goodrich: process control updates. +// +// Revision 1.1.1.1 2006/12/15 20:20:05 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:49:32 acg +// Added $Log command so that CVS check in comments are reproduced in the +// source. +// + +#include "sysc/datatypes/int/sc_nbdefs.h" + + +namespace sc_dt +{ + +#ifdef SC_MAX_NBITS +const int MAX_NDIGITS = DIV_CEIL(SC_MAX_NBITS) + 2; +// Consider a number with x bits another with y bits. The maximum +// number of bits happens when we multiply them. The result will have +// (x + y) bits. Assume that x + y <= SC_MAX_NBITS. Then, DIV_CEIL(x) + +// DIV_CEIL(y) <= DIV_CEIL(SC_MAX_NBITS) + 2. This is the reason for +2 +// above. With this change, MAX_NDIGITS must be enough to hold the +// result of any operation. +#endif + +// Support for the long long type. This type is not in the standard +// but is usually supported by compilers. +#if !defined(_WIN32) || defined(__MINGW32__) +const uint64 UINT64_ZERO = 0ULL; +const uint64 UINT64_ONE = 1ULL; +const uint64 UINT64_32ONES = 0x00000000ffffffffULL; +#else +const uint64 UINT64_ZERO = 0i64; +const uint64 UINT64_ONE = 1i64; +const uint64 UINT64_32ONES = 0x00000000ffffffffi64; +#endif + +const small_type NB_DEFAULT_BASE = SC_DEC; + +#ifndef _32BIT_ +const uint64 UINT_ZERO = UINT64_ZERO; +const uint64 UINT_ONE = UINT64_ONE; +#else +const unsigned int UINT_ZERO = 0U; +const unsigned int UINT_ONE = 1U; +#endif + +} // namespace sc_dt diff --git a/ext/systemc/src/sysc/datatypes/int/sc_nbdefs.h b/ext/systemc/src/sysc/datatypes/int/sc_nbdefs.h new file mode 100644 index 000000000..0d70b74ea --- /dev/null +++ b/ext/systemc/src/sysc/datatypes/int/sc_nbdefs.h @@ -0,0 +1,282 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_nbdefs.h -- Top level header file for arbitrary precision signed/unsigned + arithmetic. This file defines all the constants needed. + + Original Author: Ali Dasdan, Synopsys, Inc. + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + +// $Log: sc_nbdefs.h,v $ +// Revision 1.7 2011/02/18 20:19:15 acg +// Andy Goodrich: updating Copyright notice. +// +// Revision 1.6 2011/02/18 20:09:34 acg +// Philipp A. Hartmann: added alternative #define for Windows to guard. +// +// Revision 1.5 2011/01/20 16:52:20 acg +// Andy Goodrich: changes for IEEE 1666 2011. +// +// Revision 1.4 2010/02/08 18:35:55 acg +// Andy Goodrich: Philipp Hartmann's changes for Solaris and Linux 64. +// +// Revision 1.2 2009/05/22 16:06:29 acg +// Andy Goodrich: process control updates. +// +// Revision 1.1.1.1 2006/12/15 20:20:05 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:49:32 acg +// Added $Log command so that CVS check in comments are reproduced in the +// source. +// + +#ifndef SC_NBDEFS_H +#define SC_NBDEFS_H + + +#include "sysc/kernel/sc_cmnhdr.h" + +#include <climits> + +#if defined(__sun) || defined(__sun__) +# include <inttypes.h> +#elif !defined(WIN32) && !defined(_WIN32) +# include <stdint.h> +#endif + +#include "sysc/utils/sc_iostream.h" +#include "sysc/kernel/sc_constants.h" // For SC_MAX_NBITS + +// Activate support mixed operands for concatenation via the comma operator +#define SC_DT_MIXED_COMMA_OPERATORS + + +namespace sc_dt +{ + +// ---------------------------------------------------------------------------- +// ENUM : sc_numrep +// +// Enumeration of number representations for character string conversion. +// ---------------------------------------------------------------------------- + +enum sc_numrep +{ + SC_NOBASE = 0, + SC_BIN = 2, + SC_OCT = 8, + SC_DEC = 10, + SC_HEX = 16, + SC_BIN_US, + SC_BIN_SM, + SC_OCT_US, + SC_OCT_SM, + SC_HEX_US, + SC_HEX_SM, + SC_CSD +}; + + +// Sign of a number: +#define SC_NEG -1 // Negative number +#define SC_ZERO 0 // Zero +#define SC_POS 1 // Positive number +#define SC_NOSIGN 2 // Uninitialized sc_signed number + +typedef unsigned char uchar; + +// A small_type number is at least a char. Defining an int is probably +// better for alignment. +typedef int small_type; + +// Attributes of a byte. +#define BITS_PER_BYTE 8 +#define BYTE_RADIX 256 +#define BYTE_MASK 255 + +// LOG2_BITS_PER_BYTE = log2(BITS_PER_BYTE), assuming that +// BITS_PER_BYTE is a power of 2. +#define LOG2_BITS_PER_BYTE 3 + +// Attributes of the unsigned long. These definitions are used mainly in +// the functions that are aware of the internal representation of +// digits, e.g., get/set_packed_rep(). +#define BYTES_PER_DIGIT_TYPE 4 +#define BITS_PER_DIGIT_TYPE 32 + +// Attributes of a digit, i.e., unsigned long less the overflow bits. +#define BYTES_PER_DIGIT 4 +#define BITS_PER_DIGIT 30 +#define DIGIT_RADIX (1ul << BITS_PER_DIGIT) +#define DIGIT_MASK (DIGIT_RADIX - 1) +// Make sure that BYTES_PER_DIGIT = ceil(BITS_PER_DIGIT / BITS_PER_BYTE). + +// Similar attributes for the half of a digit. Note that +// HALF_DIGIT_RADIX is equal to the square root of DIGIT_RADIX. These +// definitions are used mainly in the multiplication routines. +#define BITS_PER_HALF_DIGIT (BITS_PER_DIGIT / 2) +#define HALF_DIGIT_RADIX (1ul << BITS_PER_HALF_DIGIT) +#define HALF_DIGIT_MASK (HALF_DIGIT_RADIX - 1) + +// DIV_CEIL2(x, y) = ceil(x / y). x and y are positive numbers. +#define DIV_CEIL2(x, y) (((x) - 1) / (y) + 1) + +// DIV_CEIL(x) = ceil(x / BITS_PER_DIGIT) = the number of digits to +// store x bits. x is a positive number. +#define DIV_CEIL(x) DIV_CEIL2(x, BITS_PER_DIGIT) + +#ifdef SC_MAX_NBITS +extern const int MAX_NDIGITS; +// Consider a number with x bits another with y bits. The maximum +// number of bits happens when we multiply them. The result will have +// (x + y) bits. Assume that x + y <= SC_MAX_NBITS. Then, DIV_CEIL(x) + +// DIV_CEIL(y) <= DIV_CEIL(SC_MAX_NBITS) + 2. This is the reason for +2 +// above. With this change, MAX_NDIGITS must be enough to hold the +// result of any operation. +#endif + +// Support for "digit" vectors used to hold the values of sc_signed, +// sc_unsigned, sc_bv_base, and sc_lv_base data types. This type is also used +// in the concatenation support. An sc_digit is currently an unsigned 32-bit +// quantity. The typedef used is an unsigned int, rather than an unsigned long, +// since the unsigned long data type varies in size between 32-bit and 64-bit +// machines. + +typedef unsigned int sc_digit; // 32-bit unsigned integer + +// Support for the long long type. This type is not in the standard +// but is usually supported by compilers. +#ifndef _WIN32 +# if defined(__x86_64__) + typedef long long int64; + typedef unsigned long long uint64; +# else + typedef int64_t int64; + typedef uint64_t uint64; +# endif + extern const uint64 UINT64_ZERO; + extern const uint64 UINT64_ONE; + extern const uint64 UINT64_32ONES; +#else + typedef __int64 int64; + typedef unsigned __int64 uint64; + extern const uint64 UINT64_ZERO; + extern const uint64 UINT64_ONE; + extern const uint64 UINT64_32ONES; +#endif + + +// Bits per ... +// will be deleted in the future. Use numeric_limits instead +#define BITS_PER_CHAR 8 +#define BITS_PER_INT (sizeof(int) * BITS_PER_CHAR) +#define BITS_PER_LONG (sizeof(long) * BITS_PER_CHAR) +#define BITS_PER_INT64 (sizeof(::sc_dt::int64) * BITS_PER_CHAR) +#define BITS_PER_UINT (sizeof(unsigned int) * BITS_PER_CHAR) +#define BITS_PER_ULONG (sizeof(unsigned long) * BITS_PER_CHAR) +#define BITS_PER_UINT64 (sizeof(::sc_dt::uint64) * BITS_PER_CHAR) + +// Digits per ... +#define DIGITS_PER_CHAR 1 +#define DIGITS_PER_INT ((BITS_PER_INT+29)/30) +#define DIGITS_PER_LONG ((BITS_PER_LONG+29)/30) +#define DIGITS_PER_INT64 ((BITS_PER_INT64+29)/30) +#define DIGITS_PER_UINT ((BITS_PER_UINT+29)/30) +#define DIGITS_PER_ULONG ((BITS_PER_ULONG+29)/30) +#define DIGITS_PER_UINT64 ((BITS_PER_UINT64+29)/30) + +// Above, BITS_PER_X is mainly used for sc_signed, and BITS_PER_UX is +// mainly used for sc_unsigned. + +#if defined( _WIN32 ) || defined( __HP_aCC ) +typedef unsigned long fmtflags; +#else +typedef ::std::ios::fmtflags fmtflags; +#endif + +extern const small_type NB_DEFAULT_BASE ; + +// For sc_int code: +#define LLWIDTH BITS_PER_INT64 +#define INTWIDTH BITS_PER_INT + +#ifndef _32BIT_ + +typedef int64 int_type; +typedef uint64 uint_type; +#define SC_INTWIDTH 64 +extern const uint64 UINT_ZERO; +extern const uint64 UINT_ONE; + +#else + +typedef int int_type; +typedef unsigned int uint_type; +#define SC_INTWIDTH 32 +extern const unsigned int UINT_ZERO; +extern const unsigned int UINT_ONE; + +#endif + + +#if defined(_MSC_VER) && ( _MSC_VER < 1300 ) + // VC++6 bug + ::std::ostream& operator << ( ::std::ostream&, int64 ); + ::std::ostream& operator << ( ::std::ostream&, uint64 ); +#endif + +} // namespace sc_dt + + +#if defined(_MSC_VER) && ( _MSC_VER < 1300 ) + + inline + ::std::ostream& + operator << ( ::std::ostream& os, sc_dt::int64 a ) + { + sc_dt::operator << ( os, a ); + return os; + } + + inline + ::std::ostream& + operator << ( ::std::ostream& os, sc_dt::uint64 a ) + { + sc_dt::operator << ( os, a ); + return os; + } + +#endif + + +#endif diff --git a/ext/systemc/src/sysc/datatypes/int/sc_nbexterns.cpp b/ext/systemc/src/sysc/datatypes/int/sc_nbexterns.cpp new file mode 100644 index 000000000..245df73b8 --- /dev/null +++ b/ext/systemc/src/sysc/datatypes/int/sc_nbexterns.cpp @@ -0,0 +1,894 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_nbexterns.cpp -- External functions for both sc_signed and sc_unsigned + classes. These functions work on two parameters u and + v, and copy the result to the first parameter u. This + is also the reason that they are suffixed with _on_help. + + Original Author: Ali Dasdan, Synopsys, Inc. + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + + +// $Log: sc_nbexterns.cpp,v $ +// Revision 1.2 2011/02/18 20:19:15 acg +// Andy Goodrich: updating Copyright notice. +// +// Revision 1.1.1.1 2006/12/15 20:20:05 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:49:32 acg +// Added $Log command so that CVS check in comments are reproduced in the +// source. +// + +#include "sysc/datatypes/int/sc_nbexterns.h" +#include "sysc/kernel/sc_macros.h" + + +namespace sc_dt +{ + +// ---------------------------------------------------------------------------- +// SECTION: External functions for PLUS operators. +// ---------------------------------------------------------------------------- + +// Handles the cases 3 and 4 and returns the result in u. +void +add_on_help(small_type &us, int /* unb */, int und, + sc_digit *ud, + small_type vs, int /* vnb */, int vnd, + const sc_digit *vd) +{ + + vnd = vec_skip_leading_zeros(vnd, vd); + + if (us == vs) { // case 3 + + if (und >= vnd) + vec_add_on(und, ud, vnd, vd); + else + vec_add_on2(und, ud, vnd, vd); + + } + else { // case 4 + + // vec_cmp expects that und is the number of non-zero digits in ud. + int new_und = vec_skip_leading_zeros(und, ud); + int cmp_res = vec_cmp(new_und, ud, vnd, vd); + + if (cmp_res == 0) { // u == v + us = SC_ZERO; + vec_zero(und, ud); + return; + } + + if (cmp_res > 0) // u > v + vec_sub_on(und, ud, vnd, vd); + + else { // u < v + us = -us; + vec_sub_on2(und, ud, vnd, vd); + } + + } +} + + +// ---------------------------------------------------------------------------- + +/* + +mul_on_help_signed and mul_on_help_unsigned have the same body except +that CONVERT_SM_to_2C_to_SM and COPY_DIGITS are defined for signed and +unsigned, respectively. This comment also applies to the +signed/unsigned versions of div_on_help and mod_on_help. It is +possible to take COPY_DIGITS out of these functions and create a +single version of each of these helper functions; however, this will +impose an onverhead on performance. In the versions below, any change +in the signed version of a helper function must be carried to a +corresponding change in the unsigned verion of the same function or +vice versa. + +*/ + + +// ---------------------------------------------------------------------------- +// SECTION: External functions of MULTIPLICATION operators. +// ---------------------------------------------------------------------------- + +void +mul_on_help_signed(small_type &us, + int unb, int und, + sc_digit *ud, + int vnb, int vnd, + const sc_digit *vd) +{ +#define CONVERT_SM_to_2C_to_SM convert_signed_SM_to_2C_to_SM +#define COPY_DIGITS copy_digits_signed + + { // Body of mul_on_help + + int old_und = und; + + und = vec_skip_leading_zeros(und, ud); + vnd = vec_skip_leading_zeros(vnd, vd); + + sc_digit ud0 = (*ud); + sc_digit vd0 = (*vd); + + if ((vnd == 1) && (vd0 == 1)) { + us = CONVERT_SM_to_2C_to_SM(us, unb, old_und, ud); + return; + } + + if ((und == 1) && (ud0 == 1)) { + COPY_DIGITS(us, unb, old_und, ud, vnb, vnd, vd); + return; + } + + if ((und == 1) && (vnd == 1) && + (ud0 < HALF_DIGIT_RADIX) && (vd0 < HALF_DIGIT_RADIX)) { + + sc_digit d = ud0 * vd0; + COPY_DIGITS(us, unb, old_und, ud, unb + vnb, 1, &d); + return; + + } + + int nd = und + vnd; + +#ifdef SC_MAX_NBITS + sc_digit d[MAX_NDIGITS]; +#else + sc_digit *d = new sc_digit[nd]; +#endif + + vec_zero(nd, d); + + if ((und == 1) && (ud0 < HALF_DIGIT_RADIX)) + vec_mul_small(vnd, vd, ud0, d); + + else if ((vnd == 1) && (vd0 < HALF_DIGIT_RADIX)) + vec_mul_small(und, ud, vd0, d); + + else if (vnd < und) + vec_mul(und, ud, vnd, vd, d); + + else + vec_mul(vnd, vd, und, ud, d); + + COPY_DIGITS(us, unb, old_und, ud, unb + vnb, nd, d); + +#ifndef SC_MAX_NBITS + delete [] d; +#endif + + } + +#undef COPY_DIGITS +#undef CONVERT_SM_to_2C_to_SM + +} + + +void +mul_on_help_unsigned(small_type &us, + int unb, int und, + sc_digit *ud, + int vnb, int vnd, + const sc_digit *vd) +{ +#define CONVERT_SM_to_2C_to_SM convert_unsigned_SM_to_2C_to_SM +#define COPY_DIGITS copy_digits_unsigned + + { // Body of mul_on_help + + int old_und = und; + + und = vec_skip_leading_zeros(und, ud); + vnd = vec_skip_leading_zeros(vnd, vd); + + sc_digit ud0 = (*ud); + sc_digit vd0 = (*vd); + + if ((vnd == 1) && (vd0 == 1)) { + us = CONVERT_SM_to_2C_to_SM(us, unb, old_und, ud); + return; + } + + if ((und == 1) && (ud0 == 1)) { + COPY_DIGITS(us, unb, old_und, ud, vnb, vnd, vd); + return; + } + + if ((und == 1) && (vnd == 1) && + (ud0 < HALF_DIGIT_RADIX) && (vd0 < HALF_DIGIT_RADIX)) { + + sc_digit d = ud0 * vd0; + COPY_DIGITS(us, unb, old_und, ud, unb + vnb, 1, &d); + return; + + } + + int nd = und + vnd; + +#ifdef SC_MAX_NBITS + sc_digit d[MAX_NDIGITS]; +#else + sc_digit *d = new sc_digit[nd]; +#endif + + vec_zero(nd, d); + + if ((und == 1) && (ud0 < HALF_DIGIT_RADIX)) + vec_mul_small(vnd, vd, ud0, d); + + else if ((vnd == 1) && (vd0 < HALF_DIGIT_RADIX)) + vec_mul_small(und, ud, vd0, d); + + else if (vnd < und) + vec_mul(und, ud, vnd, vd, d); + + else + vec_mul(vnd, vd, und, ud, d); + + COPY_DIGITS(us, unb, old_und, ud, unb + vnb, nd, d); + +#ifndef SC_MAX_NBITS + delete [] d; +#endif + + } + +#undef COPY_DIGITS +#undef CONVERT_SM_to_2C_to_SM + +} + + +// ---------------------------------------------------------------------------- +// SECTION: External functions for DIVISION operators. +// ---------------------------------------------------------------------------- + +void +div_on_help_signed(small_type &us, + int unb, int und, + sc_digit *ud, + int vnb, int vnd, + const sc_digit *vd) +{ +#define CONVERT_SM_to_2C_to_SM convert_signed_SM_to_2C_to_SM +#define COPY_DIGITS copy_digits_signed + + { // Body of div_on_help + + int old_und = und; + + und = vec_skip_leading_zeros(und, ud); + vnd = vec_skip_leading_zeros(vnd, vd); + + int cmp_res = vec_cmp(und, ud, vnd, vd); + + if (cmp_res < 0) { // u < v => u / v = 0 - case 4 + us = SC_ZERO; + vec_zero(old_und, ud); + return; + } + + sc_digit vd0 = (*vd); + + if ((cmp_res > 0) && (vnd == 1) && (vd0 == 1)) { + us = CONVERT_SM_to_2C_to_SM(us, unb, old_und, ud); + return; + } + + // One extra digit for d is allocated to simplify vec_div_*(). + int nd = sc_max(und, vnd) + 1; + +#ifdef SC_MAX_NBITS + sc_digit d[MAX_NDIGITS + 1]; +#else + sc_digit *d = new sc_digit[nd]; +#endif + + vec_zero(nd, d); + + // u = v => u / v = 1 - case 3 + if (cmp_res == 0) + d[0] = 1; + + else if ((vnd == 1) && (und == 1)) + d[0] = (*ud) / vd0; + + else if ((vnd == 1) && (vd0 < HALF_DIGIT_RADIX)) + vec_div_small(und, ud, vd0, d); + + else + vec_div_large(und, ud, vnd, vd, d); + + COPY_DIGITS(us, unb, old_und, ud, sc_max(unb, vnb), nd - 1, d); + +#ifndef SC_MAX_NBITS + delete [] d; +#endif + + } + +#undef COPY_DIGITS +#undef CONVERT_SM_to_2C_to_SM + +} + + +void +div_on_help_unsigned(small_type &us, + int unb, int und, + sc_digit *ud, + int vnb, int vnd, + const sc_digit *vd) +{ +#define CONVERT_SM_to_2C_to_SM convert_unsigned_SM_to_2C_to_SM +#define COPY_DIGITS copy_digits_unsigned + + { // Body of div_on_help + + int old_und = und; + + und = vec_skip_leading_zeros(und, ud); + vnd = vec_skip_leading_zeros(vnd, vd); + + int cmp_res = vec_cmp(und, ud, vnd, vd); + + if (cmp_res < 0) { // u < v => u / v = 0 - case 4 + us = SC_ZERO; + vec_zero(old_und, ud); + return; + } + + sc_digit vd0 = (*vd); + + if ((cmp_res > 0) && (vnd == 1) && (vd0 == 1)) { + us = CONVERT_SM_to_2C_to_SM(us, unb, old_und, ud); + return; + } + + // One extra digit for d is allocated to simplify vec_div_*(). + int nd = sc_max(und, vnd) + 1; + +#ifdef SC_MAX_NBITS + sc_digit d[MAX_NDIGITS + 1]; +#else + sc_digit *d = new sc_digit[nd]; +#endif + + vec_zero(nd, d); + + // u = v => u / v = 1 - case 3 + if (cmp_res == 0) + d[0] = 1; + + else if ((vnd == 1) && (und == 1)) + d[0] = (*ud) / vd0; + + else if ((vnd == 1) && (vd0 < HALF_DIGIT_RADIX)) + vec_div_small(und, ud, vd0, d); + + else + vec_div_large(und, ud, vnd, vd, d); + + COPY_DIGITS(us, unb, old_und, ud, sc_max(unb, vnb), nd - 1, d); + +#ifndef SC_MAX_NBITS + delete [] d; +#endif + + } + +#undef COPY_DIGITS +#undef CONVERT_SM_to_2C_to_SM + +} + + +// ---------------------------------------------------------------------------- +// SECTION: External functions for MOD operators. +// ---------------------------------------------------------------------------- + +void +mod_on_help_signed(small_type &us, + int unb, int und, + sc_digit *ud, + int /* vnb */, int vnd, + const sc_digit *vd) +{ + +#define COPY_DIGITS copy_digits_signed + + { // Body of mod_on_help + + int old_und = und; + + und = vec_skip_leading_zeros(und, ud); + vnd = vec_skip_leading_zeros(vnd, vd); + + int cmp_res = vec_cmp(und, ud, vnd, vd); + + // u < v => u % v = u - case 4 + if (cmp_res < 0) + return; + + // u = v => u % v = 0 - case 3 + if (cmp_res == 0) { + us = SC_ZERO; + vec_zero(old_und, ud); + return; + } + + // else if u > v - case 5 + + sc_digit vd0 = (*vd); + + if ((vnd == 1) && (vd0 == 1)) { + us = SC_ZERO; + vec_zero(old_und, ud); + return; + } + + // One extra digit for d is allocated to simplify vec_div_*(). + int nd = sc_max(und, vnd) + 1; + +#ifdef SC_MAX_NBITS + sc_digit d[MAX_NDIGITS + 1]; +#else + sc_digit *d = new sc_digit[nd]; +#endif + + vec_zero(nd, d); + + if ((vnd == 1) && (und == 1)) + d[0] = (*ud) % vd0; + + if ((vnd == 1) && (vd0 < HALF_DIGIT_RADIX)) + d[0] = vec_rem_small(und, ud, vd0); + + else + vec_rem_large(und, ud, vnd, vd, d); + + us = check_for_zero(us, nd - 1, d); + + if (us == SC_ZERO) + vec_zero(old_und, ud); + else + COPY_DIGITS(us, unb, old_und, ud, sc_min(unb, vnd), nd - 1, d); + +#ifndef SC_MAX_NBITS + delete [] d; +#endif + + } + +#undef COPY_DIGITS + +} + + +void +mod_on_help_unsigned(small_type &us, + int unb, int und, + sc_digit *ud, + int /* vnb */, int vnd, + const sc_digit *vd) +{ + +#define COPY_DIGITS copy_digits_unsigned + + { // Body of mod_on_help + + int old_und = und; + + und = vec_skip_leading_zeros(und, ud); + vnd = vec_skip_leading_zeros(vnd, vd); + + int cmp_res = vec_cmp(und, ud, vnd, vd); + + // u < v => u % v = u - case 4 + if (cmp_res < 0) + return; + + // u = v => u % v = 0 - case 3 + if (cmp_res == 0) { + us = SC_ZERO; + vec_zero(old_und, ud); + return; + } + + // else if u > v - case 5 + + sc_digit vd0 = (*vd); + + if ((vnd == 1) && (vd0 == 1)) { + us = SC_ZERO; + vec_zero(old_und, ud); + return; + } + + // One extra digit for d is allocated to simplify vec_div_*(). + int nd = sc_max(und, vnd) + 1; + +#ifdef SC_MAX_NBITS + sc_digit d[MAX_NDIGITS + 1]; +#else + sc_digit *d = new sc_digit[nd]; +#endif + + vec_zero(nd, d); + + if ((vnd == 1) && (und == 1)) + d[0] = (*ud) % vd0; + + if ((vnd == 1) && (vd0 < HALF_DIGIT_RADIX)) + d[0] = vec_rem_small(und, ud, vd0); + + else + vec_rem_large(und, ud, vnd, vd, d); + + us = check_for_zero(us, nd - 1, d); + + if (us == SC_ZERO) + vec_zero(old_und, ud); + else + COPY_DIGITS(us, unb, old_und, ud, sc_min(unb, vnd), nd - 1, d); + +#ifndef SC_MAX_NBITS + delete [] d; +#endif + + } + +#undef COPY_DIGITS + +} + + +// ---------------------------------------------------------------------------- +// SECTION: External functions for AND operators. +// ---------------------------------------------------------------------------- + +// Handles the cases 2-5 and returns the result in u. +void +and_on_help(small_type us, + int /* unb */, int und, + sc_digit *ud, + small_type vs, + int /* vnb */, int vnd, + const sc_digit *vd) +{ + + sc_digit *x = ud; + const sc_digit *y = vd; + int xnd = und; + int ynd = vnd; + + // Truncate y. + if (xnd < ynd) + ynd = xnd; + + const sc_digit *xend = (x + xnd); + const sc_digit *yend = (y + ynd); + + // x is longer than y. + + small_type s = mul_signs(us, vs); + + if (s > 0) { + + if (us > 0) { // case 2 + + while (y < yend) + (*x++) &= (*y++); + + while (x < xend) + (*x++) = 0; + + } + else { // case 3 + + sc_digit xcarry = 1; + sc_digit ycarry = 1; + + while (y < yend) { + xcarry += (~(*x) & DIGIT_MASK); + ycarry += (~(*y++) & DIGIT_MASK); + (*x++) = (xcarry & ycarry) & DIGIT_MASK; + xcarry >>= BITS_PER_DIGIT; + ycarry >>= BITS_PER_DIGIT; + } + + while (x < xend) { + xcarry += (~(*x) & DIGIT_MASK); + ycarry += DIGIT_MASK; + (*x++) = (xcarry & ycarry) & DIGIT_MASK; + xcarry >>= BITS_PER_DIGIT; + ycarry >>= BITS_PER_DIGIT; + } + + } + } + else { + + if (us > 0) { // case 4 + + sc_digit ycarry = 1; + + while (y < yend) { + ycarry += (~(*y++) & DIGIT_MASK); + (*x++) &= ycarry & DIGIT_MASK; + ycarry >>= BITS_PER_DIGIT; + } + + while (x < xend) { + ycarry += DIGIT_MASK; + (*x++) &= ycarry & DIGIT_MASK; + ycarry >>= BITS_PER_DIGIT; + } + + } + else { // case 5 + + sc_digit xcarry = 1; + + while (y < yend) { + xcarry += (~(*x) & DIGIT_MASK); + (*x++) = (xcarry & (*y++)) & DIGIT_MASK; + xcarry >>= BITS_PER_DIGIT; + } + + while (x < xend) + (*x++) = 0; + + } + } +} + + +// ---------------------------------------------------------------------------- +// SECTION: External functions for OR operators. +// ---------------------------------------------------------------------------- + +// Handles the cases 3-5 and returns the result in u. +void +or_on_help(small_type us, + int /* unb */, int und, + sc_digit *ud, + small_type vs, + int /* vnb */, int vnd, + const sc_digit *vd) +{ + + sc_digit *x = ud; + const sc_digit *y = vd; + int xnd = und; + int ynd = vnd; + + if (xnd < ynd) + ynd = xnd; + + const sc_digit *xend = (x + xnd); + const sc_digit *yend = (y + ynd); + + // x is longer than y. + + small_type s = mul_signs(us, vs); + + if (s > 0) { + + if (us > 0) { // case 3 + + while (y < yend) + (*x++) |= (*y++); + + // No change for the rest of x. + + } + else { // case 4 + + sc_digit xcarry = 1; + sc_digit ycarry = 1; + + while (y < yend) { + xcarry += (~(*x) & DIGIT_MASK); + ycarry += (~(*y++) & DIGIT_MASK); + (*x++) = (xcarry | ycarry) & DIGIT_MASK; + xcarry >>= BITS_PER_DIGIT; + ycarry >>= BITS_PER_DIGIT; + } + + while (x < xend) { + xcarry += (~(*x) & DIGIT_MASK); + ycarry += DIGIT_MASK; + (*x++) = (xcarry | ycarry) & DIGIT_MASK; + xcarry >>= BITS_PER_DIGIT; + ycarry >>= BITS_PER_DIGIT; + } + } + + } + else { + + if (us > 0) { // case 5 + + sc_digit ycarry = 1; + + while (y < yend) { + ycarry += (~(*y++) & DIGIT_MASK); + (*x) = ((*x) | ycarry) & DIGIT_MASK; + x++; + ycarry >>= BITS_PER_DIGIT; + } + + while (x < xend) { + ycarry += DIGIT_MASK; + (*x) = ((*x) | ycarry) & DIGIT_MASK; + x++; + ycarry >>= BITS_PER_DIGIT; + } + + } + else { // case 6 + + sc_digit xcarry = 1; + + while (y < yend) { + xcarry += (~(*x) & DIGIT_MASK); + (*x++) = (xcarry | (*y++)) & DIGIT_MASK; + xcarry >>= BITS_PER_DIGIT; + } + + while (x < xend) { + xcarry += (~(*x) & DIGIT_MASK); + (*x++) = xcarry & DIGIT_MASK; + xcarry >>= BITS_PER_DIGIT; + } + } + } +} + + +// ---------------------------------------------------------------------------- +// SECTION: External functions for XOR operators. +// ---------------------------------------------------------------------------- + +// Handles the cases 3-5 and returns the result in u. +void +xor_on_help(small_type us, + int /* unb */, int und, + sc_digit *ud, + small_type vs, + int /* vnb */, int vnd, + const sc_digit *vd) +{ + + sc_digit *x = ud; + const sc_digit *y = vd; + int xnd = und; + int ynd = vnd; + + if (xnd < ynd) + ynd = xnd; + + const sc_digit *xend = (x + xnd); + const sc_digit *yend = (y + ynd); + + // x is longer than y. + + small_type s = mul_signs(us, vs); + + if (s > 0) { + + if (us > 0) { // case 3 + + while (y < yend) { + (*x) = ((*x) ^ (*y)) & DIGIT_MASK; + x++; + y++; + } + + // No change for the rest of x. + + } + else { // case 4 + + sc_digit xcarry = 1; + sc_digit ycarry = 1; + + while (y < yend) { + xcarry += (~(*x) & DIGIT_MASK); + ycarry += (~(*y++) & DIGIT_MASK); + (*x++) = (xcarry ^ ycarry) & DIGIT_MASK; + xcarry >>= BITS_PER_DIGIT; + ycarry >>= BITS_PER_DIGIT; + } + + while (x < xend) { + xcarry += (~(*x) & DIGIT_MASK); + ycarry += DIGIT_MASK; + (*x++) = (xcarry ^ ycarry) & DIGIT_MASK; + xcarry >>= BITS_PER_DIGIT; + ycarry >>= BITS_PER_DIGIT; + } + } + } + else { + + if (us > 0) { // case 5 + + sc_digit ycarry = 1; + + while (y < yend) { + ycarry += (~(*y++) & DIGIT_MASK); + (*x) = ((*x) ^ ycarry) & DIGIT_MASK; + x++; + ycarry >>= BITS_PER_DIGIT; + } + + while (x < xend) { + ycarry += DIGIT_MASK; + (*x) = ((*x) ^ ycarry) & DIGIT_MASK; + x++; + ycarry >>= BITS_PER_DIGIT; + } + + } + else { // case 6 + + sc_digit xcarry = 1; + + while (y < yend) { + xcarry += (~(*x) & DIGIT_MASK); + (*x++) = (xcarry ^ (*y++)) & DIGIT_MASK; + xcarry >>= BITS_PER_DIGIT; + } + + while (x < xend) { + xcarry += (~(*x) & DIGIT_MASK); + (*x++) = xcarry & DIGIT_MASK; + xcarry >>= BITS_PER_DIGIT; + } + } + } +} + +} // namespace sc_dt + + +// End of file diff --git a/ext/systemc/src/sysc/datatypes/int/sc_nbexterns.h b/ext/systemc/src/sysc/datatypes/int/sc_nbexterns.h new file mode 100644 index 000000000..98f5cda91 --- /dev/null +++ b/ext/systemc/src/sysc/datatypes/int/sc_nbexterns.h @@ -0,0 +1,123 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_nbexterns.h -- External functions for both sc_signed and sc_unsigned + classes. These functions work on two parameters u and + v, and copy the result to the first parameter u. This + is also the reason that they are suffixed with _on_help. + + The vec_* functions are called through either these + functions or those in sc_nbfriends.cpp. The functions in + sc_nbfriends.cpp perform their work on two inputs u and v, + and return the result object. + + Original Author: Ali Dasdan, Synopsys, Inc. + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + +// $Log: sc_nbexterns.h,v $ +// Revision 1.2 2011/02/18 20:19:15 acg +// Andy Goodrich: updating Copyright notice. +// +// Revision 1.1.1.1 2006/12/15 20:20:05 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:49:32 acg +// Added $Log command so that CVS check in comments are reproduced in the +// source. +// + +#ifndef SC_NBEXTERNS_H +#define SC_NBEXTERNS_H + + +#include "sysc/datatypes/int/sc_nbutils.h" + + +namespace sc_dt +{ + +extern +void add_on_help(small_type &us, + int unb, int und, sc_digit *ud, + small_type vs, + int vnb, int vnd, const sc_digit *vd); + +extern +void mul_on_help_signed(small_type &us, + int unb, int und, sc_digit *ud, + int vnb, int vnd, const sc_digit *vd); + +void div_on_help_signed(small_type &us, + int unb, int und, sc_digit *ud, + int vnb, int vnd, const sc_digit *vd); + +extern +void mod_on_help_signed(small_type &us, + int unb, int und, sc_digit *ud, + int vnb, int vnd, const sc_digit *vd); + +extern +void mul_on_help_unsigned(small_type &us, + int unb, int und, sc_digit *ud, + int vnb, int vnd, const sc_digit *vd); + +void div_on_help_unsigned(small_type &us, + int unb, int und, sc_digit *ud, + int vnb, int vnd, const sc_digit *vd); + +extern +void mod_on_help_unsigned(small_type &us, + int unb, int und, sc_digit *ud, + int vnb, int vnd, const sc_digit *vd); + +extern +void and_on_help(small_type us, + int unb, int und, sc_digit *ud, + small_type vs, + int vnb, int vnd, const sc_digit *vd); + +extern +void or_on_help(small_type us, + int unb, int und, sc_digit *ud, + small_type vs, + int vnb, int vnd, const sc_digit *vd); + +extern +void xor_on_help(small_type us, + int unb, int und, sc_digit *ud, + small_type vs, + int vnb, int vnd, const sc_digit *vd); + +} // namespace sc_dt + + +#endif diff --git a/ext/systemc/src/sysc/datatypes/int/sc_nbfriends.inc b/ext/systemc/src/sysc/datatypes/int/sc_nbfriends.inc new file mode 100644 index 000000000..5d67939e5 --- /dev/null +++ b/ext/systemc/src/sysc/datatypes/int/sc_nbfriends.inc @@ -0,0 +1,727 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_nbfriends.inc -- Friend functions for both sc_signed and sc_unsigned + classes. The vec_* functions are called through either + these functions or those in sc_nbexterns.cpp. These + functions perform their work on two inputs u and v, and + return the result object. The functions in + sc_nbexterns.cpp perform their work on one of their + inputs. + + The functions here try to use faster algorithms in case + the input numbers are small. The bitwise functions (and, + or, and xor) need the 2's complement representations of + their inputs. Instead of complementing their inputs + first and then processing, they complement their inputs + while processing without allocating extra temporary + memory. + + Original Author: Ali Dasdan, Synopsys, Inc. + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + + +// ---------------------------------------------------------------------------- +// Naming conventions: +// For sc_signed or sc_unsigned number u: +// us : u's sign, unb : u's number of bits, +// und : u's number of digits, ud : u's digits array. +// ---------------------------------------------------------------------------- + +// ---------------------------------------------------------------------------- +// SECTION: Friend functions for PLUS operators. +// ---------------------------------------------------------------------------- + +// Handles cases 3 and 4 and returns the result. +CLASS_TYPE +ADD_HELPER(small_type us, int unb, int und, + const sc_digit *ud, + small_type vs, int vnb, int vnd, + const sc_digit *vd) +{ + + und = vec_skip_leading_zeros(und, ud); + vnd = vec_skip_leading_zeros(vnd, vd); + + int nb = sc_max(unb, vnb); + int nd = sc_max(und, vnd) + 1; + +#ifdef SC_MAX_NBITS + test_bound(nb); + sc_digit d[MAX_NDIGITS]; +#else + sc_digit *d = new sc_digit[nd]; +#endif + + d[nd - 1] = d[nd - 2] = 0; + + // case 3 + if (us == vs) { + + ++nb; + + if ((und == 1) && (vnd == 1)) { + sc_digit carry = (*ud) + (*vd); + d[0] = carry & DIGIT_MASK; + d[1] = carry >> BITS_PER_DIGIT; + } + + else if (und >= vnd) + vec_add(und, ud, vnd, vd, d); + + else + vec_add(vnd, vd, und, ud, d); + + } + + // case 4 + else { + + int cmp_res = vec_cmp(und, ud, vnd, vd); + + if (cmp_res == 0) { // u == v +#ifndef SC_MAX_NBITS + delete[] d; +#endif + return CLASS_TYPE(); + } + + if (cmp_res > 0) { // u > v + + if ((und == 1) && (vnd == 1)) + d[0] = (*ud) - (*vd); + else + vec_sub(und, ud, vnd, vd, d); + + } + else { // u < v + + us = -us; + + if ((und == 1) && (vnd == 1)) + d[0] = (*vd) - (*ud); + else + vec_sub(vnd, vd, und, ud, d); + + } + } + + return CLASS_TYPE(us, nb, nd, d); + +} + + +// ---------------------------------------------------------------------------- +// SECTION: Friend functions of MULTIPLICATION operators. +// ---------------------------------------------------------------------------- + +// Handles the case 4 and returns the result. +CLASS_TYPE +MUL_HELPER(small_type s, + int unb, int und, + const sc_digit *ud, + int vnb, int vnd, + const sc_digit *vd) +{ + + und = vec_skip_leading_zeros(und, ud); + vnd = vec_skip_leading_zeros(vnd, vd); + + int nb = unb + vnb; + int nd = und + vnd; + +#ifdef SC_MAX_NBITS + test_bound(nb); + sc_digit d[MAX_NDIGITS]; +#else + sc_digit *d = new sc_digit[nd]; +#endif + + vec_zero(nd, d); + + sc_digit ud0 = (*ud); + sc_digit vd0 = (*vd); + + if ((vnd == 1) && (vd0 == 1)) + vec_copy(und, d, ud); + + else if ((und == 1) && (ud0 == 1)) + vec_copy(vnd, d, vd); + + else if ((und == 1) && (vnd == 1) && + (ud0 < HALF_DIGIT_RADIX) && (vd0 < HALF_DIGIT_RADIX)) + d[0] = ud0 * vd0; + + else if ((und == 1) && (ud0 < HALF_DIGIT_RADIX)) + vec_mul_small(vnd, vd, ud0, d); + + else if ((vnd == 1) && (vd0 < HALF_DIGIT_RADIX)) + vec_mul_small(und, ud, vd0, d); + + else if (vnd < und) + vec_mul(und, ud, vnd, vd, d); + + else + vec_mul(vnd, vd, und, ud, d); + + return CLASS_TYPE(s, nb, nd, d); + +} + + +// ---------------------------------------------------------------------------- +// SECTION: Friend functions for DIVISION operators. +// ---------------------------------------------------------------------------- + +// Handles the cases 3-4 and returns the result. +CLASS_TYPE +DIV_HELPER(small_type s, + int unb, int und, + const sc_digit *ud, + int vnb, int vnd, + const sc_digit *vd) +{ + + und = vec_skip_leading_zeros(und, ud); + vnd = vec_skip_leading_zeros(vnd, vd); + + int cmp_res = vec_cmp(und, ud, vnd, vd); + + // u < v => u / v = 0 - case 4 + if (cmp_res < 0) + return CLASS_TYPE(); + + // One extra digit for d is allocated to simplify vec_div_*(). + int nd = sc_max(und, vnd) + 1; + +#ifdef SC_MAX_NBITS + sc_digit d[MAX_NDIGITS + 1]; +#else + sc_digit *d = new sc_digit[nd]; +#endif + + vec_zero(nd, d); + + sc_digit vd0 = (*vd); + + // u = v => u / v = 1 - case 3 + if (cmp_res == 0) + d[0] = 1; + + // else if u > v - case 5 + + else if ((vnd == 1) && (vd0 == 1)) + vec_copy(und, d, ud); + + else if ((vnd == 1) && (und == 1)) + d[0] = (*ud) / vd0; + + else if ((vnd == 1) && (vd0 < HALF_DIGIT_RADIX)) + vec_div_small(und, ud, vd0, d); + + else + vec_div_large(und, ud, vnd, vd, d); + + return CLASS_TYPE(s, sc_max(unb, vnb), nd - 1, d); + +} + + +// ---------------------------------------------------------------------------- +// SECTION: Friend functions for MOD operators. +// ---------------------------------------------------------------------------- + +// Handles the cases 3-4 and returns the result. +CLASS_TYPE +MOD_HELPER(small_type us, + int unb, int und, + const sc_digit *ud, + int vnb, int vnd, + const sc_digit *vd) +{ + + und = vec_skip_leading_zeros(und, ud); + vnd = vec_skip_leading_zeros(vnd, vd); + + int cmp_res = vec_cmp(und, ud, vnd, vd); + + // u = v => u % v = 0 - case 3 + if (cmp_res == 0) + return CLASS_TYPE(); + + sc_digit vd0 = (*vd); + + if ((cmp_res > 0) && (vnd == 1) && (vd0 == 1)) + return CLASS_TYPE(); + + // One extra digit for d is allocated to simplify vec_div_*(). + int nd = sc_max(und, vnd) + 1; + +#ifdef SC_MAX_NBITS + sc_digit d[MAX_NDIGITS + 1]; +#else + sc_digit *d = new sc_digit[nd]; +#endif + + vec_zero(nd, d); + + // u < v => u % v = u - case 4 + if (cmp_res < 0) + vec_copy(und, d, ud); + + // else if u > v - case 5 + + else if ((vnd == 1) && (und == 1)) + d[0] = (*ud) % vd0; + + else if ((vnd == 1) && (vd0 < HALF_DIGIT_RADIX)) + d[0] = vec_rem_small(und, ud, vd0); + + else + vec_rem_large(und, ud, vnd, vd, d); + + us = check_for_zero(us, nd - 1, d); + + if (us == SC_ZERO) { +#ifndef SC_MAX_NBITS + delete[] d; +#endif + return CLASS_TYPE(); + } else + return CLASS_TYPE(us, sc_min(unb, vnb), nd - 1, d); + +} + + +// ---------------------------------------------------------------------------- +// SECTION: Friend functions for AND operators. +// ---------------------------------------------------------------------------- + +// Handles the cases 2-5 and returns the result. +CLASS_TYPE +AND_HELPER(small_type us, + int unb, int und, + const sc_digit *ud, + small_type vs, + int vnb, int vnd, + const sc_digit *vd) +{ + + int nb = sc_max(unb, vnb); + int nd = sc_max(und, vnd); + +#ifdef SC_MAX_NBITS + sc_digit dbegin[MAX_NDIGITS]; +#else + sc_digit *dbegin = new sc_digit[nd]; +#endif + + sc_digit *d = dbegin; + + const sc_digit *x; + const sc_digit *y; + int xnd; + int ynd; + small_type xs; + small_type ys; + + if (und >= vnd) { + x = ud; + y = vd; + xnd = und; + ynd = vnd; + xs = us; + ys = vs; + } + else { + y = ud; + x = vd; + ynd = und; + xnd = vnd; + ys = us; + xs = vs; + } + + const sc_digit *xend = (x + xnd); + const sc_digit *yend = (y + ynd); + + // x is longer than y. + + small_type s = mul_signs(xs, ys); + + if (s > 0) { + + if (xs > 0) { // case 2 + + while (y < yend) + (*d++) = (*x++) & (*y++); + + while (x++ < xend) + (*d++) = 0; + + } + else { // case 3 + + sc_digit xcarry = 1; + sc_digit ycarry = 1; + + while (y < yend) { + xcarry += (~(*x++) & DIGIT_MASK); + ycarry += (~(*y++) & DIGIT_MASK); + (*d++) = (xcarry & ycarry) & DIGIT_MASK; + xcarry >>= BITS_PER_DIGIT; + ycarry >>= BITS_PER_DIGIT; + } + + while (x < xend) { + xcarry += (~(*x++) & DIGIT_MASK); + ycarry += DIGIT_MASK; + (*d++) = (xcarry & ycarry) & DIGIT_MASK; + xcarry >>= BITS_PER_DIGIT; + ycarry >>= BITS_PER_DIGIT; + } + + } + } + else { + + if (xs > 0) { // case 4 + + sc_digit ycarry = 1; + + while (y < yend) { + ycarry += (~(*y++) & DIGIT_MASK); + (*d++) = ((*x++) & ycarry) & DIGIT_MASK; + ycarry >>= BITS_PER_DIGIT; + } + + while (x < xend) { + ycarry += DIGIT_MASK; + (*d++) = ((*x++) & ycarry) & DIGIT_MASK; + ycarry >>= BITS_PER_DIGIT; + } + + } + else { // case 5 + + sc_digit xcarry = 1; + + while (y < yend) { + xcarry += (~(*x++) & DIGIT_MASK); + (*d++) = (xcarry & (*y++)) & DIGIT_MASK; + xcarry >>= BITS_PER_DIGIT; + } + + while (x++ < xend) + (*d++) = 0; + + } + } + + s = convert_signed_2C_to_SM(nb, nd, dbegin); + + return CLASS_TYPE(s, nb, nd, dbegin); + +} + + +// ---------------------------------------------------------------------------- +// SECTION: Friend functions for OR operators. +// ---------------------------------------------------------------------------- + +// Handles the cases 3-5 and returns the result. +CLASS_TYPE +OR_HELPER(small_type us, + int unb, int und, + const sc_digit *ud, + small_type vs, + int vnb, int vnd, + const sc_digit *vd) +{ + + int nb = sc_max(unb, vnb); + int nd = sc_max(und, vnd); + +#ifdef SC_MAX_NBITS + sc_digit dbegin[MAX_NDIGITS]; +#else + sc_digit *dbegin = new sc_digit[nd]; +#endif + + sc_digit *d = dbegin; + + const sc_digit *x; + const sc_digit *y; + int xnd; + int ynd; + small_type xs; + small_type ys; + + if (und >= vnd) { + x = ud; + y = vd; + xnd = und; + ynd = vnd; + xs = us; + ys = vs; + } + else { + y = ud; + x = vd; + ynd = und; + xnd = vnd; + ys = us; + xs = vs; + } + + const sc_digit *xend = (x + xnd); + const sc_digit *yend = (y + ynd); + + // x is longer than y. + + small_type s = mul_signs(xs, ys); + + if (s > 0) { + + if (xs > 0) { // case 3 + + while (y < yend) + (*d++) = (*x++) | (*y++); + + while (x < xend) + (*d++) = (*x++); + + } + else { // case 4 + + sc_digit xcarry = 1; + sc_digit ycarry = 1; + + while (y < yend) { + xcarry += (~(*x++) & DIGIT_MASK); + ycarry += (~(*y++) & DIGIT_MASK); + (*d++) = (xcarry | ycarry) & DIGIT_MASK; + xcarry >>= BITS_PER_DIGIT; + ycarry >>= BITS_PER_DIGIT; + } + + while (x < xend) { + xcarry += (~(*x++) & DIGIT_MASK); + ycarry += DIGIT_MASK; + (*d++) = (xcarry | ycarry) & DIGIT_MASK; + xcarry >>= BITS_PER_DIGIT; + ycarry >>= BITS_PER_DIGIT; + } + + } + + } + else { + + if (xs > 0) { // case 5 + + sc_digit ycarry = 1; + + while (y < yend) { + ycarry += (~(*y++) & DIGIT_MASK); + (*d++) = ((*x++) | ycarry) & DIGIT_MASK; + ycarry >>= BITS_PER_DIGIT; + } + + while (x < xend) { + ycarry += DIGIT_MASK; + (*d++) = ((*x++) | ycarry) & DIGIT_MASK; + ycarry >>= BITS_PER_DIGIT; + } + + } + else { // case 6 + + sc_digit xcarry = 1; + + while (y < yend) { + xcarry += (~(*x++) & DIGIT_MASK); + (*d++) = (xcarry | (*y++)) & DIGIT_MASK; + xcarry >>= BITS_PER_DIGIT; + } + + while (x < xend) { + xcarry += (~(*x++) & DIGIT_MASK); + (*d++) = xcarry & DIGIT_MASK; + xcarry >>= BITS_PER_DIGIT; + } + } + + } + + s = convert_signed_2C_to_SM(nb, nd, dbegin); + + return CLASS_TYPE(s, nb, nd, dbegin); + +} + + +// ---------------------------------------------------------------------------- +// SECTION: Friend functions for XOR operators. +// ---------------------------------------------------------------------------- + +// Handles the cases 3-5 and returns the result. +CLASS_TYPE +XOR_HELPER(small_type us, + int unb, int und, + const sc_digit *ud, + small_type vs, + int vnb, int vnd, + const sc_digit *vd) +{ + + int nb = sc_max(unb, vnb); + int nd = sc_max(und, vnd); + +#ifdef SC_MAX_NBITS + sc_digit dbegin[MAX_NDIGITS]; +#else + sc_digit *dbegin = new sc_digit[nd]; +#endif + + sc_digit *d = dbegin; + + const sc_digit *x; + const sc_digit *y; + int xnd; + int ynd; + small_type xs; + small_type ys; + + if (und >= vnd) { + x = ud; + y = vd; + xnd = und; + ynd = vnd; + xs = us; + ys = vs; + } + else { + y = ud; + x = vd; + ynd = und; + xnd = vnd; + ys = us; + xs = vs; + } + + const sc_digit *xend = (x + xnd); + const sc_digit *yend = (y + ynd); + + // x is longer than y. + + small_type s = mul_signs(xs, ys); + + if (s > 0) { + + if (xs > 0) { // case 3 + + while (y < yend) + (*d++) = ((*x++) ^ (*y++)) & DIGIT_MASK; + + while (x < xend) + (*d++) = (*x++); + + } + else { // case 4 + + sc_digit xcarry = 1; + sc_digit ycarry = 1; + + while (y < yend) { + xcarry += (~(*x++) & DIGIT_MASK); + ycarry += (~(*y++) & DIGIT_MASK); + (*d++) = (xcarry ^ ycarry) & DIGIT_MASK; + xcarry >>= BITS_PER_DIGIT; + ycarry >>= BITS_PER_DIGIT; + } + + while (x < xend) { + xcarry += (~(*x++) & DIGIT_MASK); + ycarry += DIGIT_MASK; + (*d++) = (xcarry ^ ycarry) & DIGIT_MASK; + xcarry >>= BITS_PER_DIGIT; + ycarry >>= BITS_PER_DIGIT; + } + + } + } + else { + + if (xs > 0) { // case 5 + + sc_digit ycarry = 1; + + while (y < yend) { + ycarry += (~(*y++) & DIGIT_MASK); + (*d++) = ((*x++) ^ ycarry) & DIGIT_MASK; + ycarry >>= BITS_PER_DIGIT; + } + + while (x < xend) { + ycarry += DIGIT_MASK; + (*d++) = ((*x++) ^ ycarry) & DIGIT_MASK; + ycarry >>= BITS_PER_DIGIT; + } + + } + else { // case 6 + + sc_digit xcarry = 1; + + while (y < yend) { + xcarry += (~(*x++) & DIGIT_MASK); + (*d++) = (xcarry ^ (*y++)) & DIGIT_MASK; + xcarry >>= BITS_PER_DIGIT; + } + + while (x < xend) { + xcarry += (~(*x++) & DIGIT_MASK); + (*d++) = xcarry & DIGIT_MASK; + xcarry >>= BITS_PER_DIGIT; + } + } + } + + s = convert_signed_2C_to_SM(nb, nd, dbegin); + + return CLASS_TYPE(s, nb, nd, dbegin); + +} + +// End of file. + diff --git a/ext/systemc/src/sysc/datatypes/int/sc_nbutils.cpp b/ext/systemc/src/sysc/datatypes/int/sc_nbutils.cpp new file mode 100644 index 000000000..385502aa6 --- /dev/null +++ b/ext/systemc/src/sysc/datatypes/int/sc_nbutils.cpp @@ -0,0 +1,1892 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_nbutils.cpp -- External and friend functions for both sc_signed and + sc_unsigned classes. + + Original Author: Ali Dasdan, Synopsys, Inc. + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + + +// $Log: sc_nbutils.cpp,v $ +// Revision 1.4 2011/08/24 22:05:46 acg +// Torsten Maehne: initialization changes to remove warnings. +// +// Revision 1.3 2011/02/18 20:19:15 acg +// Andy Goodrich: updating Copyright notice. +// +// Revision 1.2 2007/11/04 21:26:40 acg +// Andy Goodrich: added a buffer to the allocation of the q array to address +// an issue with references outside the array by 1 byte detected by valgrind. +// +// Revision 1.1.1.1 2006/12/15 20:20:05 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:49:32 acg +// Added $Log command so that CVS check in comments are reproduced in the +// source. +// + +#include <ctype.h> +#include <cstdio> +#include <string.h> + +#include "sysc/datatypes/int/sc_int_ids.h" +#include "sysc/datatypes/int/sc_nbutils.h" +#include "sysc/kernel/sc_macros.h" + + +namespace sc_dt +{ + +// ---------------------------------------------------------------------------- +// ENUM : sc_numrep +// +// Enumeration of number representations for character string conversion. +// ---------------------------------------------------------------------------- + +const std::string +to_string( sc_numrep numrep ) +{ + switch( numrep ) + { +# define CASE_ENUM2STR( Value ) \ + case Value: return #Value + + CASE_ENUM2STR(SC_DEC); + + CASE_ENUM2STR(SC_BIN); + CASE_ENUM2STR(SC_BIN_US); + CASE_ENUM2STR(SC_BIN_SM); + + CASE_ENUM2STR(SC_OCT); + CASE_ENUM2STR(SC_OCT_US); + CASE_ENUM2STR(SC_OCT_SM); + + CASE_ENUM2STR(SC_HEX); + CASE_ENUM2STR(SC_HEX_US); + CASE_ENUM2STR(SC_HEX_SM); + + CASE_ENUM2STR(SC_CSD); + +# undef CASE_ENUM2STR + + default: + return "unknown"; + } +} + +// ---------------------------------------------------------------------------- +// SECTION: General utility functions. +// ---------------------------------------------------------------------------- + +// Return the number of characters to advance the source of c. This +// function implements one move of the FSM to parse the following +// regular expressions. Error checking is done in the caller. + +small_type +fsm_move(char c, small_type &b, small_type &s, small_type &state) +{ + + // Possible regular expressions (REs): + // Let N = any digit depending on the base. + // 1. [0|1|..|9]N* + // 2. [+|-][0|1|..|9]N* + // 3. 0[b|B|d|D|o|O|x|X][0|1|..|F]N* + // 4. [+|-]?0[b|B|d|D|o|O|x|X][0|1|..|F]N* + // + // The finite state machine (FMS) to parse these regular expressions + // has 4 states, 0 to 3. 0 is the initial state and 3 is the final + // state. + // + // Default sign = SC_POS, default base = NB_DEFAULT_BASE. + + switch (state) { + + case 0: // The initial state. + switch (c) { + case '0': s = SC_POS; state = 1; return 0; // RE 1 or 3 + case '+': s = SC_POS; state = 2; return 1; // RE 2 + case '-': s = SC_NEG; state = 2; return 1; // RE 2 + default: s = SC_POS; b = NB_DEFAULT_BASE; state = 3; return 0; // RE 1 + } + // break; //unreachable code + case 1: // 0... + switch (c) { + case 'x': case 'X': b = SC_HEX; state = 3; return 2; // RE 3 or 4 + case 'd': case 'D': b = SC_DEC; state = 3; return 2; // RE 3 or 4 + case 'o': case 'O': b = SC_OCT; state = 3; return 2; // RE 3 or 4 + case 'b': case 'B': b = SC_BIN; state = 3; return 2; // RE 3 or 4 + default: b = NB_DEFAULT_BASE; state = 3; return 0; // RE 1 + } + // break; //unreachable code + case 2: // +... or -... + switch (c) { + case '0': state = 1; return 0; // RE 2 or 4 + default: b = NB_DEFAULT_BASE; state = 3; return 0; // RE 2 + } + // break; //unreachable code + case 3: // The final state. + break; + + default: + // Any other state is not possible. + assert((0 <= state) && (state <= 3)); + + } // switch + + return 0; + +} + + +// Get base b and sign s of the number in the char string v. Return a +// pointer to the first char after the point where b and s are +// determined or where the end of v is reached. The input string v has +// to be null terminated. +const char +*get_base_and_sign(const char *v, small_type &b, small_type &s) +{ + +#ifdef DEBUG_SYSTEMC + assert(v != NULL); +#endif + + const small_type STATE_START = 0; + const small_type STATE_FINISH = 3; + + // Default sign = SC_POS, default base = 10. + s = SC_POS; + b = NB_DEFAULT_BASE; + + small_type state = STATE_START; + small_type nskip = 0; // Skip that many chars. + const char *u = v; + + while (*u) { + if (isspace(*u)) // Skip white space. + ++u; + else { + nskip += fsm_move(*u, b, s, state); + if (state == STATE_FINISH) + break; + else + ++u; + } + } + +#ifdef DEBUG_SYSTEMC + // Test to see if the above loop executed more than it should + // have. The max number of skipped chars is equal to the length of + // the longest format specifier, e.g., "-0x". + assert(nskip <= 3); +#endif + + v += nskip; + + // Handles empty strings or strings without any digits after the + // base or base and sign specifier. + if (*v == '\0') { + char msg[BUFSIZ]; + std::sprintf( msg, + "get_base_and_sign( const char* v, small_type&, small_type& ) : " + "v = \"\" is not valid" ); + SC_REPORT_ERROR( sc_core::SC_ID_CONVERSION_FAILED_, msg ); + } + + return v; + +} + +//------------------------------------------------------------------------------ +//"parse_binary_bits" +// +// This function parses the supplied string into the supplied vector as a +// right justified bit value. +// src_p -> character string representing the bits to be parsed. +// dst_n = number of words in data_p and ctrl_p. +// data_p -> words w/BITS_PER_DIGIT bits to receive the value's data bits. +// ctrl_p -> words w/BITS_PER_DIGIT bits to receive the value's control bits, +// or zero. +// Result is true if value was non-zero. +//------------------------------------------------------------------------------ +void parse_binary_bits( + const char* src_p, int dst_n, sc_digit* data_p, sc_digit* ctrl_p ) +{ + int bit_i; // Number of bit now processing. + sc_digit ctrl; // Control word now assembling. + sc_digit data; // Data word now assembling. + int delta_n; // src_n - dst_n*BITS_PER_DIGIT. + int src_i; // Index in src_p now accessing (left to right). + int src_n; // Length of source that is left in bits. + int word_i; // Bit within word now accessing (left to right). + + // MAKE SURE WE HAVE A STRING TO PARSE: + + if( src_p == 0 ) { + SC_REPORT_ERROR( sc_core::SC_ID_CONVERSION_FAILED_, + "character string is zero" ); + } + if( *src_p == 0 ) { + SC_REPORT_ERROR( sc_core::SC_ID_CONVERSION_FAILED_, + "character string is empty" ); + } + + + // INDEX INTO THE SOURCE TO A DEPTH THAT WILL ACCOMODATE OUR SIZE: + // + // If the source is smaller than our value initialize our value to zero. + + src_n = strlen(src_p); + delta_n = src_n - (dst_n*BITS_PER_DIGIT); + if ( delta_n > 0 ) + { + src_p = &src_p[delta_n]; + src_n -= delta_n; + } + else + { + for ( word_i = 0; word_i < dst_n; word_i++ ) data_p[word_i] = 0; + if ( ctrl_p ) + for ( word_i = 0; word_i < dst_n; word_i++ ) ctrl_p[word_i] = 0; + } + + + // LOOP OVER THE SOURCE ASSEMBLING WORDS AND PLACING THEM IN OUR VALUE: + // + // We stride right to left through the source in BITS_PER_DIGIT chunks. + // Each of those chunks is processed from left to right a bit at a time. + // We process the high order word specially, since there are less bits. + + src_n = src_n - BITS_PER_DIGIT; + for (word_i=0; word_i < dst_n; word_i++) + { + src_i = src_n; + + + // PARTIAL LAST WORD TO ASSEMBLE: + + if ( src_i < 0 ) + { + src_n += BITS_PER_DIGIT; + src_i = 0; + data = 0; + ctrl = 0; + for ( src_i = 0; src_i < src_n; src_i++ ) + { + ctrl = ctrl << 1; + data = data << 1; + switch( src_p[src_i] ) + { + case 'X': + case 'x': ctrl = ctrl | 1; data = data | 1; break; + case '1': data = data | 1; break; + case 'Z': + case 'z': ctrl = ctrl | 1; break; + case '0': break; + default: + { + char msg[BUFSIZ]; + std::sprintf( msg, "character string '%s' is not valid", + src_p ); + SC_REPORT_ERROR(sc_core::SC_ID_CONVERSION_FAILED_, msg); + } + break; + } + } + if ( ctrl_p ) ctrl_p[word_i] = ctrl; + data_p[word_i] = data; + break; + } + + + // FULL WORD TO BE ASSEMBLED: + + ctrl = 0; + data = 0; + for ( bit_i = 0; bit_i < BITS_PER_DIGIT; bit_i++ ) + { + ctrl = ctrl << 1; + data = data << 1; + switch( src_p[src_i++] ) + { + case 'X': + case 'x': ctrl = ctrl | 1; data = data | 1; break; + case '1': data = data | 1; break; + case 'Z': + case 'z': ctrl = ctrl | 1; break; + case '0': break; + default: + { + char msg[BUFSIZ]; + std::sprintf( msg, "character string '%s' is not valid", + src_p ); + SC_REPORT_ERROR( sc_core::SC_ID_CONVERSION_FAILED_, msg ); + } + break; + } + } + if ( ctrl_p ) ctrl_p[word_i] = ctrl; + data_p[word_i] = data; + src_n = src_n - BITS_PER_DIGIT; + } +} + + +//------------------------------------------------------------------------------ +//"parse_hex_bits" +// +// This function parses the supplied string into the supplied vector as a +// right justified bit value. +// src_p -> character string representing the bits to be parsed. +// dst_n = number of words in data_p and ctrl_p. +// data_p -> words w/32 bits to receive the value's data bits. +// ctrl_p -> words w/32 bits to receive the value's control bits, +// or zero. +// Result is true if value was non-zero. +//------------------------------------------------------------------------------ +void parse_hex_bits( + const char* src_p, int dst_n, sc_digit* data_p, sc_digit* ctrl_p ) +{ + sc_digit ctrl; // Control word now assembling. + sc_digit data; // Data word now assembling. + int delta_n; // src_n - dst_n*BITS_PER_DIGIT. + int digit_i; // Number of digit now processing. + int src_i; // Index in src_p now accessing (left to right). + int src_n; // Length of source that is left in bits. + int word_i; // Bit within word now accessing (left to right). + + // MAKE SURE WE HAVE A STRING TO PARSE: + + if( src_p == 0 ) { + SC_REPORT_ERROR( sc_core::SC_ID_CONVERSION_FAILED_, + "character string is zero" ); + } + if( *src_p == 0 ) { + SC_REPORT_ERROR( sc_core::SC_ID_CONVERSION_FAILED_, + "character string is empty" ); + } + + + // INDEX INTO THE SOURCE TO A DEPTH THAT WILL ACCOMODATE OUR SIZE: + // + // If the source is smaller than our value initialize our value to zero. + + src_n = strlen(src_p); + delta_n = src_n - (dst_n*8); + if ( delta_n > 0 ) + { + src_p = &src_p[delta_n]; + src_n -= delta_n; + } + else + { + for ( word_i = 0; word_i < dst_n; word_i++ ) data_p[word_i] = 0; + if ( ctrl_p ) + for ( word_i = 0; word_i < dst_n; word_i++ ) ctrl_p[word_i] = 0; + } + + + // LOOP OVER THE SOURCE ASSEMBLING WORDS AND PLACING THEM IN OUR VALUE: + // + // We stride right to left through the source in BITS_PER_DIGIT chunks. + // Each of those chunks is processed from left to right a bit at a time. + // We process the high order word specially, since there are less bits. + + src_n = src_n - 8; + for (word_i=0; word_i < dst_n; word_i++) + { + src_i = src_n; + + + // PARTIAL LAST WORD TO ASSEMBLE: + + if ( src_i < 0 ) + { + src_n += 8; + src_i = 0; + data = 0; + ctrl = 0; + for ( src_i = 0; src_i < src_n; src_i++ ) + { + ctrl = ctrl << 4; + data = data << 4; + switch( src_p[src_i] ) + { + case 'X': + case 'x': ctrl = ctrl | 15; data = data | 15; break; + case 'F': + case 'f': data = data | 15; break; + case 'E': + case 'e': data = data | 14; break; + case 'D': + case 'd': data = data | 13; break; + case 'C': + case 'c': data = data | 12; break; + case 'B': + case 'b': data = data | 11; break; + case 'A': + case 'a': data = data | 10; break; + case '9': data = data | 9; break; + case '8': data = data | 8; break; + case '7': data = data | 7; break; + case '6': data = data | 6; break; + case '5': data = data | 5; break; + case '4': data = data | 4; break; + case '3': data = data | 3; break; + case '2': data = data | 2; break; + case '1': data = data | 1; break; + case '0': break; + case 'Z': + case 'z': ctrl = ctrl | 15; break; + default: + { + char msg[BUFSIZ]; + std::sprintf( msg, "character string '%s' is not valid", + src_p ); + SC_REPORT_ERROR(sc_core::SC_ID_CONVERSION_FAILED_, msg); + } + break; + } + } + if ( ctrl_p ) ctrl_p[word_i] = ctrl; + data_p[word_i] = data; + break; + } + + + // FULL WORD TO BE ASSEMBLED: + + ctrl = 0; + data = 0; + for ( digit_i = 0; digit_i < 8; digit_i++ ) + { + ctrl = ctrl << 4; + data = data << 4; + switch( src_p[src_i++] ) + { + case 'X': + case 'x': ctrl = ctrl | 15; data = data | 15; break; + case 'F': + case 'f': data = data | 15; break; + case 'E': + case 'e': data = data | 14; break; + case 'D': + case 'd': data = data | 13; break; + case 'C': + case 'c': data = data | 12; break; + case 'B': + case 'b': data = data | 11; break; + case 'A': + case 'a': data = data | 10; break; + case '9': data = data | 9; break; + case '8': data = data | 8; break; + case '7': data = data | 7; break; + case '6': data = data | 6; break; + case '5': data = data | 5; break; + case '4': data = data | 4; break; + case '3': data = data | 3; break; + case '2': data = data | 2; break; + case '1': data = data | 1; break; + case '0': break; + case 'Z': + case 'z': ctrl = ctrl | 15; break; + default: + { + char msg[BUFSIZ]; + std::sprintf( msg, "character string '%s' is not valid", + src_p ); + SC_REPORT_ERROR( sc_core::SC_ID_CONVERSION_FAILED_, msg ); + } + break; + } + } + if ( ctrl_p ) ctrl_p[word_i] = ctrl; + data_p[word_i] = data; + src_n = src_n - BITS_PER_DIGIT; + } +} + + + +// ---------------------------------------------------------------------------- +// SECTION: Utility functions involving unsigned vectors. +// ---------------------------------------------------------------------------- + +// Read u from a null terminated char string v. Note that operator>> +// in sc_nbcommon.cpp is similar to this function. +small_type +vec_from_str(int unb, int und, sc_digit *u, + const char *v, sc_numrep base) +{ + +#ifdef DEBUG_SYSTEMC + assert((unb > 0) && (und > 0) && (u != NULL)); + assert(v != NULL); +#endif + + is_valid_base(base); + + small_type b, s; // base and sign. + + v = get_base_and_sign(v, b, s); + + if (base != SC_NOBASE) { + if (b == NB_DEFAULT_BASE) + b = base; + else { + char msg[BUFSIZ]; + std::sprintf( msg, + "vec_from_str( int, int, sc_digit*, const char*, sc_numrep base ) : " + "base = %s does not match the default base", + to_string( base ).c_str() ); + SC_REPORT_ERROR( sc_core::SC_ID_CONVERSION_FAILED_, msg ); + } + } + + vec_zero(und, u); + + char c; + + for ( ; (c = *v); ++v) { + + if (isalnum(c)) { + + small_type val; // Numeric value of a char. + + if (isalpha(c)) // Hex digit. + val = toupper(c) - 'A' + 10; + else + val = c - '0'; + + if (val >= b) { + char msg[BUFSIZ]; + std::sprintf( msg, + "vec_from_str( int, int, sc_digit*, const char*, sc_numrep base ) : " + "'%c' is not a valid digit in base %d", + *v, b ); + SC_REPORT_ERROR( sc_core::SC_ID_CONVERSION_FAILED_, msg ); + } + + // digit = digit * b + val; + vec_mul_small_on(und, u, b); + + if (val) + vec_add_small_on(und, u, val); + + } + else { + char msg[BUFSIZ]; + std::sprintf( msg, + "vec_from_str( int, int, sc_digit*, const char*, sc_numrep base ) : " + "'%c' is not a valid digit in base %d", + *v, b ); + SC_REPORT_ERROR( sc_core::SC_ID_CONVERSION_FAILED_, msg ); + } + } + + return convert_signed_SM_to_2C_to_SM(s, unb, und, u); +} + + +// All vec_ functions assume that the vector to hold the result, +// called w, has sufficient length to hold the result. For efficiency +// reasons, we do not test whether or not we are out of bounds. + +// Compute w = u + v, where w, u, and v are vectors. +// - ulen >= vlen +// - wlen >= sc_max(ulen, vlen) + 1 +void +vec_add(int ulen, const sc_digit *u, + int vlen, const sc_digit *v, + sc_digit *w) +{ + +#ifdef DEBUG_SYSTEMC + assert((ulen > 0) && (u != NULL)); + assert((vlen > 0) && (v != NULL)); + assert(w != NULL); + assert(ulen >= vlen); +#endif + + const sc_digit *uend = (u + ulen); + const sc_digit *vend = (v + vlen); + + sc_digit carry = 0; // Also used as sum to save space. + + // Add along the shorter v. + while (v < vend) { + carry += (*u++) + (*v++); + (*w++) = carry & DIGIT_MASK; + carry >>= BITS_PER_DIGIT; + } + + // Propagate the carry. + while (carry && (u < uend)) { + carry = (*u++) + 1; + (*w++) = carry & DIGIT_MASK; + carry >>= BITS_PER_DIGIT; + } + + // Copy the rest of u to the result. + while (u < uend) + (*w++) = (*u++); + + // Propagate the carry if it is still 1. + if (carry) + (*w) = 1; + +} + + +// Compute u += v, where u and v are vectors. +// - ulen >= vlen +void +vec_add_on(int ulen, sc_digit *ubegin, + int vlen, const sc_digit *v) +{ + +#ifdef DEBUG_SYSTEMC + assert((ulen > 0) && (ubegin != NULL)); + assert((vlen > 0) && (v != NULL)); + assert(ulen >= vlen); +#endif + + sc_digit *u = ubegin; + const sc_digit *uend = (u + ulen); + const sc_digit *vend = (v + vlen); + + sc_digit carry = 0; // Also used as sum to save space. + + // Add along the shorter v. + while (v < vend) { + carry += (*u) + (*v++); + (*u++) = carry & DIGIT_MASK; + carry >>= BITS_PER_DIGIT; + } + + // Propagate the carry. + while (carry && (u < uend)) { + carry = (*u) + 1; + (*u++) = carry & DIGIT_MASK; + carry >>= BITS_PER_DIGIT; + } + +#ifdef DEBUG_SYSTEMC + if( carry != 0 ) { + SC_REPORT_WARNING( sc_core::SC_ID_WITHOUT_MESSAGE_, + "vec_add_on( int, sc_digit*, int, const " + "sc_digit* ) : " + "result of addition is wrapped around" ); + } +#endif + +} + + +// Compute u += v, where u and v are vectors. +// - ulen < vlen +void +vec_add_on2(int ulen, sc_digit *ubegin, + int +#ifdef DEBUG_SYSTEMC + vlen +#endif + , const sc_digit *v) +{ + +#ifdef DEBUG_SYSTEMC + assert((ulen > 0) && (ubegin != NULL)); + assert((vlen > 0) && (v != NULL)); + assert(ulen < vlen); +#endif + + sc_digit *u = ubegin; + const sc_digit *uend = (u + ulen); + + sc_digit carry = 0; // Also used as sum to save space. + + // Add along the shorter u. + while (u < uend) { + carry += (*u) + (*v++); + (*u++) = carry & DIGIT_MASK; + carry >>= BITS_PER_DIGIT; + } + +#ifdef DEBUG_SYSTEMC + if( carry != 0 ) { + SC_REPORT_WARNING( sc_core::SC_ID_WITHOUT_MESSAGE_, + "vec_add_on2( int, sc_digit*, int, const " + "sc_digit* ) : " + "result of addition is wrapped around" ); + } +#endif +} + + +// Compute w = u + v, where w and u are vectors, and v is a scalar. +void +vec_add_small(int ulen, const sc_digit *u, + sc_digit v, + sc_digit *w) +{ + +#ifdef DEBUG_SYSTEMC + assert((ulen > 0) && (u != NULL)); + assert(w != NULL); +#endif + + const sc_digit *uend = (u + ulen); + + // Add along the shorter v. + sc_digit carry = (*u++) + v; + (*w++) = carry & DIGIT_MASK; + carry >>= BITS_PER_DIGIT; + + // Propagate the carry. + while (carry && (u < uend)) { + carry = (*u++) + 1; + (*w++) = carry & DIGIT_MASK; + carry >>= BITS_PER_DIGIT; + } + + // Copy the rest of u to the result. + while (u < uend) + (*w++) = (*u++); + + // Propagate the carry if it is still 1. + if (carry) + (*w) = 1; + +} + +// Compute u += v, where u is vectors, and v is a scalar. +void +vec_add_small_on(int ulen, sc_digit *u, sc_digit v) +{ + +#ifdef DEBUG_SYSTEMC + assert((ulen > 0) && (u != NULL)); +#endif + + int i = 0; + + while (v && (i < ulen)) { + v += u[i]; + u[i++] = v & DIGIT_MASK; + v >>= BITS_PER_DIGIT; + } + +#ifdef DEBUG_SYSTEMC + if( v != 0 ) { + SC_REPORT_WARNING( sc_core::SC_ID_WITHOUT_MESSAGE_, + "vec_add_small_on( int, sc_digit*, unsigned " + "long ) : " + "result of addition is wrapped around" ); + } +#endif + +} + +// Compute w = u - v, where w, u, and v are vectors. +// - ulen >= vlen +// - wlen >= sc_max(ulen, vlen) +void +vec_sub(int ulen, const sc_digit *u, + int vlen, const sc_digit *v, + sc_digit *w) +{ + +#ifdef DEBUG_SYSTEMC + assert((ulen > 0) && (u != NULL)); + assert((vlen > 0) && (v != NULL)); + assert(w != NULL); + assert(ulen >= vlen); +#endif + + const sc_digit *uend = (u + ulen); + const sc_digit *vend = (v + vlen); + + sc_digit borrow = 0; // Also used as diff to save space. + + // Subtract along the shorter v. + while (v < vend) { + borrow = ((*u++) + DIGIT_RADIX) - (*v++) - borrow; + (*w++) = borrow & DIGIT_MASK; + borrow = 1 - (borrow >> BITS_PER_DIGIT); + } + + // Propagate the borrow. + while (borrow && (u < uend)) { + borrow = ((*u++) + DIGIT_RADIX) - 1; + (*w++) = borrow & DIGIT_MASK; + borrow = 1 - (borrow >> BITS_PER_DIGIT); + } + +#ifdef DEBUG_SYSTEMC + assert(borrow == 0); +#endif + + // Copy the rest of u to the result. + while (u < uend) + (*w++) = (*u++); + +} + +// Compute u = u - v, where u and v are vectors. +// - u > v +// - ulen >= vlen +void +vec_sub_on(int ulen, sc_digit *ubegin, + int vlen, const sc_digit *v) +{ + +#ifdef DEBUG_SYSTEMC + assert((ulen > 0) && (ubegin != NULL)); + assert((vlen > 0) && (v != NULL)); + assert(ulen >= vlen); +#endif + + sc_digit *u = ubegin; + const sc_digit *uend = (u + ulen); + const sc_digit *vend = (v + vlen); + + sc_digit borrow = 0; // Also used as diff to save space. + + // Subtract along the shorter v. + while (v < vend) { + borrow = ((*u) + DIGIT_RADIX) - (*v++) - borrow; + (*u++) = borrow & DIGIT_MASK; + borrow = 1 - (borrow >> BITS_PER_DIGIT); + } + + // Propagate the borrow. + while (borrow && (u < uend)) { + borrow = ((*u) + DIGIT_RADIX) - 1; + (*u++) = borrow & DIGIT_MASK; + borrow = 1 - (borrow >> BITS_PER_DIGIT); + } + +#ifdef DEBUG_SYSTEMC + assert(borrow == 0); +#endif + +} + +// Compute u = v - u, where u and v are vectors. +// - v > u +// - ulen <= vlen or ulen > ulen +void +vec_sub_on2(int ulen, sc_digit *ubegin, + int vlen, const sc_digit *v) +{ + +#ifdef DEBUG_SYSTEMC + assert((ulen > 0) && (ubegin != NULL)); + assert((vlen > 0) && (v != NULL)); +#endif + + sc_digit *u = ubegin; + const sc_digit *uend = (u + sc_min(ulen, vlen)); + + sc_digit borrow = 0; // Also used as diff to save space. + + // Subtract along the shorter u. + while (u < uend) { + borrow = ((*v++) + DIGIT_RADIX) - (*u) - borrow; + (*u++) = borrow & DIGIT_MASK; + borrow = 1 - (borrow >> BITS_PER_DIGIT); + } + +#ifdef DEBUG_SYSTEMC + if( borrow != 0 ) { + SC_REPORT_WARNING( sc_core::SC_ID_WITHOUT_MESSAGE_, + "vec_sub_on2( int, sc_digit*, int, const " + "sc_digit* ) : " + "result of subtraction is wrapped around" ); + } +#endif +} + +// Compute w = u - v, where w and u are vectors, and v is a scalar. +void +vec_sub_small(int ulen, const sc_digit *u, + sc_digit v, + sc_digit *w) +{ + +#ifdef DEBUG_SYSTEMC + assert(ulen > 0); + assert(u != NULL); +#endif + + const sc_digit *uend = (u + ulen); + + // Add along the shorter v. + sc_digit borrow = ((*u++) + DIGIT_RADIX) - v; + (*w++) = borrow & DIGIT_MASK; + borrow = 1 - (borrow >> BITS_PER_DIGIT); + + // Propagate the borrow. + while (borrow && (u < uend)) { + borrow = ((*u++) + DIGIT_RADIX) - 1; + (*w++) = borrow & DIGIT_MASK; + borrow = 1 - (borrow >> BITS_PER_DIGIT); + } + +#ifdef DEBUG_SYSTEMC + assert(borrow == 0); +#endif + + // Copy the rest of u to the result. + while (u < uend) + (*w++) = (*u++); + +} + + +// Compute u -= v, where u is vectors, and v is a scalar. +void +vec_sub_small_on(int ulen, sc_digit *u, sc_digit v) +{ + +#ifdef DEBUG_SYSTEMC + assert((ulen > 0) && (u != NULL)); +#endif + + for (int i = 0; i < ulen; ++i) { + v = (u[i] + DIGIT_RADIX) - v; + u[i] = v & DIGIT_MASK; + v = 1 - (v >> BITS_PER_DIGIT); + } + +#ifdef DEBUG_SYSTEMC + assert(v == 0); +#endif + +} + +// Compute w = u * v, where w, u, and v are vectors. +void +vec_mul(int ulen, const sc_digit *u, + int vlen, const sc_digit *vbegin, + sc_digit *wbegin) +{ + + /* Consider u = Ax + B and v = Cx + D where x is equal to + HALF_DIGIT_RADIX. In other words, A is the higher half of u and + B is the lower half of u. The interpretation for v is + similar. Then, we have the following picture: + + u_h u_l + u: -------- -------- + A B + + v_h v_l + v: -------- -------- + C D + + result (d): + carry_before: -------- -------- + carry_h carry_l + result_before: -------- -------- -------- -------- + R1_h R1_l R0_h R0_l + -------- -------- + BD_h BD_l + -------- -------- + AD_h AD_l + -------- -------- + BC_h BC_l + -------- -------- + AC_h AC_l + result_after: -------- -------- -------- -------- + R1_h' R1_l' R0_h' R0_l' + + prod_l = R0_h|R0_l + B * D + 0|carry_l + = R0_h|R0_l + BD_h|BD_l + 0|carry_l + + prod_h = A * D + B * C + high_half(prod_l) + carry_h + = AD_h|AD_l + BC_h|BC_l + high_half(prod_l) + 0|carry_h + + carry = A * C + high_half(prod_h) + = AC_h|AC_l + high_half(prod_h) + + R0_l' = low_half(prod_l) + + R0_h' = low_half(prod_h) + + R0 = high_half(prod_h)|low_half(prod_l) + + where '|' is the concatenation operation and the suffixes 0 and 1 + show the iteration number, i.e., 0 is the current iteration and 1 + is the next iteration. + + NOTE: sc_max(prod_l, prod_h, carry) <= 2 * x^2 - 1, so any + of these numbers can be stored in a digit. + + NOTE: low_half(u) returns the lower BITS_PER_HALF_DIGIT of u, + whereas high_half(u) returns the rest of the bits, which may + contain more bits than BITS_PER_HALF_DIGIT. + */ + +#ifdef DEBUG_SYSTEMC + assert((ulen > 0) && (u != NULL)); + assert((vlen > 0) && (vbegin != NULL)); + assert(wbegin != NULL); +#endif + +#define prod_h carry + + const sc_digit *uend = (u + ulen); + const sc_digit *vend = (vbegin + vlen); + + while (u < uend) { + + sc_digit u_h = (*u++); // A|B + sc_digit u_l = low_half(u_h); // B + u_h = high_half(u_h); // A + +#ifdef DEBUG_SYSTEMC + // The overflow bits must be zero. + assert(u_h == (u_h & HALF_DIGIT_MASK)); +#endif + + sc_digit carry = 0; + + sc_digit *w = (wbegin++); + + const sc_digit *v = vbegin; + + while (v < vend) { + + sc_digit v_h = (*v++); // C|D + sc_digit v_l = low_half(v_h); // D + + v_h = high_half(v_h); // C + +#ifdef DEBUG_SYSTEMC + // The overflow bits must be zero. + assert(v_h == (v_h & HALF_DIGIT_MASK)); +#endif + + sc_digit prod_l = (*w) + u_l * v_l + low_half(carry); + + prod_h = u_h * v_l + u_l * v_h + high_half(prod_l) + high_half(carry); + + (*w++) = concat(low_half(prod_h), low_half(prod_l)); + + carry = u_h * v_h + high_half(prod_h); + + } + + (*w) = carry; + + } + +#undef prod_h + +} + +// Compute w = u * v, where w and u are vectors, and v is a scalar. +// - 0 < v < HALF_DIGIT_RADIX. +void +vec_mul_small(int ulen, const sc_digit *u, + sc_digit v, sc_digit *w) +{ + +#ifdef DEBUG_SYSTEMC + assert((ulen > 0) && (u != NULL)); + assert(w != NULL); + assert((0 < v) && (v < HALF_DIGIT_RADIX)); +#endif + +#define prod_h carry + + const sc_digit *uend = (u + ulen); + + sc_digit carry = 0; + + while (u < uend) { + + sc_digit u_AB = (*u++); + +#ifdef DEBUG_SYSTEMC + // The overflow bits must be zero. + assert(high_half(u_AB) == high_half_masked(u_AB)); +#endif + + sc_digit prod_l = v * low_half(u_AB) + low_half(carry); + + prod_h = v * high_half(u_AB) + high_half(prod_l) + high_half(carry); + + (*w++) = concat(low_half(prod_h), low_half(prod_l)); + + carry = high_half(prod_h); + + } + + (*w) = carry; + +#undef prod_h + +} + +// Compute u = u * v, where u is a vector, and v is a scalar. +// - 0 < v < HALF_DIGIT_RADIX. +void +vec_mul_small_on(int ulen, sc_digit *u, sc_digit v) +{ + +#ifdef DEBUG_SYSTEMC + assert((ulen > 0) && (u != NULL)); + assert((0 < v) && (v < HALF_DIGIT_RADIX)); +#endif + +#define prod_h carry + + sc_digit carry = 0; + + for (int i = 0; i < ulen; ++i) { + +#ifdef DEBUG_SYSTEMC + // The overflow bits must be zero. + assert(high_half(u[i]) == high_half_masked(u[i])); +#endif + + sc_digit prod_l = v * low_half(u[i]) + low_half(carry); + + prod_h = v * high_half(u[i]) + high_half(prod_l) + high_half(carry); + + u[i] = concat(low_half(prod_h), low_half(prod_l)); + + carry = high_half(prod_h); + + } + +#undef prod_h + +#ifdef DEBUG_SYSTEMC + if( carry != 0 ) { + SC_REPORT_WARNING( sc_core::SC_ID_WITHOUT_MESSAGE_, + "vec_mul_small_on( int, sc_digit*, unsigned " + "long ) : " + "result of multiplication is wrapped around" ); + } +#endif +} + +// Compute w = u / v, where w, u, and v are vectors. +// - u and v are assumed to have at least two digits as uchars. +void +vec_div_large(int ulen, const sc_digit *u, + int vlen, const sc_digit *v, + sc_digit *w) +{ + +#ifdef DEBUG_SYSTEMC + assert((ulen > 0) && (u != NULL)); + assert((vlen > 0) && (v != NULL)); + assert(w != NULL); + assert(BITS_PER_DIGIT >= 3 * BITS_PER_BYTE); +#endif + + // We will compute q = x / y where x = u and y = v. The reason for + // using x and y is that x and y are BYTE_RADIX copies of u and v, + // respectively. The use of BYTE_RADIX radix greatly simplifies the + // complexity of the division operation. These copies are also + // needed even when we use DIGIT_RADIX representation. + + int xlen = BYTES_PER_DIGIT * ulen + 1; + int ylen = BYTES_PER_DIGIT * vlen; + +#ifdef SC_MAX_NBITS + uchar x[DIV_CEIL2(SC_MAX_NBITS, BITS_PER_BYTE)]; + uchar y[DIV_CEIL2(SC_MAX_NBITS, BITS_PER_BYTE)]; + uchar q[DIV_CEIL2(SC_MAX_NBITS, BITS_PER_BYTE)]; +#else + uchar *x = new uchar[xlen]; + uchar *y = new uchar[ylen]; + // valgrind complains about us accessing too far to so leave a buffer. + uchar *q = new uchar[(xlen - ylen) + 10]; +#endif + + // q corresponds to w. + + // Set (uchar) x = (sc_digit) u. + xlen = vec_to_char(ulen, u, xlen, x); + + // Skip all the leading zeros in x. + while ((--xlen >= 0) && (! x[xlen])) continue; + xlen++; + + // Set (uchar) y = (sc_digit) v. + ylen = vec_to_char(vlen, v, ylen, y); + + // Skip all the leading zeros in y. + while ((--ylen >= 0) && (! y[ylen])) continue; + ylen++; + +#ifdef DEBUG_SYSTEMC + assert(xlen > 1); + assert(ylen > 1); +#endif + + // At this point, all the leading zeros are eliminated from x and y. + + // Zero the last digit of x. + x[xlen] = 0; + + // The first two digits of y. + sc_digit y2 = (y[ylen - 1] << BITS_PER_BYTE) + y[ylen - 2]; + + const sc_digit DOUBLE_BITS_PER_BYTE = 2 * BITS_PER_BYTE; + + // Find each q[k]. + for (int k = (xlen - ylen); k >= 0; --k) { + + // qk is a guess for q[k] such that q[k] = qk or qk - 1. + sc_digit qk; + + // Find qk by just using 2 digits of y and 3 digits of x. The + // following code assumes that sizeof(sc_digit) >= 3 BYTEs. + int k2 = k + ylen; + + qk = ((x[k2] << DOUBLE_BITS_PER_BYTE) + + (x[k2 - 1] << BITS_PER_BYTE) + x[k2 - 2]) / y2; + + if (qk >= BYTE_RADIX) // qk cannot be larger than the largest + qk = BYTE_RADIX - 1; // digit in BYTE_RADIX. + + // q[k] = qk or qk - 1. The following if-statement determines which: + if (qk) { + + uchar *xk = (x + k); // A shortcut for x[k]. + + // x = x - y * qk : + sc_digit carry = 0; + + for (int i = 0; i < ylen; ++i) { + carry += y[i] * qk; + sc_digit diff = (xk[i] + BYTE_RADIX) - (carry & BYTE_MASK); + xk[i] = (uchar)(diff & BYTE_MASK); + carry = (carry >> BITS_PER_BYTE) + (1 - (diff >> BITS_PER_BYTE)); + } + + // If carry, qk may be one too large. + if (carry) { + + // 2's complement the last digit. + carry = (xk[ylen] + BYTE_RADIX) - carry; + xk[ylen] = (uchar)(carry & BYTE_MASK); + carry = 1 - (carry >> BITS_PER_BYTE); + + if (carry) { + + // qk was one too large, so decrement it. + --qk; + + // Since qk was decreased by one, y must be added to x: + // That is, x = x - y * (qk - 1) = x - y * qk + y = x_above + y. + carry = 0; + + for (int i = 0; i < ylen; ++i) { + carry += xk[i] + y[i]; + xk[i] = (uchar)(carry & BYTE_MASK); + carry >>= BITS_PER_BYTE; + } + + if (carry) + xk[ylen] = (uchar)((xk[ylen] + 1) & BYTE_MASK); + + } // second if carry + } // first if carry + } // if qk + + q[k] = (uchar)qk; + + } // for k + + // Set (sc_digit) w = (uchar) q. + vec_from_char(xlen - ylen + 1, q, ulen, w); + +#ifndef SC_MAX_NBITS + delete [] x; + delete [] y; + delete [] q; +#endif + +} + +// Compute w = u / v, where u and w are vectors, and v is a scalar. +// - 0 < v < HALF_DIGIT_RADIX. Below, we rename w to q. +void +vec_div_small(int ulen, const sc_digit *u, + sc_digit v, sc_digit *q) +{ + + // Given (u = u_1u_2...u_n)_b = (q = q_1q_2...q_n) * v + r, where b + // is the base, and 0 <= r < v. Then, the algorithm is as follows: + // + // r = 0; + // for (j = 1; j <= n; j++) { + // q_j = (r * b + u_j) / v; + // r = (r * b + u_j) % v; + // } + // + // In our case, b = DIGIT_RADIX, and u = Ax + B and q = Cx + D where + // x = HALF_DIGIT_RADIX. Note that r < v < x and b = x^2. Then, a + // typical situation is as follows: + // + // ---- ---- + // 0 r + // ---- ---- + // A B + // ---- ---- ---- + // r A B = r * b + u + // + // Hence, C = (r|A) / v. + // D = (((r|A) % v)|B) / v + // r = (((r|A) % v)|B) % v + +#ifdef DEBUG_SYSTEMC + assert((ulen > 0) && (u != NULL)); + assert(q != NULL); + assert((0 < v) && (v < HALF_DIGIT_RADIX)); +#endif + +#define q_h r + + sc_digit r = 0; + const sc_digit *ubegin = u; + + u += ulen; + q += ulen; + + while (ubegin < u) { + + sc_digit u_AB = (*--u); // A|B + +#ifdef DEBUG_SYSTEMC + // The overflow bits must be zero. + assert(high_half(u_AB) == high_half_masked(u_AB)); +#endif + + sc_digit num = concat(r, high_half(u_AB)); // num = r|A + q_h = num / v; // C + num = concat((num % v), low_half(u_AB)); // num = (((r|A) % v)|B) + (*--q) = concat(q_h, num / v); // q = C|D + r = num % v; + + } + +#undef q_h + +} + +// Compute w = u % v, where w, u, and v are vectors. +// - u and v are assumed to have at least two digits as uchars. +void +vec_rem_large(int ulen, const sc_digit *u, + int vlen, const sc_digit *v, + sc_digit *w) +{ + +#ifdef DEBUG_SYSTEMC + assert((ulen > 0) && (u != NULL)); + assert((vlen > 0) && (v != NULL)); + assert(w != NULL); + assert(BITS_PER_DIGIT >= 3 * BITS_PER_BYTE); +#endif + + // This function is adapted from vec_div_large. + + int xlen = BYTES_PER_DIGIT * ulen + 1; + int ylen = BYTES_PER_DIGIT * vlen; + +#ifdef SC_MAX_NBITS + uchar x[DIV_CEIL2(SC_MAX_NBITS, BITS_PER_BYTE)]; + uchar y[DIV_CEIL2(SC_MAX_NBITS, BITS_PER_BYTE)]; +#else + uchar *x = new uchar[xlen]; + uchar *y = new uchar[ylen]; +#endif + + // r corresponds to w. + + // Set (uchar) x = (sc_digit) u. + xlen = vec_to_char(ulen, u, xlen, x); + + // Skip all the leading zeros in x. + while ((--xlen >= 0) && (! x[xlen])) continue; + xlen++; + + // Set (uchar) y = (sc_digit) v. + ylen = vec_to_char(vlen, v, ylen, y); + + // Skip all the leading zeros in y. + while ((--ylen >= 0) && (! y[ylen])) continue; + ylen++; + +#ifdef DEBUG_SYSTEMC + assert(xlen > 1); + assert(ylen > 1); +#endif + + // At this point, all the leading zeros are eliminated from x and y. + + // Zero the last digit of x. + x[xlen] = 0; + + // The first two digits of y. + sc_digit y2 = (y[ylen - 1] << BITS_PER_BYTE) + y[ylen - 2]; + + const sc_digit DOUBLE_BITS_PER_BYTE = 2 * BITS_PER_BYTE; + + // Find each q[k]. + for (int k = xlen - ylen; k >= 0; --k) { + + // qk is a guess for q[k] such that q[k] = qk or qk - 1. + sc_digit qk; + + // Find qk by just using 2 digits of y and 3 digits of x. The + // following code assumes that sizeof(sc_digit) >= 3 BYTEs. + int k2 = k + ylen; + + qk = ((x[k2] << DOUBLE_BITS_PER_BYTE) + + (x[k2 - 1] << BITS_PER_BYTE) + x[k2 - 2]) / y2; + + if (qk >= BYTE_RADIX) // qk cannot be larger than the largest + qk = BYTE_RADIX - 1; // digit in BYTE_RADIX. + + // q[k] = qk or qk - 1. The following if-statement determines which. + if (qk) { + + uchar *xk = (x + k); // A shortcut for x[k]. + + // x = x - y * qk; + sc_digit carry = 0; + + for (int i = 0; i < ylen; ++i) { + carry += y[i] * qk; + sc_digit diff = (xk[i] + BYTE_RADIX) - (carry & BYTE_MASK); + xk[i] = (uchar)(diff & BYTE_MASK); + carry = (carry >> BITS_PER_BYTE) + (1 - (diff >> BITS_PER_BYTE)); + } + + if (carry) { + + // 2's complement the last digit. + carry = (xk[ylen] + BYTE_RADIX) - carry; + xk[ylen] = (uchar)(carry & BYTE_MASK); + carry = 1 - (carry >> BITS_PER_BYTE); + + if (carry) { + + // qk was one too large, so decrement it. + // --qk; + + // x = x - y * (qk - 1) = x - y * qk + y = x_above + y. + carry = 0; + + for (int i = 0; i < ylen; ++i) { + carry += xk[i] + y[i]; + xk[i] = (uchar)(carry & BYTE_MASK); + carry >>= BITS_PER_BYTE; + } + + if (carry) + xk[ylen] = (uchar)((xk[ylen] + 1) & BYTE_MASK); + + } // second if carry + } // first if carry + } // if qk + } // for k + + // Set (sc_digit) w = (uchar) x for the remainder. + vec_from_char(ylen, x, ulen, w); + +#ifndef SC_MAX_NBITS + delete [] x; + delete [] y; +#endif + +} + +// Compute r = u % v, where u is a vector, and r and v are scalars. +// - 0 < v < HALF_DIGIT_RADIX. +// - The remainder r is returned. +sc_digit +vec_rem_small(int ulen, const sc_digit *u, sc_digit v) +{ + +#ifdef DEBUG_SYSTEMC + assert((ulen > 0) && (u != NULL)); + assert((0 < v) && (v < HALF_DIGIT_RADIX)); +#endif + + // This function is adapted from vec_div_small(). + + sc_digit r = 0; + const sc_digit *ubegin = u; + + u += ulen; + + while (ubegin < u) { + sc_digit u_AB = (*--u); // A|B + +#ifdef DEBUG_SYSTEMC + // The overflow bits must be zero. + assert(high_half(u_AB) == high_half_masked(u_AB)); +#endif + + // r = (((r|A) % v)|B) % v + r = (concat(((concat(r, high_half(u_AB))) % v), low_half(u_AB))) % v; + } + + return r; + +} + +// u = u / v, r = u % v. +sc_digit +vec_rem_on_small(int ulen, sc_digit *u, sc_digit v) +{ + +#ifdef DEBUG_SYSTEMC + assert((ulen > 0) && (u != NULL)); + assert(v > 0); +#endif + +#define q_h r + + sc_digit r = 0; + const sc_digit *ubegin = u; + + u += ulen; + + while (ubegin < u) { + + sc_digit u_AB = (*--u); // A|B + +#ifdef DEBUG_SYSTEMC + // The overflow bits must be zero. + assert(high_half(u_AB) == high_half_masked(u_AB)); +#endif + + sc_digit num = concat(r, high_half(u_AB)); // num = r|A + q_h = num / v; // C + num = concat((num % v), low_half(u_AB)); // num = (((r|A) % v)|B) + (*u) = concat(q_h, num / v); // q = C|D + r = num % v; + + } + +#undef q_h + + return r; + +} + +// Set (uchar) v = (sc_digit) u. Return the new vlen. +int +vec_to_char(int ulen, const sc_digit *u, + int vlen, uchar *v) +{ + +#ifdef DEBUG_SYSTEMC + assert((ulen > 0) && (u != NULL)); + assert((vlen > 0) && (v != NULL)); +#endif + + int nbits = ulen * BITS_PER_DIGIT; + + int right = 0; + int left = right + BITS_PER_BYTE - 1; + + vlen = 0; + + while (nbits > 0) { + + int left_digit = left / BITS_PER_DIGIT; + int right_digit = right / BITS_PER_DIGIT; + + int nsr = ((vlen << LOG2_BITS_PER_BYTE) % BITS_PER_DIGIT); + + int d = u[right_digit] >> nsr; + + if (left_digit != right_digit) { + + if (left_digit < ulen) + d |= u[left_digit] << (BITS_PER_DIGIT - nsr); + + } + + v[vlen++] = (uchar)(d & BYTE_MASK); + + left += BITS_PER_BYTE; + right += BITS_PER_BYTE; + nbits -= BITS_PER_BYTE; + + } + + return vlen; + +} + +// Set (sc_digit) v = (uchar) u. +// - sizeof(uchar) <= sizeof(sc_digit), +void +vec_from_char(int ulen, const uchar *u, + int vlen, sc_digit *v) +{ + +#ifdef DEBUG_SYSTEMC + assert((ulen > 0) && (u != NULL)); + assert((vlen > 0) && (v != NULL)); + assert(sizeof(uchar) <= sizeof(sc_digit)); +#endif + + sc_digit *vend = (v + vlen); + + const int nsr = BITS_PER_DIGIT - BITS_PER_BYTE; + const sc_digit mask = one_and_ones(nsr); + + (*v) = (sc_digit) u[ulen - 1]; + + for (int i = ulen - 2; i >= 0; --i) { + + // Manual inlining of vec_shift_left(). + + sc_digit *viter = v; + + sc_digit carry = 0; + + while (viter < vend) { + sc_digit vval = (*viter); + (*viter++) = (((vval & mask) << BITS_PER_BYTE) | carry); + carry = vval >> nsr; + } + + if (viter < vend) + (*viter) = carry; + + (*v) |= (sc_digit) u[i]; + + } + +} + +// Set u <<= nsl. +// If nsl is negative, it is ignored. +void +vec_shift_left(int ulen, sc_digit *u, int nsl) +{ + +#ifdef DEBUG_SYSTEMC + assert((ulen > 0) && (u != NULL)); +#endif + + if (nsl <= 0) + return; + + // Shift left whole digits if nsl is large enough. + if (nsl >= (int) BITS_PER_DIGIT) { + + int nd; + + if (nsl % BITS_PER_DIGIT == 0) { + nd = nsl / BITS_PER_DIGIT; // No need to use DIV_CEIL(nsl). + nsl = 0; + } + else { + nd = DIV_CEIL(nsl) - 1; + nsl -= nd * BITS_PER_DIGIT; + } + + if (nd) { + + // Shift left for nd digits. + for (int j = ulen - 1; j >= nd; --j) + u[j] = u[j - nd]; + + vec_zero( sc_min( nd, ulen ), u ); + + } + + if (nsl == 0) + return; + + } + + // Shift left if nsl < BITS_PER_DIGIT. + sc_digit *uiter = u; + sc_digit *uend = uiter + ulen; + + int nsr = BITS_PER_DIGIT - nsl; + sc_digit mask = one_and_ones(nsr); + + sc_digit carry = 0; + + while (uiter < uend) { + sc_digit uval = (*uiter); + (*uiter++) = (((uval & mask) << nsl) | carry); + carry = uval >> nsr; + } + + if (uiter < uend) + (*uiter) = carry; + +} + +// Set u >>= nsr. +// If nsr is negative, it is ignored. +void +vec_shift_right(int ulen, sc_digit *u, int nsr, sc_digit fill) +{ + +#ifdef DEBUG_SYSTEMC + assert((ulen > 0) && (u != NULL)); +#endif + + // fill is usually either 0 or DIGIT_MASK; it can be any value. + + if (nsr <= 0) + return; + + // Shift right whole digits if nsr is large enough. + if (nsr >= (int) BITS_PER_DIGIT) { + + int nd; + + if (nsr % BITS_PER_DIGIT == 0) { + nd = nsr / BITS_PER_DIGIT; + nsr = 0; + } + else { + nd = DIV_CEIL(nsr) - 1; + nsr -= nd * BITS_PER_DIGIT; + } + + if (nd) { + + // Shift right for nd digits. + for (int j = 0; j < (ulen - nd); ++j) + u[j] = u[j + nd]; + + if (fill) { + for (int j = ulen - sc_min( nd, ulen ); j < ulen; ++j) + u[j] = fill; + } + else + vec_zero(ulen - sc_min( nd, ulen ), ulen, u); + + } + + if (nsr == 0) + return; + + } + + // Shift right if nsr < BITS_PER_DIGIT. + sc_digit *ubegin = u; + sc_digit *uiter = (ubegin + ulen); + + int nsl = BITS_PER_DIGIT - nsr; + sc_digit mask = one_and_ones(nsr); + + sc_digit carry = (fill & mask) << nsl; + + while (ubegin < uiter) { + sc_digit uval = (*--uiter); + (*uiter) = (uval >> nsr) | carry; + carry = (uval & mask) << nsl; + } + +} + + +// Let u[l..r], where l and r are left and right bit positions +// respectively, be equal to its mirror image. +void +vec_reverse(int unb, int und, sc_digit *ud, + int l, int r) +{ + +#ifdef DEBUG_SYSTEMC + assert((unb > 0) && (und > 0) && (ud != NULL)); + assert((0 <= r) && (r <= l) && (l < unb)); +#endif + + if (l < r) { + char msg[BUFSIZ]; + std::sprintf( msg, "vec_reverse( int, int, sc_digit*, int l, int r ) : " + "l = %d < r = %d is not valid", + l, r ); + SC_REPORT_ERROR( sc_core::SC_ID_CONVERSION_FAILED_, msg ); + } + + // Make sure that l and r are within bounds. + r = sc_max(r, 0); + l = sc_min(l, unb - 1); + + // Allocate memory for processing. +#ifdef SC_MAX_NBITS + sc_digit d[MAX_NDIGITS]; +#else + sc_digit *d = new sc_digit[und]; +#endif + + // d is a copy of ud. + vec_copy(und, d, ud); + + // Based on the value of the ith in d, find the value of the jth bit + // in ud. + + for (int i = l, j = r; i >= r; --i, ++j) { + + if ((d[digit_ord(i)] & one_and_zeros(bit_ord(i))) != 0) // Test. + ud[digit_ord(j)] |= one_and_zeros(bit_ord(j)); // Set. + else + ud[digit_ord(j)] &= ~(one_and_zeros(bit_ord(j))); // Clear. + + } + +#ifndef SC_MAX_NBITS + delete [] d; +#endif + +} + +} // namespace sc_dt + + +// End of file. diff --git a/ext/systemc/src/sysc/datatypes/int/sc_nbutils.h b/ext/systemc/src/sysc/datatypes/int/sc_nbutils.h new file mode 100644 index 000000000..0bd4b4b03 --- /dev/null +++ b/ext/systemc/src/sysc/datatypes/int/sc_nbutils.h @@ -0,0 +1,1051 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_nbutils.h -- External and friend functions for both sc_signed and + sc_unsigned classes. + + Original Author: Ali Dasdan, Synopsys, Inc. + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + +// $Log: sc_nbutils.h,v $ +// Revision 1.6 2011/09/08 16:12:15 acg +// Philipp A. Hartmann: fix issue with Sun machines wrt real math libraries. +// +// Revision 1.5 2011/08/26 23:00:01 acg +// Torsten Maehne: remove use of ieeefp.h. +// +// Revision 1.4 2011/08/15 16:43:24 acg +// Torsten Maehne: changes to remove unused argument warnings. +// +// Revision 1.3 2011/02/18 20:19:15 acg +// Andy Goodrich: updating Copyright notice. +// +// Revision 1.2 2010/09/06 16:35:48 acg +// Andy Goodrich: changed i386 to __i386__ in ifdef's. +// +// Revision 1.1.1.1 2006/12/15 20:20:05 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:49:32 acg +// Added $Log command so that CVS check in comments are reproduced in the +// source. +// + +#ifndef SC_NBUTILS_H +#define SC_NBUTILS_H + +#include <cmath> +#include <limits> + +#include "sysc/datatypes/bit/sc_bit_ids.h" +#include "sysc/datatypes/int/sc_int_ids.h" +#include "sysc/datatypes/int/sc_nbdefs.h" +#include "sysc/utils/sc_report.h" + + +namespace sc_dt +{ + +//----------------------------------------------------------------------------- +//"sc_io_base" +// +// This inline function returns the type of an i/o stream's base as a SystemC +// base designator. +// stream_object = reference to the i/o stream whose base is to be returned. +// +//"sc_io_show_base" +// +// This inline function returns true if the base should be shown when a SystemC +// value is displayed via the supplied stream operator. +// stream_object = reference to the i/o stream to return showbase value for. +//----------------------------------------------------------------------------- +#if defined(__GNUC__) || defined(_MSC_VER) || defined(__SUNPRO_CC) + inline sc_numrep + sc_io_base( systemc_ostream& os, sc_numrep def_base ) + { + std::ios::fmtflags flags = os.flags() & std::ios::basefield; + if ( flags & ::std::ios::dec ) return SC_DEC; + if ( flags & ::std::ios::hex ) return SC_HEX; + if ( flags & ::std::ios::oct ) return SC_OCT; + return def_base; + } + + inline bool + sc_io_show_base( systemc_ostream& os ) + { + return (os.flags() & ::std::ios::showbase) != 0 ; + } +#else // Other + inline sc_numrep + sc_io_base( systemc_ostream& /*unused*/, sc_numrep /*unused*/ ) + { + return SC_DEC; + } + inline bool + sc_io_show_base( systemc_ostream& /*unused*/ ) + { + return false; + } +#endif + +const std::string to_string( sc_numrep ); + +inline +systemc_ostream& +operator << ( systemc_ostream& os, sc_numrep numrep ) +{ + os << to_string( numrep ); + return os; +} + +// only used within vec_from_str (non-standard, deprecated) +inline void +is_valid_base(sc_numrep base) +{ + switch (base) { + case SC_NOBASE: case SC_BIN: + case SC_OCT: case SC_DEC: + case SC_HEX: + break; + case SC_BIN_US: case SC_BIN_SM: + case SC_OCT_US: case SC_OCT_SM: + case SC_HEX_US: case SC_HEX_SM: + case SC_CSD: + SC_REPORT_ERROR( sc_core::SC_ID_NOT_IMPLEMENTED_, + "is_valid_base( sc_numrep base ) : " + "bases SC_CSD, or ending in _US and _SM are not supported" ); + break; + default: + char msg[BUFSIZ]; + std::sprintf( msg, "is_valid_base( sc_numrep base ) : " + "base = %s is not valid", + to_string( base ).c_str() ); + SC_REPORT_ERROR( sc_core::SC_ID_VALUE_NOT_VALID_, msg ); + } +} + +// ---------------------------------------------------------------------------- + +// One transition of the FSM to find base and sign of a number. +extern +small_type +fsm_move(char c, small_type &b, small_type &s, small_type &state); + +// Parse a character string into its equivalent binary bits. +extern +void parse_binary_bits( + const char* src_p, int dst_n, sc_digit* data_p, sc_digit* ctrl_p=0 +); + + +// Parse a character string into its equivalent hexadecimal bits. +extern +void parse_hex_bits( + const char* src_p, int dst_n, sc_digit* data_p, sc_digit* ctrl_p=0 +); + + +// Find the base and sign of a number in v. +extern +const char * +get_base_and_sign(const char *v, small_type &base, small_type &sign); + +// Create a number out of v in base. +extern +small_type +vec_from_str(int unb, int und, sc_digit *u, + const char *v, sc_numrep base = SC_NOBASE) ; + + +// ---------------------------------------------------------------------------- +// Naming convention for the vec_ functions below: +// vec_OP(u, v, w) : computes w = u OP v. +// vec_OP_on(u, v) : computes u = u OP v if u has more digits than v. +// vec_OP_on2(u, v) : computes u = u OP v if u has fewer digits than v. +// _large : parameters are vectors. +// _small : one of the parameters is a single digit. +// Xlen : the number of digits in X. +// ---------------------------------------------------------------------------- + +// ---------------------------------------------------------------------------- +// Functions for vector addition: w = u + v or u += v. +// ---------------------------------------------------------------------------- + +extern +void +vec_add(int ulen, const sc_digit *u, + int vlen, const sc_digit *v, sc_digit *w); + +extern +void +vec_add_on(int ulen, sc_digit *u, + int vlen, const sc_digit *v); + +extern +void +vec_add_on2(int ulen, sc_digit *u, + int vlen, const sc_digit *v); + +extern +void +vec_add_small(int ulen, const sc_digit *u, + sc_digit v, sc_digit *w); + +extern +void +vec_add_small_on(int ulen, sc_digit *u, sc_digit v); + + +// ---------------------------------------------------------------------------- +// Functions for vector subtraction: w = u - v, u -= v, or u = v - u. +// ---------------------------------------------------------------------------- + +extern +void +vec_sub(int ulen, const sc_digit *u, + int vlen, const sc_digit *v, sc_digit *w); + +extern +void +vec_sub_on(int ulen, sc_digit *u, + int vlen, const sc_digit *v); + +extern +void +vec_sub_on2(int ulen, sc_digit *u, + int vlen, const sc_digit *v); + +extern +void +vec_sub_small(int ulen, const sc_digit *u, + sc_digit v, sc_digit *w); + +extern +void +vec_sub_small_on(int ulen, sc_digit *u, sc_digit v); + + +// ---------------------------------------------------------------------------- +// Functions for vector multiplication: w = u * v or u *= v. +// ---------------------------------------------------------------------------- + +extern +void +vec_mul(int ulen, const sc_digit *u, + int vlen, const sc_digit *v, sc_digit *w); + +extern +void +vec_mul_small(int ulen, const sc_digit *u, + sc_digit v, sc_digit *w); + +extern +void +vec_mul_small_on(int ulen, sc_digit *u, sc_digit v); + + +// ---------------------------------------------------------------------------- +// Functions for vector division: w = u / v. +// ---------------------------------------------------------------------------- + +extern +void +vec_div_large(int ulen, const sc_digit *u, + int vlen, const sc_digit *v, sc_digit *w); + +extern +void +vec_div_small(int ulen, const sc_digit *u, + sc_digit v, sc_digit *w); + + +// ---------------------------------------------------------------------------- +// Functions for vector remainder: w = u % v or u %= v. +// ---------------------------------------------------------------------------- + +extern +void +vec_rem_large(int ulen, const sc_digit *u, + int vlen, const sc_digit *v, sc_digit *w); + +extern +sc_digit +vec_rem_small(int ulen, const sc_digit *u, sc_digit v); + +extern +sc_digit +vec_rem_on_small(int ulen, sc_digit *u, sc_digit v); + + +// ---------------------------------------------------------------------------- +// Functions to convert between vectors of char and sc_digit. +// ---------------------------------------------------------------------------- + +extern +int +vec_to_char(int ulen, const sc_digit *u, + int vlen, uchar *v); + +extern +void +vec_from_char(int ulen, const uchar *u, + int vlen, sc_digit *v); + + +// ---------------------------------------------------------------------------- +// Functions to shift left or right, or to create a mirror image of vectors. +// ---------------------------------------------------------------------------- + +extern +void +vec_shift_left(int ulen, sc_digit *u, int nsl); + +extern +void +vec_shift_right(int vlen, sc_digit *u, int nsr, sc_digit fill = 0); + +extern +void +vec_reverse(int unb, int und, sc_digit *ud, + int l, int r = 0); + + +// ---------------------------------------------------------------------------- +// Various utility functions. +// ---------------------------------------------------------------------------- + +// Return the low half part of d. +inline +sc_digit +low_half(sc_digit d) +{ + return (d & HALF_DIGIT_MASK); +} + +// Return the high half part of d. The high part of the digit may have +// more bits than BITS_PER_HALF_DIGIT due to, e.g., overflow in the +// multiplication. Hence, in other functions that use high_half(), +// make sure that the result contains BITS_PER_HALF_DIGIT if +// necessary. This is done by high_half_masked(). +inline +sc_digit +high_half(sc_digit d) +{ + return (d >> BITS_PER_HALF_DIGIT); +} + +inline +sc_digit +high_half_masked(sc_digit d) +{ + return (high_half(d) & HALF_DIGIT_MASK); +} + +// Concatenate the high part h and low part l. Assumes that h and l +// are less than or equal to HALF_DIGIT_MASK; +inline +sc_digit +concat(sc_digit h, sc_digit l) +{ + return ((h << BITS_PER_HALF_DIGIT) | l); +} + +// Create a number with n 1's. +inline +sc_digit +one_and_ones(int n) +{ + return (((sc_digit) 1 << n) - 1); +} + +// Create a number with one 1 and n 0's. +inline +sc_digit +one_and_zeros(int n) +{ + return ((sc_digit) 1 << n); +} + + +// ---------------------------------------------------------------------------- + +// Find the digit that bit i is in. +inline +int +digit_ord(int i) +{ + return (i / BITS_PER_DIGIT); +} + +// Find the bit in digit_ord(i) that bit i corressponds to. +inline +int +bit_ord(int i) +{ + return (i % BITS_PER_DIGIT); +} + + +// ---------------------------------------------------------------------------- +// Functions to compare, zero, complement vector(s). +// ---------------------------------------------------------------------------- + +// Compare u and v and return r +// r = 0 if u == v +// r < 0 if u < v +// r > 0 if u > v +// - Assume that all the leading zero digits are already skipped. +// - ulen and/or vlen can be zero. +// - Every digit is less than or equal to DIGIT_MASK; +inline +int +vec_cmp(int ulen, const sc_digit *u, + int vlen, const sc_digit *v) +{ + +#ifdef DEBUG_SYSTEMC + // assert((ulen <= 0) || (u != NULL)); + // assert((vlen <= 0) || (v != NULL)); + + // ulen and vlen can be equal to 0 because vec_cmp can be called + // after vec_skip_leading_zeros. + assert((ulen >= 0) && (u != NULL)); + assert((vlen >= 0) && (v != NULL)); + // If ulen > 0, then the leading digit of u must be non-zero. + assert((ulen <= 0) || (u[ulen - 1] != 0)); + assert((vlen <= 0) || (v[vlen - 1] != 0)); +#endif + + if (ulen != vlen) + return (ulen - vlen); + + // ulen == vlen >= 1 + while ((--ulen >= 0) && (u[ulen] == v[ulen])) + ; + + if (ulen < 0) + return 0; + +#ifdef DEBUG_SYSTEMC + // Test to see if the result is wrong due to the presence of + // overflow bits. + assert((u[ulen] & DIGIT_MASK) != (v[ulen] & DIGIT_MASK)); +#endif + + return (int) (u[ulen] - v[ulen]); + +} + +// Find the index of the first non-zero digit. +// - ulen (before) = the number of digits in u. +// - the returned value = the index of the first non-zero digit. +// A negative value of -1 indicates that every digit in u is zero. +inline +int +vec_find_first_nonzero(int ulen, const sc_digit *u) +{ + +#ifdef DEBUG_SYSTEMC + // assert((ulen <= 0) || (u != NULL)); + assert((ulen > 0) && (u != NULL)); +#endif + + while ((--ulen >= 0) && (! u[ulen])) + ; + + return ulen; + +} + +// Skip all the leading zero digits. +// - ulen (before) = the number of digits in u. +// - the returned value = the number of non-zero digits in u. +// - the returned value is non-negative. +inline +int +vec_skip_leading_zeros(int ulen, const sc_digit *u) +{ + +#ifdef DEBUG_SYSTEMC + // assert((ulen <= 0) || (u != NULL)); + assert((ulen > 0) && (u != NULL)); +#endif + + return (1 + vec_find_first_nonzero(ulen, u)); + +} + +// Compare u and v and return r +// r = 0 if u == v +// r < 0 if u < v +// r > 0 if u > v +inline +int +vec_skip_and_cmp(int ulen, const sc_digit *u, + int vlen, const sc_digit *v) +{ + +#ifdef DEBUG_SYSTEMC + assert((ulen > 0) && (u != NULL)); + assert((vlen > 0) && (v != NULL)); +#endif + + ulen = vec_skip_leading_zeros(ulen, u); + vlen = vec_skip_leading_zeros(vlen, v); + // ulen and/or vlen can be equal to zero here. + return vec_cmp(ulen, u, vlen, v); + +} + +// Set u[i] = 0 where i = from ... (ulen - 1). +inline +void +vec_zero(int from, int ulen, sc_digit *u) +{ + +#ifdef DEBUG_SYSTEMC + assert((ulen > 0) && (u != NULL)); +#endif + + for(int i = from; i < ulen; i++) + u[i] = 0; + +} + +// Set u[i] = 0 where i = 0 .. (ulen - 1). +inline +void +vec_zero(int ulen, sc_digit *u) +{ + vec_zero(0, ulen, u); +} + +// Copy n digits from v to u. +inline +void +vec_copy(int n, sc_digit *u, const sc_digit *v) +{ + +#ifdef DEBUG_SYSTEMC + assert((n > 0) && (u != NULL) && (v != NULL)); +#endif + + for (int i = 0; i < n; ++i) + u[i] = v[i]; +} + +// Copy v to u, where ulen >= vlen, and zero the rest of the digits in u. +inline +void +vec_copy_and_zero(int ulen, sc_digit *u, + int vlen, const sc_digit *v) +{ + +#ifdef DEBUG_SYSTEMC + assert((ulen > 0) && (u != NULL)); + assert((vlen > 0) && (v != NULL)); + assert(ulen >= vlen); +#endif + + vec_copy(vlen, u, v); + vec_zero(vlen, ulen, u); + +} + +// 2's-complement the digits in u. +inline +void +vec_complement(int ulen, sc_digit *u) +{ + +#ifdef DEBUG_SYSTEMC + assert((ulen > 0) && (u != NULL)); +#endif + + sc_digit carry = 1; + + for (int i = 0; i < ulen; ++i) { + carry += (~u[i] & DIGIT_MASK); + u[i] = carry & DIGIT_MASK; + carry >>= BITS_PER_DIGIT; + } + +} + + +// ---------------------------------------------------------------------------- +// Functions to handle built-in types or signs. +// ---------------------------------------------------------------------------- + +// u = v +// - v is an unsigned long or uint64, and positive integer. +template< class Type > +inline +void +from_uint(int ulen, sc_digit *u, Type v) +{ + +#ifdef DEBUG_SYSTEMC + // assert((ulen <= 0) || (u != NULL)); + assert((ulen > 0) && (u != NULL)); + assert(v >= 0); +#endif + + int i = 0; + + while (v && (i < ulen)) { +#ifndef _WIN32 + u[i++] = static_cast<sc_digit>( v & DIGIT_MASK ); +#else + u[i++] = ((sc_digit) v) & DIGIT_MASK; +#endif + v >>= BITS_PER_DIGIT; + } + + vec_zero(i, ulen, u); + +} + + +// Get u's sign and return its absolute value. +// u can be long, unsigned long, int64, or uint64. +template< class Type > +inline +small_type +get_sign(Type &u) +{ + if (u > 0) + return SC_POS; + + if (u == 0) + return SC_ZERO; + + // no positive number representable for minimum value, + // leave as is to avoid Undefined Behaviour + if( SC_LIKELY_( u > (std::numeric_limits<Type>::min)() ) ) + u = -u; + + return SC_NEG; +} + + +// Return us * vs: +// - Return SC_ZERO if either sign is SC_ZERO. +// - Return SC_POS if us == vs +// - Return SC_NEG if us != vs. +inline +small_type +mul_signs(small_type us, small_type vs) +{ + if ((us == SC_ZERO) || (vs == SC_ZERO)) + return SC_ZERO; + + if (us == vs) + return SC_POS; + + return SC_NEG; +} + + +// ---------------------------------------------------------------------------- +// Functions to test for errors and print out error messages. +// ---------------------------------------------------------------------------- + +#ifdef SC_MAX_NBITS + +inline +void +test_bound(int nb) +{ + if (nb > SC_MAX_NBITS) { + char msg[BUFSIZ]; + std::sprintf( msg, "test_bound( int nb ) : " + "nb = %d > SC_MAX_NBITS = %d is not valid", + nb, SC_MAX_NBITS ); + SC_REPORT_ERROR( sc_core::SC_ID_OUT_OF_BOUNDS_, msg ); + } +} + +#endif + +template< class Type > +inline +void +div_by_zero(Type s) +{ + if (s == 0) { + SC_REPORT_ERROR( sc_core::SC_ID_OPERATION_FAILED_, + "div_by_zero<Type>( Type ) : division by zero" ); + } +} + + +// ---------------------------------------------------------------------------- +// Functions to check if a given vector is zero or make one. +// ---------------------------------------------------------------------------- + +// If u[i] is zero for every i = 0,..., ulen - 1, return SC_ZERO, +// else return s. +inline +small_type +check_for_zero(small_type s, int ulen, const sc_digit *u) +{ + +#ifdef DEBUG_SYSTEMC + // assert(ulen >= 0); + assert((ulen > 0) && (u != NULL)); +#endif + + if (vec_find_first_nonzero(ulen, u) < 0) + return SC_ZERO; + + return s; + +} + +// If u[i] is zero for every i = 0,..., ulen - 1, return true, +// else return false. +inline +bool +check_for_zero(int ulen, const sc_digit *u) +{ + +#ifdef DEBUG_SYSTEMC + // assert(ulen >= 0); + assert((ulen > 0) && (u != NULL)); +#endif + + if (vec_find_first_nonzero(ulen, u) < 0) + return true; + + return false; + +} + +inline +small_type +make_zero(int nd, sc_digit *d) +{ + vec_zero(nd, d); + return SC_ZERO; +} + + +// ---------------------------------------------------------------------------- +// Functions for both signed and unsigned numbers to convert sign-magnitude +// (SM) and 2's complement (2C) representations. +// added = 1 => for signed. +// added = 0 => for unsigned. +// IF_SC_SIGNED can be used as 'added'. +// ---------------------------------------------------------------------------- + +// Trim the extra leading bits of a signed or unsigned number. +inline +void +trim(small_type added, int nb, int nd, sc_digit *d) +{ +#ifdef DEBUG_SYSTEMC + assert((nb > 0) && (nd > 0) && (d != NULL)); +#endif + + d[nd - 1] &= one_and_ones(bit_ord(nb - 1) + added); +} + +// Convert an (un)signed number from sign-magnitude representation to +// 2's complement representation and trim the extra bits. +inline +void +convert_SM_to_2C_trimmed(small_type added, + small_type s, int nb, int nd, sc_digit *d) +{ + if (s == SC_NEG) { + vec_complement(nd, d); + trim(added, nb, nd, d); + } +} + +// Convert an (un)signed number from sign-magnitude representation to +// 2's complement representation but do not trim the extra bits. +inline +void +convert_SM_to_2C(small_type s, int nd, sc_digit *d) +{ + if (s == SC_NEG) + vec_complement(nd, d); +} + + +// ---------------------------------------------------------------------------- +// Functions to convert between sign-magnitude (SM) and 2's complement +// (2C) representations of signed numbers. +// ---------------------------------------------------------------------------- + +// Trim the extra leading bits off a signed number. +inline +void +trim_signed(int nb, int nd, sc_digit *d) +{ +#ifdef DEBUG_SYSTEMC + assert((nb > 0) && (nd > 0) && (d != NULL)); +#endif + + d[nd - 1] &= one_and_ones(bit_ord(nb - 1) + 1); +} + +// Convert a signed number from 2's complement representation to +// sign-magnitude representation, and return its sign. nd is d's +// actual size, without zeros eliminated. +inline +small_type +convert_signed_2C_to_SM(int nb, int nd, sc_digit *d) +{ + +#ifdef DEBUG_SYSTEMC + assert((nb > 0) && (nd > 0) && (d != NULL)); +#endif + + small_type s; + + int xnb = bit_ord(nb - 1) + 1; + + // Test the sign bit. + if (d[nd - 1] & one_and_zeros(xnb - 1)) { + s = SC_NEG; + vec_complement(nd, d); + } + else + s = SC_POS; + + // Trim the last digit. + d[nd - 1] &= one_and_ones(xnb); + + // Check if the new number is zero. + if (s == SC_POS) + return check_for_zero(s, nd, d); + + return s; + +} + +// Convert a signed number from sign-magnitude representation to 2's +// complement representation, get its sign, convert back to +// sign-magnitude representation, and return its sign. nd is d's +// actual size, without zeros eliminated. +inline +small_type +convert_signed_SM_to_2C_to_SM(small_type s, int nb, int nd, sc_digit *d) +{ + convert_SM_to_2C(s, nd, d); + return convert_signed_2C_to_SM(nb, nd, d); +} + +// Convert a signed number from sign-magnitude representation to 2's +// complement representation and trim the extra bits. +inline +void +convert_signed_SM_to_2C_trimmed(small_type s, int nb, int nd, sc_digit *d) +{ + convert_SM_to_2C_trimmed(1, s, nb, nd, d); +} + +// Convert a signed number from sign-magnitude representation to 2's +// complement representation but do not trim the extra bits. +inline +void +convert_signed_SM_to_2C(small_type s, int nd, sc_digit *d) +{ + convert_SM_to_2C(s, nd, d); +} + + +// ---------------------------------------------------------------------------- +// Functions to convert between sign-magnitude (SM) and 2's complement +// (2C) representations of unsigned numbers. +// ---------------------------------------------------------------------------- + +// Trim the extra leading bits off an unsigned number. +inline +void +trim_unsigned(int nb, int nd, sc_digit *d) +{ +#ifdef DEBUG_SYSTEMC + assert((nb > 0) && (nd > 0) && (d != NULL)); +#endif + + d[nd - 1] &= one_and_ones(bit_ord(nb - 1)); +} + +// Convert an unsigned number from 2's complement representation to +// sign-magnitude representation, and return its sign. nd is d's +// actual size, without zeros eliminated. +inline +small_type +convert_unsigned_2C_to_SM(int nb, int nd, sc_digit *d) +{ + trim_unsigned(nb, nd, d); + return check_for_zero(SC_POS, nd, d); +} + +// Convert an unsigned number from sign-magnitude representation to +// 2's complement representation, get its sign, convert back to +// sign-magnitude representation, and return its sign. nd is d's +// actual size, without zeros eliminated. +inline +small_type +convert_unsigned_SM_to_2C_to_SM(small_type s, int nb, int nd, sc_digit *d) +{ + convert_SM_to_2C(s, nd, d); + return convert_unsigned_2C_to_SM(nb, nd, d); +} + +// Convert an unsigned number from sign-magnitude representation to +// 2's complement representation and trim the extra bits. +inline +void +convert_unsigned_SM_to_2C_trimmed(small_type s, int nb, int nd, sc_digit *d) +{ + convert_SM_to_2C_trimmed(0, s, nb, nd, d); +} + +// Convert an unsigned number from sign-magnitude representation to +// 2's complement representation but do not trim the extra bits. +inline +void +convert_unsigned_SM_to_2C(small_type s, int nd, sc_digit *d) +{ + convert_SM_to_2C(s, nd, d); +} + + +// ---------------------------------------------------------------------------- +// Functions to copy one (un)signed number to another. +// ---------------------------------------------------------------------------- + +// Copy v to u. +inline +void +copy_digits_signed(small_type &us, + int unb, int und, sc_digit *ud, + int vnb, int vnd, const sc_digit *vd) +{ + + if (und <= vnd) { + + vec_copy(und, ud, vd); + + if (unb <= vnb) + us = convert_signed_SM_to_2C_to_SM(us, unb, und, ud); + + } + else // und > vnd + vec_copy_and_zero(und, ud, vnd, vd); + +} + +// Copy v to u. +inline +void +copy_digits_unsigned(small_type &us, + int unb, int und, sc_digit *ud, + int /* vnb */, int vnd, const sc_digit *vd) +{ + + if (und <= vnd) + vec_copy(und, ud, vd); + + else // und > vnd + vec_copy_and_zero(und, ud, vnd, vd); + + us = convert_unsigned_SM_to_2C_to_SM(us, unb, und, ud); + +} + + +// ---------------------------------------------------------------------------- +// Faster set(i, v), without bound checking. +// ---------------------------------------------------------------------------- + +// A version of set(i, v) without bound checking. +inline +void +safe_set(int i, bool v, sc_digit *d) +{ + +#ifdef DEBUG_SYSTEMC + assert((i >= 0) && (d != NULL)); +#endif + + int bit_num = bit_ord(i); + int digit_num = digit_ord(i); + + if (v) + d[digit_num] |= one_and_zeros(bit_num); + else + d[digit_num] &= ~(one_and_zeros(bit_num)); + +} + + +// ---------------------------------------------------------------------------- +// Function to check if a double number is bad (NaN or infinite). +// ---------------------------------------------------------------------------- + +inline +bool +is_nan( double v ) +{ + return std::numeric_limits<double>::has_quiet_NaN && (v != v); +} + +inline +bool +is_inf( double v ) +{ + return v == std::numeric_limits<double>::infinity() + || v == -std::numeric_limits<double>::infinity(); +} + +inline +void +is_bad_double(double v) +{ +// Windows throws exception. + if( is_nan(v) || is_inf(v) ) + SC_REPORT_ERROR( sc_core::SC_ID_VALUE_NOT_VALID_, + "is_bad_double( double v ) : " + "v is not finite - NaN or Inf" ); +} + +} // namespace sc_dt + + +#endif diff --git a/ext/systemc/src/sysc/datatypes/int/sc_signed.cpp b/ext/systemc/src/sysc/datatypes/int/sc_signed.cpp new file mode 100644 index 000000000..7e5cfacff --- /dev/null +++ b/ext/systemc/src/sysc/datatypes/int/sc_signed.cpp @@ -0,0 +1,4134 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_signed.cpp -- Arbitrary precision signed arithmetic. + + This file includes the definitions of sc_signed_bitref, + sc_signed_subref, and sc_signed classes. The first two + classes are proxy classes to reference one bit and a range + of bits of a sc_signed number, respectively. This file also + includes sc_nbcommon.cpp and sc_nbfriends.cpp, which + contain the definitions shared by sc_unsigned. + + Original Author: Ali Dasdan, Synopsys, Inc. + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + + +// $Log: sc_signed.cpp,v $ +// Revision 1.6 2011/02/18 20:19:15 acg +// Andy Goodrich: updating Copyright notice. +// +// Revision 1.5 2008/12/10 20:38:45 acg +// Andy Goodrich: fixed conversion of double values to the digits vector. +// The bits above the radix were not being masked off. +// +// Revision 1.4 2008/06/19 17:47:56 acg +// Andy Goodrich: fixes for bugs. See 2.2.1 RELEASENOTES. +// +// Revision 1.3 2008/04/29 21:20:41 acg +// Andy Goodrich: added mask to first word transferred when processing +// a negative sc_signed value in sc_signed::concat_get_data(). +// +// Revision 1.2 2007/11/04 21:27:00 acg +// Andy Goodrich: changes to make sure the proper value is returned from +// concat_get_data(). +// +// Revision 1.1.1.1 2006/12/15 20:20:05 acg +// SystemC 2.3 +// +// Revision 1.5 2006/10/23 19:32:47 acg +// Andy Goodrich: further fix for incorrect value being returned from +// concat_get_data. This one is in the non-aligned value code. +// +// Revision 1.3 2006/01/13 18:49:32 acg +// Added $Log command so that CVS check in comments are reproduced in the +// source. +// + +#include <ctype.h> +#include <math.h> + +#include "sysc/kernel/sc_cmnhdr.h" +#include "sysc/kernel/sc_macros.h" +#include "sysc/datatypes/int/sc_signed.h" +#include "sysc/datatypes/int/sc_unsigned.h" +#include "sysc/datatypes/int/sc_int_base.h" +#include "sysc/datatypes/int/sc_uint_base.h" +#include "sysc/datatypes/int/sc_int_ids.h" +#include "sysc/datatypes/bit/sc_bv_base.h" +#include "sysc/datatypes/bit/sc_lv_base.h" +#include "sysc/datatypes/misc/sc_concatref.h" +#include "sysc/datatypes/fx/sc_fix.h" +#include "sysc/datatypes/fx/scfx_other_defs.h" + + +namespace sc_dt +{ + +// Pool of temporary instances: + +sc_core::sc_vpool<sc_signed_bitref> sc_signed_bitref::m_pool(9); +sc_core::sc_vpool<sc_signed_subref> sc_signed_subref::m_pool(9); + +// ----------------------------------------------------------------------------- +// SECTION: Public members - Invalid selections. +// ----------------------------------------------------------------------------- + +void +sc_signed::invalid_index( int i ) const +{ + char msg[BUFSIZ]; + std::sprintf( msg, + "sc_bigint bit selection: index = %d violates " + "0 <= index <= %d", i, nbits - 1 ); + SC_REPORT_ERROR( sc_core::SC_ID_OUT_OF_BOUNDS_, msg ); +} + +void +sc_signed::invalid_range( int l, int r ) const +{ + char msg[BUFSIZ]; + std::sprintf( msg, + "sc_bigint part selection: left = %d, right = %d \n" + " violates either (%d >= left >= 0) or (%d >= right >= 0)", + l, r, nbits-1, nbits-1 ); + SC_REPORT_ERROR( sc_core::SC_ID_OUT_OF_BOUNDS_, msg ); +} + + +// ---------------------------------------------------------------------------- + +// ---------------------------------------------------------------------------- +// SECTION: Public members. +// ---------------------------------------------------------------------------- + +// Most public members are included from sc_nbcommon.inc. However, some +// concatenation support appears here to optimize between the signed and +// unsigned cases. + +// Insert this object's value at the specified place in a vector of biguint +// style values. + +bool sc_signed::concat_get_ctrl( sc_digit* dst_p, int low_i ) const +{ + int dst_i; // Index to next word to set in dst_p. + int end_i; // Index of high order word to set. + int left_shift; // Amount to shift value left. + sc_digit mask; // Mask for partial word sets. + + + // CALCULATE METRICS FOR DATA MOVEMENT: + + dst_i = low_i / BITS_PER_DIGIT; + end_i = (low_i + nbits - 1) / BITS_PER_DIGIT; + left_shift = low_i % BITS_PER_DIGIT; + + + // ALL DATA TO BE MOVED IS IN A SINGLE WORD: + + mask = ~(-1 << left_shift); + dst_p[dst_i] = ( dst_p[dst_i] & ~mask ); + dst_i++; + + for ( ; dst_i <= end_i; dst_i++ ) dst_p[dst_i] = 0; + + return false; +} + +bool sc_signed::concat_get_data( sc_digit* dst_p, int low_i ) const +{ + sc_digit carry; // Carry bit for complements. + int dst_i; // Index to next word to set in dst_p. + int end_i; // Index of high order word to set. + int high_i; // Index w/in word of high order bit. + int left_shift; // Amount to shift value left. + sc_digit left_word; // High word component for set. + sc_digit mask; // Mask for partial word sets. + bool result; // True if inserted non-zero data. + int right_shift; // Amount to shift value right. + sc_digit right_word; // Low word component for set. + int src_i; // Index to next word to get from digit. + + + + // CALCULATE METRICS FOR DATA MOVEMENT: + + dst_i = low_i / BITS_PER_DIGIT; + high_i = low_i + nbits - 1; + end_i = high_i / BITS_PER_DIGIT; + left_shift = low_i % BITS_PER_DIGIT; + + switch ( sgn ) + { + // POSITIVE SOURCE VALUE: + + case SC_POS: + + result = true; + + // ALL DATA TO BE MOVED IS IN A SINGLE WORD: + + if ( dst_i == end_i ) + { + mask = ~(-1 << left_shift); + dst_p[dst_i] = ( ( dst_p[dst_i] & mask ) | + (digit[0] << left_shift) ) & DIGIT_MASK; + } + + + // DATA IS IN MORE THAN ONE WORD, BUT IS WORD ALIGNED: + + else if ( left_shift == 0 ) + { + for ( src_i = 0; dst_i < end_i; dst_i++, src_i++ ) + { + dst_p[dst_i] = digit[src_i]; + } + high_i = high_i % BITS_PER_DIGIT; + mask = ~(-2 << high_i) & DIGIT_MASK; + dst_p[dst_i] = digit[src_i] & mask; + } + + + // DATA IS IN MORE THAN ONE WORD, AND NOT WORD ALIGNED: + + else + { + high_i = high_i % BITS_PER_DIGIT; + right_shift = BITS_PER_DIGIT - left_shift; + mask = ~(-1 << left_shift); + right_word = digit[0]; + dst_p[dst_i] = (dst_p[dst_i] & mask) | + ((right_word << left_shift) & DIGIT_MASK); + for ( src_i = 1, dst_i++; dst_i < end_i; dst_i++, src_i++ ) + { + left_word = digit[src_i]; + dst_p[dst_i] = ((left_word << left_shift)&DIGIT_MASK) | + (right_word >> right_shift); + right_word = left_word; + } + left_word = (src_i < ndigits) ? digit[src_i] : 0; + mask = ~(-2 << high_i) & DIGIT_MASK; + dst_p[dst_i] = ((left_word << left_shift) | + (right_word >> right_shift)) & mask; + } + break; + + + // SOURCE VALUE IS NEGATIVE: + + case SC_NEG: + + // ALL DATA TO BE MOVED IS IN A SINGLE WORD: + + result = true; + if ( dst_i == end_i ) + { + mask = ~(-1 << nbits); + right_word = ((digit[0] ^ DIGIT_MASK) + 1) & mask; + mask = ~(-1 << left_shift); + dst_p[dst_i] = ( ( dst_p[dst_i] & mask ) | + (right_word << left_shift) ) & DIGIT_MASK; + } + + + // DATA IS IN MORE THAN ONE WORD, BUT IS WORD ALIGNED: + + else if ( left_shift == 0 ) + { + carry = 1; + for ( src_i = 0; dst_i < end_i; dst_i++, src_i++ ) + { + right_word = (digit[src_i] ^ DIGIT_MASK) + carry; + dst_p[dst_i] = right_word & DIGIT_MASK; + carry = right_word >> BITS_PER_DIGIT; + } + high_i = high_i % BITS_PER_DIGIT; + mask = (~(-2 << high_i)) & DIGIT_MASK; + right_word = (src_i < ndigits) ? + (digit[src_i] ^ DIGIT_MASK) + carry : DIGIT_MASK + carry; + dst_p[dst_i] = right_word & mask; + } + + + // DATA IS IN MORE THAN ONE WORD, AND NOT WORD ALIGNED: + + else + { + high_i = high_i % BITS_PER_DIGIT; + right_shift = BITS_PER_DIGIT - left_shift; + mask = ~(-1 << left_shift); + carry = 1; + right_word = (digit[0] ^ DIGIT_MASK) + carry; + dst_p[dst_i] = (dst_p[dst_i] & mask) | + ((right_word << left_shift) & DIGIT_MASK); + carry = right_word >> BITS_PER_DIGIT; + right_word &= DIGIT_MASK; + for ( src_i = 1, dst_i++; dst_i < end_i; dst_i++, src_i++ ) + { + left_word = (digit[src_i] ^ DIGIT_MASK) + carry; + dst_p[dst_i] = ((left_word << left_shift)&DIGIT_MASK) | + (right_word >> right_shift); + carry = left_word >> BITS_PER_DIGIT; + right_word = left_word & DIGIT_MASK; + } + left_word = (src_i < ndigits) ? + (digit[src_i] ^ DIGIT_MASK) + carry : carry; + mask = ~(-2 << high_i) & DIGIT_MASK; + dst_p[dst_i] = ((left_word << left_shift) | + (right_word >> right_shift)) & mask; + } + break; + + + // VALUE IS ZERO: + + default: + result = false; + + + // ALL DATA TO BE MOVED IS IN A SINGLE WORD: + + if ( dst_i == end_i ) + { + mask = ~(-1 << nbits) << left_shift; + dst_p[dst_i] = dst_p[dst_i] & ~mask; + } + + + // DATA IS IN MORE THAN ONE WORD, BUT IS WORD ALIGNED: + + else if ( left_shift == 0 ) + { + carry = 1; + for ( src_i = 0; dst_i < end_i; dst_i++, src_i++ ) + { + dst_p[dst_i] = 0; + } + high_i = high_i % BITS_PER_DIGIT; + mask = ~(-2 << high_i) & DIGIT_MASK; + dst_p[dst_i] = 0; // #### digit[src_i] & mask; + } + + + // DATA IS IN MORE THAN ONE WORD, AND NOT WORD ALIGNED: + + else + { + high_i = high_i % BITS_PER_DIGIT; + right_shift = BITS_PER_DIGIT - left_shift; + mask = ~(-1 << left_shift); + dst_p[dst_i] = (dst_p[dst_i] & mask); + for ( dst_i++; dst_i <= end_i; dst_i++ ) + { + dst_p[dst_i] = 0; + } + } + break; + } + return result; +} + +// Return this object instance's bits as a uint64 without sign extension. + +uint64 sc_signed::concat_get_uint64() const +{ + uint64 result; + + switch ( sgn ) + { + case SC_POS: + result = 0; + if ( ndigits > 2 ) + result = digit[2]; + if ( ndigits > 1 ) + result = (result << BITS_PER_DIGIT) | digit[1]; + result = (result << BITS_PER_DIGIT) | digit[0]; + break; + case SC_NEG: + result = 0; + if ( ndigits > 2 ) + result = digit[2]; + if ( ndigits > 1 ) + result = (result << BITS_PER_DIGIT) | digit[1]; + result = (result << BITS_PER_DIGIT) | digit[0]; + result = -result; + if ( nbits < 64 ) + { + uint64 mask = ~0; + result = result & ~(mask << nbits); + } + break; + default: + result = 0; + break; + } + return result; +} + +// #### OPTIMIZE +void sc_signed::concat_set(int64 src, int low_i) +{ + *this = (low_i < 64) ? src >> low_i : src >> 63; +} + +void sc_signed::concat_set(const sc_signed& src, int low_i) +{ + if ( low_i < src.length() ) + *this = src >> low_i; + else + *this = (src<0) ? (int_type)-1 : 0; +} + +void sc_signed::concat_set(const sc_unsigned& src, int low_i) +{ + if ( low_i < src.length() ) + *this = src >> low_i; + else + *this = 0; +} + +void sc_signed::concat_set(uint64 src, int low_i) +{ + *this = (low_i < 64) ? src >> low_i : 0; +} + +// ---------------------------------------------------------------------------- +// SECTION: Public members - Reduction methods. +// ---------------------------------------------------------------------------- + +bool sc_signed::and_reduce() const +{ + sc_digit current; // Current digit examining. + int i; // Index of digit examining. + + if ( sgn == SC_NEG ) + { + current = (1 << BITS_PER_DIGIT); + for ( i = 0; i < ndigits-1; i++ ) + { + current = (current >> BITS_PER_DIGIT) + (digit[i]^DIGIT_MASK); + if ( (current & DIGIT_MASK) != DIGIT_MASK ) return false; + } + current = (current >> BITS_PER_DIGIT) + (digit[i]^DIGIT_MASK); + if ( (current & ~(-1 << (nbits % BITS_PER_DIGIT))) == + (sc_digit) ~(-1 << (nbits % BITS_PER_DIGIT)) ) + return true; + } + return false; +} + +bool sc_signed::or_reduce() const +{ + return sgn == SC_ZERO ? false : true; +} + +bool sc_signed::xor_reduce() const +{ + int i; // Digit examining. + int odd; // Flag for odd number of digits. + + odd = 0; + for ( i = 0; i < nbits; i++ ) + if ( test(i) ) odd = ~odd; + return odd ? true : false; +} + + + +// ---------------------------------------------------------------------------- +// SECTION: Public members - Assignment operators. +// ---------------------------------------------------------------------------- + +// assignment operators + +const sc_signed& +sc_signed::operator = ( const char* a ) +{ + if( a == 0 ) { + SC_REPORT_ERROR( sc_core::SC_ID_CONVERSION_FAILED_, + "character string is zero" ); + } + if( *a == 0 ) { + SC_REPORT_ERROR( sc_core::SC_ID_CONVERSION_FAILED_, + "character string is empty" ); + } + try { + int len = length(); + sc_fix aa( a, len, len, SC_TRN, SC_WRAP, 0, SC_ON ); + return this->operator = ( aa ); + } catch( sc_core::sc_report ) { + char msg[BUFSIZ]; + std::sprintf( msg, "character string '%s' is not valid", a ); + SC_REPORT_ERROR( sc_core::SC_ID_CONVERSION_FAILED_, msg ); + // never reached + } + return *this; +} + +const sc_signed& +sc_signed::operator=(int64 v) +{ + sgn = get_sign(v); + // v >= 0 now. + if (sgn == SC_ZERO) + vec_zero(ndigits, digit); + else { + from_uint(ndigits, digit, (uint64) v); + if (nbits <= (int)BITS_PER_INT64) + convert_SM_to_2C_to_SM(); + } + return *this; +} + +const sc_signed& +sc_signed::operator=(uint64 v) +{ + sgn = get_sign(v); + if (sgn == SC_ZERO) + vec_zero(ndigits, digit); + else { + from_uint(ndigits, digit, v); + if (nbits <= (int)BITS_PER_INT64) + convert_SM_to_2C_to_SM(); + } + return *this; +} + +const sc_signed& +sc_signed::operator=(long v) +{ + sgn = get_sign(v); + // v >= 0 now. + if (sgn == SC_ZERO) + vec_zero(ndigits, digit); + else { + from_uint(ndigits, digit, (unsigned long) v); + if (nbits <= (int)BITS_PER_LONG) + convert_SM_to_2C_to_SM(); + } + return *this; +} + +const sc_signed& +sc_signed::operator=(unsigned long v) +{ + sgn = get_sign(v); + if (sgn == SC_ZERO) + vec_zero(ndigits, digit); + else { + from_uint(ndigits, digit, v); + if (nbits <= (int)BITS_PER_LONG) + convert_SM_to_2C_to_SM(); + } + return *this; +} + +const sc_signed& +sc_signed::operator=(double v) +{ + is_bad_double(v); + if (v < 0) { + v = -v; + sgn = SC_NEG; + } + else + sgn = SC_POS; + int i = 0; + while (floor(v) && (i < ndigits)) { +#ifndef _WIN32 + digit[i++] = ((sc_digit)floor(remainder(v, DIGIT_RADIX))) & DIGIT_MASK; +#else + digit[i++] = ((sc_digit)floor(fmod(v, DIGIT_RADIX))) & DIGIT_MASK; +#endif + v /= DIGIT_RADIX; + } + vec_zero(i, ndigits, digit); + convert_SM_to_2C_to_SM(); + return *this; +} + + +// ---------------------------------------------------------------------------- + +const sc_signed& +sc_signed::operator = ( const sc_bv_base& v ) +{ + int minlen = sc_min( nbits, v.length() ); + int i = 0; + for( ; i < minlen; ++ i ) { + safe_set( i, v.get_bit( i ), digit ); + } + for( ; i < nbits; ++ i ) { + safe_set( i, 0, digit ); // zero-extend + } + convert_2C_to_SM(); + return *this; +} + +const sc_signed& +sc_signed::operator = ( const sc_lv_base& v ) +{ + int minlen = sc_min( nbits, v.length() ); + int i = 0; + for( ; i < minlen; ++ i ) { + safe_set( i, sc_logic( v.get_bit( i ) ).to_bool(), digit ); + } + for( ; i < nbits; ++ i ) { + safe_set( i, 0, digit ); // zero-extend + } + convert_2C_to_SM(); + return *this; +} + + +// explicit conversion to character string + +const std::string +sc_signed::to_string( sc_numrep numrep ) const +{ + int len = length(); + sc_fix aa( *this, len, len, SC_TRN, SC_WRAP, 0, SC_ON ); + return aa.to_string( numrep ); +} + +const std::string +sc_signed::to_string( sc_numrep numrep, bool w_prefix ) const +{ + int len = length(); + sc_fix aa( *this, len, len, SC_TRN, SC_WRAP, 0, SC_ON ); + return aa.to_string( numrep, w_prefix ); +} + + +// ---------------------------------------------------------------------------- +// SECTION: Interfacing with sc_int_base +// ---------------------------------------------------------------------------- + +const sc_signed& +sc_signed::operator = (const sc_int_base& v) +{ return operator=((int64) v); } + + +sc_signed +operator + ( const sc_unsigned& u, const sc_int_base& v ) +{ return operator + ( u, SCAST<int64>( v ) ); } + +sc_signed +operator + ( const sc_int_base& u, const sc_unsigned& v ) +{ return operator + ( SCAST<int64>( u ), v ); } + +sc_signed +operator + (const sc_signed& u, const sc_int_base& v) +{ return operator+(u, (int64) v); } + +sc_signed +operator + (const sc_int_base& u, const sc_signed& v) +{ return operator+((int64) u, v); } + +const sc_signed& +sc_signed::operator += (const sc_int_base& v) +{ return operator+=((int64) v); } + + +sc_signed +operator - (const sc_unsigned& u, const sc_int_base& v) +{ return operator-(u, (int64) v); } + +sc_signed +operator - (const sc_int_base& u, const sc_unsigned& v) +{ return operator-((int64) u, v); } + +sc_signed +operator-(const sc_signed& u, const sc_int_base& v) +{ return operator-(u, (int64) v); } + +sc_signed +operator - (const sc_int_base& u, const sc_signed& v) +{ return operator-((int64) u, v); } + +const sc_signed& +sc_signed::operator -= (const sc_int_base& v) +{ return operator-=((int64) v); } + + +sc_signed +operator * ( const sc_unsigned& u, const sc_int_base& v ) +{ return operator * ( u, SCAST<int64>( v ) ); } + +sc_signed +operator * ( const sc_int_base& u, const sc_unsigned& v ) +{ return operator * ( SCAST<int64>( u ), v ); } + +sc_signed +operator * (const sc_signed& u, const sc_int_base& v) +{ return operator*(u, (int64) v); } + +sc_signed +operator * (const sc_int_base& u, const sc_signed& v) +{ return operator*((int64) u, v); } + +const sc_signed& +sc_signed::operator *= (const sc_int_base& v) +{ return operator*=((int64) v); } + + +sc_signed +operator / ( const sc_unsigned& u, const sc_int_base& v ) +{ return operator / ( u, SCAST<int64>( v ) ); } + +sc_signed +operator / ( const sc_int_base& u, const sc_unsigned& v ) +{ return operator / ( SCAST<int64>( u ), v ); } + +sc_signed +operator / (const sc_signed& u, const sc_int_base& v) +{ return operator/(u, (int64) v); } + +sc_signed +operator / (const sc_int_base& u, const sc_signed& v) +{ return operator/((int64) u, v); } + +const sc_signed& +sc_signed::operator /= (const sc_int_base& v) +{ return operator/=((int64) v); } + + +sc_signed +operator % ( const sc_unsigned& u, const sc_int_base& v ) +{ return operator % ( u, SCAST<int64>( v ) ); } + +sc_signed +operator % ( const sc_int_base& u, const sc_unsigned& v ) +{ return operator % ( SCAST<int64>( u ), v ); } + +sc_signed +operator % (const sc_signed& u, const sc_int_base& v) +{ return operator%(u, (int64) v); } + +sc_signed +operator % (const sc_int_base& u, const sc_signed& v) +{ return operator%((int64) u, v); } + +const sc_signed& +sc_signed::operator %= (const sc_int_base& v) +{ return operator%=((int64) v); } + + +sc_signed +operator & ( const sc_unsigned& u, const sc_int_base& v ) +{ return operator & ( u, SCAST<int64>( v ) ); } + +sc_signed +operator & ( const sc_int_base& u, const sc_unsigned& v ) +{ return operator & ( SCAST<int64>( u ), v ); } + +sc_signed +operator & (const sc_signed& u, const sc_int_base& v) +{ return operator&(u, (int64) v); } + +sc_signed +operator & (const sc_int_base& u, const sc_signed& v) +{ return operator&((int64) u, v); } + +const sc_signed& +sc_signed::operator &= (const sc_int_base& v) +{ return operator&=((int64) v); } + + +sc_signed +operator | ( const sc_unsigned& u, const sc_int_base& v ) +{ return operator | ( u, SCAST<int64>( v ) ); } + +sc_signed +operator | ( const sc_int_base& u, const sc_unsigned& v ) +{ return operator | ( SCAST<int64>( u ), v ); } + +sc_signed +operator | (const sc_signed& u, const sc_int_base& v) +{ return operator|(u, (int64) v); } + +sc_signed +operator | (const sc_int_base& u, const sc_signed& v) +{ return operator|((int64) u, v); } + +const sc_signed& +sc_signed::operator |= (const sc_int_base& v) +{ return operator|=((int64) v); } + + +sc_signed +operator ^ ( const sc_unsigned& u, const sc_int_base& v ) +{ return operator ^ ( u, SCAST<int64>( v ) ); } + +sc_signed +operator ^ ( const sc_int_base& u, const sc_unsigned& v ) +{ return operator ^ ( SCAST<int64>( u ), v ); } + +sc_signed +operator ^ (const sc_signed& u, const sc_int_base& v) +{ return operator^(u, (int64) v); } + +sc_signed +operator ^ (const sc_int_base& u, const sc_signed& v) +{ return operator^((int64) u, v); } + +const sc_signed& +sc_signed::operator ^= (const sc_int_base& v) +{ return operator^=((int64) v); } + + +sc_signed +operator << (const sc_signed& u, const sc_int_base& v) +{ return operator<<(u, (int64) v); } + +const sc_signed& +sc_signed::operator <<= (const sc_int_base& v) +{ return operator<<=((int64) v); } + + +sc_signed +operator >> (const sc_signed& u, const sc_int_base& v) +{ return operator>>(u, (int64) v); } + +const sc_signed& +sc_signed::operator >>= (const sc_int_base& v) +{ return operator>>=((int64) v); } + + +bool +operator == (const sc_signed& u, const sc_int_base& v) +{ return operator==(u, (int64) v); } + +bool +operator == (const sc_int_base& u, const sc_signed& v) +{ return operator==((int64) u, v); } + + +bool +operator != (const sc_signed& u, const sc_int_base& v) +{ return operator!=(u, (int64) v); } + +bool +operator != (const sc_int_base& u, const sc_signed& v) +{ return operator!=((int64) u, v); } + + +bool +operator < (const sc_signed& u, const sc_int_base& v) +{ return operator<(u, (int64) v); } + +bool +operator < (const sc_int_base& u, const sc_signed& v) +{ return operator<((int64) u, v); } + + +bool +operator <= (const sc_signed& u, const sc_int_base& v) +{ return operator<=(u, (int64) v); } + +bool +operator <= (const sc_int_base& u, const sc_signed& v) +{ return operator<=((int64) u, v); } + + +bool +operator > (const sc_signed& u, const sc_int_base& v) +{ return operator>(u, (int64) v); } + +bool +operator > (const sc_int_base& u, const sc_signed& v) +{ return operator>((int64) u, v); } + + +bool +operator >= (const sc_signed& u, const sc_int_base& v) +{ return operator>=(u, (int64) v); } + +bool +operator >= (const sc_int_base& u, const sc_signed& v) +{ return operator>=((int64) u, v); } + + +// ---------------------------------------------------------------------------- +// SECTION: Interfacing with sc_uint_base +// ---------------------------------------------------------------------------- + +const sc_signed& +sc_signed::operator = (const sc_uint_base& v) +{ return operator=((uint64) v); } + + +sc_signed +operator + (const sc_signed& u, const sc_uint_base& v) +{ return operator+(u, (uint64) v); } + +sc_signed +operator + (const sc_uint_base& u, const sc_signed& v) +{ return operator+((uint64) u, v); } + +const sc_signed& +sc_signed::operator += (const sc_uint_base& v) +{ return operator+=((uint64) v); } + + +sc_signed +operator - (const sc_unsigned& u, const sc_uint_base& v) +{ return operator-(u, (uint64) v); } + +sc_signed +operator - (const sc_uint_base& u, const sc_unsigned& v) +{ return operator-((uint64) u, v); } + +sc_signed +operator - (const sc_signed& u, const sc_uint_base& v) +{ return operator-(u, (uint64) v); } + +sc_signed +operator - (const sc_uint_base& u, const sc_signed& v) +{ return operator-((uint64) u, v); } + +const sc_signed& +sc_signed::operator -= (const sc_uint_base& v) +{ return operator-=((uint64) v); } + + +sc_signed +operator * (const sc_signed& u, const sc_uint_base& v) +{ return operator*(u, (uint64) v); } + +sc_signed +operator * (const sc_uint_base& u, const sc_signed& v) +{ return operator*((uint64) u, v); } + +const sc_signed& +sc_signed::operator *= (const sc_uint_base& v) +{ return operator*=((uint64) v); } + + +sc_signed +operator / (const sc_signed& u, const sc_uint_base& v) +{ return operator/(u, (uint64) v); } + +sc_signed +operator / (const sc_uint_base& u, const sc_signed& v) +{ return operator/((uint64) u, v); } + +const sc_signed& +sc_signed::operator /= (const sc_uint_base& v) +{ return operator/=((uint64) v); } + + +sc_signed +operator % (const sc_signed& u, const sc_uint_base& v) +{ return operator%(u, (uint64) v); } + +sc_signed +operator % (const sc_uint_base& u, const sc_signed& v) +{ return operator%((uint64) u, v); } + +const sc_signed& +sc_signed::operator %= (const sc_uint_base& v) +{ return operator%=((uint64) v); } + + +sc_signed +operator & (const sc_signed& u, const sc_uint_base& v) +{ return operator&(u, (uint64) v); } + +sc_signed +operator & (const sc_uint_base& u, const sc_signed& v) +{ return operator&((uint64) u, v); } + +const sc_signed& +sc_signed::operator &= (const sc_uint_base& v) +{ return operator&=((uint64) v); } + + +sc_signed +operator | (const sc_signed& u, const sc_uint_base& v) +{ return operator|(u, (uint64) v); } + +sc_signed +operator | (const sc_uint_base& u, const sc_signed& v) +{ return operator|((uint64) u, v); } + +const sc_signed& +sc_signed::operator |= (const sc_uint_base& v) +{ return operator|=((uint64) v); } + + +sc_signed +operator ^ (const sc_signed& u, const sc_uint_base& v) +{ return operator^(u, (uint64) v); } + +sc_signed +operator ^ (const sc_uint_base& u, const sc_signed& v) +{ return operator^((uint64) u, v); } + +const sc_signed& +sc_signed::operator ^= (const sc_uint_base& v) +{ return operator^=((uint64) v); } + + +sc_signed +operator << (const sc_signed& u, const sc_uint_base& v) +{ return operator<<(u, (uint64) v); } + +const sc_signed& +sc_signed::operator <<= (const sc_uint_base& v) +{ return operator<<=((uint64) v); } + + +sc_signed +operator >> (const sc_signed& u, const sc_uint_base& v) +{ return operator>>(u, (uint64) v); } + +const sc_signed& +sc_signed::operator >>= (const sc_uint_base& v) +{ return operator>>=((uint64) v); } + + +bool +operator == (const sc_signed& u, const sc_uint_base& v) +{ return operator==(u, (uint64) v); } + +bool +operator == (const sc_uint_base& u, const sc_signed& v) +{ return operator==((uint64) u, v); } + + +bool +operator != (const sc_signed& u, const sc_uint_base& v) +{ return operator!=(u, (uint64) v); } + +bool +operator != (const sc_uint_base& u, const sc_signed& v) +{ return operator!=((uint64) u, v); } + + +bool +operator < (const sc_signed& u, const sc_uint_base& v) +{ return operator<(u, (uint64) v); } + +bool +operator < (const sc_uint_base& u, const sc_signed& v) +{ return operator<((uint64) u, v); } + + +bool +operator <= (const sc_signed& u, const sc_uint_base& v) +{ return operator<=(u, (uint64) v); } + +bool +operator <= (const sc_uint_base& u, const sc_signed& v) +{ return operator<=((uint64) u, v); } + + +bool +operator > (const sc_signed& u, const sc_uint_base& v) +{ return operator>(u, (uint64) v); } + +bool +operator > (const sc_uint_base& u, const sc_signed& v) +{ return operator>((uint64) u, v); } + + +bool +operator >= (const sc_signed& u, const sc_uint_base& v) +{ return operator>=(u, (uint64) v); } + +bool +operator >= (const sc_uint_base& u, const sc_signed& v) +{ return operator>=((uint64) u, v); } + + +// ---------------------------------------------------------------------------- +// SECTION: Input and output operators +// ---------------------------------------------------------------------------- + +// Operators in this section are included from sc_nbcommon.cpp. + + +// ---------------------------------------------------------------------------- +// SECTION: Operator macros. +// ---------------------------------------------------------------------------- + +#define CONVERT_LONG(u) \ +small_type u ## s = get_sign(u); \ +sc_digit u ## d[DIGITS_PER_ULONG]; \ +from_uint(DIGITS_PER_ULONG, u ## d, (unsigned long) u); + +#define CONVERT_LONG_2(u) \ +sc_digit u ## d[DIGITS_PER_ULONG]; \ +from_uint(DIGITS_PER_ULONG, u ## d, (unsigned long) u); + +#define CONVERT_INT(u) \ +small_type u ## s = get_sign(u); \ +sc_digit u ## d[DIGITS_PER_UINT]; \ +from_uint(DIGITS_PER_UINT, u ## d, (unsigned int) u); + +#define CONVERT_INT_2(u) \ +sc_digit u ## d[DIGITS_PER_UINT]; \ +from_uint(DIGITS_PER_UINT, u ## d, (unsigned int) u); + +#define CONVERT_INT64(u) \ +small_type u ## s = get_sign(u); \ +sc_digit u ## d[DIGITS_PER_UINT64]; \ +from_uint(DIGITS_PER_UINT64, u ## d, (uint64) u); + +#define CONVERT_INT64_2(u) \ +sc_digit u ## d[DIGITS_PER_UINT64]; \ +from_uint(DIGITS_PER_UINT64, u ## d, (uint64) u); + + +// ---------------------------------------------------------------------------- +// SECTION: PLUS operators: +, +=, ++ +// ---------------------------------------------------------------------------- + +// Cases to consider when computing u + v: +// 1. 0 + v = v +// 2. u + 0 = u +// 3. if sgn(u) == sgn(v) +// 3.1 u + v = +(u + v) = sgn(u) * (u + v) +// 3.2 (-u) + (-v) = -(u + v) = sgn(u) * (u + v) +// 4. if sgn(u) != sgn(v) +// 4.1 u + (-v) = u - v = sgn(u) * (u - v) +// 4.2 (-u) + v = -(u - v) ==> sgn(u) * (u - v) +// +// Specialization of above cases for computing ++u or u++: +// 1. 0 + 1 = 1 +// 3. u + 1 = u + 1 = sgn(u) * (u + 1) +// 4. (-u) + 1 = -(u - 1) = sgn(u) * (u - 1) + +sc_signed +operator+(const sc_unsigned& u, const sc_signed& v) +{ + + if (u.sgn == SC_ZERO) // case 1 + return sc_signed(v); + + if (v.sgn == SC_ZERO) // case 2 + return sc_signed(u); + + // cases 3 and 4 + return add_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit, + v.sgn, v.nbits, v.ndigits, v.digit); + +} + + +sc_signed +operator+(const sc_signed& u, const sc_unsigned& v) +{ + + if (u.sgn == SC_ZERO) // case 1 + return sc_signed(v); + + if (v.sgn == SC_ZERO) // case 2 + return sc_signed(u); + + // cases 3 and 4 + return add_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit, + v.sgn, v.nbits, v.ndigits, v.digit); + +} + + +sc_signed +operator+(const sc_signed& u, const sc_signed& v) +{ + + if (u.sgn == SC_ZERO) // case 1 + return sc_signed(v); + + if (v.sgn == SC_ZERO) // case 2 + return sc_signed(u); + + // cases 3 and 4 + return add_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit, + v.sgn, v.nbits, v.ndigits, v.digit); + +} + + +sc_signed +operator+(const sc_signed &u, int64 v) +{ + + if (v == 0) // case 2 + return sc_signed(u); + + CONVERT_INT64(v); + + if (u.sgn == SC_ZERO) // case 1 + return sc_signed(vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd, false); + + // cases 3 and 4 + return add_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit, + vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd); + +} + + +sc_signed +operator+(int64 u, const sc_signed &v) +{ + + if (u == 0) // case 1 + return sc_signed(v); + + CONVERT_INT64(u); + + if (v.sgn == SC_ZERO) // case 2 + return sc_signed(us, BITS_PER_UINT64, DIGITS_PER_UINT64, ud, false); + + // cases 3 and 4 + + return add_signed_friend(us, BITS_PER_UINT64, DIGITS_PER_UINT64, ud, + v.sgn, v.nbits, v.ndigits, v.digit); + +} + + +sc_signed +operator+(const sc_unsigned &u, int64 v) +{ + + if (v == 0) // case 2 + return sc_signed(u); + + CONVERT_INT64(v); + + if (u.sgn == SC_ZERO) // case 1 + return sc_signed(vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd, false); + + // cases 3 and 4 + return add_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit, + vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd); + +} + + +sc_signed +operator+(int64 u, const sc_unsigned &v) +{ + + if (u == 0) // case 1 + return sc_signed(v); + + CONVERT_INT64(u); + + if (v.sgn == SC_ZERO) // case 2 + return sc_signed(us, BITS_PER_UINT64, DIGITS_PER_UINT64, ud, false); + + // cases 3 and 4 + + return add_signed_friend(us, BITS_PER_UINT64, DIGITS_PER_UINT64, ud, + v.sgn, v.nbits, v.ndigits, v.digit); + +} + + +sc_signed +operator+(const sc_signed &u, uint64 v) +{ + + if (v == 0) // case 2 + return sc_signed(u); + + CONVERT_INT64(v); + + if (u.sgn == SC_ZERO) // case 1 + return sc_signed(vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd, false); + + // cases 3 and 4 + return add_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit, + vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd); + +} + + +sc_signed +operator+(uint64 u, const sc_signed &v) +{ + + if (u == 0) // case 1 + return sc_signed(v); + + CONVERT_INT64(u); + + if (v.sgn == SC_ZERO) // case 2 + return sc_signed(us, BITS_PER_UINT64, DIGITS_PER_UINT64, ud, false); + + // cases 3 and 4 + + return add_signed_friend(us, BITS_PER_UINT64, DIGITS_PER_UINT64, ud, + v.sgn, v.nbits, v.ndigits, v.digit); + +} + + +sc_signed +operator+(const sc_signed &u, long v) +{ + + if (v == 0) // case 2 + return sc_signed(u); + + CONVERT_LONG(v); + + if (u.sgn == SC_ZERO) // case 1 + return sc_signed(vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd, false); + + // cases 3 and 4 + return add_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit, + vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd); + +} + + +sc_signed +operator+(long u, const sc_signed &v) +{ + + if (u == 0) // case 1 + return sc_signed(v); + + CONVERT_LONG(u); + + if (v.sgn == SC_ZERO) // case 2 + return sc_signed(us, BITS_PER_ULONG, DIGITS_PER_ULONG, ud, false); + + // cases 3 and 4 + return add_signed_friend(us, BITS_PER_ULONG, DIGITS_PER_ULONG, ud, + v.sgn, v.nbits, v.ndigits, v.digit); + +} + + +sc_signed +operator+(const sc_unsigned &u, long v) +{ + + if (v == 0) // case 2 + return sc_signed(u); + + CONVERT_LONG(v); + + if (u.sgn == SC_ZERO) // case 1 + return sc_signed(vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd, false); + + // cases 3 and 4 + return add_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit, + vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd); + +} + + +sc_signed +operator+(long u, const sc_unsigned &v) +{ + + if (u == 0) // case 1 + return sc_signed(v); + + CONVERT_LONG(u); + + if (v.sgn == SC_ZERO) // case 2 + return sc_signed(us, BITS_PER_ULONG, DIGITS_PER_ULONG, ud, false); + + // cases 3 and 4 + return add_signed_friend(us, BITS_PER_ULONG, DIGITS_PER_ULONG, ud, + v.sgn, v.nbits, v.ndigits, v.digit); + +} + + +sc_signed +operator+(const sc_signed &u, unsigned long v) +{ + + if (v == 0) // case 2 + return sc_signed(u); + + CONVERT_LONG(v); + + if (u.sgn == SC_ZERO) // case 1 + return sc_signed(vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd, false); + + // cases 3 and 4 + return add_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit, + vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd); + +} + + +sc_signed +operator+(unsigned long u, const sc_signed &v) +{ + + if (u == 0) // case 1 + return sc_signed(v); + + CONVERT_LONG(u); + + if (v.sgn == SC_ZERO) // case 2 + return sc_signed(us, BITS_PER_ULONG, DIGITS_PER_ULONG, ud, false); + + // cases 3 and 4 + return add_signed_friend(us, BITS_PER_ULONG, DIGITS_PER_ULONG, ud, + v.sgn, v.nbits, v.ndigits, v.digit); + +} + +// The rest of the operators in this section are included from +// sc_nbcommon.cpp. + +// ---------------------------------------------------------------------------- +// SECTION: MINUS operators: -, -=, -- +// ---------------------------------------------------------------------------- + +// Cases to consider when computing u + v: +// 1. u - 0 = u +// 2. 0 - v = -v +// 3. if sgn(u) != sgn(v) +// 3.1 u - (-v) = u + v = sgn(u) * (u + v) +// 3.2 (-u) - v = -(u + v) ==> sgn(u) * (u + v) +// 4. if sgn(u) == sgn(v) +// 4.1 u - v = +(u - v) = sgn(u) * (u - v) +// 4.2 (-u) - (-v) = -(u - v) = sgn(u) * (u - v) +// +// Specialization of above cases for computing --u or u--: +// 1. 0 - 1 = -1 +// 3. (-u) - 1 = -(u + 1) = sgn(u) * (u + 1) +// 4. u - 1 = u - 1 = sgn(u) * (u - 1) + +sc_signed +operator-(const sc_unsigned& u, const sc_unsigned& v) +{ + + if (v.sgn == SC_ZERO) // case 1 + return sc_signed(u); + + if (u.sgn == SC_ZERO) // case 2 + return sc_signed(v, -v.sgn); + + // cases 3 and 4 + return add_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit, + -v.sgn, v.nbits, v.ndigits, v.digit); + +} + + +sc_signed +operator-(const sc_unsigned& u, const sc_signed& v) +{ + + if (v.sgn == SC_ZERO) // case 1 + return sc_signed(u); + + if (u.sgn == SC_ZERO) // case 2 + return sc_signed(v, -v.sgn); + + // cases 3 and 4 + return add_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit, + -v.sgn, v.nbits, v.ndigits, v.digit); + +} + + +sc_signed +operator-(const sc_signed& u, const sc_unsigned& v) +{ + + if (v.sgn == SC_ZERO) // case 1 + return sc_signed(u); + + if (u.sgn == SC_ZERO) // case 2 + return sc_signed(v, -v.sgn); + + // cases 3 and 4 + return add_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit, + -v.sgn, v.nbits, v.ndigits, v.digit); + +} + + +sc_signed +operator-(const sc_signed& u, const sc_signed& v) +{ + + if (v.sgn == SC_ZERO) // case 1 + return sc_signed(u); + + if (u.sgn == SC_ZERO) // case 2 + return sc_signed(v, -v.sgn); + + // cases 3 and 4 + return add_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit, + -v.sgn, v.nbits, v.ndigits, v.digit); + +} + + +sc_signed +operator-(const sc_signed &u, int64 v) +{ + + if (v == 0) // case 1 + return sc_signed(u); + + CONVERT_INT64(v); + + if (u.sgn == SC_ZERO) // case 2 + return sc_signed(-vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd, false); + + // cases 3 and 4 + return add_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit, + -vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd); + +} + + +sc_signed +operator-(int64 u, const sc_signed& v) +{ + + if (u == 0) // case 1 + return sc_signed(v, -v.sgn); + + CONVERT_INT64(u); + + if (v.sgn == SC_ZERO) // case 2 + return sc_signed(us, BITS_PER_UINT64, DIGITS_PER_UINT64, ud, false); + + // cases 3 and 4 + + return add_signed_friend(us, BITS_PER_UINT64, DIGITS_PER_UINT64, ud, + -v.sgn, v.nbits, v.ndigits, v.digit); + +} + + +sc_signed +operator-(const sc_unsigned &u, int64 v) +{ + + if (v == 0) // case 1 + return sc_signed(u); + + CONVERT_INT64(v); + + if (u.sgn == SC_ZERO) // case 2 + return sc_signed(-vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd, false); + + // cases 3 and 4 + return add_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit, + -vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd); + +} + + +sc_signed +operator-(int64 u, const sc_unsigned& v) +{ + + if (u == 0) // case 1 + return sc_signed(v, -v.sgn); + + CONVERT_INT64(u); + + if (v.sgn == SC_ZERO) // case 2 + return sc_signed(us, BITS_PER_UINT64, DIGITS_PER_UINT64, ud, false); + + // cases 3 and 4 + + return add_signed_friend(us, BITS_PER_UINT64, DIGITS_PER_UINT64, ud, + -v.sgn, v.nbits, v.ndigits, v.digit); + +} + + +sc_signed +operator-(const sc_signed &u, uint64 v) +{ + + if (v == 0) // case 1 + return sc_signed(u); + + CONVERT_INT64(v); + + if (u.sgn == SC_ZERO) // case 2 + return sc_signed(-vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd, false); + + // cases 3 and 4 + + return add_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit, + -vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd); + +} + + +sc_signed +operator-(uint64 u, const sc_signed& v) +{ + + if (u == 0) // case 1 + return sc_signed(v, -v.sgn); + + CONVERT_INT64(u); + + if (v.sgn == SC_ZERO) // case 2 + return sc_signed(us, BITS_PER_UINT64, DIGITS_PER_UINT64, ud, false); + + // cases 3 and 4 + return add_signed_friend(us, BITS_PER_UINT64, DIGITS_PER_UINT64, ud, + -v.sgn, v.nbits, v.ndigits, v.digit); + +} + + +sc_signed +operator-(const sc_unsigned &u, uint64 v) +{ + + if (v == 0) // case 1 + return sc_signed(u); + + CONVERT_INT64(v); + + if (u.sgn == SC_ZERO) // case 2 + return sc_signed(-vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd, false); + + // cases 3 and 4 + + return add_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit, + -vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd); + +} + + +sc_signed +operator-(uint64 u, const sc_unsigned& v) +{ + + if (u == 0) // case 1 + return sc_signed(v, -v.sgn); + + CONVERT_INT64(u); + + if (v.sgn == SC_ZERO) // case 2 + return sc_signed(us, BITS_PER_UINT64, DIGITS_PER_UINT64, ud, false); + + // cases 3 and 4 + return add_signed_friend(us, BITS_PER_UINT64, DIGITS_PER_UINT64, ud, + -v.sgn, v.nbits, v.ndigits, v.digit); + +} + + +sc_signed +operator-(const sc_signed &u, long v) +{ + + if (v == 0) // case 1 + return sc_signed(u); + + CONVERT_LONG(v); + + if (u.sgn == SC_ZERO) // case 2 + return sc_signed(-vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd, false); + + // cases 3 and 4 + return add_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit, + -vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd); + +} + + +sc_signed +operator-(long u, const sc_signed& v) +{ + + if (u == 0) // case 1 + return sc_signed(v, -v.sgn); + + CONVERT_LONG(u); + + if (v.sgn == SC_ZERO) // case 2 + return sc_signed(us, BITS_PER_ULONG, DIGITS_PER_ULONG, ud, false); + + // cases 3 and 4 + return add_signed_friend(us, BITS_PER_ULONG, DIGITS_PER_ULONG, ud, + -v.sgn, v.nbits, v.ndigits, v.digit); + +} + + +sc_signed +operator-(const sc_unsigned &u, long v) +{ + + if (v == 0) // case 1 + return sc_signed(u); + + CONVERT_LONG(v); + + if (u.sgn == SC_ZERO) // case 2 + return sc_signed(-vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd, false); + + // cases 3 and 4 + return add_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit, + -vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd); + +} + + +sc_signed +operator-(long u, const sc_unsigned& v) +{ + + if (u == 0) // case 1 + return sc_signed(v, -v.sgn); + + CONVERT_LONG(u); + + if (v.sgn == SC_ZERO) // case 2 + return sc_signed(us, BITS_PER_ULONG, DIGITS_PER_ULONG, ud, false); + + // cases 3 and 4 + return add_signed_friend(us, BITS_PER_ULONG, DIGITS_PER_ULONG, ud, + -v.sgn, v.nbits, v.ndigits, v.digit); + +} + + +sc_signed +operator-(const sc_signed &u, unsigned long v) +{ + + if (v == 0) // case 1 + return sc_signed(u); + + CONVERT_LONG(v); + + if (u.sgn == SC_ZERO) // case 2 + return sc_signed(-vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd, false); + + // cases 3 and 4 + return add_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit, + -vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd); + +} + + +sc_signed +operator-(unsigned long u, const sc_signed& v) +{ + if (u == 0) // case 1 + return sc_signed(v, -v.sgn); + + CONVERT_LONG(u); + + if (v.sgn == SC_ZERO) // case 2 + return sc_signed(us, BITS_PER_ULONG, DIGITS_PER_ULONG, ud, false); + + // cases 3 and 4 + return add_signed_friend(us, BITS_PER_ULONG, DIGITS_PER_ULONG, ud, + -v.sgn, v.nbits, v.ndigits, v.digit); + +} + + +sc_signed +operator-(const sc_unsigned &u, unsigned long v) +{ + + if (v == 0) // case 1 + return sc_signed(u); + + CONVERT_LONG(v); + + if (u.sgn == SC_ZERO) // case 2 + return sc_signed(-vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd, false); + + // cases 3 and 4 + return add_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit, + -vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd); + +} + + +sc_signed +operator-(unsigned long u, const sc_unsigned& v) +{ + if (u == 0) // case 1 + return sc_signed(v, -v.sgn); + + CONVERT_LONG(u); + + if (v.sgn == SC_ZERO) // case 2 + return sc_signed(us, BITS_PER_ULONG, DIGITS_PER_ULONG, ud, false); + + // cases 3 and 4 + return add_signed_friend(us, BITS_PER_ULONG, DIGITS_PER_ULONG, ud, + -v.sgn, v.nbits, v.ndigits, v.digit); + +} + +// The rest of the operators in this section are included from +// sc_nbcommon.cpp. + + +// ---------------------------------------------------------------------------- +// SECTION: MULTIPLICATION operators: *, *= +// ---------------------------------------------------------------------------- + +// Cases to consider when computing u * v: +// 1. u * 0 = 0 * v = 0 +// 2. 1 * v = v and -1 * v = -v +// 3. u * 1 = u and u * -1 = -u +// 4. u * v = u * v + +sc_signed +operator*(const sc_unsigned& u, const sc_signed& v) +{ + + small_type s = mul_signs(u.sgn, v.sgn); + + if (s == SC_ZERO) // case 1 + return sc_signed(); + + // cases 2-4 + return mul_signed_friend(s, u.nbits, u.ndigits, u.digit, + v.nbits, v.ndigits, v.digit); + +} + + +sc_signed +operator*(const sc_signed& u, const sc_unsigned& v) +{ + + small_type s = mul_signs(u.sgn, v.sgn); + + if (s == SC_ZERO) // case 1 + return sc_signed(); + + // cases 2-4 + return mul_signed_friend(s, u.nbits, u.ndigits, u.digit, + v.nbits, v.ndigits, v.digit); + +} + + +sc_signed +operator*(const sc_signed& u, const sc_signed& v) +{ + + small_type s = mul_signs(u.sgn, v.sgn); + + if (s == SC_ZERO) // case 1 + return sc_signed(); + + // cases 2-4 + return mul_signed_friend(s, u.nbits, u.ndigits, u.digit, + v.nbits, v.ndigits, v.digit); + +} + + +sc_signed +operator*(const sc_signed& u, int64 v) +{ + + small_type s = mul_signs(u.sgn, get_sign(v)); + + if (s == SC_ZERO) // case 1 + return sc_signed(); + + CONVERT_INT64_2(v); + + // cases 2-4 + return mul_signed_friend(s, u.nbits, u.ndigits, u.digit, + BITS_PER_UINT64, DIGITS_PER_UINT64, vd); + +} + + +sc_signed +operator*(int64 u, const sc_signed& v) +{ + + small_type s = mul_signs(v.sgn, get_sign(u)); + + if (s == SC_ZERO) // case 1 + return sc_signed(); + + CONVERT_INT64_2(u); + + // cases 2-4 + return mul_signed_friend(s, BITS_PER_UINT64, DIGITS_PER_UINT64, ud, + v.nbits, v.ndigits, v.digit); + +} + + +sc_signed +operator*(const sc_unsigned& u, int64 v) +{ + + small_type s = mul_signs(u.sgn, get_sign(v)); + + if (s == SC_ZERO) // case 1 + return sc_signed(); + + CONVERT_INT64_2(v); + + // cases 2-4 + return mul_signed_friend(s, u.nbits, u.ndigits, u.digit, + BITS_PER_UINT64, DIGITS_PER_UINT64, vd); + +} + + +sc_signed +operator*(int64 u, const sc_unsigned& v) +{ + + small_type s = mul_signs(v.sgn, get_sign(u)); + + if (s == SC_ZERO) // case 1 + return sc_signed(); + + CONVERT_INT64_2(u); + + // cases 2-4 + return mul_signed_friend(s, BITS_PER_UINT64, DIGITS_PER_UINT64, ud, + v.nbits, v.ndigits, v.digit); + +} + + +sc_signed +operator*(const sc_signed& u, uint64 v) +{ + + small_type s = mul_signs(u.sgn, get_sign(v)); + + if (s == SC_ZERO) // case 1 + return sc_signed(); + + CONVERT_INT64_2(v); + + // cases 2-4 + return mul_signed_friend(s, u.nbits, u.ndigits, u.digit, + BITS_PER_UINT64, DIGITS_PER_UINT64, vd); + +} + + +sc_signed +operator*(uint64 u, const sc_signed& v) +{ + + small_type s = mul_signs(v.sgn, get_sign(u)); + + if (s == SC_ZERO) // case 1 + return sc_signed(); + + CONVERT_INT64_2(u); + + // cases 2-4 + return mul_signed_friend(s, BITS_PER_UINT64, DIGITS_PER_UINT64, ud, + v.nbits, v.ndigits, v.digit); + +} + + +sc_signed +operator*(const sc_signed& u, long v) +{ + + small_type s = mul_signs(u.sgn, get_sign(v)); + + if (s == SC_ZERO) // case 1 + return sc_signed(); + + CONVERT_LONG_2(v); + + // cases 2-4 + return mul_signed_friend(s, u.nbits, u.ndigits, u.digit, + BITS_PER_ULONG, DIGITS_PER_ULONG, vd); + +} + + +sc_signed +operator*(long u, const sc_signed& v) +{ + + small_type s = mul_signs(v.sgn, get_sign(u)); + + if (s == SC_ZERO) // case 1 + return sc_signed(); + + CONVERT_LONG_2(u); + + // cases 2-4 + return mul_signed_friend(s, BITS_PER_ULONG, DIGITS_PER_ULONG, ud, + v.nbits, v.ndigits, v.digit); + +} + + +sc_signed +operator*(const sc_unsigned& u, long v) +{ + + small_type s = mul_signs(u.sgn, get_sign(v)); + + if (s == SC_ZERO) // case 1 + return sc_signed(); + + CONVERT_LONG_2(v); + + // cases 2-4 + return mul_signed_friend(s, u.nbits, u.ndigits, u.digit, + BITS_PER_ULONG, DIGITS_PER_ULONG, vd); + +} + + +sc_signed +operator*(long u, const sc_unsigned& v) +{ + + small_type s = mul_signs(v.sgn, get_sign(u)); + + if (s == SC_ZERO) // case 1 + return sc_signed(); + + CONVERT_LONG_2(u); + + // cases 2-4 + return mul_signed_friend(s, BITS_PER_ULONG, DIGITS_PER_ULONG, ud, + v.nbits, v.ndigits, v.digit); + +} + + +sc_signed +operator*(const sc_signed& u, unsigned long v) +{ + + small_type s = mul_signs(u.sgn, get_sign(v)); + + if (s == SC_ZERO) // case 1 + return sc_signed(); + + CONVERT_LONG_2(v); + + // else cases 2-4 + return mul_signed_friend(s, u.nbits, u.ndigits, u.digit, + BITS_PER_ULONG, DIGITS_PER_ULONG, vd); + +} + +sc_signed +operator*(unsigned long u, const sc_signed& v) +{ + + small_type s = mul_signs(v.sgn, get_sign(u)); + + if (s == SC_ZERO) // case 1 + return sc_signed(); + + CONVERT_LONG_2(u); + + // cases 2-4 + return mul_signed_friend(s, BITS_PER_ULONG, DIGITS_PER_ULONG, ud, + v.nbits, v.ndigits, v.digit); + +} + +// The rest of the operators in this section are included from +// sc_nbcommon.cpp. + + +// ---------------------------------------------------------------------------- +// SECTION: DIVISION operators: /, /= +// ---------------------------------------------------------------------------- + +// Cases to consider when finding the quotient q = floor(u/v): +// Note that u = q * v + r for r < q. +// 1. 0 / 0 or u / 0 => error +// 2. 0 / v => 0 = 0 * v + 0 +// 3. u / v && u = v => u = 1 * u + 0 - u or v can be 1 or -1 +// 4. u / v && u < v => u = 0 * v + u - u can be 1 or -1 +// 5. u / v && u > v => u = q * v + r - v can be 1 or -1 + +sc_signed +operator/(const sc_unsigned& u, const sc_signed& v) +{ + + small_type s = mul_signs(u.sgn, v.sgn); + + if (s == SC_ZERO) { + div_by_zero(v.sgn); // case 1 + return sc_signed(); // case 2 + } + + // other cases + return div_signed_friend(s, u.nbits, u.ndigits, u.digit, + v.nbits, v.ndigits, v.digit); + +} + + +sc_signed +operator/(const sc_signed& u, const sc_unsigned& v) +{ + + small_type s = mul_signs(u.sgn, v.sgn); + + if (s == SC_ZERO) { + div_by_zero(v.sgn); // case 1 + return sc_signed(); // case 2 + } + + // other cases + return div_signed_friend(s, u.nbits, u.ndigits, u.digit, + v.nbits, v.ndigits, v.digit); + +} + + +sc_signed +operator/(const sc_signed& u, const sc_signed& v) +{ + + small_type s = mul_signs(u.sgn, v.sgn); + + if (s == SC_ZERO) { + div_by_zero(v.sgn); // case 1 + return sc_signed(); // case 2 + } + + // other cases + return div_signed_friend(s, u.nbits, u.ndigits, u.digit, + v.nbits, v.ndigits, v.digit); + +} + + +sc_signed +operator/(const sc_signed& u, int64 v) +{ + + small_type s = mul_signs(u.sgn, get_sign(v)); + + if (s == SC_ZERO) { + div_by_zero(v); // case 1 + return sc_signed(); // case 2 + } + + CONVERT_INT64_2(v); + + // other cases + return div_signed_friend(s, u.nbits, u.ndigits, u.digit, + BITS_PER_UINT64, DIGITS_PER_UINT64, vd); + +} + + +sc_signed +operator/(int64 u, const sc_signed& v) +{ + + small_type s = mul_signs(v.sgn, get_sign(u)); + + if (s == SC_ZERO) { + div_by_zero(v.sgn); // case 1 + return sc_signed(); // case 2 + } + + CONVERT_INT64_2(u); + + // other cases + return div_signed_friend(s, BITS_PER_UINT64, DIGITS_PER_UINT64, ud, + v.nbits, v.ndigits, v.digit); + +} + + +sc_signed +operator/(const sc_unsigned& u, int64 v) +{ + + small_type s = mul_signs(u.sgn, get_sign(v)); + + if (s == SC_ZERO) { + div_by_zero(v); // case 1 + return sc_signed(); // case 2 + } + + CONVERT_INT64_2(v); + + // other cases + return div_signed_friend(s, u.nbits, u.ndigits, u.digit, + BITS_PER_UINT64, DIGITS_PER_UINT64, vd); + +} + + +sc_signed +operator/(int64 u, const sc_unsigned& v) +{ + + small_type s = mul_signs(v.sgn, get_sign(u)); + + if (s == SC_ZERO) { + div_by_zero(v.sgn); // case 1 + return sc_signed(); // case 2 + } + + CONVERT_INT64_2(u); + + // other cases + return div_signed_friend(s, BITS_PER_UINT64, DIGITS_PER_UINT64, ud, + v.nbits, v.ndigits, v.digit); + +} + + +sc_signed +operator/(const sc_signed& u, uint64 v) +{ + + small_type s = mul_signs(u.sgn, get_sign(v)); + + if (s == SC_ZERO) { + div_by_zero(v); // case 1 + return sc_signed(); // case 2 + } + + CONVERT_INT64_2(v); + + // other cases + return div_signed_friend(s, u.nbits, u.ndigits, u.digit, + BITS_PER_UINT64, DIGITS_PER_UINT64, vd); + +} + + +sc_signed +operator/(uint64 u, const sc_signed& v) +{ + + small_type s = mul_signs(v.sgn, get_sign(u)); + + if (s == SC_ZERO) { + div_by_zero(v.sgn); // case 1 + return sc_signed(); // case 2 + + } + + CONVERT_INT64_2(u); + + // other cases + return div_signed_friend(s, BITS_PER_UINT64, DIGITS_PER_UINT64, ud, + v.nbits, v.ndigits, v.digit); + +} + + +sc_signed +operator/(const sc_signed& u, long v) +{ + + small_type s = mul_signs(u.sgn, get_sign(v)); + + if (s == SC_ZERO) { + div_by_zero(v); // case 1 + return sc_signed(); // case 2 + } + + CONVERT_LONG_2(v); + + // other cases + return div_signed_friend(s, u.nbits, u.ndigits, u.digit, + BITS_PER_ULONG, DIGITS_PER_ULONG, vd); + +} + + +sc_signed +operator/(long u, const sc_signed& v) +{ + + small_type s = mul_signs(v.sgn, get_sign(u)); + + if (s == SC_ZERO) { + div_by_zero(v.sgn); // case 1 + return sc_signed(); // case 2 + } + + CONVERT_LONG_2(u); + + // other cases + return div_signed_friend(s, BITS_PER_ULONG, DIGITS_PER_ULONG, ud, + v.nbits, v.ndigits, v.digit); + +} + + +sc_signed +operator/(const sc_unsigned& u, long v) +{ + + small_type s = mul_signs(u.sgn, get_sign(v)); + + if (s == SC_ZERO) { + div_by_zero(v); // case 1 + return sc_signed(); // case 2 + } + + CONVERT_LONG_2(v); + + // other cases + return div_signed_friend(s, u.nbits, u.ndigits, u.digit, + BITS_PER_ULONG, DIGITS_PER_ULONG, vd); + +} + + +sc_signed +operator/(long u, const sc_unsigned& v) +{ + + small_type s = mul_signs(v.sgn, get_sign(u)); + + if (s == SC_ZERO) { + div_by_zero(v.sgn); // case 1 + return sc_signed(); // case 2 + } + + CONVERT_LONG_2(u); + + // other cases + return div_signed_friend(s, BITS_PER_ULONG, DIGITS_PER_ULONG, ud, + v.nbits, v.ndigits, v.digit); + +} + + +sc_signed +operator/(const sc_signed& u, unsigned long v) +{ + + small_type s = mul_signs(u.sgn, get_sign(v)); + + if (s == SC_ZERO) { + div_by_zero(v); // case 1 + return sc_signed(); // case 2 + } + + CONVERT_LONG_2(v); + + // other cases + return div_signed_friend(s, u.nbits, u.ndigits, u.digit, + BITS_PER_ULONG, DIGITS_PER_ULONG, vd); + +} + + +sc_signed +operator/(unsigned long u, const sc_signed& v) +{ + + small_type s = mul_signs(v.sgn, get_sign(u)); + + if (s == SC_ZERO) { + div_by_zero(v.sgn); // case 1 + return sc_signed(); // case 2 + + } + + CONVERT_LONG_2(u); + + // other cases + return div_signed_friend(s, BITS_PER_ULONG, DIGITS_PER_ULONG, ud, + v.nbits, v.ndigits, v.digit); + +} + +// The rest of the operators in this section are included from +// sc_nbcommon.cpp. + + +// ---------------------------------------------------------------------------- +// SECTION: MOD operators: %, %=. +// ---------------------------------------------------------------------------- + +// Cases to consider when finding the remainder r = u % v: +// Note that u = q * v + r for r < q. +// 1. 0 % 0 or u % 0 => error +// 2. 0 % v => 0 = 0 * v + 0 +// 3. u % v && u = v => u = 1 * u + 0 - u or v can be 1 or -1 +// 4. u % v && u < v => u = 0 * v + u - u can be 1 or -1 +// 5. u % v && u > v => u = q * v + r - v can be 1 or -1 + +sc_signed +operator%(const sc_unsigned& u, const sc_signed& v) +{ + + if ((u.sgn == SC_ZERO) || (v.sgn == SC_ZERO)) { + div_by_zero(v.sgn); // case 1 + return sc_signed(); // case 2 + } + + // other cases + return mod_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit, + v.nbits, v.ndigits, v.digit); +} + + +sc_signed +operator%(const sc_signed& u, const sc_unsigned& v) +{ + + if ((u.sgn == SC_ZERO) || (v.sgn == SC_ZERO)) { + div_by_zero(v.sgn); // case 1 + return sc_signed(); // case 2 + } + + // other cases + return mod_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit, + v.nbits, v.ndigits, v.digit); +} + + +sc_signed +operator%(const sc_signed& u, const sc_signed& v) +{ + + if ((u.sgn == SC_ZERO) || (v.sgn == SC_ZERO)) { + div_by_zero(v.sgn); // case 1 + return sc_signed(); // case 2 + } + + // other cases + return mod_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit, + v.nbits, v.ndigits, v.digit); +} + + +sc_signed +operator%(const sc_signed& u, int64 v) +{ + + small_type vs = get_sign(v); + + if ((u.sgn == SC_ZERO) || (vs == SC_ZERO)) { + div_by_zero(v); // case 1 + return sc_signed(); // case 2 + } + + CONVERT_INT64_2(v); + + // other cases + return mod_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit, + BITS_PER_UINT64, DIGITS_PER_UINT64, vd); + +} + + +sc_signed +operator%(int64 u, const sc_signed& v) +{ + + small_type us = get_sign(u); + + if ((us == SC_ZERO) || (v.sgn == SC_ZERO)) { + div_by_zero(v.sgn); // case 1 + return sc_signed(); // case 2 + } + + CONVERT_INT64_2(u); + + // other cases + return mod_signed_friend(us, BITS_PER_UINT64, DIGITS_PER_UINT64, ud, + v.nbits, v.ndigits, v.digit); + +} + + +sc_signed +operator%(const sc_unsigned& u, int64 v) +{ + + small_type vs = get_sign(v); + + if ((u.sgn == SC_ZERO) || (vs == SC_ZERO)) { + div_by_zero(v); // case 1 + return sc_signed(); // case 2 + } + + CONVERT_INT64_2(v); + + // other cases + return mod_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit, + BITS_PER_UINT64, DIGITS_PER_UINT64, vd); + +} + + +sc_signed +operator%(int64 u, const sc_unsigned& v) +{ + + small_type us = get_sign(u); + + if ((us == SC_ZERO) || (v.sgn == SC_ZERO)) { + div_by_zero(v.sgn); // case 1 + return sc_signed(); // case 2 + } + + CONVERT_INT64_2(u); + + // other cases + return mod_signed_friend(us, BITS_PER_UINT64, DIGITS_PER_UINT64, ud, + v.nbits, v.ndigits, v.digit); + +} + + +sc_signed +operator%(const sc_signed& u, uint64 v) +{ + + if ((u.sgn == SC_ZERO) || (v == 0)) { + div_by_zero(v); // case 1 + return sc_signed(); // case 2 + } + + CONVERT_INT64_2(v); + + // other cases + return mod_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit, + BITS_PER_UINT64, DIGITS_PER_UINT64, vd); + +} + + +sc_signed +operator%(uint64 u, const sc_signed& v) +{ + + if ((u == 0) || (v.sgn == SC_ZERO)) { + div_by_zero(v.sgn); // case 1 + return sc_signed(); // case 2 + } + + CONVERT_INT64(u); + + // other cases + return mod_signed_friend(us, BITS_PER_UINT64, DIGITS_PER_UINT64, ud, + v.nbits, v.ndigits, v.digit); + +} + + +sc_signed +operator%(const sc_signed& u, long v) +{ + + small_type vs = get_sign(v); + + if ((u.sgn == SC_ZERO) || (vs == SC_ZERO)) { + div_by_zero(v); // case 1 + return sc_signed(); // case 2 + } + + CONVERT_LONG_2(v); + + // other cases + return mod_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit, + BITS_PER_ULONG, DIGITS_PER_ULONG, vd); +} + + +sc_signed +operator%(long u, const sc_signed& v) +{ + + small_type us = get_sign(u); + + if ((us == SC_ZERO) || (v.sgn == SC_ZERO)) { + div_by_zero(v.sgn); // case 1 + return sc_signed(); // case 2 + } + + CONVERT_LONG_2(u); + + // other cases + return mod_signed_friend(us, BITS_PER_ULONG, DIGITS_PER_ULONG, ud, + v.nbits, v.ndigits, v.digit); + +} + + +sc_signed +operator%(const sc_unsigned& u, long v) +{ + + small_type vs = get_sign(v); + + if ((u.sgn == SC_ZERO) || (vs == SC_ZERO)) { + div_by_zero(v); // case 1 + return sc_signed(); // case 2 + } + + CONVERT_LONG_2(v); + + // other cases + return mod_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit, + BITS_PER_ULONG, DIGITS_PER_ULONG, vd); +} + + +sc_signed +operator%(long u, const sc_unsigned& v) +{ + + small_type us = get_sign(u); + + if ((us == SC_ZERO) || (v.sgn == SC_ZERO)) { + div_by_zero(v.sgn); // case 1 + return sc_signed(); // case 2 + } + + CONVERT_LONG_2(u); + + // other cases + return mod_signed_friend(us, BITS_PER_ULONG, DIGITS_PER_ULONG, ud, + v.nbits, v.ndigits, v.digit); + +} + + +sc_signed +operator%(const sc_signed& u, unsigned long v) +{ + + if ((u.sgn == SC_ZERO) || (v == 0)) { + div_by_zero(v); // case 1 + return sc_signed(); // case 2 + } + + CONVERT_LONG_2(v); + + // other cases + return mod_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit, + BITS_PER_ULONG, DIGITS_PER_ULONG, vd); + +} + + +sc_signed +operator%(unsigned long u, const sc_signed& v) +{ + + if ((u == 0) || (v.sgn == SC_ZERO)) { + div_by_zero(v.sgn); // case 1 + return sc_signed(); // case 2 + } + + CONVERT_LONG(u); + + // other cases + return mod_signed_friend(us, BITS_PER_ULONG, DIGITS_PER_ULONG, ud, + v.nbits, v.ndigits, v.digit); + +} + +// The rest of the operators in this section are included from +// sc_nbcommon.cpp. + + +// ---------------------------------------------------------------------------- +// SECTION: Bitwise AND operators: &, &= +// ---------------------------------------------------------------------------- + +// Cases to consider when computing u & v: +// 1. u & 0 = 0 & v = 0 +// 2. u & v => sgn = + +// 3. (-u) & (-v) => sgn = - +// 4. u & (-v) => sgn = + +// 5. (-u) & v => sgn = + + +sc_signed +operator&(const sc_unsigned& u, const sc_signed& v) +{ + + if ((u.sgn == SC_ZERO) || (v.sgn == SC_ZERO)) // case 1 + return sc_signed(); + + // other cases + return and_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit, + v.sgn, v.nbits, v.ndigits, v.digit); + +} + + +sc_signed +operator&(const sc_signed& u, const sc_unsigned& v) +{ + + if ((u.sgn == SC_ZERO) || (v.sgn == SC_ZERO)) // case 1 + return sc_signed(); + + // other cases + return and_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit, + v.sgn, v.nbits, v.ndigits, v.digit); + +} + + +sc_signed +operator&(const sc_signed& u, const sc_signed& v) +{ + + if ((u.sgn == SC_ZERO) || (v.sgn == SC_ZERO)) // case 1 + return sc_signed(); + + // other cases + return and_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit, + v.sgn, v.nbits, v.ndigits, v.digit); + +} + + +sc_signed +operator&(const sc_signed& u, int64 v) +{ + + if ((u.sgn == SC_ZERO) || (v == 0)) // case 1 + return sc_signed(); + + CONVERT_INT64(v); + + // other cases + return and_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit, + vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd); + +} + + +sc_signed +operator&(int64 u, const sc_signed& v) +{ + + if ((u == 0) || (v.sgn == SC_ZERO)) // case 1 + return sc_signed(); + + CONVERT_INT64(u); + + // other cases + return and_signed_friend(us, BITS_PER_UINT64, DIGITS_PER_UINT64, ud, + v.sgn, v.nbits, v.ndigits, v.digit); + +} + + +sc_signed +operator&(const sc_unsigned& u, int64 v) +{ + + if ((u.sgn == SC_ZERO) || (v == 0)) // case 1 + return sc_signed(); + + CONVERT_INT64(v); + + // other cases + return and_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit, + vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd); + +} + + +sc_signed +operator&(int64 u, const sc_unsigned& v) +{ + + if ((u == 0) || (v.sgn == SC_ZERO)) // case 1 + return sc_signed(); + + CONVERT_INT64(u); + + // other cases + return and_signed_friend(us, BITS_PER_UINT64, DIGITS_PER_UINT64, ud, + v.sgn, v.nbits, v.ndigits, v.digit); + +} + + +sc_signed +operator&(const sc_signed& u, uint64 v) +{ + + if ((u.sgn == SC_ZERO) || (v == 0)) // case 1 + return sc_signed(); + + CONVERT_INT64(v); + + // other cases + return and_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit, + vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd); + +} + + +sc_signed +operator&(uint64 u, const sc_signed& v) +{ + + if ((u == 0) || (v.sgn == SC_ZERO)) // case 1 + return sc_signed(); + + CONVERT_INT64(u); + + // other cases + return and_signed_friend(us, BITS_PER_UINT64, DIGITS_PER_UINT64, ud, + v.sgn, v.nbits, v.ndigits, v.digit); + +} + + +sc_signed +operator&(const sc_signed& u, long v) +{ + + if ((u.sgn == SC_ZERO) || (v == 0)) // case 1 + return sc_signed(); + + CONVERT_LONG(v); + + // other cases + return and_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit, + vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd); + +} + + +sc_signed +operator&(long u, const sc_signed& v) +{ + + if ((u == 0) || (v.sgn == SC_ZERO)) // case 1 + return sc_signed(); + + CONVERT_LONG(u); + + // other cases + return and_signed_friend(us, BITS_PER_ULONG, DIGITS_PER_ULONG, ud, + v.sgn, v.nbits, v.ndigits, v.digit); + +} + + +sc_signed +operator&(const sc_unsigned& u, long v) +{ + + if ((u.sgn == SC_ZERO) || (v == 0)) // case 1 + return sc_signed(); + + CONVERT_LONG(v); + + // other cases + return and_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit, + vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd); + +} + + +sc_signed +operator&(long u, const sc_unsigned& v) +{ + + if ((u == 0) || (v.sgn == SC_ZERO)) // case 1 + return sc_signed(); + + CONVERT_LONG(u); + + // other cases + return and_signed_friend(us, BITS_PER_ULONG, DIGITS_PER_ULONG, ud, + v.sgn, v.nbits, v.ndigits, v.digit); + +} + + +sc_signed +operator&(const sc_signed& u, unsigned long v) +{ + + if ((u.sgn == SC_ZERO) || (v == 0)) // case 1 + return sc_signed(); + + CONVERT_LONG(v); + + // other cases + return and_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit, + vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd); + +} + + +sc_signed +operator&(unsigned long u, const sc_signed& v) +{ + + if ((u == 0) || (v.sgn == SC_ZERO)) // case 1 + return sc_signed(); + + CONVERT_LONG(u); + + // other cases + return and_signed_friend(us, BITS_PER_ULONG, DIGITS_PER_ULONG, ud, + v.sgn, v.nbits, v.ndigits, v.digit); + +} + +// The rest of the operators in this section are included from +// sc_nbcommon.cpp. + + +// ---------------------------------------------------------------------------- +// SECTION: Bitwise OR operators: |, |= +// ---------------------------------------------------------------------------- + +// Cases to consider when computing u | v: +// 1. u | 0 = u +// 2. 0 | v = v +// 3. u | v => sgn = + +// 4. (-u) | (-v) => sgn = - +// 5. u | (-v) => sgn = - +// 6. (-u) | v => sgn = - + +sc_signed +operator|(const sc_unsigned& u, const sc_signed& v) +{ + + if (v.sgn == SC_ZERO) // case 1 + return sc_signed(u); + + if (u.sgn == SC_ZERO) // case 2 + return sc_signed(v); + + // other cases + return or_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit, + v.sgn, v.nbits, v.ndigits, v.digit); + +} + + +sc_signed +operator|(const sc_signed& u, const sc_unsigned& v) +{ + + if (v.sgn == SC_ZERO) // case 1 + return sc_signed(u); + + if (u.sgn == SC_ZERO) // case 2 + return sc_signed(v); + + // other cases + return or_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit, + v.sgn, v.nbits, v.ndigits, v.digit); + +} + + +sc_signed +operator|(const sc_signed& u, const sc_signed& v) +{ + + if (v.sgn == SC_ZERO) // case 1 + return sc_signed(u); + + if (u.sgn == SC_ZERO) // case 2 + return sc_signed(v); + + // other cases + return or_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit, + v.sgn, v.nbits, v.ndigits, v.digit); + +} + + +sc_signed +operator|(const sc_signed& u, int64 v) +{ + + if (v == 0) // case 1 + return sc_signed(u); + + CONVERT_INT64(v); + + if (u.sgn == SC_ZERO) // case 2 + return sc_signed(vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd, false); + + // other cases + return or_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit, + vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd); + +} + + +sc_signed +operator|(int64 u, const sc_signed& v) +{ + + if (u == 0) + return sc_signed(v); + + CONVERT_INT64(u); + + if (v.sgn == SC_ZERO) + return sc_signed(us, BITS_PER_UINT64, DIGITS_PER_UINT64, ud, false); + + // other cases + return or_signed_friend(us, BITS_PER_UINT64, DIGITS_PER_UINT64, ud, + v.sgn, v.nbits, v.ndigits, v.digit); + +} + + +sc_signed +operator|(const sc_unsigned& u, int64 v) +{ + + if (v == 0) // case 1 + return sc_signed(u); + + CONVERT_INT64(v); + + if (u.sgn == SC_ZERO) // case 2 + return sc_signed(vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd, false); + + // other cases + return or_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit, + vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd); + +} + + +sc_signed +operator|(int64 u, const sc_unsigned& v) +{ + + if (u == 0) + return sc_signed(v); + + CONVERT_INT64(u); + + if (v.sgn == SC_ZERO) + return sc_signed(us, BITS_PER_UINT64, DIGITS_PER_UINT64, ud, false); + + // other cases + return or_signed_friend(us, BITS_PER_UINT64, DIGITS_PER_UINT64, ud, + v.sgn, v.nbits, v.ndigits, v.digit); + +} + + +sc_signed +operator|(const sc_signed& u, uint64 v) +{ + + if (v == 0) // case 1 + return sc_signed(u); + + CONVERT_INT64(v); + + if (u.sgn == SC_ZERO) // case 2 + return sc_signed(vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd, false); + + // other cases + return or_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit, + vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd); + +} + + +sc_signed +operator|(uint64 u, const sc_signed& v) +{ + + if (u == 0) + return sc_signed(v); + + CONVERT_INT64(u); + + if (v.sgn == SC_ZERO) + return sc_signed(us, BITS_PER_UINT64, DIGITS_PER_UINT64, ud, false); + + // other cases + return or_signed_friend(us, BITS_PER_UINT64, DIGITS_PER_UINT64, ud, + v.sgn, v.nbits, v.ndigits, v.digit); + +} + + +sc_signed +operator|(const sc_signed& u, long v) +{ + + if (v == 0) // case 1 + return sc_signed(u); + + CONVERT_LONG(v); + + if (u.sgn == SC_ZERO) // case 2 + return sc_signed(vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd, false); + + // other cases + return or_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit, + vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd); + +} + + +sc_signed +operator|(long u, const sc_signed& v) +{ + + if (u == 0) + return sc_signed(v); + + CONVERT_LONG(u); + + if (v.sgn == SC_ZERO) + return sc_signed(us, BITS_PER_ULONG, DIGITS_PER_ULONG, ud, false); + + // other cases + return or_signed_friend(us, BITS_PER_ULONG, DIGITS_PER_ULONG, ud, + v.sgn, v.nbits, v.ndigits, v.digit); + +} + + +sc_signed +operator|(const sc_unsigned& u, long v) +{ + + if (v == 0) // case 1 + return sc_signed(u); + + CONVERT_LONG(v); + + if (u.sgn == SC_ZERO) // case 2 + return sc_signed(vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd, false); + + // other cases + return or_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit, + vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd); + +} + + +sc_signed +operator|(long u, const sc_unsigned& v) +{ + + if (u == 0) + return sc_signed(v); + + CONVERT_LONG(u); + + if (v.sgn == SC_ZERO) + return sc_signed(us, BITS_PER_ULONG, DIGITS_PER_ULONG, ud, false); + + // other cases + return or_signed_friend(us, BITS_PER_ULONG, DIGITS_PER_ULONG, ud, + v.sgn, v.nbits, v.ndigits, v.digit); + +} + + +sc_signed +operator|(const sc_signed& u, unsigned long v) +{ + + if (v == 0) // case 1 + return sc_signed(u); + + CONVERT_LONG(v); + + if (u.sgn == SC_ZERO) // case 2 + return sc_signed(vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd, false); + + // other cases + return or_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit, + vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd); + +} + + +sc_signed +operator|(unsigned long u, const sc_signed& v) +{ + + if (u == 0) + return sc_signed(v); + + CONVERT_LONG(u); + + if (v.sgn == SC_ZERO) + return sc_signed(us, BITS_PER_ULONG, DIGITS_PER_ULONG, ud, false); + + // other cases + return or_signed_friend(us, BITS_PER_ULONG, DIGITS_PER_ULONG, ud, + v.sgn, v.nbits, v.ndigits, v.digit); + +} + +// The rest of the operators in this section are included from +// sc_nbcommon.cpp. + + +// ---------------------------------------------------------------------------- +// SECTION: Bitwise XOR operators: ^, ^= +// ---------------------------------------------------------------------------- + +// Cases to consider when computing u ^ v: +// Note that u ^ v = (~u & v) | (u & ~v). +// 1. u ^ 0 = u +// 2. 0 ^ v = v +// 3. u ^ v => sgn = + +// 4. (-u) ^ (-v) => sgn = - +// 5. u ^ (-v) => sgn = - +// 6. (-u) ^ v => sgn = + + +sc_signed +operator^(const sc_unsigned& u, const sc_signed& v) +{ + + if (v.sgn == SC_ZERO) // case 1 + return sc_signed(u); + + if (u.sgn == SC_ZERO) // case 2 + return sc_signed(v); + + // other cases + return xor_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit, + v.sgn, v.nbits, v.ndigits, v.digit); + +} + + +sc_signed +operator^(const sc_signed& u, const sc_unsigned& v) +{ + + if (v.sgn == SC_ZERO) // case 1 + return sc_signed(u); + + if (u.sgn == SC_ZERO) // case 2 + return sc_signed(v); + + // other cases + return xor_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit, + v.sgn, v.nbits, v.ndigits, v.digit); + +} + + +sc_signed +operator^(const sc_signed& u, const sc_signed& v) +{ + + if (v.sgn == SC_ZERO) // case 1 + return sc_signed(u); + + if (u.sgn == SC_ZERO) // case 2 + return sc_signed(v); + + // other cases + return xor_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit, + v.sgn, v.nbits, v.ndigits, v.digit); + +} + + +sc_signed +operator^(const sc_signed& u, int64 v) +{ + + if (v == 0) // case 1 + return sc_signed(u); + + CONVERT_INT64(v); + + if (u.sgn == SC_ZERO) // case 2 + return sc_signed(vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd, false); + + // other cases + return xor_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit, + vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd); + +} + + +sc_signed +operator^(int64 u, const sc_signed& v) +{ + + if (u == 0) + return sc_signed(v); + + CONVERT_INT64(u); + + if (v.sgn == SC_ZERO) + return sc_signed(us, BITS_PER_UINT64, DIGITS_PER_UINT64, ud, false); + + // other cases + return xor_signed_friend(us, BITS_PER_UINT64, DIGITS_PER_UINT64, ud, + v.sgn, v.nbits, v.ndigits, v.digit); + +} + + +sc_signed +operator^(const sc_unsigned& u, int64 v) +{ + + if (v == 0) // case 1 + return sc_signed(u); + + CONVERT_INT64(v); + + if (u.sgn == SC_ZERO) // case 2 + return sc_signed(vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd, false); + + // other cases + return xor_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit, + vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd); + +} + + +sc_signed +operator^(int64 u, const sc_unsigned& v) +{ + + if (u == 0) + return sc_signed(v); + + CONVERT_INT64(u); + + if (v.sgn == SC_ZERO) + return sc_signed(us, BITS_PER_UINT64, DIGITS_PER_UINT64, ud, false); + + // other cases + return xor_signed_friend(us, BITS_PER_UINT64, DIGITS_PER_UINT64, ud, + v.sgn, v.nbits, v.ndigits, v.digit); + +} + + +sc_signed +operator^(const sc_signed& u, uint64 v) +{ + + if (v == 0) // case 1 + return sc_signed(u); + + CONVERT_INT64(v); + + if (u.sgn == SC_ZERO) // case 2 + return sc_signed(vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd, false); + + // other cases + return xor_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit, + vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd); + +} + +sc_signed +operator^(uint64 u, const sc_signed& v) +{ + if (u == 0) + return sc_signed(v); + + CONVERT_INT64(u); + + if (v.sgn == SC_ZERO) + return sc_signed(us, BITS_PER_UINT64, DIGITS_PER_UINT64, ud, false); + + // other cases + return xor_signed_friend(us, BITS_PER_UINT64, DIGITS_PER_UINT64, ud, + v.sgn, v.nbits, v.ndigits, v.digit); + +} + + +sc_signed +operator^(const sc_signed& u, long v) +{ + + if (v == 0) // case 1 + return sc_signed(u); + + CONVERT_LONG(v); + + if (u.sgn == SC_ZERO) // case 2 + return sc_signed(vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd, false); + + // other cases + return xor_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit, + vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd); + +} + + +sc_signed +operator^(long u, const sc_signed& v) +{ + + if (u == 0) + return sc_signed(v); + + CONVERT_LONG(u); + + if (v.sgn == SC_ZERO) + return sc_signed(us, BITS_PER_ULONG, DIGITS_PER_ULONG, ud, false); + + // other cases + return xor_signed_friend(us, BITS_PER_ULONG, DIGITS_PER_ULONG, ud, + v.sgn, v.nbits, v.ndigits, v.digit); + +} + + +sc_signed +operator^(const sc_unsigned& u, long v) +{ + + if (v == 0) // case 1 + return sc_signed(u); + + CONVERT_LONG(v); + + if (u.sgn == SC_ZERO) // case 2 + return sc_signed(vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd, false); + + // other cases + return xor_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit, + vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd); + +} + + +sc_signed +operator^(long u, const sc_unsigned& v) +{ + + if (u == 0) + return sc_signed(v); + + CONVERT_LONG(u); + + if (v.sgn == SC_ZERO) + return sc_signed(us, BITS_PER_ULONG, DIGITS_PER_ULONG, ud, false); + + // other cases + return xor_signed_friend(us, BITS_PER_ULONG, DIGITS_PER_ULONG, ud, + v.sgn, v.nbits, v.ndigits, v.digit); + +} + + +sc_signed +operator^(const sc_signed& u, unsigned long v) +{ + + if (v == 0) // case 1 + return sc_signed(u); + + CONVERT_LONG(v); + + if (u.sgn == SC_ZERO) // case 2 + return sc_signed(vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd, false); + + // other cases + return xor_signed_friend(u.sgn, u.nbits, u.ndigits, u.digit, + vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd); + +} + +sc_signed +operator^(unsigned long u, const sc_signed& v) +{ + if (u == 0) + return sc_signed(v); + + CONVERT_LONG(u); + + if (v.sgn == SC_ZERO) + return sc_signed(us, BITS_PER_ULONG, DIGITS_PER_ULONG, ud, false); + + // other cases + return xor_signed_friend(us, BITS_PER_ULONG, DIGITS_PER_ULONG, ud, + v.sgn, v.nbits, v.ndigits, v.digit); + +} + +// The rest of the operators in this section are included from +// sc_nbcommon.cpp. + + +// ---------------------------------------------------------------------------- +// SECTION: Bitwise NOT operator: ~ +// ---------------------------------------------------------------------------- + +// Operators in this section are included from sc_nbcommon.cpp. + + +// ---------------------------------------------------------------------------- +// SECTION: LEFT SHIFT operators: <<, <<= +// ---------------------------------------------------------------------------- + +sc_signed +operator<<(const sc_signed& u, const sc_unsigned& v) +{ + if (v.sgn == SC_ZERO) + return sc_signed(u); + + return operator<<(u, v.to_ulong()); +} + +// The rest of the operators in this section are included from +// sc_nbcommon.cpp. + + +// ---------------------------------------------------------------------------- +// SECTION: RIGHT SHIFT operators: >>, >>= +// ---------------------------------------------------------------------------- + +sc_signed +operator>>(const sc_signed& u, const sc_unsigned& v) +{ + + if (v.sgn == SC_ZERO) + return sc_signed(u); + + return operator>>(u, v.to_ulong()); + +} + +// The rest of the operators in this section are included from +// sc_nbcommon.cpp. + + +// ---------------------------------------------------------------------------- +// SECTION: Unary arithmetic operators. +// ---------------------------------------------------------------------------- + +sc_signed +operator+(const sc_signed& u) +{ + return sc_signed(u); +} + +sc_signed +operator-(const sc_signed& u) +{ + return sc_signed(u, -u.sgn); +} + +sc_signed +operator-(const sc_unsigned& u) +{ + return sc_signed(u, -u.sgn); +} + + +// ---------------------------------------------------------------------------- +// SECTION: EQUAL operator: == +// ---------------------------------------------------------------------------- + +bool +operator==(const sc_signed& u, const sc_signed& v) +{ + + if (u.sgn != v.sgn) + return false; + + if (&u == &v) + return true; + + if (vec_skip_and_cmp(u.ndigits, u.digit, v.ndigits, v.digit) != 0) + return false; + + return true; + +} + + +bool +operator==(const sc_signed& u, int64 v) +{ + + CONVERT_INT64(v); + + if (u.sgn != vs) + return false; + + if (vec_skip_and_cmp(u.ndigits, u.digit, DIGITS_PER_INT64, vd) != 0) + return false; + + return true; + +} + + +bool +operator==(int64 u, const sc_signed& v) +{ + + CONVERT_INT64(u); + + if (us != v.sgn) + return false; + + if (vec_skip_and_cmp(DIGITS_PER_INT64, ud, v.ndigits, v.digit) != 0) + return false; + + return true; + +} + + +bool +operator==(const sc_signed& u, uint64 v) +{ + + CONVERT_INT64(v); + + if (u.sgn != vs) + return false; + + if (vec_skip_and_cmp(u.ndigits, u.digit, DIGITS_PER_INT64, vd) != 0) + return false; + + return true; + +} + + +bool +operator==(uint64 u, const sc_signed& v) +{ + + CONVERT_INT64(u); + + if (us != v.sgn) + return false; + + if (vec_skip_and_cmp(DIGITS_PER_INT64, ud, v.ndigits, v.digit) != 0) + return false; + + return true; + +} + + +bool +operator==(const sc_signed& u, long v) +{ + + CONVERT_LONG(v); + + if (u.sgn != vs) + return false; + + if (vec_skip_and_cmp(u.ndigits, u.digit, DIGITS_PER_LONG, vd) != 0) + return false; + + return true; + +} + + +bool +operator==(long u, const sc_signed& v) +{ + + CONVERT_LONG(u); + + if (us != v.sgn) + return false; + + if (vec_skip_and_cmp(DIGITS_PER_LONG, ud, v.ndigits, v.digit) != 0) + return false; + + return true; + +} + + +bool +operator==(const sc_signed& u, unsigned long v) +{ + + CONVERT_LONG(v); + + if (u.sgn != vs) + return false; + + if (vec_skip_and_cmp(u.ndigits, u.digit, DIGITS_PER_LONG, vd) != 0) + return false; + + return true; + +} + + +bool +operator==(unsigned long u, const sc_signed& v) +{ + + CONVERT_LONG(u); + + if (us != v.sgn) + return false; + + if (vec_skip_and_cmp(DIGITS_PER_LONG, ud, v.ndigits, v.digit) != 0) + return false; + + return true; + +} + + +// ---------------------------------------------------------------------------- +// SECTION: NOT_EQUAL operator: != +// ---------------------------------------------------------------------------- + +// Operators in this section are included from sc_nbcommon.cpp. + + +// ---------------------------------------------------------------------------- +// SECTION: LESS THAN operator: < +// ---------------------------------------------------------------------------- + +bool +operator<(const sc_signed& u, const sc_signed& v) +{ + + if (u.sgn < v.sgn) + return true; + + if (u.sgn > v.sgn) + return false; + + // u.sgn == v.sgn + + if (&u == &v) + return false; + + if (u.sgn == SC_POS) { + + if (vec_skip_and_cmp(u.ndigits, u.digit, v.ndigits, v.digit) < 0) + return true; + + } + else if (u.sgn == SC_NEG) { + + if (vec_skip_and_cmp(u.ndigits, u.digit, v.ndigits, v.digit) > 0) + return true; + + } + + return false; + +} + + +bool +operator<(const sc_signed& u, int64 v) +{ + + CONVERT_INT64(v); + + if (u.sgn < vs) + return true; + + if (u.sgn > vs) + return false; + + // u.sgn == vs + + if (vs == SC_POS) { + + if (vec_skip_and_cmp(u.ndigits, u.digit, DIGITS_PER_INT64, vd) < 0) + return true; + + } + else if (vs == SC_NEG) { + + if (vec_skip_and_cmp(u.ndigits, u.digit, DIGITS_PER_INT64, vd) > 0) + return true; + + } + + return false; + +} + + +bool +operator<(int64 u, const sc_signed& v) +{ + + CONVERT_INT64(u); + + if (us < v.sgn) + return true; + + if (us > v.sgn) + return false; + + // us == v.sgn + + if (us == SC_POS) { + + if (vec_skip_and_cmp(DIGITS_PER_INT64, ud, v.ndigits, v.digit) < 0) + return true; + + } + else if (us == SC_NEG) { + + if (vec_skip_and_cmp(DIGITS_PER_INT64, ud, v.ndigits, v.digit) > 0) + return true; + + } + + return false; + +} + + +bool +operator<(const sc_signed& u, uint64 v) +{ + + CONVERT_INT64(v); + + if (u.sgn < vs) + return true; + + if (u.sgn > vs) + return false; + + // u.sgn == vs + + if (vs == SC_POS) { + + if (vec_skip_and_cmp(u.ndigits, u.digit, DIGITS_PER_INT64, vd) < 0) + return true; + + } + + return false; + +} + + +bool +operator<(uint64 u, const sc_signed& v) +{ + + CONVERT_INT64(u); + + if (us < v.sgn) + return true; + + if (us > v.sgn) + return false; + + // us == v.sgn + + if (us == SC_POS) { + + if (vec_skip_and_cmp(DIGITS_PER_INT64, ud, v.ndigits, v.digit) < 0) + return true; + + } + + return false; + +} + + +bool +operator<(const sc_signed& u, long v) +{ + + CONVERT_LONG(v); + + if (u.sgn < vs) + return true; + + if (u.sgn > vs) + return false; + + // u.sgn == vs + + if (vs == SC_POS) { + + if (vec_skip_and_cmp(u.ndigits, u.digit, DIGITS_PER_LONG, vd) < 0) + return true; + + } + else if (vs == SC_NEG) { + + if (vec_skip_and_cmp(u.ndigits, u.digit, DIGITS_PER_LONG, vd) > 0) + return true; + + } + + return false; + +} + + +bool +operator<(long u, const sc_signed& v) +{ + CONVERT_LONG(u); + + if (us < v.sgn) + return true; + + if (us > v.sgn) + return false; + + // us == v.sgn + + if (us == SC_POS) { + + if (vec_skip_and_cmp(DIGITS_PER_LONG, ud, v.ndigits, v.digit) < 0) + return true; + + } + else if (us == SC_NEG) { + + if (vec_skip_and_cmp(DIGITS_PER_LONG, ud, v.ndigits, v.digit) > 0) + return true; + + } + + return false; +} + + +bool +operator<(const sc_signed& u, unsigned long v) +{ + CONVERT_LONG(v); + + if (u.sgn < vs) + return true; + + if (u.sgn > vs) + return false; + + // u.sgn == vs + + if (vs == SC_POS) { + + if (vec_skip_and_cmp(u.ndigits, u.digit, DIGITS_PER_LONG, vd) < 0) + return true; + + } + + return false; +} + + +bool +operator<(unsigned long u, const sc_signed& v) +{ + CONVERT_LONG(u); + + if (us < v.sgn) + return true; + + if (us > v.sgn) + return false; + + // us == v.sgn + + if (us == SC_POS) { + + if (vec_skip_and_cmp(DIGITS_PER_LONG, ud, v.ndigits, v.digit) < 0) + return true; + + } + + return false; +} + + +// --------------------------------------------------------------------------- +// SECTION: LESS THAN or EQUAL operator: <= +// --------------------------------------------------------------------------- + +// Operators in this section are included from sc_nbcommon.cpp. + + +// --------------------------------------------------------------------------- +// SECTION: GREATER THAN operator: > +// --------------------------------------------------------------------------- + +// Operators in this section are included from sc_nbcommon.cpp. + + +// --------------------------------------------------------------------------- +// SECTION: GREATER THAN or EQUAL operator: >= +// --------------------------------------------------------------------------- + +// Operators in this section are included from sc_nbcommon.cpp. + + +// --------------------------------------------------------------------------- +// SECTION: Public members - Other utils. +// --------------------------------------------------------------------------- + +bool +sc_signed::iszero() const +{ + if (sgn == SC_ZERO) + return true; + else if (sgn != SC_NOSIGN) + return false; + else + return check_for_zero(ndigits, digit); +} + + +bool +sc_signed::sign() const +{ + if (sgn == SC_NEG) + return 1; + else if (sgn != SC_NOSIGN) + return 0; + else + return ((digit[ndigits - 1] & one_and_zeros(bit_ord(nbits - 1))) != 0); +} + +// The rest of the utils in this section are included from sc_nbcommon.cpp. + + +// ---------------------------------------------------------------------------- +// SECTION: Private members. +// ---------------------------------------------------------------------------- + +// The private members in this section are included from sc_nbcommon.cpp. + +#define CLASS_TYPE sc_signed +#define CLASS_TYPE_STR "sc_signed" + +#define ADD_HELPER add_signed_friend +#define SUB_HELPER sub_signed_friend +#define MUL_HELPER mul_signed_friend +#define DIV_HELPER div_signed_friend +#define MOD_HELPER mod_signed_friend +#define AND_HELPER and_signed_friend +#define OR_HELPER or_signed_friend +#define XOR_HELPER xor_signed_friend + +#include "sc_nbfriends.inc" + +#undef SC_UNSIGNED +#define SC_SIGNED +#define IF_SC_SIGNED 1 // 1 = sc_signed +#define CLASS_TYPE_SUBREF sc_signed_subref_r +#define OTHER_CLASS_TYPE sc_unsigned +#define OTHER_CLASS_TYPE_SUBREF sc_unsigned_subref_r + +#define MUL_ON_HELPER mul_on_help_signed +#define DIV_ON_HELPER div_on_help_signed +#define MOD_ON_HELPER mod_on_help_signed + +#include "sc_nbcommon.inc" + +#undef MOD_ON_HELPER +#undef DIV_ON_HELPER +#undef MUL_ON_HELPER + +#undef OTHER_CLASS_TYPE_SUBREF +#undef OTHER_CLASS_TYPE +#undef CLASS_TYPE_SUBREF +#undef IF_SC_SIGNED +#undef SC_SIGNED + +#undef XOR_HELPER +#undef OR_HELPER +#undef AND_HELPER +#undef MOD_HELPER +#undef DIV_HELPER +#undef MUL_HELPER +#undef SUB_HELPER +#undef ADD_HELPER + +#undef CLASS_TYPE +#undef CLASS_TYPE_STR + +#include "sc_signed_bitref.inc" +#include "sc_signed_subref.inc" + +#undef CONVERT_LONG +#undef CONVERT_LONG_2 +#undef CONVERT_INT64 +#undef CONVERT_INT64_2 + +} // namespace sc_dt + + +// End of file. diff --git a/ext/systemc/src/sysc/datatypes/int/sc_signed.h b/ext/systemc/src/sysc/datatypes/int/sc_signed.h new file mode 100644 index 000000000..8e2d4f541 --- /dev/null +++ b/ext/systemc/src/sysc/datatypes/int/sc_signed.h @@ -0,0 +1,2382 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_signed.h -- Arbitrary precision signed arithmetic. + + This file includes the definitions of sc_signed_bitref, + sc_signed_subref, and sc_signed classes. The first two classes are + proxy classes to reference one bit and a range of bits of a + sc_signed number, respectively. + + An sc_signed number has the sign-magnitude representation + internally. However, its interface guarantees a 2's-complement + representation. The sign-magnitude representation is chosen + because of its efficiency: The sc_signed and sc_unsigned types are + optimized for arithmetic rather than bitwise operations. For + arithmetic operations, the sign-magnitude representation performs + better. + + The implementations of sc_signed and sc_unsigned classes are + almost identical: Most of the member and friend functions are + defined in sc_nbcommon.cpp and sc_nbfriends.cpp so that they can + be shared by both of these classes. These functions are chosed by + defining a few macros before including them such as IF_SC_SIGNED + and CLASS_TYPE. Our implementation choices are mostly dictated by + performance considerations in that we tried to provide the most + efficient sc_signed and sc_unsigned types without compromising + their interface. + + For the behavior of operators, we have two semantics: the old and + new. The most important difference between these two semantics is + that the old semantics is closer to C/C++ semantics in that the + result type of a binary operator on unsigned and signed arguments + is unsigned; the new semantics, on the other hand, requires the + result type be signed. The new semantics is required by the VSIA + C/C++ data types standard. We have implemented the new semantics. + + Original Author: Ali Dasdan, Synopsys, Inc. + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + +// $Log: sc_signed.h,v $ +// Revision 1.3 2011/08/24 22:05:46 acg +// Torsten Maehne: initialization changes to remove warnings. +// +// Revision 1.2 2011/02/18 20:19:15 acg +// Andy Goodrich: updating Copyright notice. +// +// Revision 1.1.1.1 2006/12/15 20:20:05 acg +// SystemC 2.3 +// +// Revision 1.5 2006/05/08 17:50:01 acg +// Andy Goodrich: Added David Long's declarations for friend operators, +// functions, and methods, to keep the Microsoft compiler happy. +// +// Revision 1.4 2006/03/13 20:25:27 acg +// Andy Goodrich: Addition of function declarations, e.g., xor_signed_friend() +// to keep gcc 4.x happy. +// +// Revision 1.3 2006/01/13 18:49:32 acg +// Added $Log command so that CVS check in comments are reproduced in the +// source. +// + +#ifndef SC_SIGNED_H +#define SC_SIGNED_H + + +#include "sysc/kernel/sc_object.h" +#include "sysc/datatypes/misc/sc_value_base.h" +#include "sysc/utils/sc_iostream.h" +#include "sysc/utils/sc_temporary.h" +#include "sysc/datatypes/int/sc_length_param.h" +#include "sysc/datatypes/int/sc_nbdefs.h" +#include "sysc/datatypes/int/sc_nbutils.h" +#include "sysc/datatypes/int/sc_nbexterns.h" +#include "sysc/datatypes/int/sc_unsigned.h" + + +namespace sc_dt +{ + +// classes defined in this module +class sc_signed_bitref_r; +class sc_signed_bitref; +class sc_signed_subref_r; +class sc_signed_subref; +class sc_concatref; +class sc_signed; + +// forward class declarations +class sc_bv_base; +class sc_lv_base; +class sc_int_base; +class sc_uint_base; +class sc_int_subref_r; +class sc_uint_subref_r; +class sc_signed; +class sc_unsigned; +class sc_unsigned_subref_r; +class sc_fxval; +class sc_fxval_fast; +class sc_fxnum; +class sc_fxnum_fast; + + +// Helper function declarations +sc_signed add_signed_friend(small_type us, + int unb, + int und, + const sc_digit *ud, + small_type vs, + int vnb, + int vnd, + const sc_digit *vd); + +sc_signed sub_signed_friend(small_type us, + int unb, + int und, + const sc_digit *ud, + small_type vs, + int vnb, + int vnd, + const sc_digit *vd); + +sc_signed mul_signed_friend(small_type s, + int unb, + int und, + const sc_digit *ud, + int vnb, + int vnd, + const sc_digit *vd); + +sc_signed div_signed_friend(small_type s, + int unb, + int und, + const sc_digit *ud, + int vnb, + int vnd, + const sc_digit *vd); + +sc_signed mod_signed_friend(small_type us, + int unb, + int und, + const sc_digit *ud, + int vnb, + int vnd, + const sc_digit *vd); + +sc_signed and_signed_friend(small_type us, + int unb, + int und, + const sc_digit *ud, + small_type vs, + int vnb, + int vnd, + const sc_digit *vd); + +sc_signed or_signed_friend(small_type us, + int unb, + int und, + const sc_digit *ud, + small_type vs, + int vnb, + int vnd, + const sc_digit *vd); + +sc_signed xor_signed_friend(small_type us, + int unb, + int und, + const sc_digit *ud, + small_type vs, + int vnb, + int vnd, + const sc_digit *vd); + + +// friend operator declarations + // ARITHMETIC OPERATORS: + + // ADDition operators: + + sc_signed operator + (const sc_unsigned& u, const sc_signed& v); + sc_signed operator + (const sc_signed& u, const sc_unsigned& v); + + sc_signed operator + (const sc_unsigned& u, int64 v); + sc_signed operator + (const sc_unsigned& u, long v); + inline sc_signed operator + (const sc_unsigned& u, int v); + + sc_signed operator + (int64 u, const sc_unsigned& v); + sc_signed operator + (long u, const sc_unsigned& v); + inline sc_signed operator + (int u, const sc_unsigned& v); + + sc_signed operator + (const sc_signed& u, const sc_signed& v); + sc_signed operator + (const sc_signed& u, int64 v); + sc_signed operator + (const sc_signed& u, uint64 v); + sc_signed operator + (const sc_signed& u, long v); + sc_signed operator + (const sc_signed& u, unsigned long v); + inline sc_signed operator + (const sc_signed& u, int v); + inline sc_signed operator + (const sc_signed& u, unsigned int v); + + sc_signed operator + (int64 u, const sc_signed& v); + sc_signed operator + (uint64 u, const sc_signed& v); + sc_signed operator + (long u, const sc_signed& v); + sc_signed operator + (unsigned long u, const sc_signed& v); + inline sc_signed operator + (int u, const sc_signed& v); + inline sc_signed operator + (unsigned int u, const sc_signed& v); + + sc_signed operator + (const sc_unsigned& u, const sc_int_base& v); + sc_signed operator + (const sc_int_base& u, const sc_unsigned& v); + sc_signed operator + (const sc_signed& u, const sc_int_base& v); + sc_signed operator + (const sc_signed& u, const sc_uint_base& v); + sc_signed operator + (const sc_int_base& u, const sc_signed& v); + sc_signed operator + (const sc_uint_base& u, const sc_signed& v); + + + + // SUBtraction operators: + + sc_signed operator - (const sc_unsigned& u, const sc_signed& v); + sc_signed operator - (const sc_signed& u, const sc_unsigned& v); + + sc_signed operator - (const sc_unsigned& u, const sc_unsigned& v); + sc_signed operator - (const sc_unsigned& u, int64 v); + sc_signed operator - (const sc_unsigned& u, uint64 v); + sc_signed operator - (const sc_unsigned& u, long v); + sc_signed operator - (const sc_unsigned& u, unsigned long v); + inline sc_signed operator - (const sc_unsigned& u, int v); + inline sc_signed operator - (const sc_unsigned& u, unsigned int v); + + sc_signed operator - (int64 u, const sc_unsigned& v); + sc_signed operator - (uint64 u, const sc_unsigned& v); + sc_signed operator - (long u, const sc_unsigned& v); + sc_signed operator - (unsigned long u, const sc_unsigned& v); + inline sc_signed operator - (int u, const sc_unsigned& v); + inline sc_signed operator - (unsigned int u, const sc_unsigned& v); + + sc_signed operator - (const sc_signed& u, const sc_signed& v); + sc_signed operator - (const sc_signed& u, int64 v); + sc_signed operator - (const sc_signed& u, uint64 v); + sc_signed operator - (const sc_signed& u, long v); + sc_signed operator - (const sc_signed& u, unsigned long v); + inline sc_signed operator - (const sc_signed& u, int v); + inline sc_signed operator - (const sc_signed& u, unsigned int v); + + sc_signed operator - (int64 u, const sc_signed& v); + sc_signed operator - (uint64 u, const sc_signed& v); + sc_signed operator - (long u, const sc_signed& v); + sc_signed operator - (unsigned long u, const sc_signed& v); + inline sc_signed operator - (int u, const sc_signed& v); + inline sc_signed operator - (unsigned int u, const sc_signed& v); + + + sc_signed operator - (const sc_unsigned& u, const sc_int_base& v); + sc_signed operator - (const sc_unsigned& u, const sc_uint_base& v); + sc_signed operator - (const sc_int_base& u, const sc_unsigned& v); + sc_signed operator - (const sc_uint_base& u, const sc_unsigned& v); + sc_signed operator - (const sc_signed& u, const sc_int_base& v); + sc_signed operator - (const sc_signed& u, const sc_uint_base& v); + sc_signed operator - (const sc_int_base& u, const sc_signed& v); + sc_signed operator - (const sc_uint_base& u, const sc_signed& v); + + + + // MULtiplication operators: + + sc_signed operator * (const sc_unsigned& u, const sc_signed& v); + sc_signed operator * (const sc_signed& u, const sc_unsigned& v); + + sc_signed operator * (const sc_unsigned& u, int64 v); + sc_signed operator * (const sc_unsigned& u, long v); + inline sc_signed operator * (const sc_unsigned& u, int v); + + sc_signed operator * (int64 u, const sc_unsigned& v); + sc_signed operator * (long u, const sc_unsigned& v); + inline sc_signed operator * (int u, const sc_unsigned& v); + + sc_signed operator * (const sc_signed& u, const sc_signed& v); + sc_signed operator * (const sc_signed& u, int64 v); + sc_signed operator * (const sc_signed& u, uint64 v); + sc_signed operator * (const sc_signed& u, long v); + sc_signed operator * (const sc_signed& u, unsigned long v); + inline sc_signed operator * (const sc_signed& u, int v); + inline sc_signed operator * (const sc_signed& u, unsigned int v); + + sc_signed operator * (int64 u, const sc_signed& v); + sc_signed operator * (uint64 u, const sc_signed& v); + sc_signed operator * (long u, const sc_signed& v); + sc_signed operator * (unsigned long u, const sc_signed& v); + inline sc_signed operator * (int u, const sc_signed& v); + inline sc_signed operator * (unsigned int u, const sc_signed& v); + + sc_signed operator * (const sc_unsigned& u, const sc_int_base& v); + sc_signed operator * (const sc_int_base& u, const sc_unsigned& v); + sc_signed operator * (const sc_signed& u, const sc_int_base& v); + sc_signed operator * (const sc_signed& u, const sc_uint_base& v); + sc_signed operator * (const sc_int_base& u, const sc_signed& v); + sc_signed operator * (const sc_uint_base& u, const sc_signed& v); + + + + // DIVision operators: + + sc_signed operator / (const sc_unsigned& u, const sc_signed& v); + sc_signed operator / (const sc_signed& u, const sc_unsigned& v); + + sc_signed operator / (const sc_unsigned& u, int64 v); + sc_signed operator / (const sc_unsigned& u, long v); + inline sc_signed operator / (const sc_unsigned& u, int v); + + sc_signed operator / (int64 u, const sc_unsigned& v); + sc_signed operator / (long u, const sc_unsigned& v); + inline sc_signed operator / (int u, const sc_unsigned& v); + + sc_signed operator / (const sc_signed& u, const sc_signed& v); + sc_signed operator / (const sc_signed& u, int64 v); + sc_signed operator / (const sc_signed& u, uint64 v); + sc_signed operator / (const sc_signed& u, long v); + sc_signed operator / (const sc_signed& u, unsigned long v); + inline sc_signed operator / (const sc_signed& u, int v); + inline sc_signed operator / (const sc_signed& u, unsigned int v); + + sc_signed operator / (int64 u, const sc_signed& v); + sc_signed operator / (uint64 u, const sc_signed& v); + sc_signed operator / (long u, const sc_signed& v); + sc_signed operator / (unsigned long u, const sc_signed& v); + inline sc_signed operator / (int u, const sc_signed& v); + inline sc_signed operator / (unsigned int u, const sc_signed& v); + + sc_signed operator / (const sc_unsigned& u, const sc_int_base& v); + sc_signed operator / (const sc_int_base& u, const sc_unsigned& v); + sc_signed operator / (const sc_signed& u, const sc_int_base& v); + sc_signed operator / (const sc_signed& u, const sc_uint_base& v); + sc_signed operator / (const sc_int_base& u, const sc_signed& v); + sc_signed operator / (const sc_uint_base& u, const sc_signed& v); + + + + // MODulo operators: + + sc_signed operator % (const sc_unsigned& u, const sc_signed& v); + sc_signed operator % (const sc_signed& u, const sc_unsigned& v); + + sc_signed operator % (const sc_unsigned& u, int64 v); + sc_signed operator % (const sc_unsigned& u, long v); + inline sc_signed operator % (const sc_unsigned& u, int v); + + sc_signed operator % (int64 u, const sc_unsigned& v); + sc_signed operator % (long u, const sc_unsigned& v); + inline sc_signed operator % (int u, const sc_unsigned& v); + + sc_signed operator % (const sc_signed& u, const sc_signed& v); + sc_signed operator % (const sc_signed& u, int64 v); + sc_signed operator % (const sc_signed& u, uint64 v); + sc_signed operator % (const sc_signed& u, long v); + sc_signed operator % (const sc_signed& u, unsigned long v); + inline sc_signed operator % (const sc_signed& u, int v); + inline sc_signed operator % (const sc_signed& u, unsigned int v); + + sc_signed operator % (int64 u, const sc_signed& v); + sc_signed operator % (uint64 u, const sc_signed& v); + sc_signed operator % (long u, const sc_signed& v); + sc_signed operator % (unsigned long u, const sc_signed& v); + inline sc_signed operator % (int u, const sc_signed& v); + inline sc_signed operator % (unsigned int u, const sc_signed& v); + + sc_signed operator % (const sc_unsigned& u, const sc_int_base& v); + sc_signed operator % (const sc_int_base& u, const sc_unsigned& v); + sc_signed operator % (const sc_signed& u, const sc_int_base& v); + sc_signed operator % (const sc_signed& u, const sc_uint_base& v); + sc_signed operator % (const sc_int_base& u, const sc_signed& v); + sc_signed operator % (const sc_uint_base& u, const sc_signed& v); + + + + // BITWISE OPERATORS: + + // Bitwise AND operators: + + sc_signed operator & (const sc_unsigned& u, const sc_signed& v); + sc_signed operator & (const sc_signed& u, const sc_unsigned& v); + + sc_signed operator & (const sc_unsigned& u, int64 v); + sc_signed operator & (const sc_unsigned& u, long v); + inline sc_signed operator & (const sc_unsigned& u, int v); + + sc_signed operator & (int64 u, const sc_unsigned& v); + sc_signed operator & (long u, const sc_unsigned& v); + inline sc_signed operator & (int u, const sc_unsigned& v); + + sc_signed operator & (const sc_signed& u, const sc_signed& v); + sc_signed operator & (const sc_signed& u, int64 v); + sc_signed operator & (const sc_signed& u, uint64 v); + sc_signed operator & (const sc_signed& u, long v); + sc_signed operator & (const sc_signed& u, unsigned long v); + inline sc_signed operator & (const sc_signed& u, int v); + inline sc_signed operator & (const sc_signed& u, unsigned int v); + + sc_signed operator & (int64 u, const sc_signed& v); + sc_signed operator & (uint64 u, const sc_signed& v); + sc_signed operator & (long u, const sc_signed& v); + sc_signed operator & (unsigned long u, const sc_signed& v); + inline sc_signed operator & (int u, const sc_signed& v); + inline sc_signed operator & (unsigned int u, const sc_signed& v); + + sc_signed operator & (const sc_unsigned& u, const sc_int_base& v); + sc_signed operator & (const sc_int_base& u, const sc_unsigned& v); + sc_signed operator & (const sc_signed& u, const sc_int_base& v); + sc_signed operator & (const sc_signed& u, const sc_uint_base& v); + sc_signed operator & (const sc_int_base& u, const sc_signed& v); + sc_signed operator & (const sc_uint_base& u, const sc_signed& v); + + + + // Bitwise OR operators: + + sc_signed operator | (const sc_unsigned& u, const sc_signed& v); + sc_signed operator | (const sc_signed& u, const sc_unsigned& v); + + sc_signed operator | (const sc_unsigned& u, int64 v); + sc_signed operator | (const sc_unsigned& u, long v); + inline sc_signed operator | (const sc_unsigned& u, int v); + + sc_signed operator | (int64 u, const sc_unsigned& v); + sc_signed operator | (long u, const sc_unsigned& v); + inline sc_signed operator | (int u, const sc_unsigned& v); + + sc_signed operator | (const sc_signed& u, const sc_signed& v); + sc_signed operator | (const sc_signed& u, int64 v); + sc_signed operator | (const sc_signed& u, uint64 v); + sc_signed operator | (const sc_signed& u, long v); + sc_signed operator | (const sc_signed& u, unsigned long v); + inline sc_signed operator | (const sc_signed& u, int v); + inline sc_signed operator | (const sc_signed& u, unsigned int v); + + sc_signed operator | (int64 u, const sc_signed& v); + sc_signed operator | (uint64 u, const sc_signed& v); + sc_signed operator | (long u, const sc_signed& v); + sc_signed operator | (unsigned long u, const sc_signed& v); + inline sc_signed operator | (int u, const sc_signed& v); + inline sc_signed operator | (unsigned int u, const sc_signed& v); + + sc_signed operator | (const sc_unsigned& u, const sc_int_base& v); + sc_signed operator | (const sc_int_base& u, const sc_unsigned& v); + sc_signed operator | (const sc_signed& u, const sc_int_base& v); + sc_signed operator | (const sc_signed& u, const sc_uint_base& v); + sc_signed operator | (const sc_int_base& u, const sc_signed& v); + sc_signed operator | (const sc_uint_base& u, const sc_signed& v); + + + + // Bitwise XOR operators: + + sc_signed operator ^ (const sc_unsigned& u, const sc_signed& v); + sc_signed operator ^ (const sc_signed& u, const sc_unsigned& v); + + sc_signed operator ^ (const sc_unsigned& u, int64 v); + sc_signed operator ^ (const sc_unsigned& u, long v); + inline sc_signed operator ^ (const sc_unsigned& u, int v); + + sc_signed operator ^ (int64 u, const sc_unsigned& v); + sc_signed operator ^ (long u, const sc_unsigned& v); + inline sc_signed operator ^ (int u, const sc_unsigned& v); + + sc_signed operator ^ (const sc_signed& u, const sc_signed& v); + sc_signed operator ^ (const sc_signed& u, int64 v); + sc_signed operator ^ (const sc_signed& u, uint64 v); + sc_signed operator ^ (const sc_signed& u, long v); + sc_signed operator ^ (const sc_signed& u, unsigned long v); + inline sc_signed operator ^ (const sc_signed& u, int v); + inline sc_signed operator ^ (const sc_signed& u, unsigned int v); + + sc_signed operator ^ (int64 u, const sc_signed& v); + sc_signed operator ^ (uint64 u, const sc_signed& v); + sc_signed operator ^ (long u, const sc_signed& v); + sc_signed operator ^ (unsigned long u, const sc_signed& v); + inline sc_signed operator ^ (int u, const sc_signed& v); + inline sc_signed operator ^ (unsigned int u, const sc_signed& v); + + sc_signed operator ^ (const sc_unsigned& u, const sc_int_base& v); + sc_signed operator ^ (const sc_int_base& u, const sc_unsigned& v); + sc_signed operator ^ (const sc_signed& u, const sc_int_base& v); + sc_signed operator ^ (const sc_signed& u, const sc_uint_base& v); + sc_signed operator ^ (const sc_int_base& u, const sc_signed& v); + sc_signed operator ^ (const sc_uint_base& u, const sc_signed& v); + + + + // SHIFT OPERATORS: + + // LEFT SHIFT operators: + + sc_unsigned operator << (const sc_unsigned& u, const sc_signed& v); + sc_signed operator << (const sc_signed& u, const sc_unsigned& v); + + sc_signed operator << (const sc_signed& u, const sc_signed& v); + sc_signed operator << (const sc_signed& u, int64 v); + sc_signed operator << (const sc_signed& u, uint64 v); + sc_signed operator << (const sc_signed& u, long v); + sc_signed operator << (const sc_signed& u, unsigned long v); + inline sc_signed operator << (const sc_signed& u, int v); + inline sc_signed operator << (const sc_signed& u, unsigned int v); + + sc_signed operator << (const sc_signed& u, const sc_int_base& v); + sc_signed operator << (const sc_signed& u, const sc_uint_base& v); + + + + // RIGHT SHIFT operators: + + sc_unsigned operator >> (const sc_unsigned& u, const sc_signed& v); + sc_signed operator >> (const sc_signed& u, const sc_unsigned& v); + + sc_signed operator >> (const sc_signed& u, const sc_signed& v); + sc_signed operator >> (const sc_signed& u, int64 v); + sc_signed operator >> (const sc_signed& u, uint64 v); + sc_signed operator >> (const sc_signed& u, long v); + sc_signed operator >> (const sc_signed& u, unsigned long v); + inline sc_signed operator >> (const sc_signed& u, int v); + inline sc_signed operator >> (const sc_signed& u, unsigned int v); + + sc_signed operator >> (const sc_signed& u, const sc_int_base& v); + sc_signed operator >> (const sc_signed& u, const sc_uint_base& v); + + + + // Unary arithmetic operators + sc_signed operator + (const sc_signed& u); + sc_signed operator - (const sc_signed& u); + sc_signed operator - (const sc_unsigned& u); + + // LOGICAL OPERATORS: + + // Logical EQUAL operators: + + bool operator == (const sc_unsigned& u, const sc_signed& v); + bool operator == (const sc_signed& u, const sc_unsigned& v); + + bool operator == (const sc_signed& u, const sc_signed& v); + bool operator == (const sc_signed& u, int64 v); + bool operator == (const sc_signed& u, uint64 v); + bool operator == (const sc_signed& u, long v); + bool operator == (const sc_signed& u, unsigned long v); + inline bool operator == (const sc_signed& u, int v); + inline bool operator == (const sc_signed& u, unsigned int v); + + bool operator == (int64 u, const sc_signed& v); + bool operator == (uint64 u, const sc_signed& v); + bool operator == (long u, const sc_signed& v); + bool operator == (unsigned long u, const sc_signed& v); + inline bool operator == (int u, const sc_signed& v); + inline bool operator == (unsigned int u, const sc_signed& v); + + bool operator == (const sc_signed& u, const sc_int_base& v); + bool operator == (const sc_signed& u, const sc_uint_base& v); + bool operator == (const sc_int_base& u, const sc_signed& v); + bool operator == (const sc_uint_base& u, const sc_signed& v); + + // Logical NOT_EQUAL operators: + + bool operator != (const sc_unsigned& u, const sc_signed& v); + bool operator != (const sc_signed& u, const sc_unsigned& v); + + bool operator != (const sc_signed& u, const sc_signed& v); + bool operator != (const sc_signed& u, int64 v); + bool operator != (const sc_signed& u, uint64 v); + bool operator != (const sc_signed& u, long v); + bool operator != (const sc_signed& u, unsigned long v); + inline bool operator != (const sc_signed& u, int v); + inline bool operator != (const sc_signed& u, unsigned int v); + + bool operator != (int64 u, const sc_signed& v); + bool operator != (uint64 u, const sc_signed& v); + bool operator != (long u, const sc_signed& v); + bool operator != (unsigned long u, const sc_signed& v); + inline bool operator != (int u, const sc_signed& v); + inline bool operator != (unsigned int u, const sc_signed& v); + + bool operator != (const sc_signed& u, const sc_int_base& v); + bool operator != (const sc_signed& u, const sc_uint_base& v); + bool operator != (const sc_int_base& u, const sc_signed& v); + bool operator != (const sc_uint_base& u, const sc_signed& v); + + // Logical LESS_THAN operators: + + bool operator < (const sc_unsigned& u, const sc_signed& v); + bool operator < (const sc_signed& u, const sc_unsigned& v); + + bool operator < (const sc_signed& u, const sc_signed& v); + bool operator < (const sc_signed& u, int64 v); + bool operator < (const sc_signed& u, uint64 v); + bool operator < (const sc_signed& u, long v); + bool operator < (const sc_signed& u, unsigned long v); + inline bool operator < (const sc_signed& u, int v); + inline bool operator < (const sc_signed& u, unsigned int v); + + bool operator < (int64 u, const sc_signed& v); + bool operator < (uint64 u, const sc_signed& v); + bool operator < (long u, const sc_signed& v); + bool operator < (unsigned long u, const sc_signed& v); + inline bool operator < (int u, const sc_signed& v); + inline bool operator < (unsigned int u, const sc_signed& v); + + bool operator < (const sc_signed& u, const sc_int_base& v); + bool operator < (const sc_signed& u, const sc_uint_base& v); + bool operator < (const sc_int_base& u, const sc_signed& v); + bool operator < (const sc_uint_base& u, const sc_signed& v); + + // Logical LESS_THAN_AND_EQUAL operators: + + bool operator <= (const sc_unsigned& u, const sc_signed& v); + bool operator <= (const sc_signed& u, const sc_unsigned& v); + + bool operator <= (const sc_signed& u, const sc_signed& v); + bool operator <= (const sc_signed& u, int64 v); + bool operator <= (const sc_signed& u, uint64 v); + bool operator <= (const sc_signed& u, long v); + bool operator <= (const sc_signed& u, unsigned long v); + inline bool operator <= (const sc_signed& u, int v); + inline bool operator <= (const sc_signed& u, unsigned int v); + + bool operator <= (int64 u, const sc_signed& v); + bool operator <= (uint64 u, const sc_signed& v); + bool operator <= (long u, const sc_signed& v); + bool operator <= (unsigned long u, const sc_signed& v); + inline bool operator <= (int u, const sc_signed& v); + inline bool operator <= (unsigned int u, const sc_signed& v); + + bool operator <= (const sc_signed& u, const sc_int_base& v); + bool operator <= (const sc_signed& u, const sc_uint_base& v); + bool operator <= (const sc_int_base& u, const sc_signed& v); + bool operator <= (const sc_uint_base& u, const sc_signed& v); + + // Logical GREATER_THAN operators: + + bool operator > (const sc_unsigned& u, const sc_signed& v); + bool operator > (const sc_signed& u, const sc_unsigned& v); + + bool operator > (const sc_signed& u, const sc_signed& v); + bool operator > (const sc_signed& u, int64 v); + bool operator > (const sc_signed& u, uint64 v); + bool operator > (const sc_signed& u, long v); + bool operator > (const sc_signed& u, unsigned long v); + inline bool operator > (const sc_signed& u, int v); + inline bool operator > (const sc_signed& u, unsigned int v); + + bool operator > (int64 u, const sc_signed& v); + bool operator > (uint64 u, const sc_signed& v); + bool operator > (long u, const sc_signed& v); + bool operator > (unsigned long u, const sc_signed& v); + inline bool operator > (int u, const sc_signed& v); + inline bool operator > (unsigned int u, const sc_signed& v); + + bool operator > (const sc_signed& u, const sc_int_base& v); + bool operator > (const sc_signed& u, const sc_uint_base& v); + bool operator > (const sc_int_base& u, const sc_signed& v); + bool operator > (const sc_uint_base& u, const sc_signed& v); + + // Logical GREATER_THAN_AND_EQUAL operators: + + bool operator >= (const sc_unsigned& u, const sc_signed& v); + bool operator >= (const sc_signed& u, const sc_unsigned& v); + + bool operator >= (const sc_signed& u, const sc_signed& v); + bool operator >= (const sc_signed& u, int64 v); + bool operator >= (const sc_signed& u, uint64 v); + bool operator >= (const sc_signed& u, long v); + bool operator >= (const sc_signed& u, unsigned long v); + inline bool operator >= (const sc_signed& u, int v); + inline bool operator >= (const sc_signed& u, unsigned int v); + + bool operator >= (int64 u, const sc_signed& v); + bool operator >= (uint64 u, const sc_signed& v); + bool operator >= (long u, const sc_signed& v); + bool operator >= (unsigned long u, const sc_signed& v); + inline bool operator >= (int u, const sc_signed& v); + inline bool operator >= (unsigned int u, const sc_signed& v); + + bool operator >= (const sc_signed& u, const sc_int_base& v); + bool operator >= (const sc_signed& u, const sc_uint_base& v); + bool operator >= (const sc_int_base& u, const sc_signed& v); + bool operator >= (const sc_uint_base& u, const sc_signed& v); + + // Bitwise NOT operator (unary). + sc_signed operator ~ (const sc_signed& u); + +// ---------------------------------------------------------------------------- +// CLASS : sc_signed_bitref_r +// +// Proxy class for sc_signed bit selection (r-value only). +// ---------------------------------------------------------------------------- + +class sc_signed_bitref_r : public sc_value_base +{ + friend class sc_signed; + +protected: + + // constructor + + sc_signed_bitref_r() : sc_value_base(), m_index(0), m_obj_p(0) + {} + + void initialize( const sc_signed* obj_p, int index_ ) + { + m_index = index_; + m_obj_p = ( CCAST<sc_signed*>( obj_p ) ); + } + +public: + + // destructor + + virtual ~sc_signed_bitref_r() + {} + + // copy constructor + + sc_signed_bitref_r( const sc_signed_bitref_r& a ) + : sc_value_base(a), m_index( a.m_index ), m_obj_p( a.m_obj_p ) + {} + + // capacity + + int length() const + { return 1; } + + + // implicit conversion to bool + + operator uint64 () const; + bool operator ! () const; + bool operator ~ () const; + + + // explicit conversions + + bool value() const + { return operator uint64(); } + + bool to_bool() const + { return operator uint64(); } + + // concatenation support + + virtual int concat_length(bool* xz_present_p) const + { if ( xz_present_p ) *xz_present_p = false; return 1; } + virtual uint64 concat_get_uint64() const + { return (uint64)operator uint64(); } + virtual bool concat_get_ctrl( sc_digit* dst_p, int low_i ) const + { + int bit_mask = 1 << (low_i % BITS_PER_DIGIT); + int word_i = low_i / BITS_PER_DIGIT; + dst_p[word_i] &= ~bit_mask; + return false; + } + virtual bool concat_get_data( sc_digit* dst_p, int low_i ) const + { + int bit_mask = 1 << (low_i % BITS_PER_DIGIT); + bool result; // True if non-zero. + int word_i = low_i / BITS_PER_DIGIT; + if ( operator uint64() ) + { + dst_p[word_i] |= bit_mask; + result = true; + } + else + { + dst_p[word_i] &= ~bit_mask; + result = false; + } + return result; + } + + + // other methods + + void print( ::std::ostream& os = ::std::cout ) const + { os << to_bool(); } + +protected: + + int m_index; // Bit to be selected. + sc_signed* m_obj_p; // Target of this bit selection. + +private: + + // disabled + const sc_signed_bitref_r& operator = ( const sc_signed_bitref_r& ); +}; + + + +inline +::std::ostream& +operator << ( ::std::ostream&, const sc_signed_bitref_r& ); + + +// ---------------------------------------------------------------------------- +// CLASS : sc_signed_bitref +// +// Proxy class for sc_signed bit selection (r-value and l-value). +// ---------------------------------------------------------------------------- + +class sc_signed_bitref + : public sc_signed_bitref_r +{ + friend class sc_signed; + friend class sc_core::sc_vpool<sc_signed_bitref>; + + + // constructor + +protected: + + sc_signed_bitref() : sc_signed_bitref_r() + {} + +public: + + // copy constructor + + sc_signed_bitref( const sc_signed_bitref& a ) + : sc_signed_bitref_r( a ) + {} + + // assignment operators + + const sc_signed_bitref& operator = ( const sc_signed_bitref_r& ); + const sc_signed_bitref& operator = ( const sc_signed_bitref& ); + const sc_signed_bitref& operator = ( bool ); + + const sc_signed_bitref& operator &= ( bool ); + const sc_signed_bitref& operator |= ( bool ); + const sc_signed_bitref& operator ^= ( bool ); + + // concatenation methods + + virtual void concat_set(int64 src, int low_i); + virtual void concat_set(const sc_signed& src, int low_i); + virtual void concat_set(const sc_unsigned& src, int low_i); + virtual void concat_set(uint64 src, int low_i); + + + // other methods + + void scan( ::std::istream& is = ::std::cin ); + +protected: + static sc_core::sc_vpool<sc_signed_bitref> m_pool; +}; + + + +inline +::std::istream& +operator >> ( ::std::istream&, sc_signed_bitref& ); + + +// ---------------------------------------------------------------------------- +// CLASS : sc_signed_subref_r +// +// Proxy class for sc_signed part selection (r-value only). +// ---------------------------------------------------------------------------- + +class sc_signed_subref_r : public sc_value_base +{ + friend class sc_signed; + friend class sc_signed_signal; + friend class sc_unsigned; + +protected: + + // constructor + + sc_signed_subref_r() : sc_value_base(), m_left(0), m_obj_p(0), m_right(0) + {} + + void initialize( const sc_signed* obj_p, int left_, int right_ ) + { + m_obj_p = ( CCAST<sc_signed*>( obj_p )); + m_left = left_; + m_right = right_; + } + + +public: + + // destructor + + virtual ~sc_signed_subref_r() + {} + + // copy constructor + + sc_signed_subref_r( const sc_signed_subref_r& a ) + : sc_value_base(a), m_left( a.m_left ), m_obj_p( a.m_obj_p ), + m_right( a.m_right ) + {} + + + // capacity + + int length() const + { return m_left >= m_right ? (m_left-m_right+1) : (m_right-m_left+1 ); } + + + // implicit conversion to sc_unsigned + + operator sc_unsigned () const; + + + // explicit conversions + + int to_int() const; + unsigned int to_uint() const; + long to_long() const; + unsigned long to_ulong() const; + int64 to_int64() const; + uint64 to_uint64() const; + double to_double() const; + + + // explicit conversion to character string + + const std::string to_string( sc_numrep numrep = SC_DEC ) const; + const std::string to_string( sc_numrep numrep, bool w_prefix ) const; + + // concatenation support + + virtual int concat_length(bool* xz_present_p) const + { + if ( xz_present_p ) *xz_present_p = false; + return m_left - m_right + 1; + } + virtual uint64 concat_get_uint64() const; + virtual bool concat_get_ctrl( sc_digit* dst_p, int low_i ) const; + virtual bool concat_get_data( sc_digit* dst_p, int low_i ) const; + + // reduce methods + + bool and_reduce() const; + bool nand_reduce() const; + bool or_reduce() const; + bool nor_reduce() const; + bool xor_reduce() const ; + bool xnor_reduce() const; + + + // other methods + + void print( ::std::ostream& os = ::std::cout ) const + { os << to_string(sc_io_base(os,SC_DEC),sc_io_show_base(os)); } + +protected: + + int m_left; // Left-most bit in this part selection. + sc_signed* m_obj_p; // Target of this part selection. + int m_right; // Right-most bit in this part selection. + +private: + const sc_signed_subref_r& operator = ( const sc_signed_subref_r& ); + +}; + + + +inline +::std::ostream& +operator << ( ::std::ostream&, const sc_signed_subref_r& ); + + +// ---------------------------------------------------------------------------- +// CLASS : sc_signed_subref +// +// Proxy class for sc_signed part selection (r-value and l-value). +// ---------------------------------------------------------------------------- + +class sc_signed_subref + : public sc_signed_subref_r +{ + friend class sc_signed; + friend class sc_core::sc_vpool<sc_signed_subref>; + + + // constructor + + sc_signed_subref() : sc_signed_subref_r() + {} + +public: + + // copy constructor + + sc_signed_subref( const sc_signed_subref& a ) + : sc_signed_subref_r( a ) + {} + + + // assignment operators + + const sc_signed_subref& operator = ( const sc_signed_subref_r& a ); + const sc_signed_subref& operator = ( const sc_signed_subref& a ); + const sc_signed_subref& operator = ( const sc_signed& a ); + + const sc_signed_subref& operator = ( const sc_unsigned_subref_r& a ); + const sc_signed_subref& operator = ( const sc_unsigned& a ); + + template< class T > + const sc_signed_subref& operator = ( const sc_generic_base<T>& a ) + { + sc_unsigned temp( length() ); + a->to_sc_unsigned(temp); + return operator = (temp); + } + + const sc_signed_subref& operator = ( const char* a ); + const sc_signed_subref& operator = ( unsigned long a ); + const sc_signed_subref& operator = ( long a ); + const sc_signed_subref& operator = ( unsigned int a ) + { return operator = ( (unsigned long) a ); } + + const sc_signed_subref& operator = ( int a ) + { return operator = ( (long) a ); } + + const sc_signed_subref& operator = ( uint64 a ); + const sc_signed_subref& operator = ( int64 a ); + const sc_signed_subref& operator = ( double a ); + const sc_signed_subref& operator = ( const sc_int_base& a ); + const sc_signed_subref& operator = ( const sc_uint_base& a ); + + // concatenation methods + + virtual void concat_set(int64 src, int low_i); + virtual void concat_set(const sc_signed& src, int low_i); + virtual void concat_set(const sc_unsigned& src, int low_i); + virtual void concat_set(uint64 src, int low_i); + + // other methods + + void scan( ::std::istream& is = ::std::cin ); + +protected: + static sc_core::sc_vpool<sc_signed_subref> m_pool; +}; + + + +inline +::std::istream& +operator >> ( ::std::istream&, sc_signed_subref& ); + + +// ---------------------------------------------------------------------------- +// CLASS : sc_signed +// +// Arbitrary precision signed number. +// ---------------------------------------------------------------------------- + +class sc_signed : public sc_value_base +{ + friend class sc_concatref; + friend class sc_signed_bitref_r; + friend class sc_signed_bitref; + friend class sc_signed_subref_r; + friend class sc_signed_subref; + friend class sc_unsigned; + friend class sc_unsigned_subref; + + // Needed for types using sc_signed. + typedef bool elemtype; + +public: + + // constructors + + explicit sc_signed( int nb = sc_length_param().len() ); + sc_signed( const sc_signed& v ); + sc_signed( const sc_unsigned& v ); + template<class T> + explicit sc_signed( const sc_generic_base<T>& v ); + explicit sc_signed( const sc_bv_base& v ); + explicit sc_signed( const sc_lv_base& v ); + explicit sc_signed( const sc_int_subref_r& v ); + explicit sc_signed( const sc_uint_subref_r& v ); + explicit sc_signed( const sc_signed_subref_r& v ); + explicit sc_signed( const sc_unsigned_subref_r& v ); + + // assignment operators + + const sc_signed& operator = (const sc_signed& v); + const sc_signed& operator = (const sc_signed_subref_r& a ); + + template< class T > + const sc_signed& operator = ( const sc_generic_base<T>& a ) + { a->to_sc_signed(*this); return *this; } + + const sc_signed& operator = (const sc_unsigned& v); + const sc_signed& operator = (const sc_unsigned_subref_r& a ); + + const sc_signed& operator = (const char* v); + const sc_signed& operator = (int64 v); + const sc_signed& operator = (uint64 v); + const sc_signed& operator = (long v); + const sc_signed& operator = (unsigned long v); + + const sc_signed& operator = (int v) + { return operator=((long) v); } + + const sc_signed& operator = (unsigned int v) + { return operator=((unsigned long) v); } + + const sc_signed& operator = (double v); + const sc_signed& operator = (const sc_int_base& v); + const sc_signed& operator = (const sc_uint_base& v); + + const sc_signed& operator = ( const sc_bv_base& ); + const sc_signed& operator = ( const sc_lv_base& ); + +#ifdef SC_INCLUDE_FX + const sc_signed& operator = ( const sc_fxval& ); + const sc_signed& operator = ( const sc_fxval_fast& ); + const sc_signed& operator = ( const sc_fxnum& ); + const sc_signed& operator = ( const sc_fxnum_fast& ); +#endif + + + // destructor + + virtual ~sc_signed() + { +#ifndef SC_MAX_NBITS + delete [] digit; +#endif + } + + // Concatenation support: + + sc_digit* get_raw() const + { return digit; } + virtual int concat_length(bool* xz_present_p) const + { if ( xz_present_p ) *xz_present_p = false; return nbits; } + virtual bool concat_get_ctrl( sc_digit* dst_p, int low_i ) const; + virtual bool concat_get_data( sc_digit* dst_p, int low_i ) const; + virtual uint64 concat_get_uint64() const; + virtual void concat_set(int64 src, int low_i); + virtual void concat_set(const sc_signed& src, int low_i); + virtual void concat_set(const sc_unsigned& src, int low_i); + virtual void concat_set(uint64 src, int low_i); + + + + // Increment operators. + sc_signed& operator ++ (); + const sc_signed operator ++ (int); + + // Decrement operators. + sc_signed& operator -- (); + const sc_signed operator -- (int); + + + // bit selection + + inline void check_index( int i ) const + { if ( i < 0 || i >= nbits ) invalid_index(i); } + + void invalid_index( int i ) const; + + sc_signed_bitref& operator [] ( int i ) + { + check_index(i); + sc_signed_bitref* result_p = + sc_signed_bitref::m_pool.allocate(); + result_p->initialize( this, i ); + return *result_p; + } + + const sc_signed_bitref_r& operator [] ( int i ) const + { + check_index(i); + sc_signed_bitref* result_p = + sc_signed_bitref::m_pool.allocate(); + result_p->initialize( this, i ); + return *result_p; + } + + sc_signed_bitref& bit( int i ) + { + check_index(i); + sc_signed_bitref* result_p = + sc_signed_bitref::m_pool.allocate(); + result_p->initialize( this, i ); + return *result_p; + } + + const sc_signed_bitref_r& bit( int i ) const + { + check_index(i); + sc_signed_bitref* result_p = + sc_signed_bitref::m_pool.allocate(); + result_p->initialize( this, i ); + return *result_p; + } + + + // part selection + + // Subref operators. Help access the range of bits from the ith to + // jth. These indices have arbitrary precedence with respect to each + // other, i.e., we can have i <= j or i > j. Note the equivalence + // between range(i, j) and operator(i, j). Also note that + // operator(i, i) returns a signed number that corresponds to the + // bit operator[i], so these two forms are not the same. + + inline void check_range( int l, int r ) const + { + if ( l < r ) + { + if ( l < 0 || r >= nbits ) invalid_range(l,r); + } + else + { + if ( r < 0 || l >= nbits ) invalid_range(l,r); + } + } + + void invalid_range( int l, int r ) const; + + sc_signed_subref& range( int i, int j ) + { + check_range( i, j ); + sc_signed_subref* result_p = + sc_signed_subref::m_pool.allocate(); + result_p->initialize( this, i, j ); + return *result_p; + } + + const sc_signed_subref_r& range( int i, int j ) const + { + check_range( i, j ); + sc_signed_subref* result_p = + sc_signed_subref::m_pool.allocate(); + result_p->initialize( this, i, j ); + return *result_p; + } + + sc_signed_subref& operator () ( int i, int j ) + { + check_range( i, j ); + sc_signed_subref* result_p = + sc_signed_subref::m_pool.allocate(); + result_p->initialize( this, i, j ); + return *result_p; + } + + const sc_signed_subref_r& operator () ( int i, int j ) const + { + check_range( i, j ); + sc_signed_subref* result_p = + sc_signed_subref::m_pool.allocate(); + result_p->initialize( this, i, j ); + return *result_p; + } + + + // explicit conversions + + int to_int() const; + unsigned int to_uint() const; + long to_long() const; + unsigned long to_ulong() const; + int64 to_int64() const; + uint64 to_uint64() const; + double to_double() const; + +#ifdef SC_DT_DEPRECATED + int to_signed() const + { return to_int(); } + + unsigned int to_unsigned() const + { return to_uint(); } +#endif + + // explicit conversion to character string + + const std::string to_string( sc_numrep numrep = SC_DEC ) const; + const std::string to_string( sc_numrep numrep, bool w_prefix ) const; + + + // Print functions. dump prints the internals of the class. + + void print( ::std::ostream& os = ::std::cout ) const + { os << to_string(sc_io_base(os,SC_DEC),sc_io_show_base(os)); } + + void scan( ::std::istream& is = ::std::cin ); + + void dump( ::std::ostream& os = ::std::cout ) const; + + + // Functions to find various properties. + int length() const { return nbits; } // Bit width. + bool iszero() const; // Is the number zero? + bool sign() const; // Sign. + + // reduce methods + + bool and_reduce() const; + + bool nand_reduce() const + { return ( ! and_reduce() ); } + + bool or_reduce() const; + + bool nor_reduce() const + { return ( ! or_reduce() ); } + + bool xor_reduce() const; + + bool xnor_reduce() const + { return ( ! xor_reduce() ); } + + // Functions to access individual bits. + bool test(int i) const; // Is the ith bit 0 or 1? + void set(int i); // Set the ith bit to 1. + void clear(int i); // Set the ith bit to 0. + void set(int i, bool v) // Set the ith bit to v. + { if (v) set(i); else clear(i); } + void invert(int i) // Negate the ith bit. + { if (test(i)) clear(i); else set(i); } + + // Make the number equal to its mirror image. + void reverse(); + + // Get/set a packed bit representation of the number. + void get_packed_rep(sc_digit *buf) const; + void set_packed_rep(sc_digit *buf); + + /* + The comparison of the old and new semantics are as follows: + + Let s = sc_signed, + u = sc_unsigned, + un = { uint64, unsigned long, unsigned int }, + sn = { int64, long, int, char* }, and + OP = { +, -, *, /, % }. + + Old semantics: New semantics: + u OP u -> u u OP u -> u + s OP u -> u s OP u -> s + u OP s -> u u OP s -> s + s OP s -> s s OP s -> s + + u OP un = un OP u -> u u OP un = un OP u -> u + u OP sn = sn OP u -> u u OP sn = sn OP u -> s + + s OP un = un OP s -> s s OP un = un OP s -> s + s OP sn = sn OP s -> s s OP sn = sn OP s -> s + + In the new semantics, the result is u if both operands are u; the + result is s otherwise. The only exception is subtraction. The result + of a subtraction is always s. + + The old semantics is like C/C++ semantics on integer types; the + new semantics is due to the VSIA C/C++ data types standard. + */ + + // ARITHMETIC OPERATORS: + + // ADDition operators: + + friend sc_signed operator + (const sc_unsigned& u, const sc_signed& v); + friend sc_signed operator + (const sc_signed& u, const sc_unsigned& v); + + friend sc_signed operator + (const sc_unsigned& u, int64 v); + friend sc_signed operator + (const sc_unsigned& u, long v); + friend sc_signed operator + (const sc_unsigned& u, int v) + { return operator+(u, (long) v); } + + friend sc_signed operator + (int64 u, const sc_unsigned& v); + friend sc_signed operator + (long u, const sc_unsigned& v); + friend sc_signed operator + (int u, const sc_unsigned& v) + { return operator+((long) u, v); } + + friend sc_signed operator + (const sc_signed& u, const sc_signed& v); + friend sc_signed operator + (const sc_signed& u, int64 v); + friend sc_signed operator + (const sc_signed& u, uint64 v); + friend sc_signed operator + (const sc_signed& u, long v); + friend sc_signed operator + (const sc_signed& u, unsigned long v); + friend sc_signed operator + (const sc_signed& u, int v) + { return operator+(u, (long) v); } + friend sc_signed operator + (const sc_signed& u, unsigned int v) + { return operator+(u, (unsigned long) v); } + + friend sc_signed operator + (int64 u, const sc_signed& v); + friend sc_signed operator + (uint64 u, const sc_signed& v); + friend sc_signed operator + (long u, const sc_signed& v); + friend sc_signed operator + (unsigned long u, const sc_signed& v); + friend sc_signed operator + (int u, const sc_signed& v) + { return operator+((long) u, v); } + friend sc_signed operator + (unsigned int u, const sc_signed& v) + { return operator+((unsigned long) u, v); } + + const sc_signed& operator += (const sc_signed& v); + const sc_signed& operator += (const sc_unsigned& v); + const sc_signed& operator += (int64 v); + const sc_signed& operator += (uint64 v); + const sc_signed& operator += (long v); + const sc_signed& operator += (unsigned long v); + const sc_signed& operator += (int v) + { return operator+=((long) v); } + const sc_signed& operator += (unsigned int v) + { return operator+=((unsigned long) v); } + + friend sc_signed operator + (const sc_unsigned& u, const sc_int_base& v); + friend sc_signed operator + (const sc_int_base& u, const sc_unsigned& v); + friend sc_signed operator + (const sc_signed& u, const sc_int_base& v); + friend sc_signed operator + (const sc_signed& u, const sc_uint_base& v); + friend sc_signed operator + (const sc_int_base& u, const sc_signed& v); + friend sc_signed operator + (const sc_uint_base& u, const sc_signed& v); + const sc_signed& operator += (const sc_int_base& v); + const sc_signed& operator += (const sc_uint_base& v); + + // SUBtraction operators: + + friend sc_signed operator - (const sc_unsigned& u, const sc_signed& v); + friend sc_signed operator - (const sc_signed& u, const sc_unsigned& v); + + friend sc_signed operator - (const sc_unsigned& u, const sc_unsigned& v); + friend sc_signed operator - (const sc_unsigned& u, int64 v); + friend sc_signed operator - (const sc_unsigned& u, uint64 v); + friend sc_signed operator - (const sc_unsigned& u, long v); + friend sc_signed operator - (const sc_unsigned& u, unsigned long v); + friend sc_signed operator - (const sc_unsigned& u, int v) + { return operator-(u, (long) v); } + friend sc_signed operator - (const sc_unsigned& u, unsigned int v) + { return operator-(u, (unsigned long) v); } + + friend sc_signed operator - (int64 u, const sc_unsigned& v); + friend sc_signed operator - (uint64 u, const sc_unsigned& v); + friend sc_signed operator - (long u, const sc_unsigned& v); + friend sc_signed operator - (unsigned long u, const sc_unsigned& v); + friend sc_signed operator - (int u, const sc_unsigned& v) + { return operator-((long) u, v); } + friend sc_signed operator - (unsigned int u, const sc_unsigned& v) + { return operator-((unsigned long) u, v); } + + friend sc_signed operator - (const sc_signed& u, const sc_signed& v); + friend sc_signed operator - (const sc_signed& u, int64 v); + friend sc_signed operator - (const sc_signed& u, uint64 v); + friend sc_signed operator - (const sc_signed& u, long v); + friend sc_signed operator - (const sc_signed& u, unsigned long v); + friend sc_signed operator - (const sc_signed& u, int v) + { return operator-(u, (long) v); } + friend sc_signed operator - (const sc_signed& u, unsigned int v) + { return operator-(u, (unsigned long) v); } + + friend sc_signed operator - (int64 u, const sc_signed& v); + friend sc_signed operator - (uint64 u, const sc_signed& v); + friend sc_signed operator - (long u, const sc_signed& v); + friend sc_signed operator - (unsigned long u, const sc_signed& v); + friend sc_signed operator - (int u, const sc_signed& v) + { return operator-((long) u, v); } + friend sc_signed operator - (unsigned int u, const sc_signed& v) + { return operator-((unsigned long) u, v); } + + const sc_signed& operator -= (const sc_signed& v); + const sc_signed& operator -= (const sc_unsigned& v); + const sc_signed& operator -= (int64 v); + const sc_signed& operator -= (uint64 v); + const sc_signed& operator -= (long v); + const sc_signed& operator -= (unsigned long v); + const sc_signed& operator -= (int v) + { return operator -= ((long) v); } + const sc_signed& operator -= (unsigned int v) + { return operator -= ((unsigned long) v); } + + friend sc_signed operator - (const sc_unsigned& u, const sc_int_base& v); + friend sc_signed operator - (const sc_unsigned& u, const sc_uint_base& v); + friend sc_signed operator - (const sc_int_base& u, const sc_unsigned& v); + friend sc_signed operator - (const sc_uint_base& u, const sc_unsigned& v); + friend sc_signed operator - (const sc_signed& u, const sc_int_base& v); + friend sc_signed operator - (const sc_signed& u, const sc_uint_base& v); + friend sc_signed operator - (const sc_int_base& u, const sc_signed& v); + friend sc_signed operator - (const sc_uint_base& u, const sc_signed& v); + const sc_signed& operator -= (const sc_int_base& v); + const sc_signed& operator -= (const sc_uint_base& v); + + // MULtiplication operators: + + friend sc_signed operator * (const sc_unsigned& u, const sc_signed& v); + friend sc_signed operator * (const sc_signed& u, const sc_unsigned& v); + + friend sc_signed operator * (const sc_unsigned& u, int64 v); + friend sc_signed operator * (const sc_unsigned& u, long v); + friend sc_signed operator * (const sc_unsigned& u, int v) + { return operator*(u, (long) v); } + + friend sc_signed operator * (int64 u, const sc_unsigned& v); + friend sc_signed operator * (long u, const sc_unsigned& v); + friend sc_signed operator * (int u, const sc_unsigned& v) + { return operator*((long) u, v); } + + friend sc_signed operator * (const sc_signed& u, const sc_signed& v); + friend sc_signed operator * (const sc_signed& u, int64 v); + friend sc_signed operator * (const sc_signed& u, uint64 v); + friend sc_signed operator * (const sc_signed& u, long v); + friend sc_signed operator * (const sc_signed& u, unsigned long v); + friend sc_signed operator * (const sc_signed& u, int v) + { return operator*(u, (long) v); } + friend sc_signed operator * (const sc_signed& u, unsigned int v) + { return operator*(u, (unsigned long) v); } + + friend sc_signed operator * (int64 u, const sc_signed& v); + friend sc_signed operator * (uint64 u, const sc_signed& v); + friend sc_signed operator * (long u, const sc_signed& v); + friend sc_signed operator * (unsigned long u, const sc_signed& v); + friend sc_signed operator * (int u, const sc_signed& v) + { return operator*((long) u, v); } + friend sc_signed operator * (unsigned int u, const sc_signed& v) + { return operator*((unsigned long) u, v); } + + const sc_signed& operator *= (const sc_signed& v); + const sc_signed& operator *= (const sc_unsigned& v); + const sc_signed& operator *= (int64 v); + const sc_signed& operator *= (uint64 v); + const sc_signed& operator *= (long v); + const sc_signed& operator *= (unsigned long v); + const sc_signed& operator *= (int v) + { return operator*=((long) v); } + const sc_signed& operator *= (unsigned int v) + { return operator*=((unsigned long) v); } + + friend sc_signed operator * (const sc_unsigned& u, const sc_int_base& v); + friend sc_signed operator * (const sc_int_base& u, const sc_unsigned& v); + friend sc_signed operator * (const sc_signed& u, const sc_int_base& v); + friend sc_signed operator * (const sc_signed& u, const sc_uint_base& v); + friend sc_signed operator * (const sc_int_base& u, const sc_signed& v); + friend sc_signed operator * (const sc_uint_base& u, const sc_signed& v); + const sc_signed& operator *= (const sc_int_base& v); + const sc_signed& operator *= (const sc_uint_base& v); + + // DIVision operators: + + friend sc_signed operator / (const sc_unsigned& u, const sc_signed& v); + friend sc_signed operator / (const sc_signed& u, const sc_unsigned& v); + + friend sc_signed operator / (const sc_unsigned& u, int64 v); + friend sc_signed operator / (const sc_unsigned& u, long v); + friend sc_signed operator / (const sc_unsigned& u, int v) + { return operator/(u, (long) v); } + + friend sc_signed operator / (int64 u, const sc_unsigned& v); + friend sc_signed operator / (long u, const sc_unsigned& v); + friend sc_signed operator / (int u, const sc_unsigned& v) + { return operator/((long) u, v); } + + friend sc_signed operator / (const sc_signed& u, const sc_signed& v); + friend sc_signed operator / (const sc_signed& u, int64 v); + friend sc_signed operator / (const sc_signed& u, uint64 v); + friend sc_signed operator / (const sc_signed& u, long v); + friend sc_signed operator / (const sc_signed& u, unsigned long v); + friend sc_signed operator / (const sc_signed& u, int v) + { return operator/(u, (long) v); } + friend sc_signed operator / (const sc_signed& u, unsigned int v) + { return operator/(u, (unsigned long) v); } + + friend sc_signed operator / (int64 u, const sc_signed& v); + friend sc_signed operator / (uint64 u, const sc_signed& v); + friend sc_signed operator / (long u, const sc_signed& v); + friend sc_signed operator / (unsigned long u, const sc_signed& v); + friend sc_signed operator / (int u, const sc_signed& v) + { return operator/((long) u, v); } + friend sc_signed operator / (unsigned int u, const sc_signed& v) + { return operator/((unsigned long) u, v); } + + const sc_signed& operator /= (const sc_signed& v); + const sc_signed& operator /= (const sc_unsigned& v); + const sc_signed& operator /= (int64 v); + const sc_signed& operator /= (uint64 v); + const sc_signed& operator /= (long v); + const sc_signed& operator /= (unsigned long v); + const sc_signed& operator /= (int v) + { return operator/=((long) v); } + const sc_signed& operator /= (unsigned int v) + { return operator/=((unsigned long) v); } + + friend sc_signed operator / (const sc_unsigned& u, const sc_int_base& v); + friend sc_signed operator / (const sc_int_base& u, const sc_unsigned& v); + friend sc_signed operator / (const sc_signed& u, const sc_int_base& v); + friend sc_signed operator / (const sc_signed& u, const sc_uint_base& v); + friend sc_signed operator / (const sc_int_base& u, const sc_signed& v); + friend sc_signed operator / (const sc_uint_base& u, const sc_signed& v); + const sc_signed& operator /= (const sc_int_base& v); + const sc_signed& operator /= (const sc_uint_base& v); + + // MODulo operators: + + friend sc_signed operator % (const sc_unsigned& u, const sc_signed& v); + friend sc_signed operator % (const sc_signed& u, const sc_unsigned& v); + + friend sc_signed operator % (const sc_unsigned& u, int64 v); + friend sc_signed operator % (const sc_unsigned& u, long v); + friend sc_signed operator % (const sc_unsigned& u, int v) + { return operator%(u, (long) v); } + + friend sc_signed operator % (int64 u, const sc_unsigned& v); + friend sc_signed operator % (long u, const sc_unsigned& v); + friend sc_signed operator % (int u, const sc_unsigned& v) + { return operator%((long) u, v); } + + friend sc_signed operator % (const sc_signed& u, const sc_signed& v); + friend sc_signed operator % (const sc_signed& u, int64 v); + friend sc_signed operator % (const sc_signed& u, uint64 v); + friend sc_signed operator % (const sc_signed& u, long v); + friend sc_signed operator % (const sc_signed& u, unsigned long v); + friend sc_signed operator % (const sc_signed& u, int v) + { return operator%(u, (long) v); } + friend sc_signed operator % (const sc_signed& u, unsigned int v) + { return operator%(u, (unsigned long) v); } + + friend sc_signed operator % (int64 u, const sc_signed& v); + friend sc_signed operator % (uint64 u, const sc_signed& v); + friend sc_signed operator % (long u, const sc_signed& v); + friend sc_signed operator % (unsigned long u, const sc_signed& v); + friend sc_signed operator % (int u, const sc_signed& v) + { return operator%((long) u, v); } + friend sc_signed operator % (unsigned int u, const sc_signed& v) + { return operator%((unsigned long) u, v); } + + const sc_signed& operator %= (const sc_signed& v); + const sc_signed& operator %= (const sc_unsigned& v); + const sc_signed& operator %= (int64 v); + const sc_signed& operator %= (uint64 v); + const sc_signed& operator %= (long v); + const sc_signed& operator %= (unsigned long v); + const sc_signed& operator %= (int v) + { return operator%=((long) v); } + const sc_signed& operator %= (unsigned int v) + { return operator%=((unsigned long) v); } + + friend sc_signed operator % (const sc_unsigned& u, const sc_int_base& v); + friend sc_signed operator % (const sc_int_base& u, const sc_unsigned& v); + friend sc_signed operator % (const sc_signed& u, const sc_int_base& v); + friend sc_signed operator % (const sc_signed& u, const sc_uint_base& v); + friend sc_signed operator % (const sc_int_base& u, const sc_signed& v); + friend sc_signed operator % (const sc_uint_base& u, const sc_signed& v); + const sc_signed& operator %= (const sc_int_base& v); + const sc_signed& operator %= (const sc_uint_base& v); + + // BITWISE OPERATORS: + + // Bitwise AND operators: + + friend sc_signed operator & (const sc_unsigned& u, const sc_signed& v); + friend sc_signed operator & (const sc_signed& u, const sc_unsigned& v); + + friend sc_signed operator & (const sc_unsigned& u, int64 v); + friend sc_signed operator & (const sc_unsigned& u, long v); + friend sc_signed operator & (const sc_unsigned& u, int v) + { return operator&(u, (long) v); } + + friend sc_signed operator & (int64 u, const sc_unsigned& v); + friend sc_signed operator & (long u, const sc_unsigned& v); + friend sc_signed operator & (int u, const sc_unsigned& v) + { return operator&((long) u, v); } + + friend sc_signed operator & (const sc_signed& u, const sc_signed& v); + friend sc_signed operator & (const sc_signed& u, int64 v); + friend sc_signed operator & (const sc_signed& u, uint64 v); + friend sc_signed operator & (const sc_signed& u, long v); + friend sc_signed operator & (const sc_signed& u, unsigned long v); + friend sc_signed operator & (const sc_signed& u, int v) + { return operator&(u, (long) v); } + friend sc_signed operator & (const sc_signed& u, unsigned int v) + { return operator&(u, (unsigned long) v); } + + friend sc_signed operator & (int64 u, const sc_signed& v); + friend sc_signed operator & (uint64 u, const sc_signed& v); + friend sc_signed operator & (long u, const sc_signed& v); + friend sc_signed operator & (unsigned long u, const sc_signed& v); + friend sc_signed operator & (int u, const sc_signed& v) + { return operator&((long) u, v); } + friend sc_signed operator & (unsigned int u, const sc_signed& v) + { return operator&((unsigned long) u, v); } + + const sc_signed& operator &= (const sc_signed& v); + const sc_signed& operator &= (const sc_unsigned& v); + const sc_signed& operator &= (int64 v); + const sc_signed& operator &= (uint64 v); + const sc_signed& operator &= (long v); + const sc_signed& operator &= (unsigned long v); + const sc_signed& operator &= (int v) + { return operator&=((long) v); } + const sc_signed& operator &= (unsigned int v) + { return operator&=((unsigned long) v); } + + friend sc_signed operator & (const sc_unsigned& u, const sc_int_base& v); + friend sc_signed operator & (const sc_int_base& u, const sc_unsigned& v); + friend sc_signed operator & (const sc_signed& u, const sc_int_base& v); + friend sc_signed operator & (const sc_signed& u, const sc_uint_base& v); + friend sc_signed operator & (const sc_int_base& u, const sc_signed& v); + friend sc_signed operator & (const sc_uint_base& u, const sc_signed& v); + const sc_signed& operator &= (const sc_int_base& v); + const sc_signed& operator &= (const sc_uint_base& v); + + // Bitwise OR operators: + + friend sc_signed operator | (const sc_unsigned& u, const sc_signed& v); + friend sc_signed operator | (const sc_signed& u, const sc_unsigned& v); + + friend sc_signed operator | (const sc_unsigned& u, int64 v); + friend sc_signed operator | (const sc_unsigned& u, long v); + friend sc_signed operator | (const sc_unsigned& u, int v) + { return operator|(u, (long) v); } + + friend sc_signed operator | (int64 u, const sc_unsigned& v); + friend sc_signed operator | (long u, const sc_unsigned& v); + friend sc_signed operator | (int u, const sc_unsigned& v) + { return operator|((long) u, v); } + + friend sc_signed operator | (const sc_signed& u, const sc_signed& v); + friend sc_signed operator | (const sc_signed& u, int64 v); + friend sc_signed operator | (const sc_signed& u, uint64 v); + friend sc_signed operator | (const sc_signed& u, long v); + friend sc_signed operator | (const sc_signed& u, unsigned long v); + friend sc_signed operator | (const sc_signed& u, int v) + { return operator|(u, (long) v); } + friend sc_signed operator | (const sc_signed& u, unsigned int v) + { return operator|(u, (unsigned long) v); } + + friend sc_signed operator | (int64 u, const sc_signed& v); + friend sc_signed operator | (uint64 u, const sc_signed& v); + friend sc_signed operator | (long u, const sc_signed& v); + friend sc_signed operator | (unsigned long u, const sc_signed& v); + friend sc_signed operator | (int u, const sc_signed& v) + { return operator|((long) u, v); } + friend sc_signed operator | (unsigned int u, const sc_signed& v) + { return operator|((unsigned long) u, v); } + + const sc_signed& operator |= (const sc_signed& v); + const sc_signed& operator |= (const sc_unsigned& v); + const sc_signed& operator |= (int64 v); + const sc_signed& operator |= (uint64 v); + const sc_signed& operator |= (long v); + const sc_signed& operator |= (unsigned long v); + const sc_signed& operator |= (int v) + { return operator|=((long) v); } + const sc_signed& operator |= (unsigned int v) + { return operator|=((unsigned long) v); } + + friend sc_signed operator | (const sc_unsigned& u, const sc_int_base& v); + friend sc_signed operator | (const sc_int_base& u, const sc_unsigned& v); + friend sc_signed operator | (const sc_signed& u, const sc_int_base& v); + friend sc_signed operator | (const sc_signed& u, const sc_uint_base& v); + friend sc_signed operator | (const sc_int_base& u, const sc_signed& v); + friend sc_signed operator | (const sc_uint_base& u, const sc_signed& v); + const sc_signed& operator |= (const sc_int_base& v); + const sc_signed& operator |= (const sc_uint_base& v); + + // Bitwise XOR operators: + + friend sc_signed operator ^ (const sc_unsigned& u, const sc_signed& v); + friend sc_signed operator ^ (const sc_signed& u, const sc_unsigned& v); + + friend sc_signed operator ^ (const sc_unsigned& u, int64 v); + friend sc_signed operator ^ (const sc_unsigned& u, long v); + friend sc_signed operator ^ (const sc_unsigned& u, int v) + { return operator^(u, (long) v); } + + friend sc_signed operator ^ (int64 u, const sc_unsigned& v); + friend sc_signed operator ^ (long u, const sc_unsigned& v); + friend sc_signed operator ^ (int u, const sc_unsigned& v) + { return operator^((long) u, v); } + + friend sc_signed operator ^ (const sc_signed& u, const sc_signed& v); + friend sc_signed operator ^ (const sc_signed& u, int64 v); + friend sc_signed operator ^ (const sc_signed& u, uint64 v); + friend sc_signed operator ^ (const sc_signed& u, long v); + friend sc_signed operator ^ (const sc_signed& u, unsigned long v); + friend sc_signed operator ^ (const sc_signed& u, int v) + { return operator^(u, (long) v); } + friend sc_signed operator ^ (const sc_signed& u, unsigned int v) + { return operator^(u, (unsigned long) v); } + + friend sc_signed operator ^ (int64 u, const sc_signed& v); + friend sc_signed operator ^ (uint64 u, const sc_signed& v); + friend sc_signed operator ^ (long u, const sc_signed& v); + friend sc_signed operator ^ (unsigned long u, const sc_signed& v); + friend sc_signed operator ^ (int u, const sc_signed& v) + { return operator^((long) u, v); } + friend sc_signed operator ^ (unsigned int u, const sc_signed& v) + { return operator^((unsigned long) u, v); } + + const sc_signed& operator ^= (const sc_signed& v); + const sc_signed& operator ^= (const sc_unsigned& v); + const sc_signed& operator ^= (int64 v); + const sc_signed& operator ^= (uint64 v); + const sc_signed& operator ^= (long v); + const sc_signed& operator ^= (unsigned long v); + const sc_signed& operator ^= (int v) + { return operator^=((long) v); } + const sc_signed& operator ^= (unsigned int v) + { return operator^=((unsigned long) v); } + + friend sc_signed operator ^ (const sc_unsigned& u, const sc_int_base& v); + friend sc_signed operator ^ (const sc_int_base& u, const sc_unsigned& v); + friend sc_signed operator ^ (const sc_signed& u, const sc_int_base& v); + friend sc_signed operator ^ (const sc_signed& u, const sc_uint_base& v); + friend sc_signed operator ^ (const sc_int_base& u, const sc_signed& v); + friend sc_signed operator ^ (const sc_uint_base& u, const sc_signed& v); + const sc_signed& operator ^= (const sc_int_base& v); + const sc_signed& operator ^= (const sc_uint_base& v); + + // SHIFT OPERATORS: + + // LEFT SHIFT operators: + + friend sc_unsigned operator << (const sc_unsigned& u, const sc_signed& v); + friend sc_signed operator << (const sc_signed& u, const sc_unsigned& v); + + friend sc_signed operator << (const sc_signed& u, const sc_signed& v); + friend sc_signed operator << (const sc_signed& u, int64 v); + friend sc_signed operator << (const sc_signed& u, uint64 v); + friend sc_signed operator << (const sc_signed& u, long v); + friend sc_signed operator << (const sc_signed& u, unsigned long v); + friend sc_signed operator << (const sc_signed& u, int v) + { return operator<<(u, (long) v); } + friend sc_signed operator << (const sc_signed& u, unsigned int v) + { return operator<<(u, (unsigned long) v); } + + const sc_signed& operator <<= (const sc_signed& v); + const sc_signed& operator <<= (const sc_unsigned& v); + const sc_signed& operator <<= (int64 v); + const sc_signed& operator <<= (uint64 v); + const sc_signed& operator <<= (long v); + const sc_signed& operator <<= (unsigned long v); + const sc_signed& operator <<= (int v) + { return operator<<=((long) v); } + const sc_signed& operator <<= (unsigned int v) + { return operator<<=((unsigned long) v); } + + friend sc_signed operator << (const sc_signed& u, const sc_int_base& v); + friend sc_signed operator << (const sc_signed& u, const sc_uint_base& v); + const sc_signed& operator <<= (const sc_int_base& v); + const sc_signed& operator <<= (const sc_uint_base& v); + + // RIGHT SHIFT operators: + + friend sc_unsigned operator >> (const sc_unsigned& u, const sc_signed& v); + friend sc_signed operator >> (const sc_signed& u, const sc_unsigned& v); + + friend sc_signed operator >> (const sc_signed& u, const sc_signed& v); + friend sc_signed operator >> (const sc_signed& u, int64 v); + friend sc_signed operator >> (const sc_signed& u, uint64 v); + friend sc_signed operator >> (const sc_signed& u, long v); + friend sc_signed operator >> (const sc_signed& u, unsigned long v); + friend sc_signed operator >> (const sc_signed& u, int v) + { return operator>>(u, (long) v); } + friend sc_signed operator >> (const sc_signed& u, unsigned int v) + { return operator>>(u, (unsigned long) v); } + + const sc_signed& operator >>= (const sc_signed& v); + const sc_signed& operator >>= (const sc_unsigned& v); + const sc_signed& operator >>= (int64 v); + const sc_signed& operator >>= (uint64 v); + const sc_signed& operator >>= (long v); + const sc_signed& operator >>= (unsigned long v); + const sc_signed& operator >>= (int v) + { return operator>>=((long) v); } + const sc_signed& operator >>= (unsigned int v) + { return operator>>=((unsigned long) v); } + + friend sc_signed operator >> (const sc_signed& u, const sc_int_base& v); + friend sc_signed operator >> (const sc_signed& u, const sc_uint_base& v); + const sc_signed& operator >>= (const sc_int_base& v); + const sc_signed& operator >>= (const sc_uint_base& v); + + // Unary arithmetic operators + friend sc_signed operator + (const sc_signed& u); + friend sc_signed operator - (const sc_signed& u); + friend sc_signed operator - (const sc_unsigned& u); + + // LOGICAL OPERATORS: + + // Logical EQUAL operators: + + friend bool operator == (const sc_unsigned& u, const sc_signed& v); + friend bool operator == (const sc_signed& u, const sc_unsigned& v); + + friend bool operator == (const sc_signed& u, const sc_signed& v); + friend bool operator == (const sc_signed& u, int64 v); + friend bool operator == (const sc_signed& u, uint64 v); + friend bool operator == (const sc_signed& u, long v); + friend bool operator == (const sc_signed& u, unsigned long v); + friend bool operator == (const sc_signed& u, int v) + { return operator==(u, (long) v); } + friend bool operator == (const sc_signed& u, unsigned int v) + { return operator==(u, (unsigned long) v); } + + friend bool operator == (int64 u, const sc_signed& v); + friend bool operator == (uint64 u, const sc_signed& v); + friend bool operator == (long u, const sc_signed& v); + friend bool operator == (unsigned long u, const sc_signed& v); + friend bool operator == (int u, const sc_signed& v) + { return operator==((long) u, v); } + friend bool operator == (unsigned int u, const sc_signed& v) + { return operator==((unsigned long) u, v); } + + friend bool operator == (const sc_signed& u, const sc_int_base& v); + friend bool operator == (const sc_signed& u, const sc_uint_base& v); + friend bool operator == (const sc_int_base& u, const sc_signed& v); + friend bool operator == (const sc_uint_base& u, const sc_signed& v); + + // Logical NOT_EQUAL operators: + + friend bool operator != (const sc_unsigned& u, const sc_signed& v); + friend bool operator != (const sc_signed& u, const sc_unsigned& v); + + friend bool operator != (const sc_signed& u, const sc_signed& v); + friend bool operator != (const sc_signed& u, int64 v); + friend bool operator != (const sc_signed& u, uint64 v); + friend bool operator != (const sc_signed& u, long v); + friend bool operator != (const sc_signed& u, unsigned long v); + friend bool operator != (const sc_signed& u, int v) + { return operator!=(u, (long) v); } + friend bool operator != (const sc_signed& u, unsigned int v) + { return operator!=(u, (unsigned long) v); } + + friend bool operator != (int64 u, const sc_signed& v); + friend bool operator != (uint64 u, const sc_signed& v); + friend bool operator != (long u, const sc_signed& v); + friend bool operator != (unsigned long u, const sc_signed& v); + friend bool operator != (int u, const sc_signed& v) + { return operator!=((long) u, v); } + friend bool operator != (unsigned int u, const sc_signed& v) + { return operator!=((unsigned long) u, v); } + + friend bool operator != (const sc_signed& u, const sc_int_base& v); + friend bool operator != (const sc_signed& u, const sc_uint_base& v); + friend bool operator != (const sc_int_base& u, const sc_signed& v); + friend bool operator != (const sc_uint_base& u, const sc_signed& v); + + // Logical LESS_THAN operators: + + friend bool operator < (const sc_unsigned& u, const sc_signed& v); + friend bool operator < (const sc_signed& u, const sc_unsigned& v); + + friend bool operator < (const sc_signed& u, const sc_signed& v); + friend bool operator < (const sc_signed& u, int64 v); + friend bool operator < (const sc_signed& u, uint64 v); + friend bool operator < (const sc_signed& u, long v); + friend bool operator < (const sc_signed& u, unsigned long v); + friend bool operator < (const sc_signed& u, int v) + { return operator<(u, (long) v); } + friend bool operator < (const sc_signed& u, unsigned int v) + { return operator<(u, (unsigned long) v); } + + friend bool operator < (int64 u, const sc_signed& v); + friend bool operator < (uint64 u, const sc_signed& v); + friend bool operator < (long u, const sc_signed& v); + friend bool operator < (unsigned long u, const sc_signed& v); + friend bool operator < (int u, const sc_signed& v) + { return operator<((long) u, v); } + friend bool operator < (unsigned int u, const sc_signed& v) + { return operator<((unsigned long) u, v); } + + friend bool operator < (const sc_signed& u, const sc_int_base& v); + friend bool operator < (const sc_signed& u, const sc_uint_base& v); + friend bool operator < (const sc_int_base& u, const sc_signed& v); + friend bool operator < (const sc_uint_base& u, const sc_signed& v); + + // Logical LESS_THAN_AND_EQUAL operators: + + friend bool operator <= (const sc_unsigned& u, const sc_signed& v); + friend bool operator <= (const sc_signed& u, const sc_unsigned& v); + + friend bool operator <= (const sc_signed& u, const sc_signed& v); + friend bool operator <= (const sc_signed& u, int64 v); + friend bool operator <= (const sc_signed& u, uint64 v); + friend bool operator <= (const sc_signed& u, long v); + friend bool operator <= (const sc_signed& u, unsigned long v); + friend bool operator <= (const sc_signed& u, int v) + { return operator<=(u, (long) v); } + friend bool operator <= (const sc_signed& u, unsigned int v) + { return operator<=(u, (unsigned long) v); } + + friend bool operator <= (int64 u, const sc_signed& v); + friend bool operator <= (uint64 u, const sc_signed& v); + friend bool operator <= (long u, const sc_signed& v); + friend bool operator <= (unsigned long u, const sc_signed& v); + friend bool operator <= (int u, const sc_signed& v) + { return operator<=((long) u, v); } + friend bool operator <= (unsigned int u, const sc_signed& v) + { return operator<=((unsigned long) u, v); } + + friend bool operator <= (const sc_signed& u, const sc_int_base& v); + friend bool operator <= (const sc_signed& u, const sc_uint_base& v); + friend bool operator <= (const sc_int_base& u, const sc_signed& v); + friend bool operator <= (const sc_uint_base& u, const sc_signed& v); + + // Logical GREATER_THAN operators: + + friend bool operator > (const sc_unsigned& u, const sc_signed& v); + friend bool operator > (const sc_signed& u, const sc_unsigned& v); + + friend bool operator > (const sc_signed& u, const sc_signed& v); + friend bool operator > (const sc_signed& u, int64 v); + friend bool operator > (const sc_signed& u, uint64 v); + friend bool operator > (const sc_signed& u, long v); + friend bool operator > (const sc_signed& u, unsigned long v); + friend bool operator > (const sc_signed& u, int v) + { return operator>(u, (long) v); } + friend bool operator > (const sc_signed& u, unsigned int v) + { return operator>(u, (unsigned long) v); } + + friend bool operator > (int64 u, const sc_signed& v); + friend bool operator > (uint64 u, const sc_signed& v); + friend bool operator > (long u, const sc_signed& v); + friend bool operator > (unsigned long u, const sc_signed& v); + friend bool operator > (int u, const sc_signed& v) + { return operator>((long) u, v); } + friend bool operator > (unsigned int u, const sc_signed& v) + { return operator>((unsigned long) u, v); } + + friend bool operator > (const sc_signed& u, const sc_int_base& v); + friend bool operator > (const sc_signed& u, const sc_uint_base& v); + friend bool operator > (const sc_int_base& u, const sc_signed& v); + friend bool operator > (const sc_uint_base& u, const sc_signed& v); + + // Logical GREATER_THAN_AND_EQUAL operators: + + friend bool operator >= (const sc_unsigned& u, const sc_signed& v); + friend bool operator >= (const sc_signed& u, const sc_unsigned& v); + + friend bool operator >= (const sc_signed& u, const sc_signed& v); + friend bool operator >= (const sc_signed& u, int64 v); + friend bool operator >= (const sc_signed& u, uint64 v); + friend bool operator >= (const sc_signed& u, long v); + friend bool operator >= (const sc_signed& u, unsigned long v); + friend bool operator >= (const sc_signed& u, int v) + { return operator>=(u, (long) v); } + friend bool operator >= (const sc_signed& u, unsigned int v) + { return operator>=(u, (unsigned long) v); } + + friend bool operator >= (int64 u, const sc_signed& v); + friend bool operator >= (uint64 u, const sc_signed& v); + friend bool operator >= (long u, const sc_signed& v); + friend bool operator >= (unsigned long u, const sc_signed& v); + friend bool operator >= (int u, const sc_signed& v) + { return operator>=((long) u, v); } + friend bool operator >= (unsigned int u, const sc_signed& v) + { return operator>=((unsigned long) u, v); } + + friend bool operator >= (const sc_signed& u, const sc_int_base& v); + friend bool operator >= (const sc_signed& u, const sc_uint_base& v); + friend bool operator >= (const sc_int_base& u, const sc_signed& v); + friend bool operator >= (const sc_uint_base& u, const sc_signed& v); + + // Bitwise NOT operator (unary). + friend sc_signed operator ~ (const sc_signed& u); + + // Helper functions. + friend sc_signed add_signed_friend(small_type us, + int unb, + int und, + const sc_digit *ud, + small_type vs, + int vnb, + int vnd, + const sc_digit *vd); + + friend sc_signed sub_signed_friend(small_type us, + int unb, + int und, + const sc_digit *ud, + small_type vs, + int vnb, + int vnd, + const sc_digit *vd); + + friend sc_signed mul_signed_friend(small_type s, + int unb, + int und, + const sc_digit *ud, + int vnb, + int vnd, + const sc_digit *vd); + + friend sc_signed div_signed_friend(small_type s, + int unb, + int und, + const sc_digit *ud, + int vnb, + int vnd, + const sc_digit *vd); + + friend sc_signed mod_signed_friend(small_type us, + int unb, + int und, + const sc_digit *ud, + int vnb, + int vnd, + const sc_digit *vd); + + friend sc_signed and_signed_friend(small_type us, + int unb, + int und, + const sc_digit *ud, + small_type vs, + int vnb, + int vnd, + const sc_digit *vd); + + friend sc_signed or_signed_friend(small_type us, + int unb, + int und, + const sc_digit *ud, + small_type vs, + int vnb, + int vnd, + const sc_digit *vd); + + friend sc_signed xor_signed_friend(small_type us, + int unb, + int und, + const sc_digit *ud, + small_type vs, + int vnb, + int vnd, + const sc_digit *vd); + +private: + + small_type sgn; // Shortened as s. + int nbits; // Shortened as nb. + int ndigits; // Shortened as nd. + +#ifdef SC_MAX_NBITS + sc_digit digit[DIV_CEIL(SC_MAX_NBITS)]; // Shortened as d. +#else + sc_digit *digit; // Shortened as d. +#endif + + // Private constructors: + + // Create a copy of v with sign s. + sc_signed(const sc_signed& v, small_type s); + sc_signed(const sc_unsigned& v, small_type s); + + // Create a signed number with the given attributes. + sc_signed(small_type s, int nb, int nd, + sc_digit *d, bool alloc = true); + + // Create an unsigned number using the bits u[l..r]. + sc_signed(const sc_signed* u, int l, int r); + sc_signed(const sc_unsigned* u, int l, int r); + + // Private member functions. The called functions are inline functions. + + small_type default_sign() const + { return SC_NOSIGN; } + + int num_bits(int nb) const { return nb; } + + bool check_if_outside(int bit_num) const; + + void copy_digits(int nb, int nd, const sc_digit *d) + { copy_digits_signed(sgn, nbits, ndigits, digit, nb, nd, d); } + + void makezero() + { sgn = make_zero(ndigits, digit); } + + // Conversion functions between 2's complement (2C) and + // sign-magnitude (SM): + void convert_2C_to_SM() + { sgn = convert_signed_2C_to_SM(nbits, ndigits, digit); } + + void convert_SM_to_2C_to_SM() + { sgn = convert_signed_SM_to_2C_to_SM(sgn, nbits, ndigits, digit); } + + void convert_SM_to_2C() + { convert_signed_SM_to_2C(sgn, ndigits, digit); } + +}; + + + +inline +::std::ostream& +operator << ( ::std::ostream&, const sc_signed& ); + +inline +::std::istream& +operator >> ( ::std::istream&, sc_signed& ); + + + +inline +::std::ostream& +operator << ( ::std::ostream& os, const sc_signed_bitref_r& a ) +{ + a.print( os ); + return os; +} + + +inline +::std::istream& +operator >> ( ::std::istream& is, sc_signed_bitref& a ) +{ + a.scan( is ); + return is; +} + + +// ---------------------------------------------------------------------------- +// CLASS : sc_signed_subref_r +// +// Proxy class for sc_signed part selection (r-value only). +// ---------------------------------------------------------------------------- + + +// reduce methods + +inline bool sc_signed_subref_r::and_reduce() const +{ + const sc_signed* target_p = m_obj_p; + for ( int i = m_right; i <= m_left; i++ ) + if ( !target_p->test(i) ) return false; + return true; +} + +inline bool sc_signed_subref_r::nand_reduce() const +{ + return !and_reduce(); +} + +inline bool sc_signed_subref_r::or_reduce() const +{ + const sc_signed* target_p = m_obj_p; + for ( int i = m_right; i <= m_left; i++ ) + if ( target_p->test(i) ) return true; + return false; +} + +inline bool sc_signed_subref_r::nor_reduce() const +{ + return !or_reduce(); +} + +inline bool sc_signed_subref_r::xor_reduce() const +{ + int odd; + const sc_signed* target_p = m_obj_p; + odd = 0; + for ( int i = m_right; i <= m_left; i++ ) + if ( target_p->test(i) ) odd = ~odd; + return odd ? true : false; +} + +inline bool sc_signed_subref_r::xnor_reduce() const +{ + return !xor_reduce(); +} + +inline +::std::ostream& +operator << ( ::std::ostream& os, const sc_signed_subref_r& a ) +{ + a.print( os ); + return os; +} + + +// ---------------------------------------------------------------------------- +// CLASS : sc_signed_subref +// +// Proxy class for sc_signed part selection (r-value and l-value). +// ---------------------------------------------------------------------------- + +// assignment operators + +inline +const sc_signed_subref& +sc_signed_subref::operator = ( const char* a ) +{ + sc_signed aa( length() ); + return ( *this = aa = a ); +} + + + + +inline +::std::istream& +operator >> ( ::std::istream& is, sc_signed_subref& a ) +{ + a.scan( is ); + return is; +} + + + +// ---------------------------------------------------------------------------- +// CLASS : sc_signed +// +// Arbitrary precision signed number. +// ---------------------------------------------------------------------------- + +template<class T> +sc_signed::sc_signed( const sc_generic_base<T>& v ) +{ + int nb = v->length(); + sgn = default_sign(); + if( nb > 0 ) { + nbits = num_bits( nb ); + } else { + char msg[BUFSIZ]; + std::sprintf( msg, + "sc_unsigned( sc_generic_base<T> ) : nb = %d is not valid", nb); + SC_REPORT_ERROR( sc_core::SC_ID_INIT_FAILED_, msg ); + } + ndigits = DIV_CEIL(nbits); +# ifdef SC_MAX_NBITS + test_bound(nb); +# else + digit = new sc_digit[ndigits]; +# endif + makezero(); + v->to_sc_signed(*this); +} + + + +inline +::std::ostream& +operator << ( ::std::ostream& os, const sc_signed& a ) +{ + a.print( os ); + return os; +} + +inline +::std::istream& +operator >> ( ::std::istream& is, sc_signed& a ) +{ + a.scan( is ); + return is; +} + + +} // namespace sc_dt + + +#endif diff --git a/ext/systemc/src/sysc/datatypes/int/sc_signed_bitref.inc b/ext/systemc/src/sysc/datatypes/int/sc_signed_bitref.inc new file mode 100644 index 000000000..46d347d94 --- /dev/null +++ b/ext/systemc/src/sysc/datatypes/int/sc_signed_bitref.inc @@ -0,0 +1,163 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_signed_bitref.h -- Proxy class that is declared in sc_signed.h. + + Original Author: Ali Dasdan, Synopsys, Inc. + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + + +// ---------------------------------------------------------------------------- +// CLASS : sc_signed_bitref_r +// +// Proxy class for sc_signed bit selection (r-value only). +// ---------------------------------------------------------------------------- + +// implicit conversion to uint64 + +sc_signed_bitref_r::operator uint64 () const +{ + return m_obj_p->test( m_index ); +} + +bool +sc_signed_bitref_r::operator ! () const +{ + return ( ! m_obj_p->test( m_index ) ); +} + +bool +sc_signed_bitref_r::operator ~ () const +{ + return ( ! m_obj_p->test( m_index ) ); +} + + +// ---------------------------------------------------------------------------- +// CLASS : sc_signed_bitref +// +// Proxy class for sc_signed bit selection (r-value and l-value). +// ---------------------------------------------------------------------------- + +// assignment operators + +const sc_signed_bitref& +sc_signed_bitref::operator = ( const sc_signed_bitref_r& b ) +{ + m_obj_p->set( m_index, (bool) b ); + return *this; +} + +const sc_signed_bitref& +sc_signed_bitref::operator = ( const sc_signed_bitref& b ) +{ + m_obj_p->set( m_index, (bool) b ); + return *this; +} + +const sc_signed_bitref& +sc_signed_bitref::operator = ( bool b ) +{ + m_obj_p->set( m_index, b ); + return *this; +} + + +const sc_signed_bitref& +sc_signed_bitref::operator &= ( bool b ) +{ + if( ! b ) { + m_obj_p->clear( m_index ); + } + return *this; +} + +const sc_signed_bitref& +sc_signed_bitref::operator |= ( bool b ) +{ + if( b ) { + m_obj_p->set( m_index ); + } + return *this; +} + +const sc_signed_bitref& +sc_signed_bitref::operator ^= ( bool b ) +{ + if( b ) { + m_obj_p->invert( m_index ); + } + return *this; +} + +// #### OPTIMIZE +void sc_signed_bitref::concat_set(int64 src, int low_i) +{ + bool value = 1 & ((low_i < 64) ? (src >> low_i) : (src >> 63)); + m_obj_p->set(low_i, value); +} + +void sc_signed_bitref::concat_set(const sc_signed& src, int low_i) +{ + if ( low_i < src.length() ) + m_obj_p->set(low_i, src.test(low_i)); + else + m_obj_p->set(low_i, src<0); +} + +void sc_signed_bitref::concat_set(const sc_unsigned& src, int low_i) +{ + if ( low_i < src.length() ) + m_obj_p->set(low_i, src.test(low_i)); + else + m_obj_p->set(low_i, 0); +} + +void sc_signed_bitref::concat_set(uint64 src, int low_i) +{ + bool value = 1 & ((low_i < 64) ? (src >> low_i) : 0); + m_obj_p->set(low_i, value); +} + + +// other methods + +void +sc_signed_bitref::scan( ::std::istream& is ) +{ + bool b; + is >> b; + *this = b; +} + + +// End of file diff --git a/ext/systemc/src/sysc/datatypes/int/sc_signed_subref.inc b/ext/systemc/src/sysc/datatypes/int/sc_signed_subref.inc new file mode 100644 index 000000000..3f50210a7 --- /dev/null +++ b/ext/systemc/src/sysc/datatypes/int/sc_signed_subref.inc @@ -0,0 +1,408 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_signed_subref.h -- Proxy class that is declared in sc_signed.h. + + Original Author: Ali Dasdan, Synopsys, Inc. + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + + +// ---------------------------------------------------------------------------- +// CLASS : sc_signed_subref_r +// +// Proxy class for sc_signed part selection (r-value only). +// ---------------------------------------------------------------------------- + +// concatenation support + +uint64 sc_signed_subref_r::concat_get_uint64() const +{ + sc_unsigned a( m_obj_p, m_left, m_right ); + return a.to_uint64(); +} + + +bool sc_signed_subref_r::concat_get_ctrl(sc_digit* dst_p, int low_i ) const +{ + sc_unsigned a( m_obj_p, m_left, m_right ); + return a.concat_get_ctrl( dst_p, low_i ); +} + + +bool sc_signed_subref_r::concat_get_data(sc_digit* dst_p, int low_i ) const +{ + sc_unsigned a( m_obj_p, m_left, m_right ); + return a.concat_get_data( dst_p, low_i ); +} + + +// implicit conversion to sc_signed + +sc_signed_subref_r::operator sc_unsigned () const +{ + return sc_unsigned( m_obj_p, m_left, m_right ); +} + + +// explicit conversions + +int +sc_signed_subref_r::to_int() const +{ + sc_unsigned a( m_obj_p, m_left, m_right ); + return a.to_int(); +} + +unsigned int +sc_signed_subref_r::to_uint() const +{ + sc_unsigned a( m_obj_p, m_left, m_right ); + return a.to_uint(); +} + +long +sc_signed_subref_r::to_long() const +{ + sc_unsigned a( m_obj_p, m_left, m_right ); + return a.to_long(); +} + +unsigned long +sc_signed_subref_r::to_ulong() const +{ + sc_unsigned a( m_obj_p, m_left, m_right ); + return a.to_ulong(); +} + +int64 +sc_signed_subref_r::to_int64() const +{ + sc_unsigned a( m_obj_p, m_left, m_right ); + return a.to_int64(); +} + +uint64 +sc_signed_subref_r::to_uint64() const +{ + sc_unsigned a( m_obj_p, m_left, m_right ); + return a.to_uint64(); +} + +double +sc_signed_subref_r::to_double() const +{ + sc_unsigned a( m_obj_p, m_left, m_right ); + return a.to_double(); +} + + +// explicit conversion to character string + +const std::string +sc_signed_subref_r::to_string( sc_numrep numrep ) const +{ + sc_unsigned a( length() ); + a = *this; + return a.to_string( numrep ); +} + +const std::string +sc_signed_subref_r::to_string( sc_numrep numrep, bool w_prefix ) const +{ + sc_unsigned a( length() ); + a = *this; + return a.to_string( numrep, w_prefix ); +} + + +// ---------------------------------------------------------------------------- +// CLASS : sc_signed_subref +// +// Proxy class for sc_signed part selection (r-value and l-value). +// ---------------------------------------------------------------------------- + +// assignment operators + +const sc_signed_subref& +sc_signed_subref::operator = ( const sc_signed_subref_r& a ) +{ + return operator = ( (sc_unsigned)( a ) ); +} + +const sc_signed_subref& +sc_signed_subref::operator = ( const sc_signed_subref& v ) +{ + if( this == &v ) { + return *this; + } + return operator = ( (sc_unsigned)( v ) ); +} + +const sc_signed_subref& +sc_signed_subref::operator = ( const sc_signed& v ) +{ + int i; + int l = sc_min( m_left, v.nbits - 1 + m_right ); + + for( i = m_right; i <= l; ++ i ) m_obj_p->set( i, v.test( i - m_right ) ); + for ( ; i <= m_left; i++ ) m_obj_p->set( i, v.test( l ) ); + + return *this; +} + +const sc_signed_subref& +sc_signed_subref::operator = ( const sc_unsigned_subref_r& v ) +{ + return operator = ( (sc_unsigned)( v ) ); +} + +const sc_signed_subref& +sc_signed_subref::operator = ( const sc_unsigned& v ) +{ + int i; + int l = sc_min( m_left, v.nbits - 1 + m_right ); + + for( i = m_right; i <= l; ++ i ) m_obj_p->set( i, v.test( i - m_right ) ); + for ( ; i <= m_left; i++ ) m_obj_p->set( i, 0 ); + return *this; +} + +const sc_signed_subref& +sc_signed_subref::operator = ( unsigned long v ) +{ + for( int i = m_right; i <= m_left; ++ i ) { + m_obj_p->set( i, static_cast<bool>( v & 1 ) ); + v >>= 1; + } + return *this; +} + +const sc_signed_subref& +sc_signed_subref::operator = ( long v ) +{ + unsigned long v2 = (unsigned long) v; + for( int i = m_right; i <= m_left; ++ i ) { + m_obj_p->set( i, static_cast<bool>( v2 & 1 ) ); + v2 >>= 1; + } + return *this; +} + +const sc_signed_subref& +sc_signed_subref::operator = ( uint64 v ) +{ + for( int i = m_right; i <= m_left; ++ i ) { + m_obj_p->set( i, static_cast<bool>( v & 1 ) ); + v >>= 1; + } + return *this; +} + +const sc_signed_subref& +sc_signed_subref::operator = ( int64 v ) +{ + uint64 v2 = (uint64) v; + for( int i = m_right; i <= m_left; ++ i ) { + m_obj_p->set( i, static_cast<bool>( v2 & 1 ) ); + v2 >>= 1; + } + return *this; +} + +const sc_signed_subref& +sc_signed_subref::operator = ( double v ) +{ + is_bad_double(v); + + int nb = m_left - m_right + 1; + int nd = DIV_CEIL(nb); + +#ifdef SC_MAX_NBITS + sc_digit d[MAX_NDIGITS]; +#else + sc_digit *d = new sc_digit[nd]; +#endif + + if (v < 0) + v = -v; + + int i = 0; + + while (floor(v) && (i < nd)) { +#ifndef _WIN32 + d[i++] = (sc_digit) floor(remainder(v, DIGIT_RADIX)); +#else + d[i++] = (sc_digit) floor(fmod(v, DIGIT_RADIX)); +#endif + v /= DIGIT_RADIX; + } + + vec_zero(i, nd, d); + + sc_digit val = 1; // Bit value. + int j = 0; // Current digit in d. + + i = 0; // Current bit in d. + + while (i < nb) { + + m_obj_p->set(i + m_right, (bool) (d[j] & val)); + + ++i; + + if (i % BITS_PER_DIGIT == 0) { + val = 1; + ++j; + } + else + val <<= 1; + } + +#ifndef SC_MAX_NBITS + delete [] d; +#endif + + return *this; +} + +const sc_signed_subref& +sc_signed_subref::operator = ( const sc_int_base& a ) +{ + return operator = ( (int64) a ); +} + +const sc_signed_subref& +sc_signed_subref::operator = ( const sc_uint_base& a ) +{ + return operator = ( (uint64) a ); +} + +// concatenation methods + + +void sc_signed_subref::concat_set( int64 src, int low_i ) +{ + int i; + int l; + bool sign = src < 0; + + if ( low_i < 64 ) + { + src = src >> low_i; + l = sc_min( m_left, (63-low_i) + m_right ); + for( i = m_right; i <= l; ++ i ) { + m_obj_p->set( i, src & 1 ); + src = src >> 1; + } + for ( ; i <= m_left; i++ ) m_obj_p->set(i, sign); + } + else + { + for( i = m_right; i <= m_left; ++ i ) m_obj_p->set(i, sign); + } +} + +void sc_signed_subref::concat_set( const sc_signed& src, int low_i ) +{ + int i; + int l; + int src_i; + bool sign = src.test(src.nbits-1); + l = src.nbits - (low_i+1); + if ( l >= 0 ) + { + l = sc_min( m_left, l + m_right ); + src_i = low_i; + for( i = m_right; i <= l; ++ i, src_i++ ) { + m_obj_p->set( i, src.test( src_i ) ); + } + for ( ; i <= m_left; i++ ) m_obj_p->set(i, sign); + } + else + { + for( i = m_right; i <= m_left; ++ i ) m_obj_p->set(i, sign); + } +} + +void sc_signed_subref::concat_set( const sc_unsigned& src, int low_i ) +{ + int i; + int l; + int src_i; + l = src.nbits - (low_i+2); + if ( l >= 0 ) + { + l = sc_min( m_left, l + m_right ); + src_i = low_i; + for( i = m_right; i <= l; ++ i, src_i++ ) { + m_obj_p->set( i, src.test( src_i ) ); + } + for ( ; i <= m_left; i++ ) m_obj_p->set(false); + } + else + { + for( i = m_right; i <= m_left; ++ i ) m_obj_p->set(false); + } +} + +void sc_signed_subref::concat_set( uint64 src, int low_i ) +{ + int i; + int l; + + if ( low_i < 64 ) + { + src = src >> low_i; + l = sc_min( m_left, (63-low_i) + m_right ); + for( i = m_right; i <= l; ++ i ) { + m_obj_p->set( i, src & 1 ); + src = src >> 1; + } + for ( ; i <= m_left; i++ ) m_obj_p->set(false); + } + else + { + for( i = m_right; i <= m_left; ++ i ) m_obj_p->set(false); + } +} +// other methods + +void +sc_signed_subref::scan( ::std::istream& is ) +{ + std::string s; + is >> s; + *this = s.c_str(); +} + + +// End of file diff --git a/ext/systemc/src/sysc/datatypes/int/sc_uint.h b/ext/systemc/src/sysc/datatypes/int/sc_uint.h new file mode 100644 index 000000000..90ebd7f97 --- /dev/null +++ b/ext/systemc/src/sysc/datatypes/int/sc_uint.h @@ -0,0 +1,312 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_uint.h -- A sc_uint is an unsigned integer whose length is less than the + machine's native integer length. We provide two implementations + (i) sc_uint with length between 1 - 64, and (ii) sc_uint with + length between 1 - 32. Implementation (i) is the default + implementation, while implementation (ii) can be used only if + compiled with -D_32BIT_. Unlike arbitrary precision, arithmetic + and bitwise operations are performed using the native types + (hence capped at 32/64 bits). The sc_uint integer is useful + when the user does not need arbitrary precision and the + performance is superior to sc_bigint/sc_biguint. + + Original Author: Amit Rao, Synopsys, Inc. + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: Ali Dasdan, Synopsys, Inc. + Description of Modification: - Resolved ambiguity with sc_(un)signed. + - Merged the code for 64- and 32-bit versions + via the constants in sc_nbdefs.h. + - Eliminated redundant file inclusions. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + +// $Log: sc_uint.h,v $ +// Revision 1.2 2011/02/18 20:19:15 acg +// Andy Goodrich: updating Copyright notice. +// +// Revision 1.1.1.1 2006/12/15 20:20:05 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:49:32 acg +// Added $Log command so that CVS check in comments are reproduced in the +// source. +// + +#ifndef SC_UINT_H +#define SC_UINT_H + + +#include "sysc/datatypes/int/sc_uint_base.h" + + +namespace sc_dt +{ + +// classes defined in this module +template <int W> class sc_uint; + + +// ---------------------------------------------------------------------------- +// CLASS TEMPLATE : sc_uint<W> +// +// Template class sc_uint<W> is the interface that the user sees. It +// is derived from sc_uint_base and most of its methods are just +// wrappers that call the corresponding method in the parent +// class. Note that the length of sc_uint datatype is specified as a +// template parameter. +// ---------------------------------------------------------------------------- + +template <int W> +class sc_uint + : public sc_uint_base +{ +public: + + // constructors + + sc_uint() + : sc_uint_base( W ) + {} + + sc_uint( uint_type v ) + : sc_uint_base( v, W ) + {} + + sc_uint( const sc_uint<W>& a ) + : sc_uint_base( a ) + {} + + sc_uint( const sc_uint_base& a ) + : sc_uint_base( W ) + { sc_uint_base::operator = ( a ); } + + sc_uint( const sc_uint_subref_r& a ) + : sc_uint_base( W ) + { sc_uint_base::operator = ( a ); } + + template< class T > + sc_uint( const sc_generic_base<T>& a ) + : sc_uint_base( W ) + { sc_uint_base::operator = ( a ); } + + sc_uint( const sc_signed& a ) + : sc_uint_base( W ) + { sc_uint_base::operator = ( a ); } + + sc_uint( const sc_unsigned& a ) + : sc_uint_base( W ) + { sc_uint_base::operator = ( a ); } + +#ifdef SC_INCLUDE_FX + + explicit sc_uint( const sc_fxval& a ) + : sc_uint_base( W ) + { sc_uint_base::operator = ( a ); } + + explicit sc_uint( const sc_fxval_fast& a ) + : sc_uint_base( W ) + { sc_uint_base::operator = ( a ); } + + explicit sc_uint( const sc_fxnum& a ) + : sc_uint_base( W ) + { sc_uint_base::operator = ( a ); } + + explicit sc_uint( const sc_fxnum_fast& a ) + : sc_uint_base( W ) + { sc_uint_base::operator = ( a ); } + +#endif + + sc_uint( const sc_bv_base& a ) + : sc_uint_base( W ) + { sc_uint_base::operator = ( a ); } + + sc_uint( const sc_lv_base& a ) + : sc_uint_base( W ) + { sc_uint_base::operator = ( a ); } + + sc_uint( const char* a ) + : sc_uint_base( W ) + { sc_uint_base::operator = ( a ); } + + sc_uint( unsigned long a ) + : sc_uint_base( W ) + { sc_uint_base::operator = ( a ); } + + sc_uint( long a ) + : sc_uint_base( W ) + { sc_uint_base::operator = ( a ); } + + sc_uint( unsigned int a ) + : sc_uint_base( W ) + { sc_uint_base::operator = ( a ); } + + sc_uint( int a ) + : sc_uint_base( W ) + { sc_uint_base::operator = ( a ); } + + sc_uint( int64 a ) + : sc_uint_base( W ) + { sc_uint_base::operator = ( a ); } + + sc_uint( double a ) + : sc_uint_base( W ) + { sc_uint_base::operator = ( a ); } + + + // assignment operators + + sc_uint<W>& operator = ( uint_type v ) + { sc_uint_base::operator = ( v ); return *this; } + + sc_uint<W>& operator = ( const sc_uint_base& a ) + { sc_uint_base::operator = ( a ); return *this; } + + sc_uint<W>& operator = ( const sc_uint_subref_r& a ) + { sc_uint_base::operator = ( a ); return *this; } + + sc_uint<W>& operator = ( const sc_uint<W>& a ) + { m_val = a.m_val; return *this; } + + template<class T> + sc_uint<W>& operator = ( const sc_generic_base<T>& a ) + { sc_uint_base::operator = ( a ); return *this; } + + sc_uint<W>& operator = ( const sc_signed& a ) + { sc_uint_base::operator = ( a ); return *this; } + + sc_uint<W>& operator = ( const sc_unsigned& a ) + { sc_uint_base::operator = ( a ); return *this; } + +#ifdef SC_INCLUDE_FX + + sc_uint<W>& operator = ( const sc_fxval& a ) + { sc_uint_base::operator = ( a ); return *this; } + + sc_uint<W>& operator = ( const sc_fxval_fast& a ) + { sc_uint_base::operator = ( a ); return *this; } + + sc_uint<W>& operator = ( const sc_fxnum& a ) + { sc_uint_base::operator = ( a ); return *this; } + + sc_uint<W>& operator = ( const sc_fxnum_fast& a ) + { sc_uint_base::operator = ( a ); return *this; } + +#endif + + sc_uint<W>& operator = ( const sc_bv_base& a ) + { sc_uint_base::operator = ( a ); return *this; } + + sc_uint<W>& operator = ( const sc_lv_base& a ) + { sc_uint_base::operator = ( a ); return *this; } + + sc_uint<W>& operator = ( const char* a ) + { sc_uint_base::operator = ( a ); return *this; } + + sc_uint<W>& operator = ( unsigned long a ) + { sc_uint_base::operator = ( a ); return *this; } + + sc_uint<W>& operator = ( long a ) + { sc_uint_base::operator = ( a ); return *this; } + + sc_uint<W>& operator = ( unsigned int a ) + { sc_uint_base::operator = ( a ); return *this; } + + sc_uint<W>& operator = ( int a ) + { sc_uint_base::operator = ( a ); return *this; } + + sc_uint<W>& operator = ( int64 a ) + { sc_uint_base::operator = ( a ); return *this; } + + sc_uint<W>& operator = ( double a ) + { sc_uint_base::operator = ( a ); return *this; } + + + // arithmetic assignment operators + + sc_uint<W>& operator += ( uint_type v ) + { sc_uint_base::operator += ( v ); return *this; } + + sc_uint<W>& operator -= ( uint_type v ) + { sc_uint_base::operator -= ( v ); return *this; } + + sc_uint<W>& operator *= ( uint_type v ) + { sc_uint_base::operator *= ( v ); return *this; } + + sc_uint<W>& operator /= ( uint_type v ) + { sc_uint_base::operator /= ( v ); return *this; } + + sc_uint<W>& operator %= ( uint_type v ) + { sc_uint_base::operator %= ( v ); return *this; } + + + // bitwise assignment operators + + sc_uint<W>& operator &= ( uint_type v ) + { sc_uint_base::operator &= ( v ); return *this; } + + sc_uint<W>& operator |= ( uint_type v ) + { sc_uint_base::operator |= ( v ); return *this; } + + sc_uint<W>& operator ^= ( uint_type v ) + { sc_uint_base::operator ^= ( v ); return *this; } + + + sc_uint<W>& operator <<= ( uint_type v ) + { sc_uint_base::operator <<= ( v ); return *this; } + + sc_uint<W>& operator >>= ( uint_type v ) + { sc_uint_base::operator >>= ( v ); return *this; } + + + // prefix and postfix increment and decrement operators + + sc_uint<W>& operator ++ () // prefix + { sc_uint_base::operator ++ (); return *this; } + + const sc_uint<W> operator ++ ( int ) // postfix + { return sc_uint<W>( sc_uint_base::operator ++ ( 0 ) ); } + + sc_uint<W>& operator -- () // prefix + { sc_uint_base::operator -- (); return *this; } + + const sc_uint<W> operator -- ( int ) // postfix + { return sc_uint<W>( sc_uint_base::operator -- ( 0 ) ); } +}; + +} // namespace sc_dt + + +#endif + +// Taf! diff --git a/ext/systemc/src/sysc/datatypes/int/sc_uint_base.cpp b/ext/systemc/src/sysc/datatypes/int/sc_uint_base.cpp new file mode 100644 index 000000000..e3a12e4e0 --- /dev/null +++ b/ext/systemc/src/sysc/datatypes/int/sc_uint_base.cpp @@ -0,0 +1,727 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_uint_base.cpp -- contains interface definitions between sc_uint and + sc_signed, sc_unsigned, and definitions for sc_uint_subref. + + Original Author: Ali Dasdan, Synopsys, Inc. + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + + +// $Log: sc_uint_base.cpp,v $ +// Revision 1.5 2011/02/18 20:19:15 acg +// Andy Goodrich: updating Copyright notice. +// +// Revision 1.4 2010/02/04 22:23:29 acg +// Andy Goodrich: fixed bug in concatenation reads for part selections, +// the mask being used was 32 bits and should have been 64 bits. +// +// Revision 1.3 2008/06/19 17:47:57 acg +// Andy Goodrich: fixes for bugs. See 2.2.1 RELEASENOTES. +// +// Revision 1.2 2007/11/04 21:27:00 acg +// Andy Goodrich: changes to make sure the proper value is returned from +// concat_get_data(). +// +// Revision 1.1.1.1 2006/12/15 20:20:05 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:49:32 acg +// Added $Log command so that CVS check in comments are reproduced in the +// source. +// + +#include "sysc/kernel/sc_macros.h" +#include "sysc/datatypes/int/sc_signed.h" +#include "sysc/datatypes/int/sc_unsigned.h" +#include "sysc/datatypes/int/sc_uint_base.h" +#include "sysc/datatypes/int/sc_int_ids.h" +#include "sysc/datatypes/bit/sc_bv_base.h" +#include "sysc/datatypes/bit/sc_lv_base.h" +#include "sysc/datatypes/misc/sc_concatref.h" +#include "sysc/datatypes/fx/sc_ufix.h" +#include "sysc/datatypes/fx/scfx_other_defs.h" + + +namespace sc_dt +{ + +// to avoid code bloat in sc_uint_concat<T1,T2> + +void +sc_uint_concref_invalid_length( int length ) +{ + char msg[BUFSIZ]; + std::sprintf( msg, + "sc_uint_concref<T1,T2> initialization: length = %d " + "violates 1 <= length <= %d", + length, SC_INTWIDTH ); + SC_REPORT_ERROR( sc_core::SC_ID_OUT_OF_BOUNDS_, msg ); +} + + + +// ---------------------------------------------------------------------------- +// CLASS : sc_uint_bitref +// +// Proxy class for sc_uint bit selection (r-value and l-value). +// ---------------------------------------------------------------------------- + +sc_core::sc_vpool<sc_uint_bitref> sc_uint_bitref::m_pool(9); + +// concatenation methods: + +// #### OPTIMIZE +void sc_uint_bitref::concat_set(int64 src, int low_i) +{ + sc_uint_base aa( 1 ); + *this = aa = (low_i < 64) ? src >> low_i : src >> 63; +} + +void sc_uint_bitref::concat_set(const sc_signed& src, int low_i) +{ + sc_uint_base aa( 1 ); + if ( low_i < src.length() ) + *this = aa = 1 & (src >> low_i); + else + *this = aa = (src < 0) ? (int_type)-1 : 0; +} + +void sc_uint_bitref::concat_set(const sc_unsigned& src, int low_i) +{ + sc_uint_base aa( 1 ); + if ( low_i < src.length() ) + *this = aa = 1 & (src >> low_i); + else + *this = aa = 0; +} + +void sc_uint_bitref::concat_set(uint64 src, int low_i) +{ + sc_uint_base aa( 1 ); + *this = aa = (low_i < 64) ? src >> low_i : 0; +} + + +// other methods + +void +sc_uint_bitref::scan( ::std::istream& is ) +{ + bool b; + is >> b; + *this = b; +} + + +// ---------------------------------------------------------------------------- +// CLASS : sc_uint_subref_r +// +// Proxy class for sc_uint part selection (l-value). +// ---------------------------------------------------------------------------- + +bool sc_uint_subref_r::concat_get_ctrl( sc_digit* dst_p, int low_i ) const +{ + int dst_i; // Word in dst_p now processing. + int end_i; // Highest order word in dst_p to process. + int left_shift; // Left shift for val. + uint_type mask; // Mask for bits to extract or keep. + + dst_i = low_i / BITS_PER_DIGIT; + left_shift = low_i % BITS_PER_DIGIT; + end_i = (low_i + (m_left-m_right)) / BITS_PER_DIGIT; + + mask = ~(-1 << left_shift); + dst_p[dst_i] = (sc_digit)((dst_p[dst_i] & mask)); + + dst_i++; + for ( ; dst_i <= end_i; dst_i++ ) dst_p[dst_i] = 0; + + return false; +} + +bool sc_uint_subref_r::concat_get_data( sc_digit* dst_p, int low_i ) const +{ + int dst_i; // Word in dst_p now processing. + int end_i; // Highest order word in dst_p to process. + int high_i; // Index of high order bit in dst_p to set. + int left_shift; // Left shift for val. + uint_type mask; // Mask for bits to extract or keep. + bool result; // True if inserting non-zero value. + uint_type val; // Selection value extracted from m_obj_p. + + dst_i = low_i / BITS_PER_DIGIT; + left_shift = low_i % BITS_PER_DIGIT; + high_i = low_i + (m_left-m_right); + end_i = high_i / BITS_PER_DIGIT; + mask = ~mask_int[m_left][m_right]; + val = (m_obj_p->m_val & mask) >> m_right; + result = val != 0; + + + // PROCESS THE FIRST WORD: + + mask = ~(-1 << left_shift); + dst_p[dst_i] = (sc_digit)(((dst_p[dst_i] & mask)) | + ((val << left_shift) & DIGIT_MASK)); + + switch ( end_i - dst_i ) + { + // BITS ARE ACROSS TWO WORDS: + + case 1: + dst_i++; + val >>= (BITS_PER_DIGIT-left_shift); + dst_p[dst_i] = (sc_digit)val; + break; + + // BITS ARE ACROSS THREE WORDS: + + case 2: + dst_i++; + val >>= (BITS_PER_DIGIT-left_shift); + dst_p[dst_i++] = (sc_digit)(val & DIGIT_MASK); + val >>= BITS_PER_DIGIT; + dst_p[dst_i] = (sc_digit)val; + break; + + // BITS ARE ACROSS THREE WORDS: + + case 3: + dst_i++; + val >>= (BITS_PER_DIGIT-left_shift); + dst_p[dst_i++] = (sc_digit)(val & DIGIT_MASK); + val >>= BITS_PER_DIGIT; + dst_p[dst_i++] = (sc_digit)(val & DIGIT_MASK); + val >>= BITS_PER_DIGIT; + dst_p[dst_i] = (sc_digit)val; + break; + } + return result; +} + +// ---------------------------------------------------------------------------- +// CLASS : sc_uint_subref +// +// Proxy class for sc_uint part selection (r-value and l-value). +// ---------------------------------------------------------------------------- + +sc_core::sc_vpool<sc_uint_subref> sc_uint_subref::m_pool(9); + +// assignment operators + +sc_uint_subref& +sc_uint_subref::operator = ( uint_type v ) +{ + uint_type val = m_obj_p->m_val; + uint_type mask = mask_int[m_left][m_right]; + val &= mask; + val |= (v << m_right) & ~mask; + m_obj_p->m_val = val; + m_obj_p->extend_sign(); + return *this; +} + +sc_uint_subref& +sc_uint_subref::operator = ( const sc_signed& a ) +{ + sc_uint_base aa( length() ); + return ( *this = aa = a ); +} + +sc_uint_subref& +sc_uint_subref::operator = ( const sc_unsigned& a ) +{ + sc_uint_base aa( length() ); + return ( *this = aa = a ); +} + +sc_uint_subref& +sc_uint_subref::operator = ( const sc_bv_base& a ) +{ + sc_uint_base aa( length() ); + return ( *this = aa = a ); +} + +sc_uint_subref& +sc_uint_subref::operator = ( const sc_lv_base& a ) +{ + sc_uint_base aa( length() ); + return ( *this = aa = a ); +} + +// concatenation methods: + +// #### OPTIMIZE +void sc_uint_subref::concat_set(int64 src, int low_i) +{ + sc_uint_base aa( length() ); + *this = aa = (low_i < 64) ? src >> low_i : src >> 63; +} + +void sc_uint_subref::concat_set(const sc_signed& src, int low_i) +{ + sc_uint_base aa( length() ); + if ( low_i < src.length() ) + *this = aa = src >> low_i; + else + *this = aa = (src < 0) ? (int_type)-1 : 0; +} + +void sc_uint_subref::concat_set(const sc_unsigned& src, int low_i) +{ + sc_uint_base aa( length() ); + if ( low_i < src.length() ) + *this = aa = src >> low_i; + else + *this = aa = 0; +} + +void sc_uint_subref::concat_set(uint64 src, int low_i) +{ + sc_uint_base aa( length() ); + *this = aa = (low_i < 64) ? src >> low_i : 0; +} + +// other methods + +void +sc_uint_subref::scan( ::std::istream& is ) +{ + std::string s; + is >> s; + *this = s.c_str(); +} + + +// ---------------------------------------------------------------------------- +// CLASS : sc_uint_base +// +// Base class for sc_uint. +// ---------------------------------------------------------------------------- + +// support methods + +void +sc_uint_base::invalid_length() const +{ + char msg[BUFSIZ]; + std::sprintf( msg, + "sc_uint[_base] initialization: length = %d violates " + "1 <= length <= %d", + m_len, SC_INTWIDTH ); + SC_REPORT_ERROR( sc_core::SC_ID_OUT_OF_BOUNDS_, msg ); +} + +void +sc_uint_base::invalid_index( int i ) const +{ + char msg[BUFSIZ]; + std::sprintf( msg, + "sc_uint[_base] bit selection: index = %d violates " + "0 <= index <= %d", + i, m_len - 1 ); + SC_REPORT_ERROR( sc_core::SC_ID_OUT_OF_BOUNDS_, msg ); +} + +void +sc_uint_base::invalid_range( int l, int r ) const +{ + char msg[BUFSIZ]; + std::sprintf( msg, + "sc_uint[_base] part selection: left = %d, right = %d violates " + "%d >= left >= right >= 0", + l, r, m_len - 1 ); + SC_REPORT_ERROR( sc_core::SC_ID_OUT_OF_BOUNDS_, msg ); +} + + +void +sc_uint_base::check_value() const +{ + uint_type limit = (~UINT_ZERO >> m_ulen); + if( m_val > limit ) { + char msg[BUFSIZ]; + std::sprintf( msg, "sc_uint[_base]: value does not fit into a length of %d", + m_len ); + SC_REPORT_WARNING( sc_core::SC_ID_OUT_OF_BOUNDS_, msg ); + } +} + + +// constructors + +sc_uint_base::sc_uint_base( const sc_bv_base& v ) + : m_val(0), m_len( v.length() ), m_ulen( SC_INTWIDTH - m_len ) +{ + check_length(); + *this = v; +} +sc_uint_base::sc_uint_base( const sc_lv_base& v ) + : m_val(0), m_len( v.length() ), m_ulen( SC_INTWIDTH - m_len ) +{ + check_length(); + *this = v; +} +sc_uint_base::sc_uint_base( const sc_int_subref_r& v ) + : m_val(0), m_len( v.length() ), m_ulen( SC_INTWIDTH - m_len ) +{ + check_length(); + *this = v.to_uint64(); +} +sc_uint_base::sc_uint_base( const sc_signed_subref_r& v ) + : m_val(0), m_len( v.length() ), m_ulen( SC_INTWIDTH - m_len ) +{ + check_length(); + *this = v.to_uint64(); +} +sc_uint_base::sc_uint_base( const sc_unsigned_subref_r& v ) + : m_val(0), m_len( v.length() ), m_ulen( SC_INTWIDTH - m_len ) +{ + check_length(); + *this = v.to_uint64(); +} + +sc_uint_base::sc_uint_base( const sc_signed& a ) + : m_val( 0 ), m_len( a.length() ), m_ulen( SC_INTWIDTH - m_len ) +{ + check_length(); +#if 0 + for( int i = m_len - 1; i >= 0; -- i ) { + set( i, a.test( i ) ); + } + extend_sign(); +#else + *this = a.to_uint64(); +#endif +} + +sc_uint_base::sc_uint_base( const sc_unsigned& a ) + : m_val( 0 ), m_len( a.length() ), m_ulen( SC_INTWIDTH - m_len ) +{ + check_length(); +#if 0 + for( int i = m_len - 1; i >= 0; -- i ) { + set( i, a.test( i ) ); + } + extend_sign(); +#else + *this = a.to_uint64(); +#endif +} + +// assignment operators + +sc_uint_base& +sc_uint_base::operator = ( const sc_signed& a ) +{ + int minlen = sc_min( m_len, a.length() ); + int i = 0; + for( ; i < minlen; ++ i ) { + set( i, a.test( i ) ); + } + bool sgn = a.sign(); + for( ; i < m_len; ++ i ) { + // sign extension + set( i, sgn ); + } + extend_sign(); + return *this; +} + +sc_uint_base& +sc_uint_base::operator = ( const sc_unsigned& a ) +{ + int minlen = sc_min( m_len, a.length() ); + int i = 0; + for( ; i < minlen; ++ i ) { + set( i, a.test( i ) ); + } + for( ; i < m_len; ++ i ) { + // zero extension + set( i, 0 ); + } + extend_sign(); + return *this; +} + + +sc_uint_base& +sc_uint_base::operator = ( const sc_bv_base& a ) +{ + int minlen = sc_min( m_len, a.length() ); + int i = 0; + for( ; i < minlen; ++ i ) { + set( i, a.get_bit( i ) ); + } + for( ; i < m_len; ++ i ) { + // zero extension + set( i, 0 ); + } + extend_sign(); + return *this; +} + +sc_uint_base& +sc_uint_base::operator = ( const sc_lv_base& a ) +{ + int minlen = sc_min( m_len, a.length() ); + int i = 0; + for( ; i < minlen; ++ i ) { + set( i, sc_logic( a.get_bit( i ) ).to_bool() ); + } + for( ; i < m_len; ++ i ) { + // zero extension + set( i, 0 ); + } + extend_sign(); + return *this; +} + +sc_uint_base& +sc_uint_base::operator = ( const char* a ) +{ + if( a == 0 ) { + SC_REPORT_ERROR( sc_core::SC_ID_CONVERSION_FAILED_, + "character string is zero" ); + } + if( *a == 0 ) { + SC_REPORT_ERROR( sc_core::SC_ID_CONVERSION_FAILED_, + "character string is empty" ); + } + try { + int len = m_len; + sc_ufix aa( a, len, len, SC_TRN, SC_WRAP, 0, SC_ON ); + return this->operator = ( aa ); + } catch( sc_core::sc_report ) { + char msg[BUFSIZ]; + std::sprintf( msg, "character string '%s' is not valid", a ); + SC_REPORT_ERROR( sc_core::SC_ID_CONVERSION_FAILED_, msg ); + // never reached + return *this; + } +} + + +// explicit conversion to character string + +const std::string +sc_uint_base::to_string( sc_numrep numrep ) const +{ + int len = m_len; + sc_ufix aa( *this, len, len, SC_TRN, SC_WRAP, 0, SC_ON ); + return aa.to_string( numrep ); +} + +const std::string +sc_uint_base::to_string( sc_numrep numrep, bool w_prefix ) const +{ + int len = m_len; + sc_ufix aa( *this, len, len, SC_TRN, SC_WRAP, 0, SC_ON ); + return aa.to_string( numrep, w_prefix ); +} + + +// reduce methods + +bool +sc_uint_base::and_reduce() const +{ + return ( m_val == (~UINT_ZERO >> m_ulen) ); +} + +bool +sc_uint_base::or_reduce() const +{ + return ( m_val != uint_type( 0 ) ); +} + +bool +sc_uint_base::xor_reduce() const +{ + uint_type mask = ~UINT_ZERO; + uint_type val = m_val; + int n = SC_INTWIDTH; + do { + n >>= 1; + mask >>= n; + val = ((val & (mask << n)) >> n) ^ (val & mask); + } while( n != 1 ); + return ( val != uint_type( 0 ) ); +} + + +bool sc_uint_base::concat_get_ctrl( sc_digit* dst_p, int low_i ) const +{ + int dst_i; // Word in dst_p now processing. + int end_i; // Highest order word in dst_p to process. + int left_shift; // Left shift for val. + uint_type mask; // Mask for bits to extract or keep. + + dst_i = low_i / BITS_PER_DIGIT; + left_shift = low_i % BITS_PER_DIGIT; + end_i = (low_i + (m_len-1)) / BITS_PER_DIGIT; + + // PROCESS THE FIRST WORD: + + mask = ~((uint_type)-1 << left_shift); + dst_p[dst_i] = (sc_digit)((dst_p[dst_i] & mask)); + + dst_i++; + for ( ; dst_i <= end_i; dst_i++ ) dst_p[dst_i] = 0; + return false; +} + +//------------------------------------------------------------------------------ +//"sc_uint_base::concat_get_data" +// +// This method transfers the value of this object instance to the supplied +// array of sc_unsigned digits starting with the bit specified by low_i within +// the array of digits. +// +// Notes: +// (1) we don't worry about masking the high order data we transfer since +// concat_get_data() is called from low order bit to high order bit. So +// the bits above where we place ours will be filled in by someone else. +// +// dst_p -> array of sc_unsigned digits to be filled in. +// low_i = first bit within dst_p to be set. +//------------------------------------------------------------------------------ +bool sc_uint_base::concat_get_data( sc_digit* dst_p, int low_i ) const +{ + int dst_i; // Word in dst_p now processing. + int end_i; // Highest order word in dst_p to process. + int high_i; // Index of high order bit in dst_p to set. + int left_shift; // Left shift for val. + uint_type mask; // Mask for bits to extract or keep. + bool result; // True if inserting non-zero value. + uint_type val; // Value for this object. + + dst_i = low_i / BITS_PER_DIGIT; + left_shift = low_i % BITS_PER_DIGIT; + high_i = low_i + (m_len-1); + end_i = high_i / BITS_PER_DIGIT; + val = m_val; + result = val != 0; + + // MASK OFF DATA TO BE TRANSFERRED BASE ON WIDTH: + + if ( m_len < 64 ) + { + mask = ~((uint_type)-1 << m_len); + val &= mask; + } + + // PROCESS THE FIRST WORD: + + mask = ~((uint_type)-1 << left_shift); + dst_p[dst_i] = (sc_digit)(((dst_p[dst_i] & mask)) | + ((val << left_shift) & DIGIT_MASK)); + + switch ( end_i - dst_i ) + { + // BITS ARE ACROSS TWO WORDS: + + case 1: + dst_i++; + val >>= (BITS_PER_DIGIT-left_shift); + dst_p[dst_i] = (sc_digit)val; + break; + + // BITS ARE ACROSS THREE WORDS: + + case 2: + dst_i++; + val >>= (BITS_PER_DIGIT-left_shift); + dst_p[dst_i++] = (sc_digit)(val & DIGIT_MASK); + val >>= BITS_PER_DIGIT; + dst_p[dst_i] = (sc_digit)val; + break; + + // BITS ARE ACROSS FOUR WORDS: + + case 3: + dst_i++; + val >>= (BITS_PER_DIGIT-left_shift); + dst_p[dst_i++] = (sc_digit)(val & DIGIT_MASK); + val >>= BITS_PER_DIGIT; + dst_p[dst_i++] = (sc_digit)(val & DIGIT_MASK); + val >>= BITS_PER_DIGIT; + dst_p[dst_i] = (sc_digit)val; + break; + + } + return result; +} + +// #### OPTIMIZE +void sc_uint_base::concat_set(int64 src, int low_i) +{ + *this = (low_i < 64) ? src >> low_i : src >> 63; +} + +void sc_uint_base::concat_set(const sc_signed& src, int low_i) +{ + if ( low_i < src.length() ) + *this = src >> low_i; + else + *this = (src < 0) ? (int_type)-1 : 0; +} + +void sc_uint_base::concat_set(const sc_unsigned& src, int low_i) +{ + if ( low_i < src.length() ) + *this = src >> low_i; + else + *this = 0; +} + +void sc_uint_base::concat_set(uint64 src, int low_i) +{ + *this = (low_i < 64) ? src >> low_i : 0; +} + + +// other methods + +void +sc_uint_base::scan( ::std::istream& is ) +{ + std::string s; + is >> s; + *this = s.c_str(); +} + +} // namespace sc_dt + + +// Taf! diff --git a/ext/systemc/src/sysc/datatypes/int/sc_uint_base.h b/ext/systemc/src/sysc/datatypes/int/sc_uint_base.h new file mode 100644 index 000000000..87fd92bc0 --- /dev/null +++ b/ext/systemc/src/sysc/datatypes/int/sc_uint_base.h @@ -0,0 +1,1352 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_uint_base.h -- A sc_uint is an unsigned integer whose length is less than + the machine's native integer length. We provide two + implementations (i) sc_uint with length between 1 - 64, and (ii) + sc_uint with length between 1 - 32. Implementation (i) is the + default implementation, while implementation (ii) can be used + only if compiled with -D_32BIT_. Unlike arbitrary precision, + arithmetic and bitwise operations are performed using the native + types (hence capped at 32/64 bits). The sc_uint integer is + useful when the user does not need arbitrary precision and the + performance is superior to sc_bigint/sc_biguint. + + Original Author: Amit Rao, Synopsys, Inc. + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: Ali Dasdan, Synopsys, Inc. + Description of Modification: - Resolved ambiguity with sc_(un)signed. + - Merged the code for 64- and 32-bit versions + via the constants in sc_nbdefs.h. + - Eliminated redundant file inclusions. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + +// $Log: sc_uint_base.h,v $ +// Revision 1.3 2011/08/24 22:05:46 acg +// Torsten Maehne: initialization changes to remove warnings. +// +// Revision 1.2 2011/02/18 20:19:15 acg +// Andy Goodrich: updating Copyright notice. +// +// Revision 1.1.1.1 2006/12/15 20:20:05 acg +// SystemC 2.3 +// +// Revision 1.4 2006/05/08 17:50:02 acg +// Andy Goodrich: Added David Long's declarations for friend operators, +// functions, and methods, to keep the Microsoft compiler happy. +// +// Revision 1.3 2006/01/13 18:49:32 acg +// Added $Log command so that CVS check in comments are reproduced in the +// source. +// + +#ifndef SC_UINT_BASE_H +#define SC_UINT_BASE_H + + +#include "sysc/kernel/sc_object.h" +#include "sysc/datatypes/misc/sc_value_base.h" +#include "sysc/datatypes/int/sc_int_ids.h" +#include "sysc/datatypes/int/sc_length_param.h" +#include "sysc/datatypes/int/sc_nbdefs.h" +#include "sysc/datatypes/fx/scfx_ieee.h" +#include "sysc/utils/sc_iostream.h" +#include "sysc/utils/sc_temporary.h" + + +namespace sc_dt +{ + +class sc_concatref; + +// classes defined in this module +class sc_uint_bitref_r; +class sc_uint_bitref; +class sc_uint_subref_r; +class sc_uint_subref; +class sc_uint_base; + +// forward class declarations +class sc_bv_base; +class sc_lv_base; +class sc_int_subref_r; +class sc_signed_subref_r; +class sc_unsigned_subref_r; +class sc_signed; +class sc_unsigned; +class sc_fxval; +class sc_fxval_fast; +class sc_fxnum; +class sc_fxnum_fast; + + +extern const uint_type mask_int[SC_INTWIDTH][SC_INTWIDTH]; + +// friend operator declarations + inline bool operator == ( const sc_uint_base& a, const sc_uint_base& b ); + inline bool operator != ( const sc_uint_base& a, const sc_uint_base& b ); + inline bool operator < ( const sc_uint_base& a, const sc_uint_base& b ); + inline bool operator <= ( const sc_uint_base& a, const sc_uint_base& b ); + inline bool operator > ( const sc_uint_base& a, const sc_uint_base& b ); + inline bool operator >= ( const sc_uint_base& a, const sc_uint_base& b ); + + + +// ---------------------------------------------------------------------------- +// CLASS : sc_uint_bitref_r +// +// Proxy class for sc_uint bit selection (r-value only). +// ---------------------------------------------------------------------------- + +class sc_uint_bitref_r : public sc_value_base +{ + friend class sc_uint_base; + friend class sc_uint_signal; + + + // constructors + +public: + sc_uint_bitref_r( const sc_uint_bitref_r& init ) : + sc_value_base(init), m_index(init.m_index), m_obj_p(init.m_obj_p) + {} + +protected: + sc_uint_bitref_r() : sc_value_base(), m_index(0), m_obj_p(0) + {} + + // initializer for sc_core::sc_vpool: + + void initialize( const sc_uint_base* obj_p, int index_ ) + { + m_obj_p = (sc_uint_base*)obj_p; + m_index = index_; + } + +public: + + // destructor + + virtual ~sc_uint_bitref_r() + {} + + // concatenation support + + virtual int concat_length(bool* xz_present_p) const + { if ( xz_present_p ) *xz_present_p = false; return 1; } + virtual bool concat_get_ctrl( sc_digit* dst_p, int low_i ) const + { + int bit_mask = 1 << (low_i % BITS_PER_DIGIT); + int word_i = low_i / BITS_PER_DIGIT; + + dst_p[word_i] &= ~bit_mask; + return false; + } + virtual bool concat_get_data( sc_digit* dst_p, int low_i ) const + { + int bit_mask = 1 << (low_i % BITS_PER_DIGIT); + bool result; // True is non-zero. + int word_i = low_i / BITS_PER_DIGIT; + + if ( operator uint64() ) + { + dst_p[word_i] |= bit_mask; + result = true; + } + else + { + dst_p[word_i] &= ~bit_mask; + result = false; + } + return result; + } + virtual uint64 concat_get_uint64() const + { return operator uint64(); } + + // capacity + + int length() const + { return 1; } + +#ifdef SC_DT_DEPRECATED + int bitwidth() const + { return length(); } +#endif + + + // implicit conversion to uint64 + + operator uint64 () const; + bool operator ! () const; + bool operator ~ () const; + + + // explicit conversions + + uint64 value() const + { return operator uint64 (); } + + bool to_bool() const + { return operator uint64 (); } + + + // other methods + + void print( ::std::ostream& os = ::std::cout ) const + { os << to_bool(); } + +protected: + + int m_index; + sc_uint_base* m_obj_p; + +private: + + // disabled + sc_uint_bitref_r& operator = ( const sc_uint_bitref_r& ); +}; + + + +inline +::std::ostream& +operator << ( ::std::ostream&, const sc_uint_bitref_r& ); + + +// ---------------------------------------------------------------------------- +// CLASS : sc_uint_bitref +// +// Proxy class for sc_uint bit selection (r-value and l-value). +// ---------------------------------------------------------------------------- + +class sc_uint_bitref + : public sc_uint_bitref_r +{ + friend class sc_uint_base; + friend class sc_core::sc_vpool<sc_uint_bitref>; + + + // constructors + +protected: + sc_uint_bitref() : sc_uint_bitref_r() + {} +public: + sc_uint_bitref( const sc_uint_bitref& init ) : sc_uint_bitref_r(init) + {} + +public: + + // assignment operators + + sc_uint_bitref& operator = ( const sc_uint_bitref_r& b ); + sc_uint_bitref& operator = ( const sc_uint_bitref& b ); + sc_uint_bitref& operator = ( bool b ); + + sc_uint_bitref& operator &= ( bool b ); + sc_uint_bitref& operator |= ( bool b ); + sc_uint_bitref& operator ^= ( bool b ); + + // concatenation methods + + virtual void concat_set(int64 src, int low_i); + virtual void concat_set(const sc_signed& src, int low_i); + virtual void concat_set(const sc_unsigned& src, int low_i); + virtual void concat_set(uint64 src, int low_i); + + // other methods + + void scan( ::std::istream& is = ::std::cin ); + +protected: + static sc_core::sc_vpool<sc_uint_bitref> m_pool; + +}; + + + +inline +::std::istream& +operator >> ( ::std::istream&, sc_uint_bitref& ); + + +// ---------------------------------------------------------------------------- +// CLASS : sc_uint_subref_r +// +// Proxy class for sc_uint part selection (r-value only). +// ---------------------------------------------------------------------------- + +class sc_uint_subref_r : public sc_value_base +{ + friend class sc_uint_base; + friend class sc_uint_subref; + + + // constructors + +public: + sc_uint_subref_r( const sc_uint_subref_r& init ) : + sc_value_base(init), m_left(init.m_left), m_obj_p(init.m_obj_p), + m_right(init.m_right) + {} + +protected: + sc_uint_subref_r() : sc_value_base(), m_left(0), m_obj_p(0), m_right(0) + {} + + // initializer for sc_core::sc_vpool: + + void initialize( const sc_uint_base* obj_p, int left_i, int right_i ) + { + m_obj_p = (sc_uint_base*)obj_p; + m_left = left_i; + m_right = right_i; + } + +public: + + // destructor + + virtual ~sc_uint_subref_r() + {} + + // capacity + + int length() const + { return ( m_left - m_right + 1 ); } + +#ifdef SC_DT_DEPRECATED + int bitwidth() const + { return length(); } +#endif + + // concatenation support + + virtual int concat_length(bool* xz_present_p) const + { if ( xz_present_p ) *xz_present_p = false; return length(); } + virtual bool concat_get_ctrl( sc_digit* dst_p, int low_i ) const; + virtual bool concat_get_data( sc_digit* dst_p, int low_i ) const; + virtual uint64 concat_get_uint64() const + { return (uint64)operator uint_type(); } + + + // reduce methods + + bool and_reduce() const; + + bool nand_reduce() const + { return ( ! and_reduce() ); } + + bool or_reduce() const; + + bool nor_reduce() const + { return ( ! or_reduce() ); } + + bool xor_reduce() const; + + bool xnor_reduce() const + { return ( ! xor_reduce() ); } + + + // implicit conversion to uint_type + + operator uint_type() const; + + + // explicit conversions + + uint_type value() const + { return operator uint_type(); } + + + int to_int() const; + unsigned int to_uint() const; + long to_long() const; + unsigned long to_ulong() const; + int64 to_int64() const; + uint64 to_uint64() const; + double to_double() const; + + + // explicit conversion to character string + + const std::string to_string( sc_numrep numrep = SC_DEC ) const; + const std::string to_string( sc_numrep numrep, bool w_prefix ) const; + + + // other methods + + void print( ::std::ostream& os = ::std::cout ) const + { os << to_string(sc_io_base(os,SC_DEC),sc_io_show_base(os)); } + +protected: + + int m_left; + sc_uint_base* m_obj_p; + int m_right; + +private: + + // disabled + sc_uint_subref_r& operator = ( const sc_uint_subref_r& ); +}; + + + +inline +::std::ostream& +operator << ( ::std::ostream&, const sc_uint_subref_r& ); + + +// ---------------------------------------------------------------------------- +// CLASS : sc_uint_subref +// +// Proxy class for sc_uint part selection (r-value and l-value). +// ---------------------------------------------------------------------------- + +class sc_uint_subref + : public sc_uint_subref_r +{ + friend class sc_uint_base; + friend class sc_core::sc_vpool<sc_uint_subref>; + + + // constructors + +protected: + sc_uint_subref() : sc_uint_subref_r() + {} + +public: + sc_uint_subref( const sc_uint_subref& init ) : sc_uint_subref_r(init) + {} + +public: + + // assignment operators + + sc_uint_subref& operator = ( uint_type v ); + + sc_uint_subref& operator = ( const sc_uint_base& a ); + + sc_uint_subref& operator = ( const sc_uint_subref_r& a ) + { return operator = ( a.operator uint_type() ); } + + sc_uint_subref& operator = ( const sc_uint_subref& a ) + { return operator = ( a.operator uint_type() ); } + + template<class T> + sc_uint_subref& operator = ( const sc_generic_base<T>& a ) + { return operator = ( a->to_uint64() ); } + + sc_uint_subref& operator = ( const char* a ); + + sc_uint_subref& operator = ( unsigned long a ) + { return operator = ( (uint_type) a ); } + + sc_uint_subref& operator = ( long a ) + { return operator = ( (uint_type) a ); } + + sc_uint_subref& operator = ( unsigned int a ) + { return operator = ( (uint_type) a ); } + + sc_uint_subref& operator = ( int a ) + { return operator = ( (uint_type) a ); } + + sc_uint_subref& operator = ( int64 a ) + { return operator = ( (uint_type) a ); } + + sc_uint_subref& operator = ( double a ) + { return operator = ( (uint_type) a ); } + + sc_uint_subref& operator = ( const sc_signed& ); + sc_uint_subref& operator = ( const sc_unsigned& ); + sc_uint_subref& operator = ( const sc_bv_base& ); + sc_uint_subref& operator = ( const sc_lv_base& ); + + // concatenation methods + + virtual void concat_set(int64 src, int low_i); + virtual void concat_set(const sc_signed& src, int low_i); + virtual void concat_set(const sc_unsigned& src, int low_i); + virtual void concat_set(uint64 src, int low_i); + + // other methods + + void scan( ::std::istream& is = ::std::cin ); + +protected: + static sc_core::sc_vpool<sc_uint_subref> m_pool; + +}; + + + +inline +::std::istream& +operator >> ( ::std::istream&, sc_uint_subref& ); + + +// ---------------------------------------------------------------------------- +// CLASS : sc_uint_base +// +// Base class for sc_uint. +// ---------------------------------------------------------------------------- + +class sc_uint_base : public sc_value_base +{ + friend class sc_uint_bitref_r; + friend class sc_uint_bitref; + friend class sc_uint_subref_r; + friend class sc_uint_subref; + + + // support methods + + void invalid_length() const; + void invalid_index( int i ) const; + void invalid_range( int l, int r ) const; + + void check_length() const + { if( m_len <= 0 || m_len > SC_INTWIDTH ) { invalid_length(); } } + + void check_index( int i ) const + { if( i < 0 || i >= m_len ) { invalid_index( i ); } } + + void check_range( int l, int r ) const + { if( r < 0 || l >= m_len || l < r ) { invalid_range( l, r ); } } + + void check_value() const; + + void extend_sign() + { +#ifdef DEBUG_SYSTEMC + check_value(); +#endif + m_val &= ( ~UINT_ZERO >> m_ulen ); + } + +public: + + // constructors + + explicit sc_uint_base( int w = sc_length_param().len() ) + : m_val( 0 ), m_len( w ), m_ulen( SC_INTWIDTH - m_len ) + { check_length(); } + + sc_uint_base( uint_type v, int w ) + : m_val( v ), m_len( w ), m_ulen( SC_INTWIDTH - m_len ) + { check_length(); extend_sign(); } + + sc_uint_base( const sc_uint_base& a ) + : sc_value_base(a), m_val(a.m_val), m_len(a.m_len), m_ulen(a.m_ulen) + {} + + explicit sc_uint_base( const sc_uint_subref_r& a ) + : m_val( a ), m_len( a.length() ), m_ulen( SC_INTWIDTH - m_len ) + { extend_sign(); } + + template<class T> + explicit sc_uint_base( const sc_generic_base<T>& a ) + : m_val( a->to_uint64() ), m_len( a->length() ), + m_ulen( SC_INTWIDTH - m_len ) + { check_length(); extend_sign(); } + + explicit sc_uint_base( const sc_bv_base& v ); + explicit sc_uint_base( const sc_lv_base& v ); + explicit sc_uint_base( const sc_int_subref_r& v ); + explicit sc_uint_base( const sc_signed_subref_r& v ); + explicit sc_uint_base( const sc_unsigned_subref_r& v ); + explicit sc_uint_base( const sc_signed& a ); + explicit sc_uint_base( const sc_unsigned& a ); + + + // destructor + + virtual ~sc_uint_base() + {} + + + // assignment operators + + sc_uint_base& operator = ( uint_type v ) + { m_val = v; extend_sign(); return *this; } + + sc_uint_base& operator = ( const sc_uint_base& a ) + { m_val = a.m_val; extend_sign(); return *this; } + + sc_uint_base& operator = ( const sc_uint_subref_r& a ) + { m_val = a; extend_sign(); return *this; } + + template<class T> + sc_uint_base& operator = ( const sc_generic_base<T>& a ) + { m_val = a->to_uint64(); extend_sign(); return *this; } + + sc_uint_base& operator = ( const sc_signed& a ); + sc_uint_base& operator = ( const sc_unsigned& a ); + +#ifdef SC_INCLUDE_FX + sc_uint_base& operator = ( const sc_fxval& a ); + sc_uint_base& operator = ( const sc_fxval_fast& a ); + sc_uint_base& operator = ( const sc_fxnum& a ); + sc_uint_base& operator = ( const sc_fxnum_fast& a ); +#endif + + sc_uint_base& operator = ( const sc_bv_base& a ); + sc_uint_base& operator = ( const sc_lv_base& a ); + + sc_uint_base& operator = ( const char* a ); + + sc_uint_base& operator = ( unsigned long a ) + { m_val = a; extend_sign(); return *this; } + + sc_uint_base& operator = ( long a ) + { m_val = a; extend_sign(); return *this; } + + sc_uint_base& operator = ( unsigned int a ) + { m_val = a; extend_sign(); return *this; } + + sc_uint_base& operator = ( int a ) + { m_val = a; extend_sign(); return *this; } + + sc_uint_base& operator = ( int64 a ) + { m_val = a; extend_sign(); return *this; } + + sc_uint_base& operator = ( double a ) + { m_val = (uint_type) a; extend_sign(); return *this; } + + + // arithmetic assignment operators + + sc_uint_base& operator += ( uint_type v ) + { m_val += v; extend_sign(); return *this; } + + sc_uint_base& operator -= ( uint_type v ) + { m_val -= v; extend_sign(); return *this; } + + sc_uint_base& operator *= ( uint_type v ) + { m_val *= v; extend_sign(); return *this; } + + sc_uint_base& operator /= ( uint_type v ) + { m_val /= v; extend_sign(); return *this; } + + sc_uint_base& operator %= ( uint_type v ) + { m_val %= v; extend_sign(); return *this; } + + + // bitwise assignment operators + + sc_uint_base& operator &= ( uint_type v ) + { m_val &= v; extend_sign(); return *this; } + + sc_uint_base& operator |= ( uint_type v ) + { m_val |= v; extend_sign(); return *this; } + + sc_uint_base& operator ^= ( uint_type v ) + { m_val ^= v; extend_sign(); return *this; } + + + sc_uint_base& operator <<= ( uint_type v ) + { m_val <<= v; extend_sign(); return *this; } + + sc_uint_base& operator >>= ( uint_type v ) + { m_val >>= v; /* no sign extension needed */ return *this; } + + + // prefix and postfix increment and decrement operators + + sc_uint_base& operator ++ () // prefix + { ++ m_val; extend_sign(); return *this; } + + const sc_uint_base operator ++ ( int ) // postfix + { sc_uint_base tmp( *this ); ++ m_val; extend_sign(); return tmp; } + + sc_uint_base& operator -- () // prefix + { -- m_val; extend_sign(); return *this; } + + const sc_uint_base operator -- ( int ) // postfix + { sc_uint_base tmp( *this ); -- m_val; extend_sign(); return tmp; } + + + // relational operators + + friend bool operator == ( const sc_uint_base& a, const sc_uint_base& b ) + { return a.m_val == b.m_val; } + + friend bool operator != ( const sc_uint_base& a, const sc_uint_base& b ) + { return a.m_val != b.m_val; } + + friend bool operator < ( const sc_uint_base& a, const sc_uint_base& b ) + { return a.m_val < b.m_val; } + + friend bool operator <= ( const sc_uint_base& a, const sc_uint_base& b ) + { return a.m_val <= b.m_val; } + + friend bool operator > ( const sc_uint_base& a, const sc_uint_base& b ) + { return a.m_val > b.m_val; } + + friend bool operator >= ( const sc_uint_base& a, const sc_uint_base& b ) + { return a.m_val >= b.m_val; } + + + // bit selection + + sc_uint_bitref& operator [] ( int i ); + const sc_uint_bitref_r& operator [] ( int i ) const; + + sc_uint_bitref& bit( int i ); + const sc_uint_bitref_r& bit( int i ) const; + + + // part selection + + sc_uint_subref& operator () ( int left, int right ); + const sc_uint_subref_r& operator () ( int left, int right ) const; + + sc_uint_subref& range( int left, int right ); + const sc_uint_subref_r& range( int left, int right ) const; + + + // bit access, without bounds checking or sign extension + + bool test( int i ) const + { return ( 0 != (m_val & (UINT_ONE << i)) ); } + + void set( int i ) + { m_val |= (UINT_ONE << i); } + + void set( int i, bool v ) + { v ? m_val |= (UINT_ONE << i) : m_val &= ~(UINT_ONE << i); } + + + // capacity + + int length() const + { return m_len; } + +#ifdef SC_DT_DEPRECATED + int bitwidth() const + { return length(); } +#endif + + // concatenation support + + virtual int concat_length(bool* xz_present_p) const + { if ( xz_present_p ) *xz_present_p = false; return length(); } + virtual bool concat_get_ctrl( sc_digit* dst_p, int low_i ) const; + virtual bool concat_get_data( sc_digit* dst_p, int low_i ) const; + virtual uint64 concat_get_uint64() const + { return m_val; } + virtual void concat_set(int64 src, int low_i); + virtual void concat_set(const sc_signed& src, int low_i); + virtual void concat_set(const sc_unsigned& src, int low_i); + virtual void concat_set(uint64 src, int low_i); + + + // reduce methods + + bool and_reduce() const; + + bool nand_reduce() const + { return ( ! and_reduce() ); } + + bool or_reduce() const; + + bool nor_reduce() const + { return ( ! or_reduce() ); } + + bool xor_reduce() const; + + bool xnor_reduce() const + { return ( ! xor_reduce() ); } + + + // implicit conversion to uint_type + + operator uint_type() const + { return m_val; } + + + // explicit conversions + + uint_type value() const + { return operator uint_type(); } + + + int to_int() const + { return (int) m_val; } + + unsigned int to_uint() const + { return (unsigned int) m_val; } + + long to_long() const + { return (long) m_val; } + + unsigned long to_ulong() const + { return (unsigned long) m_val; } + + int64 to_int64() const + { return (int64) m_val; } + + uint64 to_uint64() const + { return (uint64) m_val; } + + double to_double() const + { return uint64_to_double( m_val ); } + + +#ifndef _32BIT_ + long long_low() const + { return (long) (m_val & UINT64_32ONES); } + + long long_high() const + { return (long) ((m_val >> 32) & UINT64_32ONES); } +#endif + + // explicit conversion to character string + + const std::string to_string( sc_numrep numrep = SC_DEC ) const; + const std::string to_string( sc_numrep numrep, bool w_prefix ) const; + + + // other methods + + void print( ::std::ostream& os = ::std::cout ) const + { os << to_string(sc_io_base(os,SC_DEC),sc_io_show_base(os)); } + + void scan( ::std::istream& is = ::std::cin ); + +protected: + + uint_type m_val; // value + int m_len; // length + int m_ulen; // unused length +}; + + + +inline +::std::ostream& +operator << ( ::std::ostream&, const sc_uint_base& ); + +inline +::std::istream& +operator >> ( ::std::istream&, sc_uint_base& ); + + + +// ---------------------------------------------------------------------------- +// CLASS : sc_uint_bitref_r +// +// Proxy class for sc_uint bit selection (r-value only). +// ---------------------------------------------------------------------------- + +// implicit conversion to bool + +inline +sc_uint_bitref_r::operator uint64 () const +{ + return m_obj_p->test( m_index ); +} + +inline +bool +sc_uint_bitref_r::operator ! () const +{ + return ! m_obj_p->test( m_index ); +} + +inline +bool +sc_uint_bitref_r::operator ~ () const +{ + return ! m_obj_p->test( m_index ); +} + + + +inline +::std::ostream& +operator << ( ::std::ostream& os, const sc_uint_bitref_r& a ) +{ + a.print( os ); + return os; +} + + +// ---------------------------------------------------------------------------- +// CLASS : sc_uint_bitref +// +// Proxy class for sc_uint bit selection (r-value and l-value). +// ---------------------------------------------------------------------------- + +// assignment operators + +inline +sc_uint_bitref& +sc_uint_bitref::operator = ( const sc_uint_bitref_r& b ) +{ + m_obj_p->set( m_index, b.to_bool() ); + return *this; +} + +inline +sc_uint_bitref& +sc_uint_bitref::operator = ( const sc_uint_bitref& b ) +{ + m_obj_p->set( m_index, b.to_bool() ); + return *this; +} + +inline +sc_uint_bitref& +sc_uint_bitref::operator = ( bool b ) +{ + m_obj_p->set( m_index, b ); + return *this; +} + + +inline +sc_uint_bitref& +sc_uint_bitref::operator &= ( bool b ) +{ + if( ! b ) { + m_obj_p->set( m_index, b ); + } + return *this; +} + +inline +sc_uint_bitref& +sc_uint_bitref::operator |= ( bool b ) +{ + if( b ) { + m_obj_p->set( m_index, b ); + } + return *this; +} + +inline +sc_uint_bitref& +sc_uint_bitref::operator ^= ( bool b ) +{ + if( b ) { + m_obj_p->m_val ^= (UINT_ONE << m_index); + } + return *this; +} + + + +inline +::std::istream& +operator >> ( ::std::istream& is, sc_uint_bitref& a ) +{ + a.scan( is ); + return is; +} + + +// ---------------------------------------------------------------------------- +// CLASS : sc_uint_subref_r +// +// Proxy class for sc_uint part selection (r-value only). +// ---------------------------------------------------------------------------- + +// implicit conversion to uint_type + +inline +sc_uint_subref_r::operator uint_type() const +{ + uint_type val = m_obj_p->m_val; + int uleft = SC_INTWIDTH - (m_left + 1); + return ( (val & (~UINT_ZERO >> uleft)) >> m_right ); +} + + +// reduce methods + +inline +bool +sc_uint_subref_r::and_reduce() const +{ + sc_uint_base a( *this ); + return a.and_reduce(); +} + +inline +bool +sc_uint_subref_r::or_reduce() const +{ + sc_uint_base a( *this ); + return a.or_reduce(); +} + +inline +bool +sc_uint_subref_r::xor_reduce() const +{ + sc_uint_base a( *this ); + return a.xor_reduce(); +} + + +// explicit conversions + +inline +int +sc_uint_subref_r::to_int() const +{ + sc_uint_base a( *this ); + return a.to_int(); +} + +inline +unsigned int +sc_uint_subref_r::to_uint() const +{ + sc_uint_base a( *this ); + return a.to_uint(); +} + +inline +long +sc_uint_subref_r::to_long() const +{ + sc_uint_base a( *this ); + return a.to_long(); +} + +inline +unsigned long +sc_uint_subref_r::to_ulong() const +{ + sc_uint_base a( *this ); + return a.to_ulong(); +} + +inline +int64 +sc_uint_subref_r::to_int64() const +{ + sc_uint_base a( *this ); + return a.to_int64(); +} + +inline +uint64 +sc_uint_subref_r::to_uint64() const +{ + sc_uint_base a( *this ); + return a.to_uint64(); +} + +inline +double +sc_uint_subref_r::to_double() const +{ + sc_uint_base a( *this ); + return a.to_double(); +} + + +// explicit conversion to character string + +inline +const std::string +sc_uint_subref_r::to_string( sc_numrep numrep ) const +{ + sc_uint_base a( *this ); + return a.to_string( numrep ); +} + +inline +const std::string +sc_uint_subref_r::to_string( sc_numrep numrep, bool w_prefix ) const +{ + sc_uint_base a( *this ); + return a.to_string( numrep, w_prefix ); +} + + +// functional notation for the reduce methods + +inline +bool +and_reduce( const sc_uint_subref_r& a ) +{ + return a.and_reduce(); +} + +inline +bool +nand_reduce( const sc_uint_subref_r& a ) +{ + return a.nand_reduce(); +} + +inline +bool +or_reduce( const sc_uint_subref_r& a ) +{ + return a.or_reduce(); +} + +inline +bool +nor_reduce( const sc_uint_subref_r& a ) +{ + return a.nor_reduce(); +} + +inline +bool +xor_reduce( const sc_uint_subref_r& a ) +{ + return a.xor_reduce(); +} + +inline +bool +xnor_reduce( const sc_uint_subref_r& a ) +{ + return a.xnor_reduce(); +} + + + +inline +::std::ostream& +operator << ( ::std::ostream& os, const sc_uint_subref_r& a ) +{ + a.print( os ); + return os; +} + + +// ---------------------------------------------------------------------------- +// CLASS : sc_uint_subref +// +// Proxy class for sc_uint part selection (r-value and l-value). +// ---------------------------------------------------------------------------- + +// assignment operators + +inline +sc_uint_subref& +sc_uint_subref::operator = ( const sc_uint_base& a ) +{ + return operator = ( a.operator uint_type() ); +} + +inline +sc_uint_subref& +sc_uint_subref::operator = ( const char* a ) +{ + sc_uint_base aa( length() ); + return ( *this = aa = a ); +} + + + +inline +::std::istream& +operator >> ( ::std::istream& is, sc_uint_subref& a ) +{ + a.scan( is ); + return is; +} + + +// ---------------------------------------------------------------------------- +// CLASS : sc_uint_base +// +// Base class for sc_uint. +// ---------------------------------------------------------------------------- + +// bit selection + +inline +sc_uint_bitref& +sc_uint_base::operator [] ( int i ) +{ + check_index( i ); + sc_uint_bitref* result_p = sc_uint_bitref::m_pool.allocate(); + result_p->initialize(this, i); + return *result_p; +} + +inline +const sc_uint_bitref_r& +sc_uint_base::operator [] ( int i ) const +{ + check_index( i ); + sc_uint_bitref* result_p = sc_uint_bitref::m_pool.allocate(); + result_p->initialize(this, i); + return *result_p; +} + + +inline +sc_uint_bitref& +sc_uint_base::bit( int i ) +{ + check_index( i ); + sc_uint_bitref* result_p = sc_uint_bitref::m_pool.allocate(); + result_p->initialize(this, i); + return *result_p; +} + +inline +const sc_uint_bitref_r& +sc_uint_base::bit( int i ) const +{ + check_index( i ); + sc_uint_bitref* result_p = sc_uint_bitref::m_pool.allocate(); + result_p->initialize(this, i); + return *result_p; +} + + +// part selection + +inline +sc_uint_subref& +sc_uint_base::operator () ( int left, int right ) +{ + check_range( left, right ); + sc_uint_subref* result_p = sc_uint_subref::m_pool.allocate(); + result_p->initialize(this, left, right); + return *result_p; +} + +inline +const sc_uint_subref_r& +sc_uint_base::operator () ( int left, int right ) const +{ + check_range( left, right ); + sc_uint_subref* result_p = sc_uint_subref::m_pool.allocate(); + result_p->initialize(this, left, right); + return *result_p; +} + + +inline +sc_uint_subref& +sc_uint_base::range( int left, int right ) +{ + check_range( left, right ); + sc_uint_subref* result_p = sc_uint_subref::m_pool.allocate(); + result_p->initialize(this, left, right); + return *result_p; +} + +inline +const sc_uint_subref_r& +sc_uint_base::range( int left, int right ) const +{ + check_range( left, right ); + sc_uint_subref* result_p = sc_uint_subref::m_pool.allocate(); + result_p->initialize(this, left, right); + return *result_p; +} + + +// functional notation for the reduce methods + +inline +bool +and_reduce( const sc_uint_base& a ) +{ + return a.and_reduce(); +} + +inline +bool +nand_reduce( const sc_uint_base& a ) +{ + return a.nand_reduce(); +} + +inline +bool +or_reduce( const sc_uint_base& a ) +{ + return a.or_reduce(); +} + +inline +bool +nor_reduce( const sc_uint_base& a ) +{ + return a.nor_reduce(); +} + +inline +bool +xor_reduce( const sc_uint_base& a ) +{ + return a.xor_reduce(); +} + +inline +bool +xnor_reduce( const sc_uint_base& a ) +{ + return a.xnor_reduce(); +} + + + +inline +::std::ostream& +operator << ( ::std::ostream& os, const sc_uint_base& a ) +{ + a.print( os ); + return os; +} + +inline +::std::istream& +operator >> ( ::std::istream& is, sc_uint_base& a ) +{ + a.scan( is ); + return is; +} + +} // namespace sc_dt + + +#endif + +// Taf! diff --git a/ext/systemc/src/sysc/datatypes/int/sc_unsigned.cpp b/ext/systemc/src/sysc/datatypes/int/sc_unsigned.cpp new file mode 100644 index 000000000..75af69deb --- /dev/null +++ b/ext/systemc/src/sysc/datatypes/int/sc_unsigned.cpp @@ -0,0 +1,2240 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_unsigned.cpp -- Arbitrary precision signed arithmetic. + + This file includes the definitions of sc_unsigned_bitref, + sc_unsigned_subref, and sc_unsigned classes. The first two classes + are proxy classes to reference one bit and a range of bits of a + sc_unsigned number, respectively. This file also includes + sc_nbcommon.cpp and sc_nbfriends.cpp, which contain the + definitions shared by sc_unsigned. + + Original Author: Ali Dasdan, Synopsys, Inc. + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + + +// $Log: sc_unsigned.cpp,v $ +// Revision 1.7 2011/02/18 20:19:15 acg +// Andy Goodrich: updating Copyright notice. +// +// Revision 1.6 2008/12/10 20:38:45 acg +// Andy Goodrich: fixed conversion of double values to the digits vector. +// The bits above the radix were not being masked off. +// +// Revision 1.5 2008/06/19 17:47:57 acg +// Andy Goodrich: fixes for bugs. See 2.2.1 RELEASENOTES. +// +// Revision 1.4 2008/06/19 16:57:57 acg +// Andy Goodrich: added case for negative unsigned values to the support in +// concate_get_data(). +// +// Revision 1.3 2007/11/04 21:27:00 acg +// Andy Goodrich: changes to make sure the proper value is returned from +// concat_get_data(). +// +// Revision 1.2 2007/02/22 21:35:05 acg +// Andy Goodrich: cleaned up comments in concat_get_ctrl and concat_get_data. +// +// Revision 1.1.1.1 2006/12/15 20:20:05 acg +// SystemC 2.3 +// +// Revision 1.4 2006/08/29 23:36:54 acg +// Andy Goodrich: fixed and_reduce and optimized or_reduce. +// +// Revision 1.3 2006/01/13 18:49:32 acg +// Added $Log command so that CVS check in comments are reproduced in the +// source. +// + +#include <ctype.h> +#include <math.h> + +#include "sysc/kernel/sc_cmnhdr.h" +#include "sysc/kernel/sc_macros.h" +#include "sysc/datatypes/int/sc_unsigned.h" +#include "sysc/datatypes/int/sc_signed.h" +#include "sysc/datatypes/int/sc_int_base.h" +#include "sysc/datatypes/int/sc_uint_base.h" +#include "sysc/datatypes/int/sc_int_ids.h" +#include "sysc/datatypes/bit/sc_bv_base.h" +#include "sysc/datatypes/bit/sc_lv_base.h" +#include "sysc/datatypes/misc/sc_concatref.h" +#include "sysc/datatypes/fx/sc_ufix.h" +#include "sysc/datatypes/fx/scfx_other_defs.h" + +namespace sc_dt +{ + +// Pool of temporary instances: +// The sc_unsigned pool is used by the concatenation support. +// The bit and part reference pools allow references to be returned. + +sc_core::sc_vpool<sc_unsigned> sc_unsigned::m_pool(8); +sc_core::sc_vpool<sc_unsigned_bitref> sc_unsigned_bitref::m_pool(9); +sc_core::sc_vpool<sc_unsigned_subref> sc_unsigned_subref::m_pool(9); + +// ----------------------------------------------------------------------------- +// SECTION: Public members - Invalid selections. +// ----------------------------------------------------------------------------- + +void +sc_unsigned::invalid_index( int i ) const +{ + char msg[BUFSIZ]; + std::sprintf( msg, + "sc_biguint bit selection: index = %d violates " + "0 <= index <= %d", + i, nbits - 2 ); + SC_REPORT_ERROR( sc_core::SC_ID_OUT_OF_BOUNDS_, msg ); +} + +void +sc_unsigned::invalid_range( int l, int r ) const +{ + char msg[BUFSIZ]; + std::sprintf( msg, + "sc_biguint part selection: left = %d, right = %d \n" + " violates either (%d >= left >= 0) or (%d >= right >= 0)", + l, r, nbits-2, nbits-2 ); + SC_REPORT_ERROR( sc_core::SC_ID_OUT_OF_BOUNDS_, msg ); +} + +// ---------------------------------------------------------------------------- +// SECTION: Public members - Concatenation support. +// ---------------------------------------------------------------------------- + +// Most public members are included from sc_nbcommon.inc. However, some +// concatenation support appears here to optimize between the signed and +// unsigned cases. + + + +// Insert this object's value at the specified place in a vector of big style +// values. + +bool sc_unsigned::concat_get_ctrl( sc_digit* dst_p, int low_i ) const +{ + int dst_i; // Index to next word to set in dst_p. + int end_i; // Index of high order word to set. + int left_shift; // Amount to shift value left. + sc_digit mask; // Mask for partial word sets. + + + // CALCULATE METRICS FOR DATA MOVEMENT: + + dst_i = low_i / BITS_PER_DIGIT; + end_i = (low_i + nbits - 2) / BITS_PER_DIGIT; + left_shift = low_i % BITS_PER_DIGIT; + + + // MOVE FIRST WORD (IT MAY BE PARTIAL) AND THEN ANY OTHERS: + // + // We may "clobber" upper bits, but they will be written at some point + // anyway. + + mask = ~(-1 << left_shift); + dst_p[dst_i] = ( dst_p[dst_i] & ~mask ); + dst_i++; + + for ( ; dst_i <= end_i; dst_i++ ) dst_p[dst_i] = 0; + + return false; +} + +bool sc_unsigned::concat_get_data( sc_digit* dst_p, int low_i ) const +{ + sc_digit carry; // Carry for negating value. + int dst_i; // Index to next word to set in dst_p. + int end_i; // Index of high order word to set. + int high_i; // Index w/in word of high order bit. + int left_shift; // Amount to shift value left. + sc_digit left_word; // High word component for set. + sc_digit mask; // Mask for partial word sets. + bool result; // True if inserting non-zero data. + int right_shift; // Amount to shift value right. + sc_digit right_word; // Low word component for set. + int real_bits; // nbits - 1. + int src_i; // Index to next word to get from digit. + + + // CALCULATE METRICS FOR DATA MOVEMENT: + + real_bits = nbits - 1; // Remove that extra sign bit. + dst_i = low_i / BITS_PER_DIGIT; + high_i = low_i + real_bits - 1; + end_i = high_i / BITS_PER_DIGIT; + left_shift = low_i % BITS_PER_DIGIT; + + + switch ( sgn ) + { + + // POSITIVE SOURCE VALUE: + + case SC_POS: + result = true; + + // ALL DATA TO BE MOVED IS IN A SINGLE WORD: + + if ( dst_i == end_i ) + { + mask = ~(-1 << left_shift); + dst_p[dst_i] = ( ( dst_p[dst_i] & mask ) | + (digit[0] << left_shift) ) & DIGIT_MASK; + } + + + // DATA IS IN MORE THAN ONE WORD, BUT IS WORD ALIGNED: + + else if ( left_shift == 0 ) + { + for ( src_i = 0; dst_i < end_i; dst_i++, src_i++ ) + { + dst_p[dst_i] = digit[src_i]; + } + high_i = high_i % BITS_PER_DIGIT; + mask = ~(-2 << high_i) & DIGIT_MASK; + dst_p[dst_i] = digit[src_i] & mask; + } + + + // DATA IS IN MORE THAN ONE WORD, AND NOT WORD ALIGNED: + + else + { + high_i = high_i % BITS_PER_DIGIT; + right_shift = BITS_PER_DIGIT - left_shift; + mask = ~(-1 << left_shift); + right_word = digit[0]; + dst_p[dst_i] = (dst_p[dst_i] & mask) | + ((right_word << left_shift) & DIGIT_MASK); + for ( src_i = 1, dst_i++; dst_i < end_i; dst_i++, src_i++ ) + { + left_word = digit[src_i]; + dst_p[dst_i] = ((left_word << left_shift)&DIGIT_MASK) | + (right_word >> right_shift); + right_word = left_word; + } + left_word = (src_i < ndigits) ? digit[src_i] : 0; + mask = ~(-2 << high_i) & DIGIT_MASK; + dst_p[dst_i] = ((left_word << left_shift) | + (right_word >> right_shift)) & mask; + } + break; + + // SOURCE VALUE IS NEGATIVE: + + case SC_NEG: + + // ALL DATA TO BE MOVED IS IN A SINGLE WORD: + + result = true; + if ( dst_i == end_i ) + { + mask = ~(-1 << nbits); + right_word = ((digit[0] ^ DIGIT_MASK) + 1) & mask; + mask = ~(-1 << left_shift); + dst_p[dst_i] = ( ( dst_p[dst_i] & mask ) | + (right_word << left_shift) ) & DIGIT_MASK; + } + + + // DATA IS IN MORE THAN ONE WORD, BUT IS WORD ALIGNED: + + else if ( left_shift == 0 ) + { + carry = 1; + for ( src_i = 0; dst_i < end_i; dst_i++, src_i++ ) + { + right_word = (digit[src_i] ^ DIGIT_MASK) + carry; + dst_p[dst_i] = right_word & DIGIT_MASK; + carry = right_word >> BITS_PER_DIGIT; + } + high_i = high_i % BITS_PER_DIGIT; + mask = (~(-2 << high_i)) & DIGIT_MASK; + right_word = (src_i < ndigits) ? + (digit[src_i] ^ DIGIT_MASK) + carry : DIGIT_MASK + carry; + dst_p[dst_i] = right_word & mask; + } + + + // DATA IS IN MORE THAN ONE WORD, AND NOT WORD ALIGNED: + + else + { + high_i = high_i % BITS_PER_DIGIT; + right_shift = BITS_PER_DIGIT - left_shift; + mask = ~(-1 << left_shift); + carry = 1; + right_word = (digit[0] ^ DIGIT_MASK) + carry; + dst_p[dst_i] = (dst_p[dst_i] & mask) | + ((right_word << left_shift) & DIGIT_MASK); + carry = right_word >> BITS_PER_DIGIT; + right_word &= DIGIT_MASK; + for ( src_i = 1, dst_i++; dst_i < end_i; dst_i++, src_i++ ) + { + left_word = (digit[src_i] ^ DIGIT_MASK) + carry; + dst_p[dst_i] = ((left_word << left_shift)&DIGIT_MASK) | + (right_word >> right_shift); + carry = left_word >> BITS_PER_DIGIT; + right_word = left_word & DIGIT_MASK; + } + left_word = (src_i < ndigits) ? + (digit[src_i] ^ DIGIT_MASK) + carry : carry; + mask = ~(-2 << high_i) & DIGIT_MASK; + dst_p[dst_i] = ((left_word << left_shift) | + (right_word >> right_shift)) & mask; + } + break; + + + // VALUE IS ZERO: + + default: + result = false; + + // ALL DATA TO BE MOVED IS IN A SINGLE WORD: + + if ( dst_i == end_i ) + { + mask = ~(-1 << real_bits) << left_shift; + dst_p[dst_i] = dst_p[dst_i] & ~mask; + } + + + // DATA IS IN MORE THAN ONE WORD, BUT IS WORD ALIGNED: + + else if ( left_shift == 0 ) + { + for ( src_i = 0; dst_i < end_i; dst_i++, src_i++ ) + { + dst_p[dst_i] = 0; + } + high_i = high_i % BITS_PER_DIGIT; + mask = ~(-2 << high_i) & DIGIT_MASK; + dst_p[dst_i] = 0; + } + + + // DATA IS IN MORE THAN ONE WORD, AND NOT WORD ALIGNED: + + else + { + high_i = high_i % BITS_PER_DIGIT; + right_shift = BITS_PER_DIGIT - left_shift; + mask = ~(-1 << left_shift); + dst_p[dst_i] = (dst_p[dst_i] & mask); + for ( dst_i++; dst_i <= end_i; dst_i++ ) + { + dst_p[dst_i] = 0; + } + } + break; + } + return result; +} + +// Return this object instance's bits as a uint64 without sign extension. + +uint64 sc_unsigned::concat_get_uint64() const +{ + uint64 result; + + switch ( sgn ) + { + case SC_POS: + result = 0; + if ( ndigits > 2 ) + result = digit[2]; + if ( ndigits > 1 ) + result = (result << BITS_PER_DIGIT) | digit[1]; + result = (result << BITS_PER_DIGIT) | digit[0]; + break; + default: + result = 0; + break; + } + return result; +} + +// #### OPTIMIZE +void sc_unsigned::concat_set(int64 src, int low_i) +{ + *this = (low_i < 64) ? src >> low_i : src >> 63; +} + +void sc_unsigned::concat_set(const sc_signed& src, int low_i) +{ + if ( low_i < src.length() ) + *this = src >> low_i; + else + *this = (src<0) ? (int_type)-1 : 0; +} + +void sc_unsigned::concat_set(const sc_unsigned& src, int low_i) +{ + if ( low_i < src.length() ) + *this = src >> low_i; + else + *this = 0; +} + +void sc_unsigned::concat_set(uint64 src, int low_i) +{ + *this = (low_i < 64) ? src >> low_i : 0; +} + + +// ---------------------------------------------------------------------------- +// SECTION: Public members - Reduction methods. +// ---------------------------------------------------------------------------- + +bool sc_unsigned::and_reduce() const +{ + int i; // Digit examining. + + if ( sgn == SC_ZERO ) return false; + for ( i = 0; i < ndigits-1; i++ ) + if ( (digit[i] & DIGIT_MASK) != DIGIT_MASK ) return false; + if ( (digit[i] & ~(-1 << ((nbits-1) % BITS_PER_DIGIT))) == + (sc_digit)~(-1 << ((nbits-1) % BITS_PER_DIGIT))) + return true; + return false; +} + +bool sc_unsigned::or_reduce() const +{ + return ( sgn == SC_ZERO ) ? false : true; +} + +bool sc_unsigned::xor_reduce() const +{ + int i; // Digit examining. + int odd; // Flag for odd number of digits. + + odd = 0; + for ( i = 0; i < nbits-1; i++ ) + if ( test(i) ) odd = ~odd; + return odd ? true : false; +} + + +// ---------------------------------------------------------------------------- +// SECTION: Public members - Assignment operators. +// ---------------------------------------------------------------------------- + +// assignment operators + +const sc_unsigned& +sc_unsigned::operator = ( const char* a ) +{ + if( a == 0 ) { + SC_REPORT_ERROR( sc_core::SC_ID_CONVERSION_FAILED_, + "character string is zero" ); + } + if( *a == 0 ) { + SC_REPORT_ERROR( sc_core::SC_ID_CONVERSION_FAILED_, + "character string is empty" ); + } + try { + int len = length(); + sc_ufix aa( a, len, len, SC_TRN, SC_WRAP, 0, SC_ON ); + return this->operator = ( aa ); + } catch( sc_core::sc_report ) { + char msg[BUFSIZ]; + std::sprintf( msg, "character string '%s' is not valid", a ); + SC_REPORT_ERROR( sc_core::SC_ID_CONVERSION_FAILED_, msg ); + // never reached + } + return *this; +} + +const sc_unsigned& +sc_unsigned::operator=(int64 v) +{ + sgn = get_sign(v); + if ( sgn == SC_ZERO ) { + vec_zero(ndigits, digit); + } + else { + from_uint(ndigits, digit, (uint64) v); + convert_SM_to_2C_to_SM(); + } + return *this; +} + +const sc_unsigned& +sc_unsigned::operator=(uint64 v) +{ + if (v == 0) { + sgn = SC_ZERO; + vec_zero(ndigits, digit); + } + else { + sgn = SC_POS; + from_uint(ndigits, digit, v); + convert_SM_to_2C_to_SM(); + } + return *this; +} + +const sc_unsigned& +sc_unsigned::operator=(long v) +{ + sgn = get_sign(v); + if ( sgn == SC_ZERO ) { + vec_zero(ndigits, digit); + } + else { + from_uint(ndigits, digit, (unsigned long) v); + convert_SM_to_2C_to_SM(); + } + return *this; +} + +const sc_unsigned& +sc_unsigned::operator=(unsigned long v) +{ + if (v == 0) { + sgn = SC_ZERO; + vec_zero(ndigits, digit); + } + else { + sgn = SC_POS; + from_uint(ndigits, digit, v); + convert_SM_to_2C_to_SM(); + } + return *this; +} + +const sc_unsigned& +sc_unsigned::operator=(double v) +{ + is_bad_double(v); + sgn = SC_POS; + int i = 0; + while (floor(v) && (i < ndigits)) { +#ifndef _WIN32 + digit[i++] = ((sc_digit)floor(remainder(v, DIGIT_RADIX))) & DIGIT_MASK; +#else + digit[i++] = ((sc_digit)floor(fmod(v, DIGIT_RADIX))) & DIGIT_MASK; +#endif + v /= DIGIT_RADIX; + } + vec_zero(i, ndigits, digit); + convert_SM_to_2C_to_SM(); + return *this; +} + + +// ---------------------------------------------------------------------------- + +const sc_unsigned& +sc_unsigned::operator = ( const sc_bv_base& v ) +{ + int minlen = sc_min( nbits, v.length() ); + int i = 0; + for( ; i < minlen; ++ i ) { + safe_set( i, v.get_bit( i ), digit ); + } + for( ; i < nbits; ++ i ) { + safe_set( i, 0, digit ); // zero-extend + } + convert_2C_to_SM(); + return *this; +} + +const sc_unsigned& +sc_unsigned::operator = ( const sc_lv_base& v ) +{ + int minlen = sc_min( nbits, v.length() ); + int i = 0; + for( ; i < minlen; ++ i ) { + safe_set( i, sc_logic( v.get_bit( i ) ).to_bool(), digit ); + } + for( ; i < nbits; ++ i ) { + safe_set( i, 0, digit ); // zero-extend + } + convert_2C_to_SM(); + return *this; +} + + +// explicit conversion to character string + +const std::string +sc_unsigned::to_string( sc_numrep numrep ) const +{ + int len = length(); + sc_ufix aa( *this, len, len, SC_TRN, SC_WRAP, 0, SC_ON ); + return aa.to_string( numrep ); +} + +const std::string +sc_unsigned::to_string( sc_numrep numrep, bool w_prefix ) const +{ + int len = length(); + sc_ufix aa( *this, len, len, SC_TRN, SC_WRAP, 0, SC_ON ); + return aa.to_string( numrep, w_prefix ); +} + + +// ---------------------------------------------------------------------------- +// SECTION: Interfacing with sc_int_base +// ---------------------------------------------------------------------------- + +const sc_unsigned& +sc_unsigned::operator= (const sc_int_base& v) +{ return operator=((int64) v); } + +const sc_unsigned& +sc_unsigned::operator+=(const sc_int_base& v) +{ return operator+=((int64) v); } + +const sc_unsigned& +sc_unsigned::operator-=(const sc_int_base& v) +{ return operator-=((int64) v); } + +const sc_unsigned& +sc_unsigned::operator*=(const sc_int_base& v) +{ return operator*=((int64) v); } + +const sc_unsigned& +sc_unsigned::operator/=(const sc_int_base& v) +{ return operator/=((int64) v); } + +const sc_unsigned& +sc_unsigned::operator%=(const sc_int_base& v) +{ return operator%=((int64) v); } + +const sc_unsigned& +sc_unsigned::operator&=(const sc_int_base& v) +{ return operator&=((int64) v); } + +const sc_unsigned& +sc_unsigned::operator|=(const sc_int_base& v) +{ return operator|=((int64) v); } + +const sc_unsigned& +sc_unsigned::operator^=(const sc_int_base& v) +{ return operator^=((int64) v); } + +sc_unsigned +operator<<(const sc_unsigned& u, const sc_int_base& v) +{ return operator<<(u, (int64) v); } +const sc_unsigned& +sc_unsigned::operator<<=(const sc_int_base& v) +{ return operator<<=((int64) v); } + +sc_unsigned +operator>>(const sc_unsigned& u, const sc_int_base& v) +{ return operator>>(u, (int64) v); } +const sc_unsigned& +sc_unsigned::operator>>=(const sc_int_base& v) +{ return operator>>=((int64) v); } + +bool +operator==(const sc_unsigned& u, const sc_int_base& v) +{ return operator==(u, (int64) v); } +bool +operator==(const sc_int_base& u, const sc_unsigned& v) +{ return operator==((int64) u, v); } + +bool +operator!=(const sc_unsigned& u, const sc_int_base& v) +{ return operator!=(u, (int64) v); } +bool +operator!=(const sc_int_base& u, const sc_unsigned& v) +{ return operator!=((int64) u, v); } + +bool +operator<(const sc_unsigned& u, const sc_int_base& v) +{ return operator<(u, (int64) v); } +bool +operator<(const sc_int_base& u, const sc_unsigned& v) +{ return operator<((int64) u, v); } + +bool +operator<=(const sc_unsigned& u, const sc_int_base& v) +{ return operator<=(u, (int64) v); } +bool +operator<=(const sc_int_base& u, const sc_unsigned& v) +{ return operator<=((int64) u, v); } + +bool +operator>(const sc_unsigned& u, const sc_int_base& v) +{ return operator>(u, (int64) v); } +bool +operator>(const sc_int_base& u, const sc_unsigned& v) +{ return operator>((int64) u, v); } + +bool +operator>=(const sc_unsigned& u, const sc_int_base& v) +{ return operator>=(u, (int64) v); } +bool +operator>=(const sc_int_base& u, const sc_unsigned& v) +{ return operator>=((int64) u, v); } + + +// ---------------------------------------------------------------------------- +// SECTION: Interfacing with sc_uint_base +// ---------------------------------------------------------------------------- + +const sc_unsigned& +sc_unsigned::operator= (const sc_uint_base& v) +{ return operator=((uint64) v); } + +sc_unsigned +operator+(const sc_unsigned& u, const sc_uint_base& v) +{ return operator+(u, (uint64) v); } +sc_unsigned +operator+(const sc_uint_base& u, const sc_unsigned& v) +{ return operator+((uint64) u, v); } +const sc_unsigned& +sc_unsigned::operator+=(const sc_uint_base& v) +{ return operator+=((uint64) v); } + +const sc_unsigned& +sc_unsigned::operator-=(const sc_uint_base& v) +{ return operator-=((uint64) v); } + +sc_unsigned +operator*(const sc_unsigned& u, const sc_uint_base& v) +{ return operator*(u, (uint64) v); } +sc_unsigned +operator*(const sc_uint_base& u, const sc_unsigned& v) +{ return operator*((uint64) u, v); } +const sc_unsigned& +sc_unsigned::operator*=(const sc_uint_base& v) +{ return operator*=((uint64) v); } + +sc_unsigned +operator/(const sc_unsigned& u, const sc_uint_base& v) +{ return operator/(u, (uint64) v); } +sc_unsigned +operator/(const sc_uint_base& u, const sc_unsigned& v) +{ return operator/((uint64) u, v); } +const sc_unsigned& +sc_unsigned::operator/=(const sc_uint_base& v) +{ return operator/=((uint64) v); } + +sc_unsigned +operator%(const sc_unsigned& u, const sc_uint_base& v) +{ return operator%(u, (uint64) v); } +sc_unsigned +operator%(const sc_uint_base& u, const sc_unsigned& v) +{ return operator%((uint64) u, v); } +const sc_unsigned& +sc_unsigned::operator%=(const sc_uint_base& v) +{ return operator%=((uint64) v); } + +sc_unsigned +operator&(const sc_unsigned& u, const sc_uint_base& v) +{ return operator&(u, (uint64) v); } +sc_unsigned +operator&(const sc_uint_base& u, const sc_unsigned& v) +{ return operator&((uint64) u, v); } +const sc_unsigned& +sc_unsigned::operator&=(const sc_uint_base& v) +{ return operator&=((uint64) v); } + +sc_unsigned +operator|(const sc_unsigned& u, const sc_uint_base& v) +{ return operator|(u, (uint64) v); } +sc_unsigned +operator|(const sc_uint_base& u, const sc_unsigned& v) +{ return operator|((uint64) u, v); } +const sc_unsigned& +sc_unsigned::operator|=(const sc_uint_base& v) +{ return operator|=((uint64) v); } + +sc_unsigned +operator^(const sc_unsigned& u, const sc_uint_base& v) +{ return operator^(u, (uint64) v); } +sc_unsigned +operator^(const sc_uint_base& u, const sc_unsigned& v) +{ return operator^((uint64) u, v); } +const sc_unsigned& +sc_unsigned::operator^=(const sc_uint_base& v) +{ return operator^=((uint64) v); } + +sc_unsigned +operator<<(const sc_unsigned& u, const sc_uint_base& v) +{ return operator<<(u, (uint64) v); } +const sc_unsigned& +sc_unsigned::operator<<=(const sc_uint_base& v) +{ return operator<<=((uint64) v); } + +sc_unsigned +operator>>(const sc_unsigned& u, const sc_uint_base& v) +{ return operator>>(u, (uint64) v); } +const sc_unsigned& +sc_unsigned::operator>>=(const sc_uint_base& v) +{ return operator>>=((uint64) v); } + +bool +operator==(const sc_unsigned& u, const sc_uint_base& v) +{ return operator==(u, (uint64) v); } +bool +operator==(const sc_uint_base& u, const sc_unsigned& v) +{ return operator==((uint64) u, v); } + +bool +operator!=(const sc_unsigned& u, const sc_uint_base& v) +{ return operator!=(u, (uint64) v); } +bool +operator!=(const sc_uint_base& u, const sc_unsigned& v) +{ return operator!=((uint64) u, v); } + +bool +operator<(const sc_unsigned& u, const sc_uint_base& v) +{ return operator<(u, (uint64) v); } +bool +operator<(const sc_uint_base& u, const sc_unsigned& v) +{ return operator<((uint64) u, v); } + +bool +operator<=(const sc_unsigned& u, const sc_uint_base& v) +{ return operator<=(u, (uint64) v); } +bool +operator<=(const sc_uint_base& u, const sc_unsigned& v) +{ return operator<=((uint64) u, v); } + +bool +operator>(const sc_unsigned& u, const sc_uint_base& v) +{ return operator>(u, (uint64) v); } +bool +operator>(const sc_uint_base& u, const sc_unsigned& v) +{ return operator>((uint64) u, v); } + +bool +operator>=(const sc_unsigned& u, const sc_uint_base& v) +{ return operator>=(u, (uint64) v); } +bool +operator>=(const sc_uint_base& u, const sc_unsigned& v) +{ return operator>=((uint64) u, v); } + + +// ---------------------------------------------------------------------------- +// SECTION: Input and output operators +// ---------------------------------------------------------------------------- + +// The operators in this section are included from sc_nbcommon.cpp. + + +// ---------------------------------------------------------------------------- +// SECTION: Operator macros. +// ---------------------------------------------------------------------------- + +#define CONVERT_LONG(u) \ +small_type u ## s = get_sign(u); \ +sc_digit u ## d[DIGITS_PER_ULONG]; \ +from_uint(DIGITS_PER_ULONG, u ## d, (unsigned long) u); + +#define CONVERT_LONG_2(u) \ +sc_digit u ## d[DIGITS_PER_ULONG]; \ +from_uint(DIGITS_PER_ULONG, u ## d, (unsigned long) u); + +#define CONVERT_INT(u) \ +small_type u ## s = get_sign(u); \ +sc_digit u ## d[DIGITS_PER_UINT]; \ +from_uint(DIGITS_PER_UINT, u ## d, (unsigned int) u); + +#define CONVERT_INT_2(u) \ +sc_digit u ## d[DIGITS_PER_UINT]; \ +from_uint(DIGITS_PER_UINT, u ## d, (unsigned int) u); + +#define CONVERT_INT64(u) \ +small_type u ## s = get_sign(u); \ +sc_digit u ## d[DIGITS_PER_UINT64]; \ +from_uint(DIGITS_PER_UINT64, u ## d, (uint64) u); + +#define CONVERT_INT64_2(u) \ +sc_digit u ## d[DIGITS_PER_UINT64]; \ +from_uint(DIGITS_PER_UINT64, u ## d, (uint64) u); + + +// ---------------------------------------------------------------------------- +// SECTION: PLUS operators: +, +=, ++ +// ---------------------------------------------------------------------------- + +// Cases to consider when computing u + v: +// 1. 0 + v = v +// 2. u + 0 = u +// 3. if sgn(u) == sgn(v) +// 3.1 u + v = +(u + v) = sgn(u) * (u + v) +// 3.2 (-u) + (-v) = -(u + v) = sgn(u) * (u + v) +// 4. if sgn(u) != sgn(v) +// 4.1 u + (-v) = u - v = sgn(u) * (u - v) +// 4.2 (-u) + v = -(u - v) ==> sgn(u) * (u - v) +// +// Specialization of above cases for computing ++u or u++: +// 1. 0 + 1 = 1 +// 3. u + 1 = u + 1 = sgn(u) * (u + 1) +// 4. (-u) + 1 = -(u - 1) = sgn(u) * (u - 1) + +sc_unsigned +operator+(const sc_unsigned& u, const sc_unsigned& v) +{ + + if (u.sgn == SC_ZERO) // case 1 + return sc_unsigned(v); + + if (v.sgn == SC_ZERO) // case 2 + return sc_unsigned(u); + + // cases 3 and 4 + return add_unsigned_friend(u.sgn, u.nbits, u.ndigits, u.digit, + v.sgn, v.nbits, v.ndigits, v.digit); + +} + + +sc_unsigned +operator+(const sc_unsigned &u, uint64 v) +{ + + if (v == 0) // case 2 + return sc_unsigned(u); + + CONVERT_INT64(v); + + if (u.sgn == SC_ZERO) // case 1 + return sc_unsigned(vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd, false); + + // cases 3 and 4 + return add_unsigned_friend(u.sgn, u.nbits, u.ndigits, u.digit, + vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd); + +} + + +sc_unsigned +operator+(uint64 u, const sc_unsigned &v) +{ + + if (u == 0) // case 1 + return sc_unsigned(v); + + CONVERT_INT64(u); + + if (v.sgn == SC_ZERO) // case 2 + return sc_unsigned(us, BITS_PER_UINT64, DIGITS_PER_UINT64, ud, false); + + // cases 3 and 4 + + return add_unsigned_friend(us, BITS_PER_UINT64, DIGITS_PER_UINT64, ud, + v.sgn, v.nbits, v.ndigits, v.digit); + +} + + +sc_unsigned +operator+(const sc_unsigned &u, unsigned long v) +{ + + if (v == 0) // case 2 + return sc_unsigned(u); + + CONVERT_LONG(v); + + if (u.sgn == SC_ZERO) // case 1 + return sc_unsigned(vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd, false); + + // cases 3 and 4 + return add_unsigned_friend(u.sgn, u.nbits, u.ndigits, u.digit, + vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd); + +} + + +sc_unsigned +operator+(unsigned long u, const sc_unsigned &v) +{ + + if (u == 0) // case 1 + return sc_unsigned(v); + + CONVERT_LONG(u); + + if (v.sgn == SC_ZERO) // case 2 + return sc_unsigned(us, BITS_PER_ULONG, DIGITS_PER_ULONG, ud, false); + + // cases 3 and 4 + return add_unsigned_friend(us, BITS_PER_ULONG, DIGITS_PER_ULONG, ud, + v.sgn, v.nbits, v.ndigits, v.digit); + +} + +// The rest of the operators in this section are included from +// sc_nbcommon.cpp. + + +// ---------------------------------------------------------------------------- +// SECTION: MINUS operators: -, -=, -- +// ---------------------------------------------------------------------------- + +// Cases to consider when computing u + v: +// 1. u - 0 = u +// 2. 0 - v = -v +// 3. if sgn(u) != sgn(v) +// 3.1 u - (-v) = u + v = sgn(u) * (u + v) +// 3.2 (-u) - v = -(u + v) ==> sgn(u) * (u + v) +// 4. if sgn(u) == sgn(v) +// 4.1 u - v = +(u - v) = sgn(u) * (u - v) +// 4.2 (-u) - (-v) = -(u - v) = sgn(u) * (u - v) +// +// Specialization of above cases for computing --u or u--: +// 1. 0 - 1 = -1 +// 3. (-u) - 1 = -(u + 1) = sgn(u) * (u + 1) +// 4. u - 1 = u - 1 = sgn(u) * (u - 1) + +// The operators in this section are included from sc_nbcommon.cpp. + + +// ---------------------------------------------------------------------------- +// SECTION: MULTIPLICATION operators: *, *= +// ---------------------------------------------------------------------------- + +// Cases to consider when computing u * v: +// 1. u * 0 = 0 * v = 0 +// 2. 1 * v = v and -1 * v = -v +// 3. u * 1 = u and u * -1 = -u +// 4. u * v = u * v + +sc_unsigned +operator*(const sc_unsigned& u, const sc_unsigned& v) +{ + + small_type s = mul_signs(u.sgn, v.sgn); + + if (s == SC_ZERO) // case 1 + return sc_unsigned(); + + // cases 2-4 + return mul_unsigned_friend(s, u.nbits, u.ndigits, u.digit, + v.nbits, v.ndigits, v.digit); + +} + + +sc_unsigned +operator*(const sc_unsigned& u, uint64 v) +{ + + small_type s = mul_signs(u.sgn, get_sign(v)); + + if (s == SC_ZERO) // case 1 + return sc_unsigned(); + + CONVERT_INT64_2(v); + + // cases 2-4 + return mul_unsigned_friend(s, u.nbits, u.ndigits, u.digit, + BITS_PER_UINT64, DIGITS_PER_UINT64, vd); + +} + + +sc_unsigned +operator*(uint64 u, const sc_unsigned& v) +{ + + small_type s = mul_signs(v.sgn, get_sign(u)); + + if (s == SC_ZERO) // case 1 + return sc_unsigned(); + + CONVERT_INT64_2(u); + + // cases 2-4 + return mul_unsigned_friend(s, BITS_PER_UINT64, DIGITS_PER_UINT64, ud, + v.nbits, v.ndigits, v.digit); + +} + + +sc_unsigned +operator*(const sc_unsigned& u, unsigned long v) +{ + + small_type s = mul_signs(u.sgn, get_sign(v)); + + if (s == SC_ZERO) // case 1 + return sc_unsigned(); + + CONVERT_LONG_2(v); + + // else cases 2-4 + return mul_unsigned_friend(s, u.nbits, u.ndigits, u.digit, + BITS_PER_ULONG, DIGITS_PER_ULONG, vd); + +} + +sc_unsigned +operator*(unsigned long u, const sc_unsigned& v) +{ + + small_type s = mul_signs(v.sgn, get_sign(u)); + + if (s == SC_ZERO) // case 1 + return sc_unsigned(); + + CONVERT_LONG_2(u); + + // cases 2-4 + return mul_unsigned_friend(s, BITS_PER_ULONG, DIGITS_PER_ULONG, ud, + v.nbits, v.ndigits, v.digit); + +} + +// The rest of the operators in this section are included from +// sc_nbcommon.cpp. + + +// ---------------------------------------------------------------------------- +// SECTION: DIVISION operators: /, /= +// ---------------------------------------------------------------------------- + +// Cases to consider when finding the quotient q = floor(u/v): +// Note that u = q * v + r for r < q. +// 1. 0 / 0 or u / 0 => error +// 2. 0 / v => 0 = 0 * v + 0 +// 3. u / v && u = v => u = 1 * u + 0 - u or v can be 1 or -1 +// 4. u / v && u < v => u = 0 * v + u - u can be 1 or -1 +// 5. u / v && u > v => u = q * v + r - v can be 1 or -1 + +sc_unsigned +operator/(const sc_unsigned& u, const sc_unsigned& v) +{ + + small_type s = mul_signs(u.sgn, v.sgn); + + if (s == SC_ZERO) { + div_by_zero(v.sgn); // case 1 + return sc_unsigned(); // case 2 + } + + // other cases + return div_unsigned_friend(s, u.nbits, u.ndigits, u.digit, + v.nbits, v.ndigits, v.digit); + +} + + +sc_unsigned +operator/(const sc_unsigned& u, uint64 v) +{ + + small_type s = mul_signs(u.sgn, get_sign(v)); + + if (s == SC_ZERO) { + div_by_zero(v); // case 1 + return sc_unsigned(); // case 2 + } + + CONVERT_INT64_2(v); + + // other cases + return div_unsigned_friend(s, u.nbits, u.ndigits, u.digit, + BITS_PER_UINT64, DIGITS_PER_UINT64, vd); + +} + + +sc_unsigned +operator/(uint64 u, const sc_unsigned& v) +{ + + small_type s = mul_signs(v.sgn, get_sign(u)); + + if (s == SC_ZERO) { + div_by_zero(v.sgn); // case 1 + return sc_unsigned(); // case 2 + + } + + CONVERT_INT64_2(u); + + // other cases + return div_unsigned_friend(s, BITS_PER_UINT64, DIGITS_PER_UINT64, ud, + v.nbits, v.ndigits, v.digit); + +} + + +sc_unsigned +operator/(const sc_unsigned& u, unsigned long v) +{ + + small_type s = mul_signs(u.sgn, get_sign(v)); + + if (s == SC_ZERO) { + div_by_zero(v); // case 1 + return sc_unsigned(); // case 2 + } + + CONVERT_LONG_2(v); + + // other cases + return div_unsigned_friend(s, u.nbits, u.ndigits, u.digit, + BITS_PER_ULONG, DIGITS_PER_ULONG, vd); + +} + + +sc_unsigned +operator/(unsigned long u, const sc_unsigned& v) +{ + + small_type s = mul_signs(v.sgn, get_sign(u)); + + if (s == SC_ZERO) { + div_by_zero(v.sgn); // case 1 + return sc_unsigned(); // case 2 + + } + + CONVERT_LONG_2(u); + + // other cases + return div_unsigned_friend(s, BITS_PER_ULONG, DIGITS_PER_ULONG, ud, + v.nbits, v.ndigits, v.digit); + +} + +// The rest of the operators in this section are included from +// sc_nbcommon.cpp. + + +// ---------------------------------------------------------------------------- +// SECTION: MOD operators: %, %=. +// ---------------------------------------------------------------------------- + +// Cases to consider when finding the remainder r = u % v: +// Note that u = q * v + r for r < q. +// 1. 0 % 0 or u % 0 => error +// 2. 0 % v => 0 = 0 * v + 0 +// 3. u % v && u = v => u = 1 * u + 0 - u or v can be 1 or -1 +// 4. u % v && u < v => u = 0 * v + u - u can be 1 or -1 +// 5. u % v && u > v => u = q * v + r - v can be 1 or -1 + +sc_unsigned +operator%(const sc_unsigned& u, const sc_unsigned& v) +{ + + if ((u.sgn == SC_ZERO) || (v.sgn == SC_ZERO)) { + div_by_zero(v.sgn); // case 1 + return sc_unsigned(); // case 2 + } + + // other cases + return mod_unsigned_friend(u.sgn, u.nbits, u.ndigits, u.digit, + v.nbits, v.ndigits, v.digit); +} + + +sc_unsigned +operator%(const sc_unsigned& u, uint64 v) +{ + + if ((u.sgn == SC_ZERO) || (v == 0)) { + div_by_zero(v); // case 1 + return sc_unsigned(); // case 2 + } + + CONVERT_INT64_2(v); + + // other cases + return mod_unsigned_friend(u.sgn, u.nbits, u.ndigits, u.digit, + BITS_PER_UINT64, DIGITS_PER_UINT64, vd); + +} + + +sc_unsigned +operator%(uint64 u, const sc_unsigned& v) +{ + + if ((u == 0) || (v.sgn == SC_ZERO)) { + div_by_zero(v.sgn); // case 1 + return sc_unsigned(); // case 2 + } + + CONVERT_INT64(u); + + // other cases + return mod_unsigned_friend(us, BITS_PER_UINT64, DIGITS_PER_UINT64, ud, + v.nbits, v.ndigits, v.digit); + +} + + +sc_unsigned +operator%(const sc_unsigned& u, unsigned long v) +{ + + if ((u.sgn == SC_ZERO) || (v == 0)) { + div_by_zero(v); // case 1 + return sc_unsigned(); // case 2 + } + + CONVERT_LONG_2(v); + + // other cases + return mod_unsigned_friend(u.sgn, u.nbits, u.ndigits, u.digit, + BITS_PER_ULONG, DIGITS_PER_ULONG, vd); + +} + + +sc_unsigned +operator%(unsigned long u, const sc_unsigned& v) +{ + + if ((u == 0) || (v.sgn == SC_ZERO)) { + div_by_zero(v.sgn); // case 1 + return sc_unsigned(); // case 2 + } + + CONVERT_LONG(u); + + // other cases + return mod_unsigned_friend(us, BITS_PER_ULONG, DIGITS_PER_ULONG, ud, + v.nbits, v.ndigits, v.digit); + +} + +// The rest of the operators in this section are included from +// sc_nbcommon.cpp. + + +// ---------------------------------------------------------------------------- +// SECTION: Bitwise AND operators: &, &= +// ---------------------------------------------------------------------------- + +// Cases to consider when computing u & v: +// 1. u & 0 = 0 & v = 0 +// 2. u & v => sgn = + +// 3. (-u) & (-v) => sgn = - +// 4. u & (-v) => sgn = + +// 5. (-u) & v => sgn = + + +sc_unsigned +operator&(const sc_unsigned& u, const sc_unsigned& v) +{ + + if ((u.sgn == SC_ZERO) || (v.sgn == SC_ZERO)) // case 1 + return sc_unsigned(); + + // other cases + return and_unsigned_friend(u.sgn, u.nbits, u.ndigits, u.digit, + v.sgn, v.nbits, v.ndigits, v.digit); + +} + + +sc_unsigned +operator&(const sc_unsigned& u, uint64 v) +{ + + if ((u.sgn == SC_ZERO) || (v == 0)) // case 1 + return sc_unsigned(); + + CONVERT_INT64(v); + + // other cases + return and_unsigned_friend(u.sgn, u.nbits, u.ndigits, u.digit, + vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd); + +} + + +sc_unsigned +operator&(uint64 u, const sc_unsigned& v) +{ + + if ((u == 0) || (v.sgn == SC_ZERO)) // case 1 + return sc_unsigned(); + + CONVERT_INT64(u); + + // other cases + return and_unsigned_friend(us, BITS_PER_UINT64, DIGITS_PER_UINT64, ud, + v.sgn, v.nbits, v.ndigits, v.digit); + +} + + +sc_unsigned +operator&(const sc_unsigned& u, unsigned long v) +{ + + if ((u.sgn == SC_ZERO) || (v == 0)) // case 1 + return sc_unsigned(); + + CONVERT_LONG(v); + + // other cases + return and_unsigned_friend(u.sgn, u.nbits, u.ndigits, u.digit, + vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd); + +} + + +sc_unsigned +operator&(unsigned long u, const sc_unsigned& v) +{ + + if ((u == 0) || (v.sgn == SC_ZERO)) // case 1 + return sc_unsigned(); + + CONVERT_LONG(u); + + // other cases + return and_unsigned_friend(us, BITS_PER_ULONG, DIGITS_PER_ULONG, ud, + v.sgn, v.nbits, v.ndigits, v.digit); + +} + +// The rest of the operators in this section are included from +// sc_nbcommon.cpp. + + +// ---------------------------------------------------------------------------- +// SECTION: Bitwise OR operators: |, |= +// ---------------------------------------------------------------------------- + +// Cases to consider when computing u | v: +// 1. u | 0 = u +// 2. 0 | v = v +// 3. u | v => sgn = + +// 4. (-u) | (-v) => sgn = - +// 5. u | (-v) => sgn = - +// 6. (-u) | v => sgn = - + +sc_unsigned +operator|(const sc_unsigned& u, const sc_unsigned& v) +{ + + if (v.sgn == SC_ZERO) // case 1 + return sc_unsigned(u); + + if (u.sgn == SC_ZERO) // case 2 + return sc_unsigned(v); + + // other cases + return or_unsigned_friend(u.sgn, u.nbits, u.ndigits, u.digit, + v.sgn, v.nbits, v.ndigits, v.digit); + +} + + +sc_unsigned +operator|(const sc_unsigned& u, uint64 v) +{ + + if (v == 0) // case 1 + return sc_unsigned(u); + + CONVERT_INT64(v); + + if (u.sgn == SC_ZERO) // case 2 + return sc_unsigned(vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd, false); + + // other cases + return or_unsigned_friend(u.sgn, u.nbits, u.ndigits, u.digit, + vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd); + +} + + +sc_unsigned +operator|(uint64 u, const sc_unsigned& v) +{ + + if (u == 0) + return sc_unsigned(v); + + CONVERT_INT64(u); + + if (v.sgn == SC_ZERO) + return sc_unsigned(us, BITS_PER_UINT64, DIGITS_PER_UINT64, ud, false); + + // other cases + return or_unsigned_friend(us, BITS_PER_UINT64, DIGITS_PER_UINT64, ud, + v.sgn, v.nbits, v.ndigits, v.digit); + +} + + +sc_unsigned +operator|(const sc_unsigned& u, unsigned long v) +{ + + if (v == 0) // case 1 + return sc_unsigned(u); + + CONVERT_LONG(v); + + if (u.sgn == SC_ZERO) // case 2 + return sc_unsigned(vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd, false); + + // other cases + return or_unsigned_friend(u.sgn, u.nbits, u.ndigits, u.digit, + vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd); + +} + + +sc_unsigned +operator|(unsigned long u, const sc_unsigned& v) +{ + + if (u == 0) + return sc_unsigned(v); + + CONVERT_LONG(u); + + if (v.sgn == SC_ZERO) + return sc_unsigned(us, BITS_PER_ULONG, DIGITS_PER_ULONG, ud, false); + + // other cases + return or_unsigned_friend(us, BITS_PER_ULONG, DIGITS_PER_ULONG, ud, + v.sgn, v.nbits, v.ndigits, v.digit); + +} + +// The rest of the operators in this section are included from +// sc_nbcommon.cpp. + + +// ---------------------------------------------------------------------------- +// SECTION: Bitwise XOR operators: ^, ^= +// ---------------------------------------------------------------------------- + +// Cases to consider when computing u ^ v: +// Note that u ^ v = (~u & v) | (u & ~v). +// 1. u ^ 0 = u +// 2. 0 ^ v = v +// 3. u ^ v => sgn = + +// 4. (-u) ^ (-v) => sgn = - +// 5. u ^ (-v) => sgn = - +// 6. (-u) ^ v => sgn = + + +sc_unsigned +operator^(const sc_unsigned& u, const sc_unsigned& v) +{ + + if (v.sgn == SC_ZERO) // case 1 + return sc_unsigned(u); + + if (u.sgn == SC_ZERO) // case 2 + return sc_unsigned(v); + + // other cases + return xor_unsigned_friend(u.sgn, u.nbits, u.ndigits, u.digit, + v.sgn, v.nbits, v.ndigits, v.digit); + +} + + +sc_unsigned +operator^(const sc_unsigned& u, uint64 v) +{ + + if (v == 0) // case 1 + return sc_unsigned(u); + + CONVERT_INT64(v); + + if (u.sgn == SC_ZERO) // case 2 + return sc_unsigned(vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd, false); + + // other cases + return xor_unsigned_friend(u.sgn, u.nbits, u.ndigits, u.digit, + vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd); + +} + +sc_unsigned +operator^(uint64 u, const sc_unsigned& v) +{ + if (u == 0) + return sc_unsigned(v); + + CONVERT_INT64(u); + + if (v.sgn == SC_ZERO) + return sc_unsigned(us, BITS_PER_UINT64, DIGITS_PER_UINT64, ud, false); + + // other cases + return xor_unsigned_friend(us, BITS_PER_UINT64, DIGITS_PER_UINT64, ud, + v.sgn, v.nbits, v.ndigits, v.digit); + +} + + +sc_unsigned +operator^(const sc_unsigned& u, unsigned long v) +{ + + if (v == 0) // case 1 + return sc_unsigned(u); + + CONVERT_LONG(v); + + if (u.sgn == SC_ZERO) // case 2 + return sc_unsigned(vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd, false); + + // other cases + return xor_unsigned_friend(u.sgn, u.nbits, u.ndigits, u.digit, + vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd); + +} + +sc_unsigned +operator^(unsigned long u, const sc_unsigned& v) +{ + if (u == 0) + return sc_unsigned(v); + + CONVERT_LONG(u); + + if (v.sgn == SC_ZERO) + return sc_unsigned(us, BITS_PER_ULONG, DIGITS_PER_ULONG, ud, false); + + // other cases + return xor_unsigned_friend(us, BITS_PER_ULONG, DIGITS_PER_ULONG, ud, + v.sgn, v.nbits, v.ndigits, v.digit); + +} + +// The rest of the operators in this section are included from +// sc_nbcommon.cpp. + + +// ---------------------------------------------------------------------------- +// SECTION: Bitwise NOT operator: ~ +// ---------------------------------------------------------------------------- + +// Operators in this section are included from sc_nbcommon.cpp. + + +// ---------------------------------------------------------------------------- +// SECTION: LEFT SHIFT operators: <<, <<= +// ---------------------------------------------------------------------------- + +sc_unsigned +operator<<(const sc_unsigned& u, const sc_signed& v) +{ + if ((v.sgn == SC_ZERO) || (v.sgn == SC_NEG)) + return sc_unsigned(u); + + return operator<<(u, v.to_ulong()); +} + +// The rest of the operators in this section are included from +// sc_nbcommon.cpp. + + +// ---------------------------------------------------------------------------- +// SECTION: RIGHT SHIFT operators: >>, >>= +// ---------------------------------------------------------------------------- + +sc_unsigned +operator>>(const sc_unsigned& u, const sc_signed& v) +{ + + if ((v.sgn == SC_ZERO) || (v.sgn == SC_NEG)) + return sc_unsigned(u); + + return operator>>(u, v.to_long()); + +} + +// The rest of the operators in this section are included from +// sc_nbcommon.cpp. + + +// ---------------------------------------------------------------------------- +// SECTION: Unary arithmetic operators. +// ---------------------------------------------------------------------------- + +sc_unsigned +operator+(const sc_unsigned& u) +{ + return sc_unsigned(u); +} + + +// ---------------------------------------------------------------------------- +// SECTION: EQUAL operator: == +// ---------------------------------------------------------------------------- + +bool +operator==(const sc_unsigned& u, const sc_unsigned& v) +{ + if (&u == &v) + return true; + if (compare_unsigned(u.sgn, u.nbits, u.ndigits, u.digit, + v.sgn, v.nbits, v.ndigits, v.digit) != 0) + return false; + return true; +} + + +bool +operator==(const sc_unsigned& u, const sc_signed& v) +{ + if (v.sgn == SC_NEG) + return false; + if (compare_unsigned(u.sgn, u.nbits, u.ndigits, u.digit, + v.sgn, v.nbits, v.ndigits, v.digit, 0, 1) != 0) + return false; + return true; +} + + +bool +operator==(const sc_signed& u, const sc_unsigned& v) +{ + if (u.sgn == SC_NEG) + return false; + if (compare_unsigned(u.sgn, u.nbits, u.ndigits, u.digit, + v.sgn, v.nbits, v.ndigits, v.digit, 1, 0) != 0) + return false; + return true; +} + + +bool +operator==(const sc_unsigned& u, int64 v) +{ + if (v < 0) + return false; + CONVERT_INT64(v); + if (compare_unsigned(u.sgn, u.nbits, u.ndigits, u.digit, + vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd) != 0) + return false; + return true; +} + + +bool +operator==(int64 u, const sc_unsigned& v) +{ + if (u < 0) + return false; + CONVERT_INT64(u); + if (compare_unsigned(us, BITS_PER_UINT64, DIGITS_PER_UINT64, ud, + v.sgn, v.nbits, v.ndigits, v.digit) != 0) + return false; + return true; +} + + +bool +operator==(const sc_unsigned& u, uint64 v) +{ + CONVERT_INT64(v); + if (compare_unsigned(u.sgn, u.nbits, u.ndigits, u.digit, + vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd) != 0) + return false; + return true; +} + + +bool +operator==(uint64 u, const sc_unsigned& v) +{ + CONVERT_INT64(u); + if (compare_unsigned(us, BITS_PER_UINT64, DIGITS_PER_UINT64, ud, + v.sgn, v.nbits, v.ndigits, v.digit) != 0) + return false; + return true; +} + + +bool +operator==(const sc_unsigned& u, long v) +{ + if (v < 0) + return false; + CONVERT_LONG(v); + if (compare_unsigned(u.sgn, u.nbits, u.ndigits, u.digit, + vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd) != 0) + return false; + return true; +} + + +bool +operator==(long u, const sc_unsigned& v) +{ + if (u < 0) + return false; + CONVERT_LONG(u); + if (compare_unsigned(us, BITS_PER_ULONG, DIGITS_PER_ULONG, ud, + v.sgn, v.nbits, v.ndigits, v.digit) != 0) + return false; + return true; +} + + +bool +operator==(const sc_unsigned& u, unsigned long v) +{ + CONVERT_LONG(v); + if (compare_unsigned(u.sgn, u.nbits, u.ndigits, u.digit, + vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd) != 0) + return false; + return true; +} + + +bool +operator==(unsigned long u, const sc_unsigned& v) +{ + CONVERT_LONG(u); + if (compare_unsigned(us, BITS_PER_ULONG, DIGITS_PER_ULONG, ud, + v.sgn, v.nbits, v.ndigits, v.digit) != 0) + return false; + return true; +} + + +// ---------------------------------------------------------------------------- +// SECTION: NOT_EQUAL operator: != +// ---------------------------------------------------------------------------- + +bool +operator!=(const sc_unsigned& u, const sc_signed& v) +{ + return (! operator==(u, v)); +} + + +bool +operator!=(const sc_signed& u, const sc_unsigned& v) +{ + return (! operator==(u, v)); +} + +// The rest of the operators in this section are included from sc_nbcommon.cpp. + + +// ---------------------------------------------------------------------------- +// SECTION: LESS THAN operator: < +// ---------------------------------------------------------------------------- + +bool +operator<(const sc_unsigned& u, const sc_unsigned& v) +{ + if (&u == &v) + return false; + if (compare_unsigned(u.sgn, u.nbits, u.ndigits, u.digit, + v.sgn, v.nbits, v.ndigits, v.digit) < 0) + return true; + return false; +} + + +bool +operator<(const sc_unsigned& u, const sc_signed& v) +{ + if (v.sgn == SC_NEG) + return false; + if (compare_unsigned(u.sgn, u.nbits, u.ndigits, u.digit, + v.sgn, v.nbits, v.ndigits, v.digit, 0, 1) < 0) + return true; + return false; +} + + +bool +operator<(const sc_signed& u, const sc_unsigned& v) +{ + if (u.sgn == SC_NEG) + return true; + if (compare_unsigned(u.sgn, u.nbits, u.ndigits, u.digit, + v.sgn, v.nbits, v.ndigits, v.digit, 1, 0) < 0) + return true; + return false; +} + + +bool +operator<(const sc_unsigned& u, int64 v) +{ + if (v < 0) + return false; + CONVERT_INT64(v); + if (compare_unsigned(u.sgn, u.nbits, u.ndigits, u.digit, + vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd) < 0) + return true; + return false; +} + + +bool +operator<(int64 u, const sc_unsigned& v) +{ + if (u < 0) + return true; + CONVERT_INT64(u); + if (compare_unsigned(us, BITS_PER_UINT64, DIGITS_PER_UINT64, ud, + v.sgn, v.nbits, v.ndigits, v.digit) < 0) + return true; + return false; +} + + +bool +operator<(const sc_unsigned& u, uint64 v) +{ + CONVERT_INT64(v); + if (compare_unsigned(u.sgn, u.nbits, u.ndigits, u.digit, + vs, BITS_PER_UINT64, DIGITS_PER_UINT64, vd) < 0) + return true; + return false; +} + + +bool +operator<(uint64 u, const sc_unsigned& v) +{ + CONVERT_INT64(u); + if (compare_unsigned(us, BITS_PER_UINT64, DIGITS_PER_UINT64, ud, + v.sgn, v.nbits, v.ndigits, v.digit) < 0) + return true; + return false; +} + + +bool +operator<(const sc_unsigned& u, long v) +{ + if (v < 0) + return false; + CONVERT_LONG(v); + if (compare_unsigned(u.sgn, u.nbits, u.ndigits, u.digit, + vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd) < 0) + return true; + return false; +} + + +bool +operator<(long u, const sc_unsigned& v) +{ + if (u < 0) + return true; + CONVERT_LONG(u); + if (compare_unsigned(us, BITS_PER_ULONG, DIGITS_PER_ULONG, ud, + v.sgn, v.nbits, v.ndigits, v.digit) < 0) + return true; + return false; +} + + +bool +operator<(const sc_unsigned& u, unsigned long v) +{ + CONVERT_LONG(v); + if (compare_unsigned(u.sgn, u.nbits, u.ndigits, u.digit, + vs, BITS_PER_ULONG, DIGITS_PER_ULONG, vd) < 0) + return true; + return false; +} + + +bool +operator<(unsigned long u, const sc_unsigned& v) +{ + CONVERT_LONG(u); + if (compare_unsigned(us, BITS_PER_ULONG, DIGITS_PER_ULONG, ud, + v.sgn, v.nbits, v.ndigits, v.digit) < 0) + return true; + return false; +} + + +// ---------------------------------------------------------------------------- +// SECTION: LESS THAN or EQUAL operator: <= +// ---------------------------------------------------------------------------- + +bool +operator<=(const sc_unsigned& u, const sc_signed& v) +{ + return (operator<(u, v) || operator==(u, v)); +} + + +bool +operator<=(const sc_signed& u, const sc_unsigned& v) +{ + return (operator<(u, v) || operator==(u, v)); +} + +// The rest of the operators in this section are included from sc_nbcommon.cpp. + + +// ---------------------------------------------------------------------------- +// SECTION: GREATER THAN operator: > +// ---------------------------------------------------------------------------- + +bool +operator>(const sc_unsigned& u, const sc_signed& v) +{ + return (! (operator<=(u, v))); +} + + +bool +operator>(const sc_signed& u, const sc_unsigned& v) +{ + return (! (operator<=(u, v))); +} + +// The rest of the operators in this section are included from sc_nbcommon.cpp. + + +// ---------------------------------------------------------------------------- +// SECTION: GREATER THAN or EQUAL operator: >= +// ---------------------------------------------------------------------------- + +bool +operator>=(const sc_unsigned& u, const sc_signed& v) +{ + return (! (operator<(u, v))); +} + + +bool +operator>=(const sc_signed& u, const sc_unsigned& v) +{ + return (! (operator<(u, v))); +} + +// The rest of the operators in this section are included from sc_nbcommon.cpp. + + +// ---------------------------------------------------------------------------- +// SECTION: Friends +// ---------------------------------------------------------------------------- + +// Compare u and v as unsigned and return r +// r = 0 if u == v +// r < 0 if u < v +// r > 0 if u > v + +int +compare_unsigned(small_type us, + int unb, int und, const sc_digit *ud, + small_type vs, + int vnb, int vnd, const sc_digit *vd, + small_type if_u_signed, + small_type if_v_signed) +{ + + if (us == vs) { + + if (us == SC_ZERO) + return 0; + + else { + + int cmp_res = vec_skip_and_cmp(und, ud, vnd, vd); + + if (us == SC_POS) + return cmp_res; + else + return -cmp_res; + + } + } + else { + + if (us == SC_ZERO) + return -vs; + + if (vs == SC_ZERO) + return us; + + int cmp_res; + + int nd = (us == SC_NEG ? und : vnd); + +#ifdef SC_MAX_NBITS + sc_digit d[MAX_NDIGITS]; +#else + sc_digit *d = new sc_digit[nd]; +#endif + + if (us == SC_NEG) { + + vec_copy(nd, d, ud); + vec_complement(nd, d); + trim(if_u_signed, unb, nd, d); + cmp_res = vec_skip_and_cmp(nd, d, vnd, vd); + + } + else { + + vec_copy(nd, d, vd); + vec_complement(nd, d); + trim(if_v_signed, vnb, nd, d); + cmp_res = vec_skip_and_cmp(und, ud, nd, d); + + } + +#ifndef SC_MAX_NBITS + delete [] d; +#endif + + return cmp_res; + + } +} + + +// ---------------------------------------------------------------------------- +// SECTION: Public members - Other utils. +// ---------------------------------------------------------------------------- + +bool +sc_unsigned::iszero() const +{ + if (sgn == SC_ZERO) + return true; + + else if (sgn == SC_NEG) { + + // A negative unsigned number can be zero, e.g., -16 in 4 bits, so + // check that. + +#ifdef SC_MAX_NBITS + sc_digit d[MAX_NDIGITS]; +#else + sc_digit *d = new sc_digit[ndigits]; +#endif + + vec_copy(ndigits, d, digit); + vec_complement(ndigits, d); + trim_unsigned(nbits, ndigits, d); + + bool res = check_for_zero(ndigits, d); + +#ifndef SC_MAX_NBITS + delete [] d; +#endif + + return res; + + } + else + return false; +} + +// The rest of the utils in this section are included from sc_nbcommon.cpp. + + +// ---------------------------------------------------------------------------- +// SECTION: Private members. +// ---------------------------------------------------------------------------- + +// The private members in this section are included from +// sc_nbcommon.cpp. + +#define CLASS_TYPE sc_unsigned +#define CLASS_TYPE_STR "sc_unsigned" + +#define ADD_HELPER add_unsigned_friend +#define SUB_HELPER sub_unsigned_friend +#define MUL_HELPER mul_unsigned_friend +#define DIV_HELPER div_unsigned_friend +#define MOD_HELPER mod_unsigned_friend +#define AND_HELPER and_unsigned_friend +#define OR_HELPER or_unsigned_friend +#define XOR_HELPER xor_unsigned_friend + +#include "sc_nbfriends.inc" + +#undef SC_SIGNED +#define SC_UNSIGNED +#define IF_SC_SIGNED 0 // 0 = sc_unsigned +#define CLASS_TYPE_SUBREF sc_unsigned_subref_r +#define OTHER_CLASS_TYPE sc_signed +#define OTHER_CLASS_TYPE_SUBREF sc_signed_subref_r + +#define MUL_ON_HELPER mul_on_help_unsigned +#define DIV_ON_HELPER div_on_help_unsigned +#define MOD_ON_HELPER mod_on_help_unsigned + +#include "sc_nbcommon.inc" + +#undef MOD_ON_HELPER +#undef DIV_ON_HELPER +#undef MUL_ON_HELPER + +#undef OTHER_CLASS_TYPE_SUBREF +#undef OTHER_CLASS_TYPE +#undef CLASS_TYPE_SUBREF +#undef IF_SC_SIGNED +#undef SC_UNSIGNED + +#undef XOR_HELPER +#undef OR_HELPER +#undef AND_HELPER +#undef MOD_HELPER +#undef DIV_HELPER +#undef MUL_HELPER +#undef SUB_HELPER +#undef ADD_HELPER + +#undef CLASS_TYPE +#undef CLASS_TYPE_STR + +#include "sc_unsigned_bitref.inc" +#include "sc_unsigned_subref.inc" + +#undef CONVERT_LONG +#undef CONVERT_LONG_2 +#undef CONVERT_INT64 +#undef CONVERT_INT64_2 + +} // namespace sc_dt + + +// End of file. diff --git a/ext/systemc/src/sysc/datatypes/int/sc_unsigned.h b/ext/systemc/src/sysc/datatypes/int/sc_unsigned.h new file mode 100644 index 000000000..4260542a3 --- /dev/null +++ b/ext/systemc/src/sysc/datatypes/int/sc_unsigned.h @@ -0,0 +1,2191 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_unsigned.h -- Arbitrary precision unsigned arithmetic. + + This file includes the definitions of sc_unsigned_bitref, + sc_unsigned_subref, and sc_unsigned classes. The first two classes + are proxy classes to reference one bit and a range of bits of a + sc_unsigned number, respectively. + + An sc_signed number has the sign-magnitude representation + internally. However, its interface guarantees a 2's-complement + representation. The sign-magnitude representation is chosen + because of its efficiency: The sc_signed and sc_unsigned types are + optimized for arithmetic rather than bitwise operations. For + arithmetic operations, the sign-magnitude representation performs + better. + + It is also important to note that an sc_unsigned number with n + bits is equivalent to an sc_signed non-negative number with n + 1 + bits. + + The implementations of sc_signed and sc_unsigned classes are + almost identical: Most of the member and friend functions are + defined in sc_nbcommon.cpp and sc_nbfriends.cpp so that they can + be shared by both of these classes. These functions are chosed by + defining a few macros before including them such as IF_SC_SIGNED + and CLASS_TYPE. Our implementation choices are mostly dictated by + performance considerations in that we tried to provide the most + efficient sc_signed and sc_unsigned types without compromising + their interface. + + For the behavior of operators, we have two semantics: the old and + new. The most important difference between these two semantics is + that the old semantics is closer to C/C++ semantics in that the + result type of a binary operator on unsigned and signed arguments + is unsigned; the new semantics, on the other hand, requires the + result type be signed. The new semantics is required by the VSIA + C/C++ data types standard. We have implemented the new semantics. + + Original Author: Ali Dasdan, Synopsys, Inc. + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + +// $Log: sc_unsigned.h,v $ +// Revision 1.4 2011/08/24 22:05:46 acg +// Torsten Maehne: initialization changes to remove warnings. +// +// Revision 1.3 2011/02/18 20:19:15 acg +// Andy Goodrich: updating Copyright notice. +// +// Revision 1.2 2009/02/28 00:26:26 acg +// Andy Goodrich: bug fixes. +// +// Revision 1.1.1.1 2006/12/15 20:20:05 acg +// SystemC 2.3 +// +// Revision 1.5 2006/05/08 17:50:02 acg +// Andy Goodrich: Added David Long's declarations for friend operators, +// functions, and methods, to keep the Microsoft compiler happy. +// +// Revision 1.4 2006/03/13 20:25:27 acg +// Andy Goodrich: Addition of function declarations, e.g., xor_signed_friend() +// to keep gcc 4.x happy. +// +// Revision 1.3 2006/01/13 18:49:32 acg +// Added $Log command so that CVS check in comments are reproduced in the +// source. +// + +#ifndef SC_UNSIGNED_H +#define SC_UNSIGNED_H + + +#include "sysc/kernel/sc_object.h" +#include "sysc/datatypes/misc/sc_value_base.h" +#include "sysc/utils/sc_iostream.h" +#include "sysc/utils/sc_temporary.h" +#include "sysc/datatypes/int/sc_length_param.h" +#include "sysc/datatypes/int/sc_nbdefs.h" +#include "sysc/datatypes/int/sc_nbutils.h" +#include "sysc/datatypes/int/sc_nbexterns.h" +#include "sysc/utils/sc_temporary.h" + + +namespace sc_dt +{ + +// classes defined in this module +class sc_unsigned_bitref_r; +class sc_unsigned_bitref; +class sc_unsigned_subref_r; +class sc_unsigned_subref; +class sc_concatref; +class sc_unsigned; + +// forward class declarations +class sc_bv_base; +class sc_lv_base; +class sc_int_base; +class sc_uint_base; +class sc_int_subref_r; +class sc_uint_subref_r; +class sc_signed; +class sc_signed_subref_r; +class sc_fxval; +class sc_fxval_fast; +class sc_fxnum; +class sc_fxnum_fast; + +// Helper function declarions +int compare_unsigned(small_type us, + int unb, + int und, + const sc_digit *ud, + small_type vs, + int vnb, + int vnd, + const sc_digit *vd, + small_type if_u_signed=0, + small_type if_v_signed=0); + +sc_unsigned add_unsigned_friend(small_type us, + int unb, + int und, + const sc_digit *ud, + small_type vs, + int vnb, + int vnd, + const sc_digit *vd); + +sc_unsigned sub_unsigned_friend(small_type us, + int unb, + int und, + const sc_digit *ud, + small_type vs, + int vnb, + int vnd, + const sc_digit *vd); + +sc_unsigned mul_unsigned_friend(small_type s, + int unb, + int und, + const sc_digit *ud, + int vnb, + int vnd, + const sc_digit *vd); + +sc_unsigned div_unsigned_friend(small_type s, + int unb, + int und, + const sc_digit *ud, + int vnb, + int vnd, + const sc_digit *vd); + +sc_unsigned mod_unsigned_friend(small_type us, + int unb, + int und, + const sc_digit *ud, + int vnb, + int vnd, + const sc_digit *vd); + +sc_unsigned and_unsigned_friend(small_type us, + int unb, + int und, + const sc_digit *ud, + small_type vs, + int vnb, + int vnd, + const sc_digit *vd); + + +sc_unsigned or_unsigned_friend(small_type us, + int unb, + int und, + const sc_digit *ud, + small_type vs, + int vnb, + int vnd, + const sc_digit *vd); + +sc_unsigned xor_unsigned_friend(small_type us, + int unb, + int und, + const sc_digit *ud, + small_type vs, + int vnb, + int vnd, + const sc_digit *vd); + +// friend operator declarations + // ARITHMETIC OPERATORS: + + // ADDition operators: + + sc_signed operator + (const sc_unsigned& u, const sc_signed& v); + sc_signed operator + (const sc_signed& u, const sc_unsigned& v); + + sc_unsigned operator + (const sc_unsigned& u, const sc_unsigned& v); + sc_signed operator + (const sc_unsigned& u, int64 v); + sc_unsigned operator + (const sc_unsigned& u, uint64 v); + sc_signed operator + (const sc_unsigned& u, long v); + sc_unsigned operator + (const sc_unsigned& u, unsigned long v); + sc_signed operator + (const sc_unsigned& u, int v); + inline sc_unsigned operator + (const sc_unsigned& u, unsigned int v); + + sc_signed operator + (int64 u, const sc_unsigned& v); + sc_unsigned operator + (uint64 u, const sc_unsigned& v); + sc_signed operator + (long u, const sc_unsigned& v); + sc_unsigned operator + (unsigned long u, const sc_unsigned& v); + sc_signed operator + (int u, const sc_unsigned& v); + inline sc_unsigned operator + (unsigned int u, const sc_unsigned& v); + + sc_unsigned operator + (const sc_unsigned& u, const sc_uint_base& v); + sc_signed operator + (const sc_unsigned& u, const sc_int_base& v); + sc_unsigned operator + (const sc_uint_base& u, const sc_unsigned& v); + sc_signed operator + (const sc_int_base& u, const sc_unsigned& v); + + // SUBtraction operators: + + sc_signed operator - (const sc_unsigned& u, const sc_signed& v); + sc_signed operator - (const sc_signed& u, const sc_unsigned& v); + + sc_signed operator - (const sc_unsigned& u, const sc_unsigned& v); + sc_signed operator - (const sc_unsigned& u, int64 v); + sc_signed operator - (const sc_unsigned& u, uint64 v); + sc_signed operator - (const sc_unsigned& u, long v); + sc_signed operator - (const sc_unsigned& u, unsigned long v); + sc_signed operator - (const sc_unsigned& u, int v); + sc_signed operator - (const sc_unsigned& u, unsigned int v); + + sc_signed operator - (int64 u, const sc_unsigned& v); + sc_signed operator - (uint64 u, const sc_unsigned& v); + sc_signed operator - (long u, const sc_unsigned& v); + sc_signed operator - (unsigned long u, const sc_unsigned& v); + sc_signed operator - (int u, const sc_unsigned& v); + sc_signed operator - (unsigned int u, const sc_unsigned& v); + + sc_signed operator - (const sc_unsigned& u, const sc_uint_base& v); + sc_signed operator - (const sc_unsigned& u, const sc_int_base& v); + sc_signed operator - (const sc_uint_base& u, const sc_unsigned& v); + sc_signed operator - (const sc_int_base& u, const sc_unsigned& v); + + // MULtiplication operators: + + sc_signed operator * (const sc_unsigned& u, const sc_signed& v); + sc_signed operator * (const sc_signed& u, const sc_unsigned& v); + + sc_unsigned operator * (const sc_unsigned& u, const sc_unsigned& v); + sc_signed operator * (const sc_unsigned& u, int64 v); + sc_unsigned operator * (const sc_unsigned& u, uint64 v); + sc_signed operator * (const sc_unsigned& u, long v); + sc_unsigned operator * (const sc_unsigned& u, unsigned long v); + sc_signed operator * (const sc_unsigned& u, int v); + inline sc_unsigned operator * (const sc_unsigned& u, unsigned int v); + + sc_signed operator * (int64 u, const sc_unsigned& v); + sc_unsigned operator * (uint64 u, const sc_unsigned& v); + sc_signed operator * (long u, const sc_unsigned& v); + sc_unsigned operator * (unsigned long u, const sc_unsigned& v); + sc_signed operator * (int u, const sc_unsigned& v); + inline sc_unsigned operator * (unsigned int u, const sc_unsigned& v); + + sc_unsigned operator * (const sc_unsigned& u, const sc_uint_base& v); + sc_signed operator * (const sc_unsigned& u, const sc_int_base& v); + sc_unsigned operator * (const sc_uint_base& u, const sc_unsigned& v); + sc_signed operator * (const sc_int_base& u, const sc_unsigned& v); + + // DIVision operators: + + sc_signed operator / (const sc_unsigned& u, const sc_signed& v); + sc_signed operator / (const sc_signed& u, const sc_unsigned& v); + + sc_unsigned operator / (const sc_unsigned& u, const sc_unsigned& v); + sc_signed operator / (const sc_unsigned& u, int64 v); + sc_unsigned operator / (const sc_unsigned& u, uint64 v); + sc_signed operator / (const sc_unsigned& u, long v); + sc_unsigned operator / (const sc_unsigned& u, unsigned long v); + sc_signed operator / (const sc_unsigned& u, int v); + inline sc_unsigned operator / (const sc_unsigned& u, unsigned int v); + + sc_signed operator / (int64 u, const sc_unsigned& v); + sc_unsigned operator / (uint64 u, const sc_unsigned& v); + sc_signed operator / (long u, const sc_unsigned& v); + sc_unsigned operator / (unsigned long u, const sc_unsigned& v); + sc_signed operator / (int u, const sc_unsigned& v); + inline sc_unsigned operator / (unsigned int u, const sc_unsigned& v); + + sc_unsigned operator / (const sc_unsigned& u, const sc_uint_base& v); + sc_signed operator / (const sc_unsigned& u, const sc_int_base& v); + sc_unsigned operator / (const sc_uint_base& u, const sc_unsigned& v); + sc_signed operator / (const sc_int_base& u, const sc_unsigned& v); + + // MODulo operators: + + sc_signed operator % (const sc_unsigned& u, const sc_signed& v); + sc_signed operator % (const sc_signed& u, const sc_unsigned& v); + + sc_unsigned operator % (const sc_unsigned& u, const sc_unsigned& v); + sc_signed operator % (const sc_unsigned& u, int64 v); + sc_unsigned operator % (const sc_unsigned& u, uint64 v); + sc_signed operator % (const sc_unsigned& u, long v); + sc_unsigned operator % (const sc_unsigned& u, unsigned long v); + sc_signed operator % (const sc_unsigned& u, int v); + inline sc_unsigned operator % (const sc_unsigned& u, unsigned int v); + + sc_signed operator % (int64 u, const sc_unsigned& v); + sc_unsigned operator % (uint64 u, const sc_unsigned& v); + sc_signed operator % (long u, const sc_unsigned& v); + sc_unsigned operator % (unsigned long u, const sc_unsigned& v); + sc_signed operator % (int u, const sc_unsigned& v); + inline sc_unsigned operator % (unsigned int u, const sc_unsigned& v); + + sc_unsigned operator % (const sc_unsigned& u, const sc_uint_base& v); + sc_signed operator % (const sc_unsigned& u, const sc_int_base& v); + sc_unsigned operator % (const sc_uint_base& u, const sc_unsigned& v); + sc_signed operator % (const sc_int_base& u, const sc_unsigned& v); + + // BITWISE OPERATORS: + + // Bitwise AND operators: + + sc_signed operator & (const sc_unsigned& u, const sc_signed& v); + sc_signed operator & (const sc_signed& u, const sc_unsigned& v); + + sc_unsigned operator & (const sc_unsigned& u, const sc_unsigned& v); + sc_signed operator & (const sc_unsigned& u, int64 v); + sc_unsigned operator & (const sc_unsigned& u, uint64 v); + sc_signed operator & (const sc_unsigned& u, long v); + sc_unsigned operator & (const sc_unsigned& u, unsigned long v); + sc_signed operator & (const sc_unsigned& u, int v); + inline sc_unsigned operator & (const sc_unsigned& u, unsigned int v); + + sc_signed operator & (int64 u, const sc_unsigned& v); + sc_unsigned operator & (uint64 u, const sc_unsigned& v); + sc_signed operator & (long u, const sc_unsigned& v); + sc_unsigned operator & (unsigned long u, const sc_unsigned& v); + sc_signed operator & (int u, const sc_unsigned& v); + inline sc_unsigned operator & (unsigned int u, const sc_unsigned& v); + + sc_unsigned operator & (const sc_unsigned& u, const sc_uint_base& v); + sc_signed operator & (const sc_unsigned& u, const sc_int_base& v); + sc_unsigned operator & (const sc_uint_base& u, const sc_unsigned& v); + sc_signed operator & (const sc_int_base& u, const sc_unsigned& v); + + // Bitwise OR operators: + + sc_signed operator | (const sc_unsigned& u, const sc_signed& v); + sc_signed operator | (const sc_signed& u, const sc_unsigned& v); + + sc_unsigned operator | (const sc_unsigned& u, const sc_unsigned& v); + sc_signed operator | (const sc_unsigned& u, int64 v); + sc_unsigned operator | (const sc_unsigned& u, uint64 v); + sc_signed operator | (const sc_unsigned& u, long v); + sc_unsigned operator | (const sc_unsigned& u, unsigned long v); + sc_signed operator | (const sc_unsigned& u, int v); + inline sc_unsigned operator | (const sc_unsigned& u, unsigned int v); + + sc_signed operator | (int64 u, const sc_unsigned& v); + sc_unsigned operator | (uint64 u, const sc_unsigned& v); + sc_signed operator | (long u, const sc_unsigned& v); + sc_unsigned operator | (unsigned long u, const sc_unsigned& v); + sc_signed operator | (int u, const sc_unsigned& v); + inline sc_unsigned operator | (unsigned int u, const sc_unsigned& v); + + sc_unsigned operator | (const sc_unsigned& u, const sc_uint_base& v); + sc_signed operator | (const sc_unsigned& u, const sc_int_base& v); + sc_unsigned operator | (const sc_uint_base& u, const sc_unsigned& v); + sc_signed operator | (const sc_int_base& u, const sc_unsigned& v); + + // Bitwise XOR operators: + + sc_signed operator ^ (const sc_unsigned& u, const sc_signed& v); + sc_signed operator ^ (const sc_signed& u, const sc_unsigned& v); + + sc_unsigned operator ^ (const sc_unsigned& u, const sc_unsigned& v); + sc_signed operator ^ (const sc_unsigned& u, int64 v); + sc_unsigned operator ^ (const sc_unsigned& u, uint64 v); + sc_signed operator ^ (const sc_unsigned& u, long v); + sc_unsigned operator ^ (const sc_unsigned& u, unsigned long v); + sc_signed operator ^ (const sc_unsigned& u, int v); + inline sc_unsigned operator ^ (const sc_unsigned& u, unsigned int v); + + sc_signed operator ^ (int64 u, const sc_unsigned& v); + sc_unsigned operator ^ (uint64 u, const sc_unsigned& v); + sc_signed operator ^ (long u, const sc_unsigned& v); + sc_unsigned operator ^ (unsigned long u, const sc_unsigned& v); + sc_signed operator ^ (int u, const sc_unsigned& v); + inline sc_unsigned operator ^ (unsigned int u, const sc_unsigned& v); + + sc_unsigned operator ^ (const sc_unsigned& u, const sc_uint_base& v); + sc_signed operator ^ (const sc_unsigned& u, const sc_int_base& v); + sc_unsigned operator ^ (const sc_uint_base& u, const sc_unsigned& v); + sc_signed operator ^ (const sc_int_base& u, const sc_unsigned& v); + + // SHIFT OPERATORS: + + // LEFT SHIFT operators: + + sc_unsigned operator << (const sc_unsigned& u, const sc_signed& v); + sc_signed operator << (const sc_signed& u, const sc_unsigned& v); + + sc_unsigned operator << (const sc_unsigned& u, const sc_unsigned& v); + sc_unsigned operator << (const sc_unsigned& u, int64 v); + sc_unsigned operator << (const sc_unsigned& u, uint64 v); + sc_unsigned operator << (const sc_unsigned& u, long v); + sc_unsigned operator << (const sc_unsigned& u, unsigned long v); + inline sc_unsigned operator << (const sc_unsigned& u, int v); + inline sc_unsigned operator << (const sc_unsigned& u, unsigned int v); + + sc_unsigned operator << (const sc_unsigned& u, const sc_uint_base& v); + sc_unsigned operator << (const sc_unsigned& u, const sc_int_base& v); + + // RIGHT SHIFT operators: + + sc_unsigned operator >> (const sc_unsigned& u, const sc_signed& v); + sc_signed operator >> (const sc_signed& u, const sc_unsigned& v); + + sc_unsigned operator >> (const sc_unsigned& u, const sc_unsigned& v); + sc_unsigned operator >> (const sc_unsigned& u, int64 v); + sc_unsigned operator >> (const sc_unsigned& u, uint64 v); + sc_unsigned operator >> (const sc_unsigned& u, long v); + sc_unsigned operator >> (const sc_unsigned& u, unsigned long v); + inline sc_unsigned operator >> (const sc_unsigned& u, int v); + inline sc_unsigned operator >> (const sc_unsigned& u, unsigned int v); + + sc_unsigned operator >> ( const sc_unsigned& , const sc_uint_base& ); + sc_unsigned operator >> ( const sc_unsigned&, const sc_int_base& ); + + // Unary arithmetic operators + sc_unsigned operator + (const sc_unsigned& u); + sc_signed operator - (const sc_unsigned& u); + + // LOGICAL OPERATORS: + + // Logical EQUAL operators: + + bool operator == (const sc_unsigned& u, const sc_signed& v); + bool operator == (const sc_signed& u, const sc_unsigned& v); + + bool operator == (const sc_unsigned& u, const sc_unsigned& v); + bool operator == (const sc_unsigned& u, int64 v); + bool operator == (const sc_unsigned& u, uint64 v); + bool operator == (const sc_unsigned& u, long v); + bool operator == (const sc_unsigned& u, unsigned long v); + inline bool operator == (const sc_unsigned& u, int v); + inline bool operator == (const sc_unsigned& u, unsigned int v); + + bool operator == (int64 u, const sc_unsigned& v); + bool operator == (uint64 u, const sc_unsigned& v); + bool operator == (long u, const sc_unsigned& v); + bool operator == (unsigned long u, const sc_unsigned& v); + inline bool operator == (int u, const sc_unsigned& v); + inline bool operator == (unsigned int u, const sc_unsigned& v) ; + + bool operator == (const sc_unsigned& u, const sc_uint_base& v); + bool operator == (const sc_unsigned& u, const sc_int_base& v); + bool operator == (const sc_uint_base& u, const sc_unsigned& v); + bool operator == (const sc_int_base& u, const sc_unsigned& v); + + // Logical NOT_EQUAL operators: + + bool operator != (const sc_unsigned& u, const sc_signed& v); + bool operator != (const sc_signed& u, const sc_unsigned& v); + + bool operator != (const sc_unsigned& u, const sc_unsigned& v); + bool operator != (const sc_unsigned& u, int64 v); + bool operator != (const sc_unsigned& u, uint64 v); + bool operator != (const sc_unsigned& u, long v); + bool operator != (const sc_unsigned& u, unsigned long v); + inline bool operator != (const sc_unsigned& u, int v); + inline bool operator != (const sc_unsigned& u, unsigned int v); + + bool operator != (int64 u, const sc_unsigned& v); + bool operator != (uint64 u, const sc_unsigned& v); + bool operator != (long u, const sc_unsigned& v); + bool operator != (unsigned long u, const sc_unsigned& v); + inline bool operator != (int u, const sc_unsigned& v); + inline bool operator != (unsigned int u, const sc_unsigned& v); + + bool operator != (const sc_unsigned& u, const sc_uint_base& v); + bool operator != (const sc_unsigned& u, const sc_int_base& v); + bool operator != (const sc_uint_base& u, const sc_unsigned& v); + bool operator != (const sc_int_base& u, const sc_unsigned& v); + + // Logical LESS_THAN operators: + + bool operator < (const sc_unsigned& u, const sc_signed& v); + bool operator < (const sc_signed& u, const sc_unsigned& v); + + bool operator < (const sc_unsigned& u, const sc_unsigned& v); + bool operator < (const sc_unsigned& u, int64 v); + bool operator < (const sc_unsigned& u, uint64 v); + bool operator < (const sc_unsigned& u, long v); + bool operator < (const sc_unsigned& u, unsigned long v); + inline bool operator < (const sc_unsigned& u, int v); + inline bool operator < (const sc_unsigned& u, unsigned int v); + + bool operator < (int64 u, const sc_unsigned& v); + bool operator < (uint64 u, const sc_unsigned& v); + bool operator < (long u, const sc_unsigned& v); + bool operator < (unsigned long u, const sc_unsigned& v); + inline bool operator < (int u, const sc_unsigned& v); + inline bool operator < (unsigned int u, const sc_unsigned& v); + + bool operator < (const sc_unsigned& u, const sc_uint_base& v); + bool operator < (const sc_unsigned& u, const sc_int_base& v); + bool operator < (const sc_uint_base& u, const sc_unsigned& v); + bool operator < (const sc_int_base& u, const sc_unsigned& v); + + // Logical LESS_THAN_AND_EQUAL operators: + + bool operator <= (const sc_unsigned& u, const sc_signed& v); + bool operator <= (const sc_signed& u, const sc_unsigned& v); + + bool operator <= (const sc_unsigned& u, const sc_unsigned& v); + bool operator <= (const sc_unsigned& u, int64 v); + bool operator <= (const sc_unsigned& u, uint64 v); + bool operator <= (const sc_unsigned& u, long v); + bool operator <= (const sc_unsigned& u, unsigned long v); + inline bool operator <= (const sc_unsigned& u, int v); + inline bool operator <= (const sc_unsigned& u, unsigned int v); + + bool operator <= (int64 u, const sc_unsigned& v); + bool operator <= (uint64 u, const sc_unsigned& v); + bool operator <= (long u, const sc_unsigned& v); + bool operator <= (unsigned long u, const sc_unsigned& v); + inline bool operator <= (int u, const sc_unsigned& v); + inline bool operator <= (unsigned int u, const sc_unsigned& v); + + bool operator <= (const sc_unsigned& u, const sc_uint_base& v); + bool operator <= (const sc_unsigned& u, const sc_int_base& v); + bool operator <= (const sc_uint_base& u, const sc_unsigned& v); + bool operator <= (const sc_int_base& u, const sc_unsigned& v); + + // Logical GREATER_THAN operators: + + bool operator > (const sc_unsigned& u, const sc_signed& v); + bool operator > (const sc_signed& u, const sc_unsigned& v); + + bool operator > (const sc_unsigned& u, const sc_unsigned& v); + bool operator > (const sc_unsigned& u, int64 v); + bool operator > (const sc_unsigned& u, uint64 v); + bool operator > (const sc_unsigned& u, long v); + bool operator > (const sc_unsigned& u, unsigned long v); + inline bool operator > (const sc_unsigned& u, int v); + inline bool operator > (const sc_unsigned& u, unsigned int v); + + bool operator > (int64 u, const sc_unsigned& v); + bool operator > (uint64 u, const sc_unsigned& v); + bool operator > (long u, const sc_unsigned& v); + bool operator > (unsigned long u, const sc_unsigned& v); + inline bool operator > (int u, const sc_unsigned& v); + inline bool operator > (unsigned int u, const sc_unsigned& v); + + bool operator > (const sc_unsigned& u, const sc_uint_base& v); + bool operator > (const sc_unsigned& u, const sc_int_base& v); + bool operator > (const sc_uint_base& u, const sc_unsigned& v); + bool operator > (const sc_int_base& u, const sc_unsigned& v); + + // Logical GREATER_THAN_AND_EQUAL operators: + + bool operator >= (const sc_unsigned& u, const sc_signed& v); + bool operator >= (const sc_signed& u, const sc_unsigned& v); + + bool operator >= (const sc_unsigned& u, const sc_unsigned& v); + bool operator >= (const sc_unsigned& u, int64 v); + bool operator >= (const sc_unsigned& u, uint64 v); + bool operator >= (const sc_unsigned& u, long v); + bool operator >= (const sc_unsigned& u, unsigned long v); + inline bool operator >= (const sc_unsigned& u, int v); + inline bool operator >= (const sc_unsigned& u, unsigned int v); + + bool operator >= (int64 u, const sc_unsigned& v); + bool operator >= (uint64 u, const sc_unsigned& v); + bool operator >= (long u, const sc_unsigned& v); + bool operator >= (unsigned long u, const sc_unsigned& v); + inline bool operator >= (int u, const sc_unsigned& v); + inline bool operator >= (unsigned int u, const sc_unsigned& v); + + bool operator >= (const sc_unsigned& u, const sc_uint_base& v); + bool operator >= (const sc_unsigned& u, const sc_int_base& v); + bool operator >= (const sc_uint_base& u, const sc_unsigned& v); + bool operator >= (const sc_int_base& u, const sc_unsigned& v); + + // Bitwise NOT operator (unary). + sc_unsigned operator ~ (const sc_unsigned& u); + +// ---------------------------------------------------------------------------- +// CLASS : sc_unsigned_bitref_r +// +// Proxy class for sc_unsigned bit selection (r-value only). +// ---------------------------------------------------------------------------- + +class sc_unsigned_bitref_r : public sc_value_base +{ + friend class sc_unsigned; + +protected: + + // construction and initialization: + + sc_unsigned_bitref_r() : sc_value_base(), m_index(0), m_obj_p(0) + {} + + void initialize( const sc_unsigned* obj_p, int index_ ) + { + m_obj_p = CCAST<sc_unsigned*>( obj_p ); + m_index = index_; + } + +public: + + // destructor + + virtual ~sc_unsigned_bitref_r() + {} + + // copy constructor + + sc_unsigned_bitref_r( const sc_unsigned_bitref_r& a ) + : sc_value_base(a), m_index( a.m_index ), m_obj_p( a.m_obj_p ) + {} + + // capacity + + int length() const + { return 1; } + + + // implicit conversion to bool + + operator uint64 () const; + bool operator ! () const; + bool operator ~ () const; + + + // explicit conversions + + uint64 value() const + { return operator uint64(); } + + bool to_bool() const + { return operator uint64(); } + + + // concatenation support + + virtual int concat_length(bool* xz_present_p) const + { if ( xz_present_p ) *xz_present_p = false; return 1; } + virtual uint64 concat_get_uint64() const + { return (uint64)operator uint64(); } + virtual bool concat_get_ctrl( sc_digit* dst_p, int low_i ) const + { + int bit_mask = 1 << (low_i % BITS_PER_DIGIT); + int word_i = low_i / BITS_PER_DIGIT; + dst_p[word_i] &= ~bit_mask; + return false; + } + virtual bool concat_get_data( sc_digit* dst_p, int low_i ) const + { + int bit_mask = 1 << (low_i % BITS_PER_DIGIT); + bool result; // True if non-zero. + int word_i = low_i / BITS_PER_DIGIT; + if ( operator uint64() ) + { + dst_p[word_i] |= bit_mask; + result = true; + } + else + { + dst_p[word_i] &= ~bit_mask; + result = false; + } + return result; + } + + // other methods + + void print( ::std::ostream& os = ::std::cout ) const + { os << to_bool(); } + +protected: + + int m_index; + sc_unsigned* m_obj_p; + +private: + + // disabled + const sc_unsigned_bitref_r& operator = ( const sc_unsigned_bitref_r& ); +}; + + + +inline +::std::ostream& +operator << ( ::std::ostream&, const sc_unsigned_bitref_r& ); + + +// ---------------------------------------------------------------------------- +// CLASS : sc_unsigned_bitref +// +// Proxy class for sc_unsigned bit selection (r-value and l-value). +// ---------------------------------------------------------------------------- + +class sc_unsigned_bitref + : public sc_unsigned_bitref_r +{ + friend class sc_unsigned; + friend class sc_core::sc_vpool<sc_unsigned_bitref>; + + +protected: // construction + + sc_unsigned_bitref() : sc_unsigned_bitref_r() + {} + +public: + + // copy constructor + + sc_unsigned_bitref( const sc_unsigned_bitref& a ) + : sc_unsigned_bitref_r( a ) + {} + + + // assignment operators + + const sc_unsigned_bitref& operator = ( const sc_unsigned_bitref_r& ); + const sc_unsigned_bitref& operator = ( const sc_unsigned_bitref& ); + const sc_unsigned_bitref& operator = ( bool ); + + const sc_unsigned_bitref& operator &= ( bool ); + const sc_unsigned_bitref& operator |= ( bool ); + const sc_unsigned_bitref& operator ^= ( bool ); + + // concatenation methods + + virtual void concat_set(int64 src, int low_i); + virtual void concat_set(const sc_signed& src, int low_i); + virtual void concat_set(const sc_unsigned& src, int low_i); + virtual void concat_set(uint64 src, int low_i); + + + // other methods + + void scan( ::std::istream& is = ::std::cin ); + +protected: + static sc_core::sc_vpool<sc_unsigned_bitref> m_pool; +}; + + + +inline +::std::istream& +operator >> ( ::std::istream&, sc_unsigned_bitref& ); + + +// ---------------------------------------------------------------------------- +// CLASS : sc_unsigned_subref_r +// +// Proxy class for sc_unsigned part selection (r-value only). +// ---------------------------------------------------------------------------- + +class sc_unsigned_subref_r : public sc_value_base +{ + friend class sc_signed; + friend class sc_unsigned; + friend class sc_unsigned_signal; + +protected: + + // constructor + + sc_unsigned_subref_r() : sc_value_base(), m_left(0), m_obj_p(0), m_right(0) + {} + + void initialize( const sc_unsigned* obj_p, int left_, int right_ ) + { + m_obj_p = CCAST<sc_unsigned*>( obj_p ); + m_left = left_; + m_right = right_; + } + +public: + + // destructor + + virtual ~sc_unsigned_subref_r() + {} + + + // copy constructor + + sc_unsigned_subref_r( const sc_unsigned_subref_r& a ) + : sc_value_base(a), m_left( a.m_left ), m_obj_p( a.m_obj_p ), + m_right( a.m_right ) + {} + + + // capacity + + int length() const + { return m_left >= m_right ? (m_left-m_right+1) : (m_right-m_left+1 ); } + + + // implicit conversion to sc_unsigned + + operator sc_unsigned () const; + + + // explicit conversions + + int to_int() const; + unsigned int to_uint() const; + long to_long() const; + unsigned long to_ulong() const; + int64 to_int64() const; + uint64 to_uint64() const; + double to_double() const; + + + // explicit conversion to character string + + const std::string to_string( sc_numrep numrep = SC_DEC ) const; + const std::string to_string( sc_numrep numrep, bool w_prefix ) const; + + + // concatenation support + + virtual int concat_length(bool* xz_present_p) const + { + if ( xz_present_p ) *xz_present_p = false; + return m_left - m_right + 1; + } + virtual uint64 concat_get_uint64() const; + virtual bool concat_get_ctrl( sc_digit* dst_p, int low_i ) const; + virtual bool concat_get_data( sc_digit* dst_p, int low_i ) const; + + // reduce methods + + bool and_reduce() const; + bool nand_reduce() const; + bool or_reduce() const; + bool nor_reduce() const; + bool xor_reduce() const ; + bool xnor_reduce() const; + + // other methods + + void print( ::std::ostream& os = ::std::cout ) const + { os << to_string(sc_io_base(os,SC_DEC),sc_io_show_base(os)); } + +protected: + + int m_left; // Left-most bit in this part selection. + sc_unsigned* m_obj_p; // Target of this part selection. + int m_right; // Right-most bit in this part selection. + +private: + + // disabled + const sc_unsigned_subref_r& operator = ( const sc_unsigned_subref_r& ); +}; + + + +inline +::std::ostream& +operator << ( ::std::ostream&, const sc_unsigned_subref_r& ); + + +// ---------------------------------------------------------------------------- +// CLASS : sc_unsigned_subref +// +// Proxy class for sc_unsigned part selection (r-value and l-value). +// ---------------------------------------------------------------------------- + +class sc_unsigned_subref + : public sc_unsigned_subref_r +{ + friend class sc_unsigned; + friend class sc_core::sc_vpool<sc_unsigned_subref>; + + + // constructor + +protected: + sc_unsigned_subref() : sc_unsigned_subref_r() + {} + +public: + + // copy constructor + + sc_unsigned_subref( const sc_unsigned_subref& a ) + : sc_unsigned_subref_r( a ) + {} + + // assignment operators + + const sc_unsigned_subref& operator = ( const sc_unsigned_subref_r& a ); + const sc_unsigned_subref& operator = ( const sc_unsigned_subref& a ); + const sc_unsigned_subref& operator = ( const sc_unsigned& a ); + + template<class T> + const sc_unsigned_subref& operator = ( const sc_generic_base<T>& a ); + const sc_unsigned_subref& operator = ( const sc_signed_subref_r& a ); + const sc_unsigned_subref& operator = ( const sc_signed& a ); + + const sc_unsigned_subref& operator = ( const char* a ); + const sc_unsigned_subref& operator = ( unsigned long a ); + const sc_unsigned_subref& operator = ( long a ); + + const sc_unsigned_subref& operator = ( unsigned int a ) + { return operator = ( (unsigned long) a ); } + + const sc_unsigned_subref& operator = ( int a ) + { return operator = ( (long) a ); } + + const sc_unsigned_subref& operator = ( uint64 a ); + const sc_unsigned_subref& operator = ( int64 a ); + const sc_unsigned_subref& operator = ( double a ); + const sc_unsigned_subref& operator = ( const sc_int_base& a ); + const sc_unsigned_subref& operator = ( const sc_uint_base& a ); + + // concatenation methods + + virtual void concat_set(int64 src, int low_i); + virtual void concat_set(const sc_signed& src, int low_i); + virtual void concat_set(const sc_unsigned& src, int low_i); + virtual void concat_set(uint64 src, int low_i); + + // other methods + + void scan( ::std::istream& is = ::std::cin ); + +protected: + static sc_core::sc_vpool<sc_unsigned_subref> m_pool; +}; + + + +inline +::std::istream& +operator >> ( ::std::istream&, sc_unsigned_subref& ); + + +// ---------------------------------------------------------------------------- +// CLASS : sc_unsigned +// +// Arbitrary precision unsigned number. +// ---------------------------------------------------------------------------- + +class sc_unsigned : public sc_value_base +{ + friend class sc_concatref; + friend class sc_unsigned_bitref_r; + friend class sc_unsigned_bitref; + friend class sc_unsigned_subref_r; + friend class sc_unsigned_subref; + friend class sc_signed; + friend class sc_signed_subref; + friend class sc_signed_subref_r; + + // Needed for types using sc_unsigned. + typedef bool elemtype; + +public: + + // constructors + + explicit sc_unsigned( int nb = sc_length_param().len() ); + sc_unsigned( const sc_unsigned& v ); + sc_unsigned( const sc_signed& v ); + template<class T> + explicit sc_unsigned( const sc_generic_base<T>& v ); + explicit sc_unsigned( const sc_bv_base& v ); + explicit sc_unsigned( const sc_lv_base& v ); + explicit sc_unsigned( const sc_int_subref_r& v ); + explicit sc_unsigned( const sc_uint_subref_r& v ); + explicit sc_unsigned( const sc_signed_subref_r& v ); + explicit sc_unsigned( const sc_unsigned_subref_r& v ); + + + + // assignment operators + + const sc_unsigned& operator = (const sc_unsigned& v); + const sc_unsigned& operator = (const sc_unsigned_subref_r& a ); + + template<class T> + const sc_unsigned& operator = ( const sc_generic_base<T>& a ) + { a->to_sc_unsigned(*this); return *this; } + + const sc_unsigned& operator = (const sc_signed& v); + const sc_unsigned& operator = (const sc_signed_subref_r& a ); + + const sc_unsigned& operator = ( const char* v); + const sc_unsigned& operator = ( int64 v); + const sc_unsigned& operator = ( uint64 v); + const sc_unsigned& operator = ( long v); + const sc_unsigned& operator = ( unsigned long v); + + const sc_unsigned& operator = ( int v) + { return operator=((long) v); } + + const sc_unsigned& operator = ( unsigned int v) + { return operator=((unsigned long) v); } + + const sc_unsigned& operator = ( double v); + const sc_unsigned& operator = ( const sc_int_base& v); + const sc_unsigned& operator = ( const sc_uint_base& v); + + const sc_unsigned& operator = ( const sc_bv_base& ); + const sc_unsigned& operator = ( const sc_lv_base& ); + +#ifdef SC_INCLUDE_FX + const sc_unsigned& operator = ( const sc_fxval& ); + const sc_unsigned& operator = ( const sc_fxval_fast& ); + const sc_unsigned& operator = ( const sc_fxnum& ); + const sc_unsigned& operator = ( const sc_fxnum_fast& ); +#endif + + + // destructor + + virtual ~sc_unsigned() + { +# ifndef SC_MAX_NBITS + delete [] digit; +# endif + } + + // Concatenation support: + + sc_digit* get_raw() const { return digit; } + virtual int concat_length(bool* xz_present_p) const + { if ( xz_present_p ) *xz_present_p = false; return nbits-1; } + virtual bool concat_get_ctrl( sc_digit* dst_p, int low_i ) const; + virtual bool concat_get_data( sc_digit* dst_p, int low_i ) const; + virtual uint64 concat_get_uint64() const; + virtual void concat_set(int64 src, int low_i); + virtual void concat_set(const sc_signed& src, int low_i); + virtual void concat_set(const sc_unsigned& src, int low_i); + virtual void concat_set(uint64 src, int low_i); + + // Increment operators. + + sc_unsigned& operator ++ (); + const sc_unsigned operator ++ (int); + + // Decrement operators. + + sc_unsigned& operator -- (); + const sc_unsigned operator -- (int); + + + // bit selection + + inline void check_index( int i ) const + { if ( (i < 0) || (i >= nbits-1) ) invalid_index(i); } + + void invalid_index( int i ) const; + + sc_unsigned_bitref& operator [] ( int i ) + { + check_index(i); + sc_unsigned_bitref* result_p = + sc_unsigned_bitref::m_pool.allocate(); + result_p->initialize( this, i ); + return *result_p; + } + + const sc_unsigned_bitref_r& operator [] ( int i ) const + { + check_index(i); + sc_unsigned_bitref* result_p = + sc_unsigned_bitref::m_pool.allocate(); + result_p->initialize( this, i ); + return *result_p; + } + + sc_unsigned_bitref& bit( int i ) + { + check_index(i); + sc_unsigned_bitref* result_p = + sc_unsigned_bitref::m_pool.allocate(); + result_p->initialize( this, i ); + return *result_p; + } + + const sc_unsigned_bitref_r& bit( int i ) const + { + check_index(i); + sc_unsigned_bitref* result_p = + sc_unsigned_bitref::m_pool.allocate(); + result_p->initialize( this, i ); + return *result_p; + } + + + // part selection + + // Subref operators. Help access the range of bits from the ith to + // jth. These indices have arbitrary precedence with respect to each + // other, i.e., we can have i <= j or i > j. Note the equivalence + // between range(i, j) and operator (i, j). Also note that + // operator (i, i) returns an unsigned number that corresponds to the + // bit operator [i], so these two forms are not the same. + + inline void check_range( int l, int r ) const + { + if ( l < r ) + { + if ( (l < 0) || (r >= nbits-1) ) invalid_range(l,r); + } + else + { + if ( (r < 0) || (l >= nbits-1) ) invalid_range(l,r); + } + } + + void invalid_range( int l, int r ) const; + + sc_unsigned_subref& range( int i, int j ) + { + check_range(i,j); + sc_unsigned_subref* result_p = + sc_unsigned_subref::m_pool.allocate(); + result_p->initialize( this, i, j ); + return *result_p; + } + + const sc_unsigned_subref_r& range( int i, int j ) const + { + check_range(i,j); + sc_unsigned_subref* result_p = + sc_unsigned_subref::m_pool.allocate(); + result_p->initialize( this, i, j ); + return *result_p; + } + + sc_unsigned_subref& operator () ( int i, int j ) + { + check_range(i,j); + sc_unsigned_subref* result_p = + sc_unsigned_subref::m_pool.allocate(); + result_p->initialize( this, i, j ); + return *result_p; + } + + const sc_unsigned_subref_r& operator () ( int i, int j ) const + { + check_range(i,j); + sc_unsigned_subref* result_p = + sc_unsigned_subref::m_pool.allocate(); + result_p->initialize( this, i, j ); + return *result_p; + } + + // explicit conversions + + int to_int() const; + unsigned int to_uint() const; + long to_long() const; + unsigned long to_ulong() const; + int64 to_int64() const; + uint64 to_uint64() const; + double to_double() const; + +#ifdef SC_DT_DEPRECATED + int to_signed() const + { return to_int(); } + + unsigned int to_unsigned() const + { return to_uint(); } +#endif + + // explicit conversion to character string + + const std::string to_string( sc_numrep numrep = SC_DEC ) const; + const std::string to_string( sc_numrep numrep, bool w_prefix ) const; + + // Print functions. dump prints the internals of the class. + + void print( ::std::ostream& os = ::std::cout ) const + { os << to_string(sc_io_base(os,SC_DEC),sc_io_show_base(os)); } + + void scan( ::std::istream& is = ::std::cin ); + + void dump( ::std::ostream& os = ::std::cout ) const; + + + // Functions to find various properties. + int length() const { return nbits - 1; } // Bit width. + bool iszero() const; // Is the number zero? + bool sign() const { return 0; } // Sign. + + // reduce methods + + bool and_reduce() const; + + bool nand_reduce() const + { return ( ! and_reduce() ); } + + bool or_reduce() const; + + bool nor_reduce() const + { return ( ! or_reduce() ); } + + bool xor_reduce() const; + + bool xnor_reduce() const + { return ( ! xor_reduce() ); } + + + // Functions to access individual bits. + bool test(int i) const; // Is the ith bit 0 or 1? + void set(int i); // Set the ith bit to 1. + void clear(int i); // Set the ith bit to 0. + void set(int i, bool v) // Set the ith bit to v. + { if (v) set(i); else clear(i); } + void invert(int i) // Negate the ith bit. + { if (test(i)) clear(i); else set(i); } + + // Make the number equal to its mirror image. + void reverse(); + + // Get/set a packed bit representation of the number. + void get_packed_rep(sc_digit *buf) const; + void set_packed_rep(sc_digit *buf); + + /* + The comparison of the old and new semantics are as follows: + + Let s = sc_signed, + u = sc_unsigned, + un = { uint64, unsigned long, unsigned int }, + sn = { int64, long, int, char* }, and + OP = { +, -, *, /, % }. + + Old semantics: New semantics: + u OP u -> u u OP u -> u + s OP u -> u s OP u -> s + u OP s -> u u OP s -> s + s OP s -> s s OP s -> s + + u OP un = un OP u -> u u OP un = un OP u -> u + u OP sn = sn OP u -> u u OP sn = sn OP u -> s + + s OP un = un OP s -> s s OP un = un OP s -> s + s OP sn = sn OP s -> s s OP sn = sn OP s -> s + + In the new semantics, the result is u if both operands are u; the + result is s otherwise. The only exception is subtraction. The result + of a subtraction is always s. + + The old semantics is like C/C++ semantics on integer types; the + new semantics is due to the VSIA C/C++ data types standard. + */ + + // ARITHMETIC OPERATORS: + + // ADDition operators: + + friend sc_signed operator + (const sc_unsigned& u, const sc_signed& v); + friend sc_signed operator + (const sc_signed& u, const sc_unsigned& v); + + friend sc_unsigned operator + (const sc_unsigned& u, const sc_unsigned& v); + friend sc_signed operator + (const sc_unsigned& u, int64 v); + friend sc_unsigned operator + (const sc_unsigned& u, uint64 v); + friend sc_signed operator + (const sc_unsigned& u, long v); + friend sc_unsigned operator + (const sc_unsigned& u, unsigned long v); + friend sc_signed operator + (const sc_unsigned& u, int v); + friend sc_unsigned operator + (const sc_unsigned& u, unsigned int v) + { return operator+(u, (unsigned long) v); } + + friend sc_signed operator + (int64 u, const sc_unsigned& v); + friend sc_unsigned operator + (uint64 u, const sc_unsigned& v); + friend sc_signed operator + (long u, const sc_unsigned& v); + friend sc_unsigned operator + (unsigned long u, const sc_unsigned& v); + friend sc_signed operator + (int u, const sc_unsigned& v); + friend sc_unsigned operator + (unsigned int u, const sc_unsigned& v) + { return operator+((unsigned long) u, v); } + + const sc_unsigned& operator += (const sc_signed& v); + const sc_unsigned& operator += (const sc_unsigned& v); + const sc_unsigned& operator += (int64 v); + const sc_unsigned& operator += (uint64 v); + const sc_unsigned& operator += (long v); + const sc_unsigned& operator += (unsigned long v); + const sc_unsigned& operator += (int v) + { return operator+=((long) v); } + const sc_unsigned& operator += (unsigned int v) + { return operator+=((unsigned long) v); } + + friend sc_unsigned operator + (const sc_unsigned& u, const sc_uint_base& v); + friend sc_signed operator + (const sc_unsigned& u, const sc_int_base& v); + friend sc_unsigned operator + (const sc_uint_base& u, const sc_unsigned& v); + friend sc_signed operator + (const sc_int_base& u, const sc_unsigned& v); + const sc_unsigned& operator += (const sc_int_base& v); + const sc_unsigned& operator += (const sc_uint_base& v); + + // SUBtraction operators: + + friend sc_signed operator - (const sc_unsigned& u, const sc_signed& v); + friend sc_signed operator - (const sc_signed& u, const sc_unsigned& v); + + friend sc_signed operator - (const sc_unsigned& u, const sc_unsigned& v); + friend sc_signed operator - (const sc_unsigned& u, int64 v); + friend sc_signed operator - (const sc_unsigned& u, uint64 v); + friend sc_signed operator - (const sc_unsigned& u, long v); + friend sc_signed operator - (const sc_unsigned& u, unsigned long v); + friend sc_signed operator - (const sc_unsigned& u, int v); + friend sc_signed operator - (const sc_unsigned& u, unsigned int v); + + friend sc_signed operator - (int64 u, const sc_unsigned& v); + friend sc_signed operator - (uint64 u, const sc_unsigned& v); + friend sc_signed operator - (long u, const sc_unsigned& v); + friend sc_signed operator - (unsigned long u, const sc_unsigned& v); + friend sc_signed operator - (int u, const sc_unsigned& v); + friend sc_signed operator - (unsigned int u, const sc_unsigned& v); + + const sc_unsigned& operator -= (const sc_signed& v); + const sc_unsigned& operator -= (const sc_unsigned& v); + const sc_unsigned& operator -= (int64 v); + const sc_unsigned& operator -= (uint64 v); + const sc_unsigned& operator -= (long v); + const sc_unsigned& operator -= (unsigned long v); + const sc_unsigned& operator -= (int v) + { return operator-=((long) v); } + const sc_unsigned& operator -= (unsigned int v) + { return operator-=((unsigned long) v); } + + friend sc_signed operator - (const sc_unsigned& u, const sc_uint_base& v); + friend sc_signed operator - (const sc_unsigned& u, const sc_int_base& v); + friend sc_signed operator - (const sc_uint_base& u, const sc_unsigned& v); + friend sc_signed operator - (const sc_int_base& u, const sc_unsigned& v); + const sc_unsigned& operator -= (const sc_int_base& v); + const sc_unsigned& operator -= (const sc_uint_base& v); + + // MULtiplication operators: + + friend sc_signed operator * (const sc_unsigned& u, const sc_signed& v); + friend sc_signed operator * (const sc_signed& u, const sc_unsigned& v); + + friend sc_unsigned operator * (const sc_unsigned& u, const sc_unsigned& v); + friend sc_signed operator * (const sc_unsigned& u, int64 v); + friend sc_unsigned operator * (const sc_unsigned& u, uint64 v); + friend sc_signed operator * (const sc_unsigned& u, long v); + friend sc_unsigned operator * (const sc_unsigned& u, unsigned long v); + friend sc_signed operator * (const sc_unsigned& u, int v); + friend sc_unsigned operator * (const sc_unsigned& u, unsigned int v) + { return operator*(u, (unsigned long) v); } + + friend sc_signed operator * (int64 u, const sc_unsigned& v); + friend sc_unsigned operator * (uint64 u, const sc_unsigned& v); + friend sc_signed operator * (long u, const sc_unsigned& v); + friend sc_unsigned operator * (unsigned long u, const sc_unsigned& v); + friend sc_signed operator * (int u, const sc_unsigned& v); + friend sc_unsigned operator * (unsigned int u, const sc_unsigned& v) + { return operator*((unsigned long) u, v); } + + const sc_unsigned& operator *= (const sc_signed& v); + const sc_unsigned& operator *= (const sc_unsigned& v); + const sc_unsigned& operator *= (int64 v); + const sc_unsigned& operator *= (uint64 v); + const sc_unsigned& operator *= (long v); + const sc_unsigned& operator *= (unsigned long v); + const sc_unsigned& operator *= (int v) + { return operator*=((long) v); } + const sc_unsigned& operator *= (unsigned int v) + { return operator*=((unsigned long) v); } + + friend sc_unsigned operator * (const sc_unsigned& u, const sc_uint_base& v); + friend sc_signed operator * (const sc_unsigned& u, const sc_int_base& v); + friend sc_unsigned operator * (const sc_uint_base& u, const sc_unsigned& v); + friend sc_signed operator * (const sc_int_base& u, const sc_unsigned& v); + const sc_unsigned& operator *= (const sc_int_base& v); + const sc_unsigned& operator *= (const sc_uint_base& v); + + // DIVision operators: + + friend sc_signed operator / (const sc_unsigned& u, const sc_signed& v); + friend sc_signed operator / (const sc_signed& u, const sc_unsigned& v); + + friend sc_unsigned operator / (const sc_unsigned& u, const sc_unsigned& v); + friend sc_signed operator / (const sc_unsigned& u, int64 v); + friend sc_unsigned operator / (const sc_unsigned& u, uint64 v); + friend sc_signed operator / (const sc_unsigned& u, long v); + friend sc_unsigned operator / (const sc_unsigned& u, unsigned long v); + friend sc_signed operator / (const sc_unsigned& u, int v); + friend sc_unsigned operator / (const sc_unsigned& u, unsigned int v) + { return operator/(u, (unsigned long) v); } + + friend sc_signed operator / (int64 u, const sc_unsigned& v); + friend sc_unsigned operator / (uint64 u, const sc_unsigned& v); + friend sc_signed operator / (long u, const sc_unsigned& v); + friend sc_unsigned operator / (unsigned long u, const sc_unsigned& v); + friend sc_signed operator / (int u, const sc_unsigned& v); + friend sc_unsigned operator / (unsigned int u, const sc_unsigned& v) + { return operator/((unsigned long) u, v); } + + const sc_unsigned& operator /= (const sc_signed& v); + const sc_unsigned& operator /= (const sc_unsigned& v); + const sc_unsigned& operator /= (int64 v); + const sc_unsigned& operator /= (uint64 v); + const sc_unsigned& operator /= (long v); + const sc_unsigned& operator /= (unsigned long v); + const sc_unsigned& operator /= (int v) + { return operator/=((long) v); } + const sc_unsigned& operator /= (unsigned int v) + { return operator/=((unsigned long) v); } + + friend sc_unsigned operator / (const sc_unsigned& u, const sc_uint_base& v); + friend sc_signed operator / (const sc_unsigned& u, const sc_int_base& v); + friend sc_unsigned operator / (const sc_uint_base& u, const sc_unsigned& v); + friend sc_signed operator / (const sc_int_base& u, const sc_unsigned& v); + const sc_unsigned& operator /= (const sc_int_base& v); + const sc_unsigned& operator /= (const sc_uint_base& v); + + // MODulo operators: + + friend sc_signed operator % (const sc_unsigned& u, const sc_signed& v); + friend sc_signed operator % (const sc_signed& u, const sc_unsigned& v); + + friend sc_unsigned operator % (const sc_unsigned& u, const sc_unsigned& v); + friend sc_signed operator % (const sc_unsigned& u, int64 v); + friend sc_unsigned operator % (const sc_unsigned& u, uint64 v); + friend sc_signed operator % (const sc_unsigned& u, long v); + friend sc_unsigned operator % (const sc_unsigned& u, unsigned long v); + friend sc_signed operator % (const sc_unsigned& u, int v); + friend sc_unsigned operator % (const sc_unsigned& u, unsigned int v) + { return operator%(u, (unsigned long) v); } + + friend sc_signed operator % (int64 u, const sc_unsigned& v); + friend sc_unsigned operator % (uint64 u, const sc_unsigned& v); + friend sc_signed operator % (long u, const sc_unsigned& v); + friend sc_unsigned operator % (unsigned long u, const sc_unsigned& v); + friend sc_signed operator % (int u, const sc_unsigned& v); + friend sc_unsigned operator % (unsigned int u, const sc_unsigned& v) + { return operator%((unsigned long) u, v); } + + const sc_unsigned& operator %= (const sc_signed& v); + const sc_unsigned& operator %= (const sc_unsigned& v); + const sc_unsigned& operator %= (int64 v); + const sc_unsigned& operator %= (uint64 v); + const sc_unsigned& operator %= (long v); + const sc_unsigned& operator %= (unsigned long v); + const sc_unsigned& operator %= (int v) + { return operator%=((long) v); } + const sc_unsigned& operator %= (unsigned int v) + { return operator%=((unsigned long) v); } + + friend sc_unsigned operator % (const sc_unsigned& u, const sc_uint_base& v); + friend sc_signed operator % (const sc_unsigned& u, const sc_int_base& v); + friend sc_unsigned operator % (const sc_uint_base& u, const sc_unsigned& v); + friend sc_signed operator % (const sc_int_base& u, const sc_unsigned& v); + const sc_unsigned& operator %= (const sc_int_base& v); + const sc_unsigned& operator %= (const sc_uint_base& v); + + // BITWISE OPERATORS: + + // Bitwise AND operators: + + friend sc_signed operator & (const sc_unsigned& u, const sc_signed& v); + friend sc_signed operator & (const sc_signed& u, const sc_unsigned& v); + + friend sc_unsigned operator & (const sc_unsigned& u, const sc_unsigned& v); + friend sc_signed operator & (const sc_unsigned& u, int64 v); + friend sc_unsigned operator & (const sc_unsigned& u, uint64 v); + friend sc_signed operator & (const sc_unsigned& u, long v); + friend sc_unsigned operator & (const sc_unsigned& u, unsigned long v); + friend sc_signed operator & (const sc_unsigned& u, int v); + friend sc_unsigned operator & (const sc_unsigned& u, unsigned int v) + { return operator&(u, (unsigned long) v); } + + friend sc_signed operator & (int64 u, const sc_unsigned& v); + friend sc_unsigned operator & (uint64 u, const sc_unsigned& v); + friend sc_signed operator & (long u, const sc_unsigned& v); + friend sc_unsigned operator & (unsigned long u, const sc_unsigned& v); + friend sc_signed operator & (int u, const sc_unsigned& v); + friend sc_unsigned operator & (unsigned int u, const sc_unsigned& v) + { return operator&((unsigned long) u, v); } + + const sc_unsigned& operator &= (const sc_signed& v); + const sc_unsigned& operator &= (const sc_unsigned& v); + const sc_unsigned& operator &= (int64 v); + const sc_unsigned& operator &= (uint64 v); + const sc_unsigned& operator &= (long v); + const sc_unsigned& operator &= (unsigned long v); + const sc_unsigned& operator &= (int v) + { return operator&=((long) v); } + const sc_unsigned& operator &= (unsigned int v) + { return operator&=((unsigned long) v); } + + friend sc_unsigned operator & (const sc_unsigned& u, const sc_uint_base& v); + friend sc_signed operator & (const sc_unsigned& u, const sc_int_base& v); + friend sc_unsigned operator & (const sc_uint_base& u, const sc_unsigned& v); + friend sc_signed operator & (const sc_int_base& u, const sc_unsigned& v); + const sc_unsigned& operator &= (const sc_int_base& v); + const sc_unsigned& operator &= (const sc_uint_base& v); + + // Bitwise OR operators: + + friend sc_signed operator | (const sc_unsigned& u, const sc_signed& v); + friend sc_signed operator | (const sc_signed& u, const sc_unsigned& v); + + friend sc_unsigned operator | (const sc_unsigned& u, const sc_unsigned& v); + friend sc_signed operator | (const sc_unsigned& u, int64 v); + friend sc_unsigned operator | (const sc_unsigned& u, uint64 v); + friend sc_signed operator | (const sc_unsigned& u, long v); + friend sc_unsigned operator | (const sc_unsigned& u, unsigned long v); + friend sc_signed operator | (const sc_unsigned& u, int v); + friend sc_unsigned operator | (const sc_unsigned& u, unsigned int v) + { return operator|(u, (unsigned long) v); } + + friend sc_signed operator | (int64 u, const sc_unsigned& v); + friend sc_unsigned operator | (uint64 u, const sc_unsigned& v); + friend sc_signed operator | (long u, const sc_unsigned& v); + friend sc_unsigned operator | (unsigned long u, const sc_unsigned& v); + friend sc_signed operator | (int u, const sc_unsigned& v); + friend sc_unsigned operator | (unsigned int u, const sc_unsigned& v) + { return operator|((unsigned long) u, v); } + + const sc_unsigned& operator |= (const sc_signed& v); + const sc_unsigned& operator |= (const sc_unsigned& v); + const sc_unsigned& operator |= (int64 v); + const sc_unsigned& operator |= (uint64 v); + const sc_unsigned& operator |= (long v); + const sc_unsigned& operator |= (unsigned long v); + const sc_unsigned& operator |= (int v) + { return operator|=((long) v); } + const sc_unsigned& operator |= (unsigned int v) + { return operator|=((unsigned long) v); } + + friend sc_unsigned operator | (const sc_unsigned& u, const sc_uint_base& v); + friend sc_signed operator | (const sc_unsigned& u, const sc_int_base& v); + friend sc_unsigned operator | (const sc_uint_base& u, const sc_unsigned& v); + friend sc_signed operator | (const sc_int_base& u, const sc_unsigned& v); + const sc_unsigned& operator |= (const sc_int_base& v); + const sc_unsigned& operator |= (const sc_uint_base& v); + + // Bitwise XOR operators: + + friend sc_signed operator ^ (const sc_unsigned& u, const sc_signed& v); + friend sc_signed operator ^ (const sc_signed& u, const sc_unsigned& v); + + friend sc_unsigned operator ^ (const sc_unsigned& u, const sc_unsigned& v); + friend sc_signed operator ^ (const sc_unsigned& u, int64 v); + friend sc_unsigned operator ^ (const sc_unsigned& u, uint64 v); + friend sc_signed operator ^ (const sc_unsigned& u, long v); + friend sc_unsigned operator ^ (const sc_unsigned& u, unsigned long v); + friend sc_signed operator ^ (const sc_unsigned& u, int v); + friend sc_unsigned operator ^ (const sc_unsigned& u, unsigned int v) + { return operator^(u, (unsigned long) v); } + + friend sc_signed operator ^ (int64 u, const sc_unsigned& v); + friend sc_unsigned operator ^ (uint64 u, const sc_unsigned& v); + friend sc_signed operator ^ (long u, const sc_unsigned& v); + friend sc_unsigned operator ^ (unsigned long u, const sc_unsigned& v); + friend sc_signed operator ^ (int u, const sc_unsigned& v); + friend sc_unsigned operator ^ (unsigned int u, const sc_unsigned& v) + { return operator^((unsigned long) u, v); } + + const sc_unsigned& operator ^= (const sc_signed& v); + const sc_unsigned& operator ^= (const sc_unsigned& v); + const sc_unsigned& operator ^= (int64 v); + const sc_unsigned& operator ^= (uint64 v); + const sc_unsigned& operator ^= (long v); + const sc_unsigned& operator ^= (unsigned long v); + const sc_unsigned& operator ^= (int v) + { return operator^=((long) v); } + const sc_unsigned& operator ^= (unsigned int v) + { return operator^=((unsigned long) v); } + + friend sc_unsigned operator ^ (const sc_unsigned& u, const sc_uint_base& v); + friend sc_signed operator ^ (const sc_unsigned& u, const sc_int_base& v); + friend sc_unsigned operator ^ (const sc_uint_base& u, const sc_unsigned& v); + friend sc_signed operator ^ (const sc_int_base& u, const sc_unsigned& v); + const sc_unsigned& operator ^= (const sc_int_base& v); + const sc_unsigned& operator ^= (const sc_uint_base& v); + + // SHIFT OPERATORS: + + // LEFT SHIFT operators: + + friend sc_unsigned operator << (const sc_unsigned& u, const sc_signed& v); + friend sc_signed operator << (const sc_signed& u, const sc_unsigned& v); + + friend sc_unsigned operator << (const sc_unsigned& u, const sc_unsigned& v); + friend sc_unsigned operator << (const sc_unsigned& u, int64 v); + friend sc_unsigned operator << (const sc_unsigned& u, uint64 v); + friend sc_unsigned operator << (const sc_unsigned& u, long v); + friend sc_unsigned operator << (const sc_unsigned& u, unsigned long v); + friend sc_unsigned operator << (const sc_unsigned& u, int v) + { return operator<<(u, (long) v); } + friend sc_unsigned operator << (const sc_unsigned& u, unsigned int v) + { return operator<<(u, (unsigned long) v); } + + const sc_unsigned& operator <<= (const sc_signed& v); + const sc_unsigned& operator <<= (const sc_unsigned& v); + const sc_unsigned& operator <<= (int64 v); + const sc_unsigned& operator <<= (uint64 v); + const sc_unsigned& operator <<= (long v); + const sc_unsigned& operator <<= (unsigned long v); + const sc_unsigned& operator <<= (int v) + { return operator<<=((long) v); } + const sc_unsigned& operator <<= (unsigned int v) + { return operator<<=((unsigned long) v); } + + friend sc_unsigned operator << (const sc_unsigned& u, const sc_uint_base& v); + friend sc_unsigned operator << (const sc_unsigned& u, const sc_int_base& v); + const sc_unsigned& operator <<= (const sc_int_base& v); + const sc_unsigned& operator <<= (const sc_uint_base& v); + + // RIGHT SHIFT operators: + + friend sc_unsigned operator >> (const sc_unsigned& u, const sc_signed& v); + friend sc_signed operator >> (const sc_signed& u, const sc_unsigned& v); + + friend sc_unsigned operator >> (const sc_unsigned& u, const sc_unsigned& v); + friend sc_unsigned operator >> (const sc_unsigned& u, int64 v); + friend sc_unsigned operator >> (const sc_unsigned& u, uint64 v); + friend sc_unsigned operator >> (const sc_unsigned& u, long v); + friend sc_unsigned operator >> (const sc_unsigned& u, unsigned long v); + friend sc_unsigned operator >> (const sc_unsigned& u, int v) + { return operator>>(u, (long) v); } + friend sc_unsigned operator >> (const sc_unsigned& u, unsigned int v) + { return operator>>(u, (unsigned long) v); } + + const sc_unsigned& operator >>= (const sc_signed& v); + const sc_unsigned& operator >>= (const sc_unsigned& v); + const sc_unsigned& operator >>= (int64 v); + const sc_unsigned& operator >>= (uint64 v); + const sc_unsigned& operator >>= (long v); + const sc_unsigned& operator >>= (unsigned long v); + const sc_unsigned& operator >>= (int v) + { return operator>>=((long) v); } + const sc_unsigned& operator >>= (unsigned int v) + { return operator>>=((unsigned long) v); } + + friend sc_unsigned operator >> ( const sc_unsigned& , const sc_uint_base& ); + friend sc_unsigned operator >> ( const sc_unsigned&, const sc_int_base& ); + const sc_unsigned& operator >>= (const sc_int_base& v); + const sc_unsigned& operator >>= (const sc_uint_base& v); + + // Unary arithmetic operators + friend sc_unsigned operator + (const sc_unsigned& u); + friend sc_signed operator - (const sc_unsigned& u); + + // LOGICAL OPERATORS: + + // Logical EQUAL operators: + + friend bool operator == (const sc_unsigned& u, const sc_signed& v); + friend bool operator == (const sc_signed& u, const sc_unsigned& v); + + friend bool operator == (const sc_unsigned& u, const sc_unsigned& v); + friend bool operator == (const sc_unsigned& u, int64 v); + friend bool operator == (const sc_unsigned& u, uint64 v); + friend bool operator == (const sc_unsigned& u, long v); + friend bool operator == (const sc_unsigned& u, unsigned long v); + friend bool operator == (const sc_unsigned& u, int v) + { return operator==(u, (long) v); } + friend bool operator == (const sc_unsigned& u, unsigned int v) + { return operator==(u, (unsigned long) v); } + + friend bool operator == (int64 u, const sc_unsigned& v); + friend bool operator == (uint64 u, const sc_unsigned& v); + friend bool operator == (long u, const sc_unsigned& v); + friend bool operator == (unsigned long u, const sc_unsigned& v); + friend bool operator == (int u, const sc_unsigned& v) + { return operator==((long) u, v); } + friend bool operator == (unsigned int u, const sc_unsigned& v) + { return operator==((unsigned long) u, v); } + + friend bool operator == (const sc_unsigned& u, const sc_uint_base& v); + friend bool operator == (const sc_unsigned& u, const sc_int_base& v); + friend bool operator == (const sc_uint_base& u, const sc_unsigned& v); + friend bool operator == (const sc_int_base& u, const sc_unsigned& v); + + // Logical NOT_EQUAL operators: + + friend bool operator != (const sc_unsigned& u, const sc_signed& v); + friend bool operator != (const sc_signed& u, const sc_unsigned& v); + + friend bool operator != (const sc_unsigned& u, const sc_unsigned& v); + friend bool operator != (const sc_unsigned& u, int64 v); + friend bool operator != (const sc_unsigned& u, uint64 v); + friend bool operator != (const sc_unsigned& u, long v); + friend bool operator != (const sc_unsigned& u, unsigned long v); + friend bool operator != (const sc_unsigned& u, int v) + { return operator!=(u, (long) v); } + friend bool operator != (const sc_unsigned& u, unsigned int v) + { return operator!=(u, (unsigned long) v); } + + friend bool operator != (int64 u, const sc_unsigned& v); + friend bool operator != (uint64 u, const sc_unsigned& v); + friend bool operator != (long u, const sc_unsigned& v); + friend bool operator != (unsigned long u, const sc_unsigned& v); + friend bool operator != (int u, const sc_unsigned& v) + { return operator!=((long) u, v); } + friend bool operator != (unsigned int u, const sc_unsigned& v) + { return operator!=((unsigned long) u, v); } + + friend bool operator != (const sc_unsigned& u, const sc_uint_base& v); + friend bool operator != (const sc_unsigned& u, const sc_int_base& v); + friend bool operator != (const sc_uint_base& u, const sc_unsigned& v); + friend bool operator != (const sc_int_base& u, const sc_unsigned& v); + + // Logical LESS_THAN operators: + + friend bool operator < (const sc_unsigned& u, const sc_signed& v); + friend bool operator < (const sc_signed& u, const sc_unsigned& v); + + friend bool operator < (const sc_unsigned& u, const sc_unsigned& v); + friend bool operator < (const sc_unsigned& u, int64 v); + friend bool operator < (const sc_unsigned& u, uint64 v); + friend bool operator < (const sc_unsigned& u, long v); + friend bool operator < (const sc_unsigned& u, unsigned long v); + friend bool operator < (const sc_unsigned& u, int v) + { return operator<(u, (long) v); } + friend bool operator < (const sc_unsigned& u, unsigned int v) + { return operator<(u, (unsigned long) v); } + + friend bool operator < (int64 u, const sc_unsigned& v); + friend bool operator < (uint64 u, const sc_unsigned& v); + friend bool operator < (long u, const sc_unsigned& v); + friend bool operator < (unsigned long u, const sc_unsigned& v); + friend bool operator < (int u, const sc_unsigned& v) + { return operator<((long) u, v); } + friend bool operator < (unsigned int u, const sc_unsigned& v) + { return operator<((unsigned long) u, v); } + + friend bool operator < (const sc_unsigned& u, const sc_uint_base& v); + friend bool operator < (const sc_unsigned& u, const sc_int_base& v); + friend bool operator < (const sc_uint_base& u, const sc_unsigned& v); + friend bool operator < (const sc_int_base& u, const sc_unsigned& v); + + // Logical LESS_THAN_AND_EQUAL operators: + + friend bool operator <= (const sc_unsigned& u, const sc_signed& v); + friend bool operator <= (const sc_signed& u, const sc_unsigned& v); + + friend bool operator <= (const sc_unsigned& u, const sc_unsigned& v); + friend bool operator <= (const sc_unsigned& u, int64 v); + friend bool operator <= (const sc_unsigned& u, uint64 v); + friend bool operator <= (const sc_unsigned& u, long v); + friend bool operator <= (const sc_unsigned& u, unsigned long v); + friend bool operator <= (const sc_unsigned& u, int v) + { return operator<=(u, (long) v); } + friend bool operator <= (const sc_unsigned& u, unsigned int v) + { return operator<=(u, (unsigned long) v); } + + friend bool operator <= (int64 u, const sc_unsigned& v); + friend bool operator <= (uint64 u, const sc_unsigned& v); + friend bool operator <= (long u, const sc_unsigned& v); + friend bool operator <= (unsigned long u, const sc_unsigned& v); + friend bool operator <= (int u, const sc_unsigned& v) + { return operator<=((long) u, v); } + friend bool operator <= (unsigned int u, const sc_unsigned& v) + { return operator<=((unsigned long) u, v); } + + friend bool operator <= (const sc_unsigned& u, const sc_uint_base& v); + friend bool operator <= (const sc_unsigned& u, const sc_int_base& v); + friend bool operator <= (const sc_uint_base& u, const sc_unsigned& v); + friend bool operator <= (const sc_int_base& u, const sc_unsigned& v); + + // Logical GREATER_THAN operators: + + friend bool operator > (const sc_unsigned& u, const sc_signed& v); + friend bool operator > (const sc_signed& u, const sc_unsigned& v); + + friend bool operator > (const sc_unsigned& u, const sc_unsigned& v); + friend bool operator > (const sc_unsigned& u, int64 v); + friend bool operator > (const sc_unsigned& u, uint64 v); + friend bool operator > (const sc_unsigned& u, long v); + friend bool operator > (const sc_unsigned& u, unsigned long v); + friend bool operator > (const sc_unsigned& u, int v) + { return operator>(u, (long) v); } + friend bool operator > (const sc_unsigned& u, unsigned int v) + { return operator>(u, (unsigned long) v); } + + friend bool operator > (int64 u, const sc_unsigned& v); + friend bool operator > (uint64 u, const sc_unsigned& v); + friend bool operator > (long u, const sc_unsigned& v); + friend bool operator > (unsigned long u, const sc_unsigned& v); + friend bool operator > (int u, const sc_unsigned& v) + { return operator>((long) u, v); } + friend bool operator > (unsigned int u, const sc_unsigned& v) + { return operator>((unsigned long) u, v); } + + friend bool operator > (const sc_unsigned& u, const sc_uint_base& v); + friend bool operator > (const sc_unsigned& u, const sc_int_base& v); + friend bool operator > (const sc_uint_base& u, const sc_unsigned& v); + friend bool operator > (const sc_int_base& u, const sc_unsigned& v); + + // Logical GREATER_THAN_AND_EQUAL operators: + + friend bool operator >= (const sc_unsigned& u, const sc_signed& v); + friend bool operator >= (const sc_signed& u, const sc_unsigned& v); + + friend bool operator >= (const sc_unsigned& u, const sc_unsigned& v); + friend bool operator >= (const sc_unsigned& u, int64 v); + friend bool operator >= (const sc_unsigned& u, uint64 v); + friend bool operator >= (const sc_unsigned& u, long v); + friend bool operator >= (const sc_unsigned& u, unsigned long v); + friend bool operator >= (const sc_unsigned& u, int v) + { return operator>=(u, (long) v); } + friend bool operator >= (const sc_unsigned& u, unsigned int v) + { return operator>=(u, (unsigned long) v); } + + friend bool operator >= (int64 u, const sc_unsigned& v); + friend bool operator >= (uint64 u, const sc_unsigned& v); + friend bool operator >= (long u, const sc_unsigned& v); + friend bool operator >= (unsigned long u, const sc_unsigned& v); + friend bool operator >= (int u, const sc_unsigned& v) + { return operator>=((long) u, v); } + friend bool operator >= (unsigned int u, const sc_unsigned& v) + { return operator>=((unsigned long) u, v); } + + friend bool operator >= (const sc_unsigned& u, const sc_uint_base& v); + friend bool operator >= (const sc_unsigned& u, const sc_int_base& v); + friend bool operator >= (const sc_uint_base& u, const sc_unsigned& v); + friend bool operator >= (const sc_int_base& u, const sc_unsigned& v); + + // Bitwise NOT operator (unary). + friend sc_unsigned operator ~ (const sc_unsigned& u); + + // Helper functions. + friend int compare_unsigned(small_type us, + int unb, + int und, + const sc_digit *ud, + small_type vs, + int vnb, + int vnd, + const sc_digit *vd, + small_type if_u_signed, + small_type if_v_signed); + + friend sc_unsigned add_unsigned_friend(small_type us, + int unb, + int und, + const sc_digit *ud, + small_type vs, + int vnb, + int vnd, + const sc_digit *vd); + + friend sc_unsigned sub_unsigned_friend(small_type us, + int unb, + int und, + const sc_digit *ud, + small_type vs, + int vnb, + int vnd, + const sc_digit *vd); + + friend sc_unsigned mul_unsigned_friend(small_type s, + int unb, + int und, + const sc_digit *ud, + int vnb, + int vnd, + const sc_digit *vd); + + friend sc_unsigned div_unsigned_friend(small_type s, + int unb, + int und, + const sc_digit *ud, + int vnb, + int vnd, + const sc_digit *vd); + + friend sc_unsigned mod_unsigned_friend(small_type us, + int unb, + int und, + const sc_digit *ud, + int vnb, + int vnd, + const sc_digit *vd); + + friend sc_unsigned and_unsigned_friend(small_type us, + int unb, + int und, + const sc_digit *ud, + small_type vs, + int vnb, + int vnd, + const sc_digit *vd); + + friend sc_unsigned or_unsigned_friend(small_type us, + int unb, + int und, + const sc_digit *ud, + small_type vs, + int vnb, + int vnd, + const sc_digit *vd); + + friend sc_unsigned xor_unsigned_friend(small_type us, + int unb, + int und, + const sc_digit *ud, + small_type vs, + int vnb, + int vnd, + const sc_digit *vd); + +public: + static sc_core::sc_vpool<sc_unsigned> m_pool; + +private: + + small_type sgn; // Shortened as s. + int nbits; // Shortened as nb. + int ndigits; // Shortened as nd. + +#ifdef SC_MAX_NBITS + sc_digit digit[DIV_CEIL(SC_MAX_NBITS)]; // Shortened as d. +#else + sc_digit *digit; // Shortened as d. +#endif + + // Private constructors: + + // Create a copy of v with sign s. + sc_unsigned(const sc_unsigned& v, small_type s); + sc_unsigned(const sc_signed& v, small_type s); + + // Create an unsigned number with the given attributes. + sc_unsigned(small_type s, int nb, int nd, + sc_digit *d, bool alloc = true); + + // Create an unsigned number using the bits u[l..r]. + sc_unsigned(const sc_signed* u, int l, int r); + sc_unsigned(const sc_unsigned* u, int l, int r); + + // Private member functions. The called functions are inline functions. + + small_type default_sign() const + { return SC_POS; } + + int num_bits(int nb) const { return nb + 1; } + + bool check_if_outside(int bit_num) const; + + void copy_digits(int nb, int nd, const sc_digit *d) + { copy_digits_unsigned(sgn, nbits, ndigits, digit, nb, nd, d); } + + void makezero() + { sgn = make_zero(ndigits, digit); } + + // Conversion functions between 2's complement (2C) and + // sign-magnitude (SM): + void convert_2C_to_SM() + { sgn = convert_unsigned_2C_to_SM(nbits, ndigits, digit); } + + void convert_SM_to_2C_to_SM() + { sgn = convert_unsigned_SM_to_2C_to_SM(sgn, nbits, ndigits, digit); } + + void convert_SM_to_2C() + { convert_unsigned_SM_to_2C(sgn, ndigits, digit); } + +}; + + + +inline +::std::ostream& +operator << ( ::std::ostream&, const sc_unsigned& ); + +inline +::std::istream& +operator >> ( ::std::istream&, sc_unsigned& ); + + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + +// ---------------------------------------------------------------------------- +// CLASS : sc_unsigned_bitref_r +// +// Proxy class for sc_unsigned bit selection (r-value only). +// ---------------------------------------------------------------------------- + + +inline +::std::ostream& +operator << ( ::std::ostream& os, const sc_unsigned_bitref_r& a ) +{ + a.print( os ); + return os; +} + + +// ---------------------------------------------------------------------------- +// CLASS : sc_unsigned_bitref +// +// Proxy class for sc_unsigned bit selection (r-value and l-value). +// ---------------------------------------------------------------------------- + +template<class T> +inline const sc_unsigned_subref& sc_unsigned_subref::operator = ( + const sc_generic_base<T>& a ) +{ + sc_unsigned temp( length() ); + a->to_sc_unsigned(temp); + return *this = temp; +} + +inline +::std::istream& +operator >> ( ::std::istream& is, sc_unsigned_bitref& a ) +{ + a.scan( is ); + return is; +} + + +// ---------------------------------------------------------------------------- +// CLASS : sc_unsigned_subref_r +// +// Proxy class for sc_unsigned part selection (r-value only). +// ---------------------------------------------------------------------------- + +// reduce methods + +inline bool sc_unsigned_subref_r::and_reduce() const +{ + const sc_unsigned* target_p = m_obj_p; + for ( int i = m_right; i <= m_left; i++ ) + if ( !target_p->test(i) ) return false; + return true; +} + +inline bool sc_unsigned_subref_r::nand_reduce() const +{ + return !and_reduce(); +} + +inline bool sc_unsigned_subref_r::or_reduce() const +{ + const sc_unsigned* target_p = m_obj_p; + for ( int i = m_right; i <= m_left; i++ ) + if ( target_p->test(i) ) return true; + return false; +} + +inline bool sc_unsigned_subref_r::nor_reduce() const +{ + return !or_reduce(); +} + +inline bool sc_unsigned_subref_r::xor_reduce() const +{ + int odd; + const sc_unsigned* target_p = m_obj_p; + odd = 0; + for ( int i = m_right; i <= m_left; i++ ) + if ( target_p->test(i) ) odd = ~odd; + return odd ? true : false; +} + +inline bool sc_unsigned_subref_r::xnor_reduce() const +{ + return !xor_reduce(); +} + + +inline +::std::ostream& +operator << ( ::std::ostream& os, const sc_unsigned_subref_r& a ) +{ + a.print( os ); + return os; +} + + +// ---------------------------------------------------------------------------- +// CLASS : sc_unsigned_subref +// +// Proxy class for sc_unsigned part selection (r-value and l-value). +// ---------------------------------------------------------------------------- + +// assignment operators + +inline +const sc_unsigned_subref& +sc_unsigned_subref::operator = ( const char* a ) +{ + sc_unsigned aa( length() ); + return ( *this = aa = a ); +} + + +inline +::std::istream& +operator >> ( ::std::istream& is, sc_unsigned_subref& a ) +{ + a.scan( is ); + return is; +} + + + +// ---------------------------------------------------------------------------- +// CLASS : sc_unsigned +// +// Arbitrary precision signed number. +// ---------------------------------------------------------------------------- + +template<class T> +sc_unsigned::sc_unsigned( const sc_generic_base<T>& v ) +{ + int nb = v->length(); + sgn = default_sign(); + if( nb > 0 ) { + nbits = num_bits( nb ); + } else { + char msg[BUFSIZ]; + std::sprintf( msg, + "sc_unsigned( sc_generic_base<T> ) : nb = %d is not valid", nb); + SC_REPORT_ERROR( sc_core::SC_ID_INIT_FAILED_, msg ); + } + ndigits = DIV_CEIL(nbits); +# ifdef SC_MAX_NBITS + test_bound(nb); +# else + digit = new sc_digit[ndigits]; +# endif + makezero(); + v->to_sc_unsigned(*this); +} + + +inline +::std::ostream& +operator << ( ::std::ostream& os, const sc_unsigned& a ) +{ + a.print( os ); + return os; +} + +inline +::std::istream& +operator >> ( ::std::istream& is, sc_unsigned& a ) +{ + a.scan( is ); + return is; +} + + +} // namespace sc_dt + + +#endif diff --git a/ext/systemc/src/sysc/datatypes/int/sc_unsigned_bitref.inc b/ext/systemc/src/sysc/datatypes/int/sc_unsigned_bitref.inc new file mode 100644 index 000000000..c1ad02662 --- /dev/null +++ b/ext/systemc/src/sysc/datatypes/int/sc_unsigned_bitref.inc @@ -0,0 +1,162 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_unsigned_bitref.h -- Proxy class that is declared in sc_unsigned.h. + + Original Author: Ali Dasdan, Synopsys, Inc. + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + + +// ---------------------------------------------------------------------------- +// CLASS : sc_unsigned_bitref_r +// +// Proxy class for sc_unsigned bit selection (r-value only). +// ---------------------------------------------------------------------------- + +// implicit conversion to uint64 + +sc_unsigned_bitref_r::operator uint64 () const +{ + return m_obj_p->test( m_index ); +} + +bool +sc_unsigned_bitref_r::operator ! () const +{ + return ( ! m_obj_p->test( m_index ) ); +} + +bool +sc_unsigned_bitref_r::operator ~ () const +{ + return ( ! m_obj_p->test( m_index ) ); +} + + +// ---------------------------------------------------------------------------- +// CLASS : sc_unsigned_bitref +// +// Proxy class for sc_unsigned bit selection (r-value and l-value). +// ---------------------------------------------------------------------------- + +// assignment operators + +const sc_unsigned_bitref& +sc_unsigned_bitref::operator = ( const sc_unsigned_bitref_r& b ) +{ + m_obj_p->set( m_index, (bool) b ); + return *this; +} + +const sc_unsigned_bitref& +sc_unsigned_bitref::operator = ( const sc_unsigned_bitref& b ) +{ + m_obj_p->set( m_index, (bool) b ); + return *this; +} + +const sc_unsigned_bitref& +sc_unsigned_bitref::operator = ( bool b ) +{ + m_obj_p->set( m_index, b ); + return *this; +} + + +const sc_unsigned_bitref& +sc_unsigned_bitref::operator &= ( bool b ) +{ + if( ! b ) { + m_obj_p->clear( m_index ); + } + return *this; +} + +const sc_unsigned_bitref& +sc_unsigned_bitref::operator |= ( bool b ) +{ + if( b ) { + m_obj_p->set( m_index ); + } + return *this; +} + +const sc_unsigned_bitref& +sc_unsigned_bitref::operator ^= ( bool b ) +{ + if( b ) { + m_obj_p->invert( m_index ); + } + return *this; +} + +// #### OPTIMIZE +void sc_unsigned_bitref::concat_set(int64 src, int low_i) +{ + bool value = 1 & ((low_i < 64) ? (src >> low_i) : (src >> 63)); + m_obj_p->set(low_i, value); +} + +void sc_unsigned_bitref::concat_set(const sc_signed& src, int low_i) +{ + if ( low_i < src.length() ) + m_obj_p->set(low_i, src.test(low_i)); + else + m_obj_p->set(low_i, src<0); +} + +void sc_unsigned_bitref::concat_set(const sc_unsigned& src, int low_i) +{ + if ( low_i < src.nbits ) + m_obj_p->set(low_i, src.test(low_i)); + else + m_obj_p->set(low_i, 0); +} + +void sc_unsigned_bitref::concat_set(uint64 src, int low_i) +{ + bool value = ((low_i < 64) ? (src >> low_i)&1 : 0); + m_obj_p->set(low_i, value); +} + +// other methods + +void +sc_unsigned_bitref::scan( ::std::istream& is ) +{ + bool b; + is >> b; + *this = b; +} + + +// End of file diff --git a/ext/systemc/src/sysc/datatypes/int/sc_unsigned_subref.inc b/ext/systemc/src/sysc/datatypes/int/sc_unsigned_subref.inc new file mode 100644 index 000000000..142d6b2dc --- /dev/null +++ b/ext/systemc/src/sysc/datatypes/int/sc_unsigned_subref.inc @@ -0,0 +1,407 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_unsigned_subref.h -- Proxy class that is declared in sc_unsigned.h. + + Original Author: Ali Dasdan, Synopsys, Inc. + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + + +// ---------------------------------------------------------------------------- +// CLASS : sc_unsigned_subref_r +// +// Proxy class for sc_unsigned part selection (r-value only). +// ---------------------------------------------------------------------------- + +// concatenation support + +uint64 sc_unsigned_subref_r::concat_get_uint64() const // #### Speed up! +{ + sc_unsigned a( m_obj_p, m_left, m_right ); + return a.to_uint64(); +} + + +bool sc_unsigned_subref_r::concat_get_ctrl(sc_digit* dst_p, int low_i) const + // #### Speed up! +{ + sc_unsigned a( m_obj_p, m_left, m_right ); + return a.concat_get_ctrl( dst_p, low_i ); +} + +bool sc_unsigned_subref_r::concat_get_data(sc_digit* dst_p, int low_i) const + // #### Speed up! +{ + sc_unsigned a( m_obj_p, m_left, m_right ); + return a.concat_get_data( dst_p, low_i ); +} + + +// implicit conversion to sc_unsigned + +sc_unsigned_subref_r::operator sc_unsigned () const +{ + return sc_unsigned( m_obj_p, m_left, m_right ); +} + + +// explicit conversions + +int +sc_unsigned_subref_r::to_int() const +{ + sc_unsigned a( m_obj_p, m_left, m_right ); + return a.to_int(); +} + +unsigned int +sc_unsigned_subref_r::to_uint() const +{ + sc_unsigned a( m_obj_p, m_left, m_right ); + return a.to_uint(); +} + +long +sc_unsigned_subref_r::to_long() const +{ + sc_unsigned a( m_obj_p, m_left, m_right ); + return a.to_long(); +} + +unsigned long +sc_unsigned_subref_r::to_ulong() const +{ + sc_unsigned a( m_obj_p, m_left, m_right ); + return a.to_ulong(); +} + +int64 +sc_unsigned_subref_r::to_int64() const +{ + sc_unsigned a( m_obj_p, m_left, m_right ); + return a.to_int64(); +} + +uint64 +sc_unsigned_subref_r::to_uint64() const +{ + sc_unsigned a( m_obj_p, m_left, m_right ); + return a.to_uint64(); +} + +double +sc_unsigned_subref_r::to_double() const +{ + sc_unsigned a( m_obj_p, m_left, m_right ); + return a.to_double(); +} + + +// explicit conversion to character string + +const std::string +sc_unsigned_subref_r::to_string( sc_numrep numrep ) const +{ + sc_unsigned a( length() ); + a = *this; + return a.to_string( numrep ); +} + +const std::string +sc_unsigned_subref_r::to_string( sc_numrep numrep, bool w_prefix ) const +{ + sc_unsigned a( length() ); + a = *this; + return a.to_string( numrep, w_prefix ); +} + + +// ---------------------------------------------------------------------------- +// CLASS : sc_unsigned_subref +// +// Proxy class for sc_unsigned part selection (r-value and l-value). +// ---------------------------------------------------------------------------- + +// assignment operators + +const sc_unsigned_subref& +sc_unsigned_subref::operator = ( const sc_unsigned_subref_r& a ) +{ + return operator = ( (sc_unsigned)( a ) ); +} + +const sc_unsigned_subref& +sc_unsigned_subref::operator = ( const sc_unsigned_subref& a ) +{ + if( this == &a ) { + return *this; + } + return operator = ( (sc_unsigned)( a ) ); +} + +const sc_unsigned_subref& +sc_unsigned_subref::operator = ( const sc_unsigned& v ) +{ + int i; + int l = sc_min( m_left, v.nbits - 1 + m_right ); + + for( i = m_right; i <= l; ++ i ) m_obj_p->set( i, v.test( i - m_right ) ); + for ( ; i <= m_left; i++ ) m_obj_p->set( i, v.test( l ) ); + return *this; +} + +const sc_unsigned_subref& +sc_unsigned_subref::operator = ( const sc_signed_subref_r& v ) +{ + return operator = ( (sc_unsigned)( v ) ); +} + +const sc_unsigned_subref& +sc_unsigned_subref::operator = ( const sc_signed& v ) +{ + int i; + int l = sc_min( m_left, v.nbits - 1 + m_right ); + + for( i = m_right; i <= l; ++ i ) m_obj_p->set( i, v.test( i - m_right ) ); + for ( ; i <= m_left; i++ ) m_obj_p->set( i, 0 ); + return *this; +} + +const sc_unsigned_subref& +sc_unsigned_subref::operator = ( unsigned long v ) +{ + for( int i = m_right; i <= m_left; ++ i ) { + m_obj_p->set( i, static_cast<bool>( v & 1 ) ); + v >>= 1; + } + return *this; +} + +const sc_unsigned_subref& +sc_unsigned_subref::operator = ( long v ) +{ + unsigned long v2 = (unsigned long) v; + for( int i = m_right; i <= m_left; ++ i ) { + m_obj_p->set( i, static_cast<bool>( v2 & 1 ) ); + v2 >>= 1; + } + return *this; +} + +const sc_unsigned_subref& +sc_unsigned_subref::operator = ( uint64 v ) +{ + for( int i = m_right; i <= m_left; ++ i ) { + m_obj_p->set( i, static_cast<bool>( v & 1 ) ); + v >>= 1; + } + return *this; +} + +const sc_unsigned_subref& +sc_unsigned_subref::operator = ( int64 v ) +{ + uint64 v2 = (uint64) v; + for( int i = m_right; i <= m_left; ++ i ) { + m_obj_p->set( i, static_cast<bool>( v2 & 1 ) ); + v2 >>= 1; + } + return *this; +} + +const sc_unsigned_subref& +sc_unsigned_subref::operator = ( double v ) +{ + is_bad_double(v); + + int nb = m_left - m_right + 1; + int nd = DIV_CEIL(nb); + +#ifdef SC_MAX_NBITS + sc_digit d[MAX_NDIGITS]; +#else + sc_digit *d = new sc_digit[nd]; +#endif + + if (v < 0) + v = -v; + + int i = 0; + + while (floor(v) && (i < nd)) { +#ifndef _WIN32 + d[i++] = (sc_digit) floor(remainder(v, DIGIT_RADIX)); +#else + d[i++] = (sc_digit) floor(fmod(v, DIGIT_RADIX)); +#endif + v /= DIGIT_RADIX; + } + + vec_zero(i, nd, d); + + sc_digit val = 1; // Bit value. + int j = 0; // Current digit in d. + + i = 0; // Current bit in d. + + while (i < nb) { + + m_obj_p->set(i + m_right, (bool) (d[j] & val)); + + ++i; + + if (i % BITS_PER_DIGIT == 0) { + val = 1; + ++j; + } + else + val <<= 1; + } + +#ifndef SC_MAX_NBITS + delete [] d; +#endif + + return *this; +} + +const sc_unsigned_subref& +sc_unsigned_subref::operator = ( const sc_int_base& a ) +{ + return operator = ( (int64) a ); +} + +const sc_unsigned_subref& +sc_unsigned_subref::operator = ( const sc_uint_base& a ) +{ + return operator = ( (uint64) a ); +} + +// concatenation methods + +void sc_unsigned_subref::concat_set( int64 src, int low_i ) +{ + int i; + int l; + bool sign = src < 0; + + if ( low_i < 64 ) + { + src = src >> low_i; + l = sc_min( m_left, (63-low_i) + m_right ); + for( i = m_right; i <= l; ++ i ) { + m_obj_p->set( i, src & 1 ); + src = src >> 1; + } + for ( ; i <= m_left; i++ ) m_obj_p->set(sign); + } + else + { + for( i = m_right; i <= m_left; ++ i ) m_obj_p->set(sign); + } +} + +void sc_unsigned_subref::concat_set( const sc_signed& src, int low_i ) +{ + int i; + int l; + int src_i; + bool sign = src.test(src.nbits-1); + l = src.nbits - (low_i+1); + if ( l >= 0 ) + { + src_i = low_i; + l = sc_min( m_left, l + m_right ); + for( i = m_right; i <= l; ++ i, src_i++ ) { + m_obj_p->set( i, src.test( src_i ) ); + } + for ( ; i <= m_left; i++ ) m_obj_p->set(i, sign); + } + else + { + for( i = m_right; i <= m_left; ++ i ) m_obj_p->set(i, sign); + } +} + +void sc_unsigned_subref::concat_set( const sc_unsigned& src, int low_i ) +{ + int i; + int l; + int src_i; + l = src.nbits - (low_i+2); + if ( l >= 0 ) + { + src_i = low_i; + l = sc_min( m_left, l + m_right ); + for( i = m_right; i <= l; ++ i, src_i++ ) { + m_obj_p->set( i, src.test( src_i ) ); + } + for ( ; i <= m_left; i++ ) m_obj_p->set(i, false); + } + else + { + for( i = m_right; i <= m_left; ++ i ) m_obj_p->set(i, false); + } +} + +void sc_unsigned_subref::concat_set( uint64 src, int low_i ) +{ + int i; + int l; + + if ( low_i < 64 ) + { + src = src >> low_i; + l = sc_min( m_left, (63-low_i) + m_right ); + for( i = m_right; i <= l; ++ i ) { + m_obj_p->set( i, src & 1 ); + src = src >> 1; + } + for ( ; i <= m_left; i++ ) m_obj_p->set(false); + } + else + { + for( i = m_right; i <= m_left; ++ i ) m_obj_p->set(false); + } +} +// other methods + +void +sc_unsigned_subref::scan( ::std::istream& is ) +{ + std::string s; + is >> s; + *this = s.c_str(); +} + + +// End of file diff --git a/ext/systemc/src/sysc/datatypes/misc/sc_concatref.cpp b/ext/systemc/src/sysc/datatypes/misc/sc_concatref.cpp new file mode 100644 index 000000000..566bee234 --- /dev/null +++ b/ext/systemc/src/sysc/datatypes/misc/sc_concatref.cpp @@ -0,0 +1,59 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_concatref.cpp -- Concatenation support. + + Original Author: Andy Goodrich, Forte Design Systems, Inc. + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + +// $Log: sc_concatref.cpp,v $ +// Revision 1.1.1.1 2006/12/15 20:20:05 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:54:01 acg +// Andy Goodrich: added $Log command so that CVS comments are reproduced in +// the source. +// + +#include "sysc/datatypes/misc/sc_concatref.h" +#include "sysc/utils/sc_temporary.h" + +// STORAGE POOLS USED BY sc_concatref: + +namespace sc_dt { + sc_core::sc_vpool<sc_concat_bool> sc_concat_bool::m_pool(9); + sc_core::sc_vpool<sc_concatref> sc_concatref::m_pool(9); +} // namespace sc_dt + +namespace sc_core { + sc_byte_heap sc_temp_heap(0x300000); +} // namespace sc_core diff --git a/ext/systemc/src/sysc/datatypes/misc/sc_concatref.h b/ext/systemc/src/sysc/datatypes/misc/sc_concatref.h new file mode 100644 index 000000000..92dcc18ec --- /dev/null +++ b/ext/systemc/src/sysc/datatypes/misc/sc_concatref.h @@ -0,0 +1,855 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_concatref.h -- Concatenation support. + + Original Author: Andy Goodrich, Forte Design, Inc. + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + Andy Goodrich, Forte Design Systems, 17 Nov 2002 + Creation of sc_concatref class by merging the capabilities of + sc_int_concref, sc_int_concref, sc_uint_concref, sc_uint_concref, + and implementing the capabilities of sc_signed_concref, sc_signed_concref, + sc_unsigned_concref, and sc_unsigned_concref. The resultant class allows + mixed mode concatenations on the left and right sides of an assignment. + + *****************************************************************************/ + +// $Log: sc_concatref.h,v $ +// Revision 1.6 2011/08/24 22:05:48 acg +// Torsten Maehne: initialization changes to remove warnings. +// +// Revision 1.5 2009/11/17 19:58:15 acg +// Andy Goodrich: fix of shift rhs possibilities to include "int". +// +// Revision 1.4 2009/02/28 00:26:29 acg +// Andy Goodrich: bug fixes. +// +// Revision 1.3 2008/04/29 20:23:55 acg +// Andy Goodrich: fixed the code that assigns the value of a string to +// an sc_concatref instance. +// +// Revision 1.2 2008/02/14 20:57:26 acg +// Andy Goodrich: added casts to ~0 instances to keep MSVC compiler happy. +// +// Revision 1.1.1.1 2006/12/15 20:20:05 acg +// SystemC 2.3 +// +// Revision 1.4 2006/10/23 19:36:59 acg +// Andy Goodrich: changed casts for operations on concatenation values to +// mirror those of sc_unsigned. For instance, an sc_unsigned minus a value +// returns an sc_signed result, whereas an sc_concatref minus a value was +// returning an sc_unsigned result. Now both sc_unsigned and sc_concatref +// minus a value return an sc_signed result. +// +// Revision 1.3 2006/01/13 18:54:01 acg +// Andy Goodrich: added $Log command so that CVS comments are reproduced in +// the source. +// + +#ifndef SC_CONCATREF_H +#define SC_CONCATREF_H + +#include "sysc/kernel/sc_object.h" +#include "sysc/datatypes/misc/sc_value_base.h" +#include "sysc/utils/sc_temporary.h" +#include "sysc/datatypes/bit/sc_bv.h" +#include "sysc/datatypes/bit/sc_lv.h" +#include "sysc/datatypes/int/sc_int_base.h" +#include "sysc/datatypes/int/sc_uint_base.h" +#include "sysc/datatypes/int/sc_signed.h" +#include "sysc/datatypes/int/sc_unsigned.h" + +namespace sc_core { + extern sc_byte_heap sc_temp_heap; // Temporary storage. +} // namespace sc_core + +namespace sc_dt +{ + +// ---------------------------------------------------------------------------- +// CLASS TEMPLATE : sc_concatref +// +// Proxy class for sized bit concatenation. +// ---------------------------------------------------------------------------- + +class sc_concatref : public sc_generic_base<sc_concatref>, public sc_value_base +{ +public: + friend class sc_core::sc_vpool<sc_concatref>; + + inline void initialize( + sc_value_base& left, sc_value_base& right ) + { + bool left_xz; // True if x's and/or z's found in left. + bool right_xz; // True if x's and/or z's found in right. + + m_left_p = (sc_value_base*)&left; + m_right_p = (sc_value_base*)&right; + m_len_r = right.concat_length(&right_xz); + m_len = left.concat_length(&left_xz) + m_len_r; + m_flags = ( left_xz || right_xz ) ? cf_xz_present : cf_none; + } + + + inline void initialize( + const sc_value_base& left, const sc_value_base& right ) + { + bool left_xz; // True if x's and/or z's found in left. + bool right_xz; // True if x's and/or z's found in right. + + m_left_p = (sc_value_base*)&left; + m_right_p = (sc_value_base*)&right; + m_len_r = right.concat_length(&right_xz); + m_len = left.concat_length(&left_xz) + m_len_r; + m_flags = ( left_xz || right_xz ) ? cf_xz_present : cf_none; + } + + // destructor + + virtual ~sc_concatref() + {} + + + // capacity + + unsigned int length() const + { return m_len; } + +#ifdef SC_DT_DEPRECATED + int bitwidth() const + { return length(); } +#endif + + // concatenation + + virtual int concat_length( bool* xz_present_p ) const + { + if ( xz_present_p ) + *xz_present_p = m_flags & cf_xz_present ? true : false; + return m_len; + } + + virtual void concat_clear_data( bool to_ones ) + { + m_left_p->concat_clear_data(to_ones); + m_right_p->concat_clear_data(to_ones); + } + + virtual bool concat_get_ctrl( sc_digit* dst_p, int low_i ) const + { + bool rnz = m_right_p->concat_get_ctrl( dst_p, low_i ); + bool lnz = m_left_p->concat_get_ctrl( dst_p, low_i+m_len_r ); + return rnz || lnz; + } + + virtual bool concat_get_data( sc_digit* dst_p, int low_i ) const + { + bool rnz = m_right_p->concat_get_data( dst_p, low_i ); + bool lnz = m_left_p->concat_get_data( dst_p, low_i+m_len_r ); + return rnz || lnz; + } + + virtual uint64 concat_get_uint64() const + { + if ( m_len_r >= 64 ) + return m_right_p->concat_get_uint64(); + else + { + return (m_left_p->concat_get_uint64() << m_len_r) | + m_right_p->concat_get_uint64(); + } + } + + virtual void concat_set( int64 src, int low_i ) + { + m_right_p->concat_set( src, low_i ); + m_left_p->concat_set( src, low_i+m_len_r); + } + + virtual void concat_set( const sc_signed& src, int low_i ) + { + m_right_p->concat_set( src, low_i ); + m_left_p->concat_set( src, low_i+m_len_r); + } + + virtual void concat_set( const sc_unsigned& src, int low_i ) + { + m_right_p->concat_set( src, low_i ); + m_left_p->concat_set( src, low_i+m_len_r); + } + + virtual void concat_set( uint64 src, int low_i ) + { + m_right_p->concat_set( src, low_i ); + m_left_p->concat_set( src, low_i+m_len_r); + } + + + // explicit conversions + + uint64 to_uint64() const + { + uint64 mask; + uint64 result; + + result = m_right_p->concat_get_uint64(); + if ( m_len_r < 64 ) + { + mask = (uint64)~0; + result = (m_left_p->concat_get_uint64() << m_len_r) | + (result & ~(mask << m_len_r)); + } + if ( m_len < 64 ) + { + mask = (uint64)~0; + result = result & ~(mask << m_len); + } + return result; + } + + const sc_unsigned& value() const + { + bool left_non_zero; + sc_unsigned* result_p = sc_unsigned::m_pool.allocate(); + bool right_non_zero; + + result_p->nbits = result_p->num_bits(m_len); + result_p->ndigits = DIV_CEIL(result_p->nbits); + result_p->digit = (sc_digit*)sc_core::sc_temp_heap.allocate( + sizeof(sc_digit)*result_p->ndigits ); +#if defined(_MSC_VER) + // workaround spurious initialisation issue on MS Visual C++ + memset( result_p->digit, 0, sizeof(sc_digit)*result_p->ndigits ); +#else + result_p->digit[result_p->ndigits-1] = 0; +#endif + right_non_zero = m_right_p->concat_get_data( result_p->digit, 0 ); + left_non_zero = m_left_p->concat_get_data(result_p->digit, m_len_r); + if ( left_non_zero || right_non_zero ) + result_p->sgn = SC_POS; + else + result_p->sgn = SC_ZERO; + return *result_p; + } + + int64 to_int64() const + { + return (int64)to_uint64(); + } + int to_int() const + { return (int)to_int64(); } + unsigned int to_uint() const + { return (unsigned int)to_uint64(); } + long to_long() const + { return (long)to_int64(); } + unsigned long to_ulong() const + { return (unsigned long)to_uint64(); } + double to_double() const + { return value().to_double(); } + + void to_sc_signed( sc_signed& target ) const + { target = value(); } + + void to_sc_unsigned( sc_unsigned& target ) const + { target = value(); } + + // implicit conversions: + + operator uint64 () const + { return to_uint64(); } + + operator const sc_unsigned& () const + { return value(); } + + // unary operators: + + sc_unsigned operator + () const + { return value(); } + + sc_signed operator - () const + { return -value(); } + + sc_unsigned operator ~ () const + { return ~value(); } + + // explicit conversion to character string + + const std::string to_string( sc_numrep numrep = SC_DEC ) const + { return value().to_string(numrep); } + + const std::string to_string( sc_numrep numrep, bool w_prefix ) const + { return value().to_string(numrep,w_prefix); } + + + + // assignments + + inline const sc_concatref& operator = ( int v ) + { + m_right_p->concat_set((int64)v, 0); + m_left_p->concat_set((int64)v, m_len_r); + return *this; + } + + inline const sc_concatref& operator = ( long v ) + { + m_right_p->concat_set((int64)v, 0); + m_left_p->concat_set((int64)v, m_len_r); + return *this; + } + + inline const sc_concatref& operator = ( int64 v ) + { + m_right_p->concat_set(v, 0); + m_left_p->concat_set(v, m_len_r); + return *this; + } + + inline const sc_concatref& operator = ( unsigned int v ) + { + m_right_p->concat_set((uint64)v, 0); + m_left_p->concat_set((uint64)v, m_len_r); + return *this; + } + + inline const sc_concatref& operator = ( unsigned long v ) + { + m_right_p->concat_set((uint64)v, 0); + m_left_p->concat_set((uint64)v, m_len_r); + return *this; + } + + inline const sc_concatref& operator = ( uint64 v ) + { + m_right_p->concat_set(v, 0); + m_left_p->concat_set(v, m_len_r); + return *this; + } + + const sc_concatref& operator = ( const sc_concatref& v ) + { + sc_unsigned temp(v.length()); + temp = v.value(); + m_right_p->concat_set(temp, 0); + m_left_p->concat_set(temp, m_len_r); + return *this; + } + + const sc_concatref& operator = ( const sc_signed& v ) + { + m_right_p->concat_set(v, 0); + m_left_p->concat_set(v, m_len_r); + return *this; + } + + const sc_concatref& operator = ( const sc_unsigned& v ) + { + m_right_p->concat_set(v, 0); + m_left_p->concat_set(v, m_len_r); + return *this; + } + + const sc_concatref& operator = ( const char* v_p ) + { + sc_unsigned v(m_len); + v = v_p; + m_right_p->concat_set(v, 0); + m_left_p->concat_set(v, m_len_r); + return *this; + } + + const sc_concatref& operator = ( const sc_bv_base& v ) + { + sc_unsigned temp(v.length()); + temp = v; + m_right_p->concat_set(temp, 0); + m_left_p->concat_set(temp, m_len_r); + return *this; + } + + const sc_concatref& operator = ( const sc_lv_base& v ) + { + sc_unsigned data(v.length()); + data = v; + m_right_p->concat_set(data, 0); + m_left_p->concat_set(data, m_len_r); + return *this; + } + + + // reduce methods + + bool and_reduce() const + { return value().and_reduce(); } + + bool nand_reduce() const + { return value().nand_reduce(); } + + bool or_reduce() const + { return value().or_reduce(); } + + bool nor_reduce() const + { return value().nor_reduce(); } + + bool xor_reduce() const + { return value().xor_reduce(); } + + bool xnor_reduce() const + { return value().xnor_reduce(); } + + // other methods + + void print( ::std::ostream& os = ::std::cout ) const + { os << this->value(); } + + void scan( ::std::istream& is ) + { + std::string s; + is >> s; + *this = s.c_str(); + } + +public: + static sc_core::sc_vpool<sc_concatref> m_pool; // Pool of temporary objects. + +public: + enum concat_flags { + cf_none = 0, // Normal value. + cf_xz_present = 1 // X and/or Z values present. + }; + +protected: + sc_value_base* m_left_p; // Left hand operand of concatenation. + sc_value_base* m_right_p; // Right hand operand of concatenation. + int m_len; // Length of concatenation. + int m_len_r; // Length of m_rightt_p. + concat_flags m_flags; // Value is read only. + +private: + sc_concatref(const sc_concatref&); + sc_concatref() : m_left_p(0), m_right_p(0), m_len(0), m_len_r(0), m_flags() + {} +}; + + +// functional notation for the reduce methods + +inline +bool +and_reduce( const sc_concatref& a ) +{ + return a.and_reduce(); +} + +inline +bool +nand_reduce( const sc_concatref& a ) +{ + return a.nand_reduce(); +} + +inline +bool +or_reduce( const sc_concatref& a ) +{ + return a.or_reduce(); +} + +inline +bool +nor_reduce( const sc_concatref& a ) +{ + return a.nor_reduce(); +} + +inline +bool +xor_reduce( const sc_concatref& a ) +{ + return a.xor_reduce(); +} + +inline +bool +xnor_reduce( const sc_concatref& a ) +{ + return a.xnor_reduce(); +} + + +// SHIFT OPERATORS FOR sc_concatref OBJECT INSTANCES: +// +// Because sc_concatref has implicit casts to both uint64 and sc_unsigned +// it is necessary to disambiguate the use of the shift operators. We do +// this in favor of sc_unsigned so that precision is not lost. To get an +// integer-based result use a cast to uint64 before performing the shift. + +inline const sc_unsigned operator << (const sc_concatref& target, uint64 shift) +{ + return target.value() << (int)shift; +} + +inline const sc_unsigned operator << (const sc_concatref& target, int64 shift) +{ + return target.value() << (int)shift; +} + +inline const sc_unsigned operator << ( + const sc_concatref& target, unsigned long shift ) +{ + return target.value() << (int)shift; +} + +inline const sc_unsigned operator << ( + const sc_concatref& target, int shift ) +{ + return target.value() << shift; +} + +inline const sc_unsigned operator << ( + const sc_concatref& target, unsigned int shift ) +{ + return target.value() << (int)shift; +} + +inline const sc_unsigned operator << ( const sc_concatref& target, long shift ) +{ + return target.value() << (int)shift; +} + +inline const sc_unsigned operator >> (const sc_concatref& target, uint64 shift) +{ + return target.value() >> (int)shift; +} + +inline const sc_unsigned operator >> (const sc_concatref& target, int64 shift) +{ + return target.value() >> (int)shift; +} + +inline const sc_unsigned operator >> ( + const sc_concatref& target, unsigned long shift ) +{ + return target.value() >> (int)shift; +} + +inline const sc_unsigned operator >> ( + const sc_concatref& target, int shift ) +{ + return target.value() >> shift; +} + +inline const sc_unsigned operator >> ( + const sc_concatref& target, unsigned int shift ) +{ + return target.value() >> (int)shift; +} + +inline const sc_unsigned operator >> ( const sc_concatref& target, long shift ) +{ + return target.value() >> (int)shift; +} + + +// STREAM OPERATORS FOR sc_concatref OBJECT INSTANCES: + +inline +::std::ostream& +operator << ( ::std::ostream& os, const sc_concatref& v ) +{ + return os << v.value(); +} + +inline +::std::istream& +operator >> ( ::std::istream& is, sc_concatref& a ) +{ + sc_unsigned temp(a.concat_length(0)); + temp.scan( is ); + a = temp; + return is; +} + + +// ---------------------------------------------------------------------------- +// CLASS TEMPLATE : sc_concat_bool +// +// Proxy class for read-only boolean values in concatenations. +// ---------------------------------------------------------------------------- + +class sc_concat_bool : public sc_value_base +{ + protected: + static sc_core::sc_vpool<sc_concat_bool> m_pool; // Temporaries pool. + bool m_value; // Value for this obj. + + public: + + // constructor: + + sc_concat_bool() + : sc_value_base(), m_value() + {} + + // destructor: + + virtual ~sc_concat_bool() + { } + + // allocation of temporary object: + + static inline sc_concat_bool* allocate( bool v ) + { + sc_concat_bool* result_p = m_pool.allocate(); + result_p->m_value = v; + return result_p; + } + + // concatenation: + + virtual int concat_length( bool* xz_present_p ) const + { + if ( xz_present_p ) *xz_present_p = false; + return 1; + } + + virtual bool concat_get_ctrl( sc_digit* dst_p, int low_i ) const + { + int bit = 1 << (low_i % BITS_PER_DIGIT); + int word_i = low_i / BITS_PER_DIGIT; + dst_p[word_i] &= ~bit; + return false; + } + + virtual bool concat_get_data( sc_digit* dst_p, int low_i ) const + { + int bit = 1 << (low_i % BITS_PER_DIGIT); + int word_i = low_i / BITS_PER_DIGIT; + if ( m_value ) + dst_p[word_i] |= bit; + else + dst_p[word_i] &= ~bit; + return m_value; + } + + virtual uint64 concat_get_uint64() const + { + return m_value ? 1 : 0; + } +}; + + +// ---------------------------------------------------------------------------- +// ARITHMETIC AND LOGIC OPERATORS FOR sc_concatref +// ---------------------------------------------------------------------------- + +#define SC_CONCAT_OP_TYPE(RESULT,OP,OTHER_TYPE) \ + inline RESULT operator OP ( const sc_concatref& a, OTHER_TYPE b ) \ + { \ + return a.value() OP b; \ + } \ + inline RESULT operator OP ( OTHER_TYPE a, const sc_concatref& b ) \ + { \ + return a OP b.value(); \ + } + + +#define SC_CONCAT_OP(RESULT,OP) \ + inline RESULT operator OP ( const sc_concatref& a, const sc_concatref& b ) \ + { \ + return a.value() OP b.value(); \ + } \ + SC_CONCAT_OP_TYPE(const sc_signed,OP,int) \ + SC_CONCAT_OP_TYPE(const sc_signed,OP,long) \ + SC_CONCAT_OP_TYPE(const sc_signed,OP,int64) \ + SC_CONCAT_OP_TYPE(RESULT,OP,unsigned int) \ + SC_CONCAT_OP_TYPE(RESULT,OP,unsigned long) \ + SC_CONCAT_OP_TYPE(RESULT,OP,uint64) \ + SC_CONCAT_OP_TYPE(const sc_signed,OP,const sc_int_base&) \ + SC_CONCAT_OP_TYPE(RESULT,OP,const sc_uint_base&) \ + SC_CONCAT_OP_TYPE(const sc_signed,OP,const sc_signed&) \ + SC_CONCAT_OP_TYPE(RESULT,OP,const sc_unsigned&) \ + inline RESULT operator OP ( const sc_concatref& a, bool b ) \ + { \ + return a.value() OP (int)b; \ + } \ + inline RESULT operator OP ( bool a, const sc_concatref& b ) \ + { \ + return (int)a OP b.value(); \ + } + +#define SC_CONCAT_BOOL_OP(OP) \ + inline bool operator OP ( const sc_concatref& a, const sc_concatref& b ) \ + { \ + return a.value() OP b.value(); \ + } \ + SC_CONCAT_OP_TYPE(bool,OP,int) \ + SC_CONCAT_OP_TYPE(bool,OP,long) \ + SC_CONCAT_OP_TYPE(bool,OP,int64) \ + SC_CONCAT_OP_TYPE(bool,OP,unsigned int) \ + SC_CONCAT_OP_TYPE(bool,OP,unsigned long) \ + SC_CONCAT_OP_TYPE(bool,OP,uint64) \ + SC_CONCAT_OP_TYPE(bool,OP,const sc_int_base&) \ + SC_CONCAT_OP_TYPE(bool,OP,const sc_uint_base&) \ + SC_CONCAT_OP_TYPE(bool,OP,const sc_signed&) \ + SC_CONCAT_OP_TYPE(bool,OP,const sc_unsigned&) \ + inline bool operator OP ( const sc_concatref& a, bool b ) \ + { \ + return a.value() OP (int)b; \ + } \ + inline bool operator OP ( bool a, const sc_concatref& b ) \ + { \ + return (int)a OP b.value(); \ + } + +SC_CONCAT_OP(const sc_unsigned,+) +SC_CONCAT_OP(const sc_signed,-) +SC_CONCAT_OP(const sc_unsigned,*) +SC_CONCAT_OP(const sc_unsigned,/) +SC_CONCAT_OP(const sc_unsigned,%) +SC_CONCAT_OP(const sc_unsigned,&) +SC_CONCAT_OP(const sc_unsigned,|) +SC_CONCAT_OP(const sc_unsigned,^) +SC_CONCAT_BOOL_OP(==) +SC_CONCAT_BOOL_OP(<=) +SC_CONCAT_BOOL_OP(>=) +SC_CONCAT_BOOL_OP(!=) +SC_CONCAT_BOOL_OP(>) +SC_CONCAT_BOOL_OP(<) + +#undef SC_CONCAT_OP +#undef SC_CONCAT_OP_TYPE + + +// ---------------------------------------------------------------------------- +// CONCATENATION FUNCTION AND OPERATOR FOR STANDARD SYSTEM C DATA TYPES: +// ---------------------------------------------------------------------------- + +inline sc_dt::sc_concatref& concat( + sc_dt::sc_value_base& a, sc_dt::sc_value_base& b) +{ + sc_dt::sc_concatref* result_p; // Proxy for the concatenation. + + result_p = sc_dt::sc_concatref::m_pool.allocate(); + result_p->initialize( a, b ); + return *result_p; +} + +inline +const +sc_dt::sc_concatref& concat( + const sc_dt::sc_value_base& a, const sc_dt::sc_value_base& b) +{ + sc_dt::sc_concatref* result_p; // Proxy for the concatenation. + + result_p = sc_dt::sc_concatref::m_pool.allocate(); + result_p->initialize( a, b ); + return *result_p; +} + +inline +const +sc_dt::sc_concatref& concat(const sc_dt::sc_value_base& a, bool b) +{ + const sc_dt::sc_concat_bool* b_p; // Proxy for boolean value. + sc_dt::sc_concatref* result_p; // Proxy for the concatenation. + + b_p = sc_dt::sc_concat_bool::allocate(b); + result_p = sc_dt::sc_concatref::m_pool.allocate(); + result_p->initialize( a, *b_p ); + return *result_p; +} + +inline +const +sc_dt::sc_concatref& concat(bool a, const sc_dt::sc_value_base& b) +{ + const sc_dt::sc_concat_bool* a_p; // Proxy for boolean value. + sc_dt::sc_concatref* result_p; // Proxy for the concatenation. + + a_p = sc_dt::sc_concat_bool::allocate(a); + result_p = sc_dt::sc_concatref::m_pool.allocate(); + result_p->initialize( *a_p, b ); + return *result_p; +} + +inline sc_dt::sc_concatref& operator , ( + sc_dt::sc_value_base& a, sc_dt::sc_value_base& b) +{ + sc_dt::sc_concatref* result_p; // Proxy for the concatenation. + + result_p = sc_dt::sc_concatref::m_pool.allocate(); + result_p->initialize( a, b ); + return *result_p; +} + +inline +const +sc_dt::sc_concatref& operator , ( + const sc_dt::sc_value_base& a, const sc_dt::sc_value_base& b) +{ + sc_dt::sc_concatref* result_p; // Proxy for the concatenation. + + result_p = sc_dt::sc_concatref::m_pool.allocate(); + result_p->initialize( a, b ); + return *result_p; +} + +inline +const +sc_dt::sc_concatref& operator , (const sc_dt::sc_value_base& a, bool b) +{ + const sc_dt::sc_concat_bool* b_p; // Proxy for boolean value. + sc_dt::sc_concatref* result_p; // Proxy for the concatenation. + + b_p = sc_dt::sc_concat_bool::allocate(b); + result_p = sc_dt::sc_concatref::m_pool.allocate(); + result_p->initialize( a, *b_p ); + return *result_p; +} + +inline +const +sc_dt::sc_concatref& operator , (bool a, const sc_dt::sc_value_base& b) +{ + const sc_dt::sc_concat_bool* a_p; // Proxy for boolean value. + sc_dt::sc_concatref* result_p; // Proxy for the concatenation. + + a_p = sc_dt::sc_concat_bool::allocate(a); + result_p = sc_dt::sc_concatref::m_pool.allocate(); + result_p->initialize( *a_p, b ); + return *result_p; +} + +} // namespace sc_dt + +#endif // SC_CONCATREF_H + diff --git a/ext/systemc/src/sysc/datatypes/misc/sc_value_base.cpp b/ext/systemc/src/sysc/datatypes/misc/sc_value_base.cpp new file mode 100644 index 000000000..5f16341a7 --- /dev/null +++ b/ext/systemc/src/sysc/datatypes/misc/sc_value_base.cpp @@ -0,0 +1,138 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_value_base.cpp -- Base class for all SystemC data values. + + Original Author: Andy Goodrich, Forte Design Systems + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + + +// $Log: sc_value_base.cpp,v $ +// Revision 1.2 2011/08/15 16:43:24 acg +// Torsten Maehne: changes to remove unused argument warnings. +// +// Revision 1.1.1.1 2006/12/15 20:20:05 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:54:01 acg +// Andy Goodrich: added $Log command so that CVS comments are reproduced in +// the source. +// + +#include <cstdlib> +#include <assert.h> +#include <ctype.h> +#include <cstdio> + +#include "sysc/datatypes/int/sc_int_ids.h" +#include "sysc/datatypes/misc/sc_value_base.h" + +namespace sc_dt +{ + +void sc_value_base::concat_clear_data( bool /* to_ones */ ) +{ + char error_message[128]; + std::sprintf(error_message, + "concat_clear_data method not supported by this type"); + SC_REPORT_ERROR( sc_core::SC_ID_OPERATION_FAILED_, error_message ); +} + +bool sc_value_base::concat_get_ctrl( sc_digit* /*dst_p*/, int /*low_i*/ ) const +{ + char error_message[128]; + std::sprintf(error_message, + "concat_get_ctrl method not supported by this type"); + SC_REPORT_ERROR( sc_core::SC_ID_OPERATION_FAILED_, error_message ); + return false; +} + +bool sc_value_base::concat_get_data( sc_digit* /*dst_p*/, int /*low_i*/ ) const +{ + char error_message[128]; + std::sprintf(error_message, + "concat_get_data method not supported by this type"); + SC_REPORT_ERROR( sc_core::SC_ID_OPERATION_FAILED_, error_message ); + return false; +} + +sc_dt::uint64 sc_value_base::concat_get_uint64() const +{ + char error_message[128]; + std::sprintf(error_message, + "concat_get_uint64 method not supported by this type"); + SC_REPORT_ERROR( sc_core::SC_ID_OPERATION_FAILED_, error_message ); + return 0; +} + +int sc_value_base::concat_length(bool* /*xz_present_p*/) const +{ + char error_message[128]; + std::sprintf(error_message, + "concat_length method not supported by this type"); + SC_REPORT_ERROR( sc_core::SC_ID_OPERATION_FAILED_, error_message ); + return 0; +} + +void sc_value_base::concat_set( int64 /*src*/, int /*low_i*/ ) +{ + char error_message[128]; + std::sprintf(error_message, + "concat_set(int64) method not supported by this type"); + SC_REPORT_ERROR( sc_core::SC_ID_OPERATION_FAILED_, error_message ); +} + +void sc_value_base::concat_set( const sc_signed& /*src*/, int /*low_i*/ ) +{ + char error_message[128]; + std::sprintf(error_message, + "concat_set(sc_signed) method not supported by this type"); + SC_REPORT_ERROR( sc_core::SC_ID_OPERATION_FAILED_, error_message ); +} + +void sc_value_base::concat_set( const sc_unsigned& /*src*/, int /*low_i*/ ) +{ + char error_message[128]; + std::sprintf(error_message, + "concat_set(sc_unsigned) method not supported by this type"); + SC_REPORT_ERROR( sc_core::SC_ID_OPERATION_FAILED_, error_message ); +} + +void sc_value_base::concat_set( uint64 /*src*/, int /*low_i*/ ) +{ + char error_message[128]; + std::sprintf(error_message, + "concat_set(uint64) method not supported by this type"); + SC_REPORT_ERROR( sc_core::SC_ID_OPERATION_FAILED_, error_message ); +} + +} // namespace sc_dt diff --git a/ext/systemc/src/sysc/datatypes/misc/sc_value_base.h b/ext/systemc/src/sysc/datatypes/misc/sc_value_base.h new file mode 100644 index 000000000..1a2c73d42 --- /dev/null +++ b/ext/systemc/src/sysc/datatypes/misc/sc_value_base.h @@ -0,0 +1,129 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_value_base.h -- Base class for SystemC bit values. + + Original Author: Andy Goodrich, Forte Design Systems + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + +// $Log: sc_value_base.h,v $ +// Revision 1.4 2011/08/29 18:04:32 acg +// Philipp A. Hartmann: miscellaneous clean ups. +// +// Revision 1.3 2011/08/24 22:05:48 acg +// Torsten Maehne: initialization changes to remove warnings. +// +// Revision 1.2 2011/06/28 21:23:04 acg +// Andy Goodrich: merging of SCV tree. +// +// Revision 1.1.1.1 2006/12/15 20:20:05 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:54:01 acg +// Andy Goodrich: added $Log command so that CVS comments are reproduced in +// the source. +// + +#ifndef SC_VALUE_BASE_H +#define SC_VALUE_BASE_H + + +#include "sysc/datatypes/int/sc_nbdefs.h" + +namespace sc_dt +{ + +class sc_signed; +class sc_unsigned; + +// ---------------------------------------------------------------------------- +// CLASS : sc_value_base +// +// Abstract base class of all SystemC native variables. It provides +// support for concatenation operations via a set of virtual methods. +// A general description of the methods appear with their default +// definitions in sc_object.cpp. +// ---------------------------------------------------------------------------- + +class sc_value_base +{ + friend class sc_concatref; + private: + virtual void concat_clear_data( bool to_ones=false ); + virtual bool concat_get_ctrl( sc_digit* dst_p, int low_i ) const; + virtual bool concat_get_data( sc_digit* dst_p, int low_i ) const; + virtual uint64 concat_get_uint64() const; + virtual int concat_length(bool* xz_present_p=0) const; + virtual void concat_set( int64 src, int low_i ); + virtual void concat_set( const sc_signed& src, int low_i ); + virtual void concat_set( const sc_unsigned& src, int low_i ); + virtual void concat_set( uint64 src, int low_i ); + public: + virtual ~sc_value_base() {} +}; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_generic_base +// +// Proxy class for user-defined value classes and other classes that +// are defined outside of SystemC. +// The class is utilized as a base class for the arbitrary class: +// +// class my_class : public sc_generic_base<my_class> +// +// The purpose of the class is to allow to_XXXX methods defined within that +// class so that assignments and casts from the arbitrary class to native +// SystemC types are possible. To interact correctly with the SystemC library +// the class derived from sc_generic_base must implement the following +// methods: +// (1) uint64 to_uint64() const +// (2) int64 to_int64() const +// (3) void to_sc_unsigned( sc_unsigned& ) const +// (4) void to_sc_signed( sc_signed& ) const +// ---------------------------------------------------------------------------- +template< class T > +class sc_generic_base { + public: + inline const T* operator-> () const + { + return (const T*)this; + } + inline T* operator-> () + { + return (T*)this; + } +}; + +} // namespace sc_dt + +#endif diff --git a/ext/systemc/src/sysc/kernel/sc_attribute.cpp b/ext/systemc/src/sysc/kernel/sc_attribute.cpp new file mode 100644 index 000000000..de89c6adf --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_attribute.cpp @@ -0,0 +1,191 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_attribute.cpp -- Attribute classes. + + Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21 + + CHANGE LOG APPEARS AT THE END OF THE FILE + *****************************************************************************/ + +#include "sysc/kernel/sc_attribute.h" + +namespace sc_core { + +// ---------------------------------------------------------------------------- +// CLASS : sc_attr_base +// +// Attribute base class. +// ---------------------------------------------------------------------------- + +// constructors + +sc_attr_base::sc_attr_base( const std::string& name_ ) +: m_name( name_ ) +{} + +sc_attr_base::sc_attr_base( const sc_attr_base& a ) +: m_name( a.m_name ) +{} + + +// destructor (does nothing) + +sc_attr_base::~sc_attr_base() +{} + + +// get the name +const std::string& +sc_attr_base::name() const +{ + return m_name; +} + + +// ---------------------------------------------------------------------------- +// CLASS : sc_attr_cltn +// +// Attribute collection class. Stores pointers to attributes. +// Note: iterate over the collection by using iterators. +// ---------------------------------------------------------------------------- + +// constructors + +sc_attr_cltn::sc_attr_cltn() : m_cltn() +{} + +sc_attr_cltn::sc_attr_cltn( const sc_attr_cltn& a ) +: m_cltn( a.m_cltn ) +{} + + +// destructor +sc_attr_cltn::~sc_attr_cltn() +{ + remove_all(); +} + + +// add attribute to the collection. +// returns 'true' if the name of the attribute is unique, +// returns 'false' otherwise (attribute is not added). + +bool +sc_attr_cltn::push_back( sc_attr_base* attribute_ ) +{ + if( attribute_ == 0 ) { + return false; + } + for( int i = m_cltn.size() - 1; i >= 0; -- i ) { + if( attribute_->name() == m_cltn[i]->name() ) { + return false; + } + } + m_cltn.push_back( attribute_ ); + return true; +} + + +// get attribute by name. +// returns pointer to attribute, or 0 if name does not exist. + +sc_attr_base* +sc_attr_cltn::operator [] ( const std::string& name_ ) +{ + for( int i = m_cltn.size() - 1; i >= 0; -- i ) { + if( name_ == m_cltn[i]->name() ) { + return m_cltn[i]; + } + } + return 0; +} + +const sc_attr_base* +sc_attr_cltn::operator [] ( const std::string& name_ ) const +{ + for( int i = m_cltn.size() - 1; i >= 0; -- i ) { + if( name_ == m_cltn[i]->name() ) { + return m_cltn[i]; + } + } + return 0; +} + + +// remove attribute by name. +// returns pointer to attribute, or 0 if name does not exist. + +sc_attr_base* +sc_attr_cltn::remove( const std::string& name_ ) +{ + for( int i = m_cltn.size() - 1; i >= 0; -- i ) { + if( name_ == m_cltn[i]->name() ) { + sc_attr_base* attribute = m_cltn[i]; + std::swap( m_cltn[i], m_cltn.back() ); + m_cltn.pop_back(); + return attribute; + } + } + return 0; +} + + +// remove all attributes + +void +sc_attr_cltn::remove_all() +{ + m_cltn.clear(); +} + +} // namespace sc_core + +// $Log: sc_attribute.cpp,v $ +// Revision 1.7 2011/08/26 20:46:08 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +// Revision 1.6 2011/08/24 22:05:50 acg +// Torsten Maehne: initialization changes to remove warnings. +// +// Revision 1.5 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.4 2011/02/13 21:47:37 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.3 2010/07/22 20:02:33 acg +// Andy Goodrich: bug fixes. +// +// Revision 1.2 2008/05/22 17:06:24 acg +// Andy Goodrich: updated copyright notice to include 2008. +// +// Revision 1.1.1.1 2006/12/15 20:20:05 acg +// SystemC 2.3 +// +// Revision 1.4 2006/01/16 22:27:08 acg +// Test of $Log comment. +// +// Revision 1.3 2006/01/13 18:44:29 acg +// Added $Log to record CVS changes into the source. + +// Taf! diff --git a/ext/systemc/src/sysc/kernel/sc_attribute.h b/ext/systemc/src/sysc/kernel/sc_attribute.h new file mode 100644 index 000000000..0efa70de5 --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_attribute.h @@ -0,0 +1,209 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_attribute.h -- Attribute classes. + + Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21 + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + + +#ifndef SC_ATTRIBUTE_H +#define SC_ATTRIBUTE_H + +#include <string> +#include <vector> + +namespace sc_core { + +// ---------------------------------------------------------------------------- +// CLASS : sc_attr_base +// +// Attribute base class. +// ---------------------------------------------------------------------------- + +class sc_attr_base +{ +public: + + // constructors + sc_attr_base( const std::string& name_ ); + sc_attr_base( const sc_attr_base& ); + + // destructor (does nothing) + virtual ~sc_attr_base(); + + // get the name + const std::string& name() const; + +private: + + std::string m_name; + +private: + + // disabled + sc_attr_base(); + sc_attr_base& operator = ( const sc_attr_base& ); +}; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_attr_cltn +// +// Attribute collection class. Stores pointers to attributes. +// Note: iterate over the collection by using iterators. +// ---------------------------------------------------------------------------- + +class sc_attr_cltn +{ +public: + + // typedefs + typedef sc_attr_base* elem_type; + typedef std::vector<elem_type>::iterator iterator; + typedef std::vector<elem_type>::const_iterator const_iterator; + + // constructors + sc_attr_cltn(); + sc_attr_cltn( const sc_attr_cltn& ); + + // destructor + ~sc_attr_cltn(); + + // add attribute to the collection. + // returns 'true' if the name of the attribute is unique, + // returns 'false' otherwise (attribute is not added). + bool push_back( sc_attr_base* ); + + // get attribute by name. + // returns pointer to attribute, or 0 if name does not exist. + sc_attr_base* operator [] ( const std::string& name_ ); + const sc_attr_base* operator [] ( const std::string& name_ ) const; + + // remove attribute by name. + // returns pointer to attribute, or 0 if name does not exist. + sc_attr_base* remove( const std::string& name_ ); + + // remove all attributes + void remove_all(); + + // get the size of the collection + int size() const + { return m_cltn.size(); } + + // get the begin iterator + iterator begin() + { return m_cltn.begin(); } + const_iterator begin() const + { return m_cltn.begin(); } + + // get the end iterator + iterator end() + { return m_cltn.end(); } + const_iterator end() const + { return m_cltn.end(); } + +private: + std::vector<sc_attr_base*> m_cltn; + +private: + + // disabled + sc_attr_cltn& operator = ( const sc_attr_cltn& ); +}; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_attribute<T> +// +// Attribute class. +// Note: T must have a default constructor and copy constructor. +// ---------------------------------------------------------------------------- + +template <class T> +class sc_attribute +: public sc_attr_base +{ +public: + + // constructors + + sc_attribute( const std::string& name_ ) + : sc_attr_base( name_ ), value() + {} + + sc_attribute( const std::string& name_, const T& value_ ) + : sc_attr_base( name_ ), value( value_ ) + {} + + sc_attribute( const sc_attribute<T>& a ) + : sc_attr_base( a.name() ), value( a.value ) + {} + + + // destructor (does nothing) + + virtual ~sc_attribute() + {} + +public: + + // public data member; for easy access + T value; + +private: + + // disabled + sc_attribute(); + sc_attribute<T>& operator = ( const sc_attribute<T>& ); +}; + +} // namespace sc_core + +// $Log: sc_attribute.h,v $ +// Revision 1.6 2011/08/26 20:46:08 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +// Revision 1.5 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.4 2011/02/13 21:47:37 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.3 2010/07/22 20:02:33 acg +// Andy Goodrich: bug fixes. +// +// Revision 1.2 2008/05/22 17:06:24 acg +// Andy Goodrich: updated copyright notice to include 2008. +// +// Revision 1.1.1.1 2006/12/15 20:20:05 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:44:29 acg +// Added $Log to record CVS changes into the source. +// + +#endif + +// Taf! diff --git a/ext/systemc/src/sysc/kernel/sc_boost.h b/ext/systemc/src/sysc/kernel/sc_boost.h new file mode 100644 index 000000000..4383c21c9 --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_boost.h @@ -0,0 +1,94 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_boost.h -- Thread Semantics Provided By The Boost Library + + Original Author: Stuart Swan, Cadence Design Systems, Inc + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + + +#ifndef SC_BOOST_H +#define SC_BOOST_H + +// namespace sc_dp { This is off because of bugs with gcc 2.9x + +// SET THE NAME OF OBJECTS THAT THE SC_BOOST LIBRARY WILL PRODUCE AND INCLUDE IT + +#if defined(_MSC_VER) && !defined(__ICL) && !defined(__COMO__) +# pragma warning(disable: 4786) // identifier truncated in debug info +# pragma warning(disable: 4710) // function not inlined +# pragma warning(disable: 4711) // funct. selected for auto-inline expansion +# pragma warning(disable: 4514) // unreferenced inline removed +#endif + +#include <functional> + +#if defined(SC_BOOST_MSVC) && (SC_BOOST_MSVC < 1300) +# pragma warning(push, 3) +#endif + +#if defined(SC_BOOST_MSVC) && (SC_BOOST_MSVC < 1300) +# pragma warning(pop) +#endif + +// } // namespace sc_dp This is off because of bugs with gcc 2.9x + +// macros to help avoid direct user code dependencies on boost lib +// +// note the use of the sc_boost namespace for the SystemC version of +// boost. to replace the version shipped with SystemC with another boost +// you will need to change the namespace prefix back to boost. + +#define sc_bind std::bind +#define sc_ref(r) std::ref(r) +#define sc_cref(r) std::cref(r) + +// $Log: sc_boost.h,v $ +// Revision 1.7 2011/08/26 20:46:09 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +// Revision 1.6 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.5 2011/02/13 21:47:37 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.4 2009/07/28 01:10:53 acg +// Andy Goodrich: updates for 2.3 release candidate. +// +// Revision 1.3 2009/02/28 00:26:58 acg +// Andy Goodrich: changed boost name space to sc_boost to allow use with +// full boost library applications. +// +// Revision 1.2 2008/05/22 17:06:24 acg +// Andy Goodrich: updated copyright notice to include 2008. +// +// Revision 1.1.1.1 2006/12/15 20:20:05 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:44:29 acg +// Added $Log to record CVS changes into the source. +// + +#endif // SC_BOOST_H diff --git a/ext/systemc/src/sysc/kernel/sc_cmnhdr.h b/ext/systemc/src/sysc/kernel/sc_cmnhdr.h new file mode 100644 index 000000000..fcbb2f568 --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_cmnhdr.h @@ -0,0 +1,138 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_cmnhdr.h - Common header file containing handy pragmas, macros and + definitions common to all SystemC source files. + + Original Author: Amit Rao, Synopsys, Inc. + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + + +#ifndef SC_CMNHDR_H +#define SC_CMNHDR_H + +#if defined(_WIN32) || defined(_MSC_VER) || defined(__BORLANDC__) || \ + defined(__MINGW32__) + +// all windows 32-bit compilers should define WIN32 +#if !defined(WIN32) && !defined(WIN64) && !defined(_WIN64) +#define WIN32 +#endif + +// Windows Version Build Option +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0400 +#endif + +// remember to later include windows.h, if needed +#define SC_HAS_WINDOWS_H_ + +#endif // WIN32 + +// ---------------------------------------------------------------------------- + +#ifdef _MSC_VER + +// Disable VC++ warnings that are harmless + +// this : used in base member initializer list +#pragma warning(disable: 4355) + +// new and delete warning when exception handling is turned on +#pragma warning(disable: 4291) + +// in many places implicit conversion to bool +// from other integral types is performed +#pragma warning(disable: 4800) + +// unary minus operator applied to unsigned +#pragma warning(disable: 4146) + +// multiple copy constructors +#pragma warning(disable: 4521) + +// identifier was truncated to '255' characters in the browser information +#pragma warning(disable: 4786) + +#endif + +// ---------------------------------------------------------------------------- +// helper macros to aid branch prediction on GCC (compatible) compilers + +#ifndef __GNUC__ +# define SC_LIKELY_( x ) !!(x) +# define SC_UNLIKELY_( x ) !!(x) +#else +# define SC_LIKELY_( x ) __builtin_expect( !!(x), 1 ) +# define SC_UNLIKELY_( x ) __builtin_expect( !!(x), 0 ) +#endif + +// ---------------------------------------------------------------------------- + +#include <cassert> +#include <cstdio> +#include <cstdlib> + +#endif // SC_CMNHDR_H + +// ---------------------------------------------------------------------------- +// only include Windows.h, if explicitly requested +// (deliberately outside of include guards to enable later effect) +#if defined(SC_HAS_WINDOWS_H_) && defined(SC_INCLUDE_WINDOWS_H) +# undef SC_HAS_WINDOWS_H_ +# include <Windows.h> +#endif + +// $Log: sc_cmnhdr.h,v $ +// Revision 1.8 2011/08/26 20:46:09 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +// Revision 1.7 2011/05/09 04:07:48 acg +// Philipp A. Hartmann: +// (1) Restore hierarchy in all phase callbacks. +// (2) Ensure calls to before_end_of_elaboration. +// +// Revision 1.6 2011/05/05 17:45:27 acg +// Philip A. Hartmann: changes in WIN64 support. +// Andy Goodrich: additional DEBUG_MSG instances to trace process handling. +// +// Revision 1.5 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.4 2011/02/13 21:47:37 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.3 2009/05/22 16:06:29 acg +// Andy Goodrich: process control updates. +// +// Revision 1.2 2008/05/22 17:06:24 acg +// Andy Goodrich: updated copyright notice to include 2008. +// +// Revision 1.1.1.1 2006/12/15 20:20:05 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:44:29 acg +// Added $Log to record CVS changes into the source. + +// Taf! diff --git a/ext/systemc/src/sysc/kernel/sc_constants.h b/ext/systemc/src/sysc/kernel/sc_constants.h new file mode 100644 index 000000000..1ff20adbd --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_constants.h @@ -0,0 +1,82 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_constants.h -- Default constants whose values may need to be + changed depending on the application. + + Original Author: Ali Dasdan, Synopsys, Inc. + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + +#ifndef SC_CONSTANTS_H +#define SC_CONSTANTS_H + +namespace sc_core { + +// Maximum number of bits for arbitrary precision arithmetic. If +// defined, the arithmetic becomes faster. If not defined, the +// arithmetic becomes slower and the precision becomes infinite. It +// is a good idea to define this constant as a multiple of +// BITS_PER_DIGIT, which is defined in numeric_bit/sc_nbdefs.h. +//#define SC_MAX_NBITS 510 // 17 * BITS_PER_DIGIT + + +// deprecated in 1666-2005 and later, but kept for backwards compatibility +// - can be set by defining SC_OVERRIDE_DEFAULT_STACK_SIZE +// - defaults defined in sc_thread_process.cpp +extern const int SC_DEFAULT_STACK_SIZE; + + +#ifdef DEBUG_SYSTEMC +const int SC_MAX_NUM_DELTA_CYCLES = 10000; +#endif + +} // namespace sc_core + +// $Log: sc_constants.h,v $ +// Revision 1.7 2011/08/26 20:46:09 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +// Revision 1.6 2011/02/18 20:33:26 acg +// Philipp A. Hartmann: added default stack size for CYGWIN32. +// +// Revision 1.5 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.4 2011/02/13 21:47:37 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.3 2010/03/15 18:29:25 acg +// Andy Goodrich: Changed the default stack size to 128K from 64K. +// +// Revision 1.2 2008/05/22 17:06:24 acg +// Andy Goodrich: updated copyright notice to include 2008. +// +// Revision 1.1.1.1 2006/12/15 20:20:05 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:44:29 acg +// Added $Log to record CVS changes into the source. +// + +#endif diff --git a/ext/systemc/src/sysc/kernel/sc_cor.h b/ext/systemc/src/sysc/kernel/sc_cor.h new file mode 100644 index 000000000..49892ca7a --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_cor.h @@ -0,0 +1,157 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_cor.h -- Coroutine abstract base classes. + + Original Author: Martin Janssen, Synopsys, Inc., 2001-12-18 + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + + +#ifndef SC_COR_H +#define SC_COR_H + + +#include <cassert> +#include <cstdlib> + +namespace sc_core { + +class sc_simcontext; + + +// ---------------------------------------------------------------------------- +// TYPEDEF : sc_cor_fn +// +// Function type for creating coroutines. +// ---------------------------------------------------------------------------- + +typedef void (sc_cor_fn)( void* ); + + +// ---------------------------------------------------------------------------- +// CLASS : sc_cor +// +// Coroutine abstract base class. +// ---------------------------------------------------------------------------- + +class sc_cor +{ +protected: + + // constructor + sc_cor() {} + +public: + + // destructor + virtual ~sc_cor() {} + + // switch stack protection on/off + virtual void stack_protect( bool /* enable */ ) {} + +private: + + // disabled + sc_cor( const sc_cor& ); + sc_cor& operator = ( const sc_cor& ); +}; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_cor_pkg +// +// Coroutine package abstract base class. +// ---------------------------------------------------------------------------- + +class sc_cor_pkg +{ +public: + + // constructor + sc_cor_pkg( sc_simcontext* simc ) + : m_simc( simc ) { assert( simc != 0 ); } + + // destructor + virtual ~sc_cor_pkg() {} + + // create a new coroutine + virtual sc_cor* create( + std::size_t stack_size, sc_cor_fn* fn, void* arg ) = 0; + + // yield to the next coroutine + virtual void yield( sc_cor* next_cor ) = 0; + + // abort the current coroutine (and resume the next coroutine) + virtual void abort( sc_cor* next_cor ) = 0; + + // get the main coroutine + virtual sc_cor* get_main() = 0; + + // get the simulation context + sc_simcontext* simcontext() + { return m_simc; } + +private: + + sc_simcontext* m_simc; + +private: + + // disabled + sc_cor_pkg(); + sc_cor_pkg( const sc_cor_pkg& ); + sc_cor_pkg& operator = ( const sc_cor_pkg& ); +}; + +} // namespace sc_core + +// $Log: sc_cor.h,v $ +// Revision 1.7 2011/08/26 20:46:09 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +// Revision 1.6 2011/08/15 16:43:24 acg +// Torsten Maehne: changes to remove unused argument warnings. +// +// Revision 1.5 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.4 2011/02/13 21:47:37 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.3 2011/01/19 23:21:49 acg +// Andy Goodrich: changes for IEEE 1666 2011 +// +// Revision 1.2 2008/05/22 17:06:24 acg +// Andy Goodrich: updated copyright notice to include 2008. +// +// Revision 1.1.1.1 2006/12/15 20:20:05 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:44:29 acg +// Added $Log to record CVS changes into the source. +// + +#endif + +// Taf! diff --git a/ext/systemc/src/sysc/kernel/sc_cor_fiber.cpp b/ext/systemc/src/sysc/kernel/sc_cor_fiber.cpp new file mode 100644 index 000000000..77cec8227 --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_cor_fiber.cpp @@ -0,0 +1,224 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_cor_fiber.cpp -- Coroutine implementation with fibers. + + Original Author: Martin Janssen, Synopsys, Inc., 2001-12-18 + + CHANGE LOG APPEARS AT THE END OF THE FILE + *****************************************************************************/ + +#if defined(_WIN32) || defined(WIN32) || defined(WIN64) + +#ifndef SC_INCLUDE_WINDOWS_H +# define SC_INCLUDE_WINDOWS_H // include Windows.h, if needed +#endif + +#include "sysc/kernel/sc_cor_fiber.h" +#include "sysc/kernel/sc_simcontext.h" +#if defined(__GNUC__) && __USING_SJLJ_EXCEPTIONS__ +# if (__GNUC__ > 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ > 2)) +# include <unwind.h> +# else + extern "C" void _Unwind_SjLj_Register (struct SjLj_Function_Context *); + extern "C" void _Unwind_SjLj_Unregister (struct SjLj_Function_Context *); +# endif +#endif + +namespace sc_core { + +// ---------------------------------------------------------------------------- +// File static variables. +// ---------------------------------------------------------------------------- + +// main coroutine + +static sc_cor_fiber main_cor; +#if defined(__GNUC__) && __USING_SJLJ_EXCEPTIONS__ +// current coroutine +static sc_cor_fiber* curr_cor; +#endif + + +// ---------------------------------------------------------------------------- +// CLASS : sc_cor_fiber +// +// Coroutine class implemented with Windows fibers. +// ---------------------------------------------------------------------------- + +// destructor + +sc_cor_fiber::~sc_cor_fiber() +{ + if( m_fiber != 0 ) { + PVOID cur_fiber = GetCurrentFiber(); + if (m_fiber != cur_fiber) + DeleteFiber( m_fiber ); + } +} + + +// ---------------------------------------------------------------------------- +// CLASS : sc_cor_pkg_fiber +// +// Coroutine package class implemented with QuickThreads. +// ---------------------------------------------------------------------------- + +int sc_cor_pkg_fiber::instance_count = 0; + + +// constructor + +sc_cor_pkg_fiber::sc_cor_pkg_fiber( sc_simcontext* simc ) +: sc_cor_pkg( simc ) +{ + if( ++ instance_count == 1 ) { + // initialize the main coroutine + assert( main_cor.m_fiber == 0 ); + main_cor.m_fiber = ConvertThreadToFiber( 0 ); + + if( !main_cor.m_fiber && GetLastError() == ERROR_ALREADY_FIBER ) { + // conversion of current thread to fiber has failed, because + // someone else already converted the main thread to a fiber + // -> store current fiber + main_cor.m_fiber = GetCurrentFiber(); + } + assert( main_cor.m_fiber != 0 ); + +# if defined(__GNUC__) && __USING_SJLJ_EXCEPTIONS__ + // initialize the current coroutine + assert( curr_cor == 0 ); + curr_cor = &main_cor; +# endif + } +} + + +// destructor + +sc_cor_pkg_fiber::~sc_cor_pkg_fiber() +{ + if( -- instance_count == 0 ) { + // cleanup the main coroutine + main_cor.m_fiber = 0; +# if defined(__GNUC__) && __USING_SJLJ_EXCEPTIONS__ + // cleanup the current coroutine + curr_cor = 0; +# endif + } +} + + +// create a new coroutine + +sc_cor* +sc_cor_pkg_fiber::create( std::size_t stack_size, sc_cor_fn* fn, void* arg ) +{ + sc_cor_fiber* cor = new sc_cor_fiber; + cor->m_pkg = this; + cor->m_stack_size = stack_size; + cor->m_fiber = CreateFiberEx( cor->m_stack_size / 2, cor->m_stack_size, 0, + (LPFIBER_START_ROUTINE) fn, arg ); + return cor; +} + + +// yield to the next coroutine + +void +sc_cor_pkg_fiber::yield( sc_cor* next_cor ) +{ + sc_cor_fiber* new_cor = SCAST<sc_cor_fiber*>( next_cor ); +# if defined(__GNUC__) && __USING_SJLJ_EXCEPTIONS__ + // Switch SJLJ exception handling function contexts + _Unwind_SjLj_Register(&curr_cor->m_eh); + _Unwind_SjLj_Unregister(&new_cor->m_eh); + curr_cor = new_cor; +# endif + SwitchToFiber( new_cor->m_fiber ); +} + + +// abort the current coroutine (and resume the next coroutine) + +void +sc_cor_pkg_fiber::abort( sc_cor* next_cor ) +{ + sc_cor_fiber* new_cor = SCAST<sc_cor_fiber*>( next_cor ); +# if defined(__GNUC__) && __USING_SJLJ_EXCEPTIONS__ + // Switch SJLJ exception handling function contexts + _Unwind_SjLj_Register(&curr_cor->m_eh); + _Unwind_SjLj_Unregister(&new_cor->m_eh); + curr_cor = new_cor; +# endif + SwitchToFiber( new_cor->m_fiber ); +} + + +// get the main coroutine + +sc_cor* +sc_cor_pkg_fiber::get_main() +{ + return &main_cor; +} + +} // namespace sc_core + + +// $Log: sc_cor_fiber.cpp,v $ +// Revision 1.9 2011/09/08 16:12:45 acg +// Philipp A. Hartmann: make sure we don't try to make a thread a fiber if +// its already a fiber. +// +// Revision 1.8 2011/08/26 20:46:09 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +// Revision 1.7 2011/06/25 17:08:39 acg +// Andy Goodrich: Jerome Cornet's changes to use libtool to build the +// library. +// +// Revision 1.6 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.5 2011/02/13 21:47:37 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.4 2011/01/19 23:21:50 acg +// Andy Goodrich: changes for IEEE 1666 2011 +// +// Revision 1.3 2009/05/22 16:06:29 acg +// Andy Goodrich: process control updates. +// +// Revision 1.2 2008/05/22 17:06:25 acg +// Andy Goodrich: updated copyright notice to include 2008. +// +// Revision 1.1.1.1 2006/12/15 20:20:05 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:44:29 acg +// Added $Log to record CVS changes into the source. +// + +#endif + +// Taf! diff --git a/ext/systemc/src/sysc/kernel/sc_cor_fiber.h b/ext/systemc/src/sysc/kernel/sc_cor_fiber.h new file mode 100644 index 000000000..96163f497 --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_cor_fiber.h @@ -0,0 +1,169 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_cor_fiber.h -- Coroutine implementation with fibers. + + Original Author: Martin Janssen, Synopsys, Inc., 2001-12-18 + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + + +#ifndef SC_COR_FIBER_H +#define SC_COR_FIBER_H + +#if defined(_WIN32) || defined(WIN32) || defined(WIN64) + +#include "sysc/kernel/sc_cor.h" +#include "sysc/kernel/sc_cmnhdr.h" + +#if defined(__GNUC__) && __USING_SJLJ_EXCEPTIONS__ + // _Unwind_SjLj_Register() & _Unwind_SjLj_Unregister() only need first field. + struct SjLj_Function_Context { + struct SjLj_Function_Context *prev; + }; +#endif + +namespace sc_core { + +class sc_cor_pkg_fiber; +typedef sc_cor_pkg_fiber sc_cor_pkg_t; + +#if( defined(_MSC_VER) && _MSC_VER >= 1300 ) +typedef std::size_t size_t; +#endif + +// ---------------------------------------------------------------------------- +// CLASS : sc_cor_fiber +// +// Coroutine class implemented with QuickThreads. +// ---------------------------------------------------------------------------- + +class sc_cor_fiber +: public sc_cor +{ + +public: + + // constructor + sc_cor_fiber() + : m_stack_size( 0 ), m_fiber( 0 ), m_pkg( 0 ) + { +# if defined(__GNUC__) && __USING_SJLJ_EXCEPTIONS__ + m_eh.prev = 0; +# endif + } + + // destructor + virtual ~sc_cor_fiber(); + +public: + + std::size_t m_stack_size; // stack size + void* m_fiber; // fiber + + sc_cor_pkg_fiber* m_pkg; // the creating coroutine package +#if defined(__GNUC__) && __USING_SJLJ_EXCEPTIONS__ + struct SjLj_Function_Context m_eh; // the exception handling context +#endif + + +private: + + // disabled + sc_cor_fiber( const sc_cor_fiber& ); + sc_cor_fiber& operator = ( const sc_cor_fiber& ); +}; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_cor_pkg_fiber +// +// Coroutine package class implemented with QuickThreads. +// ---------------------------------------------------------------------------- + +class sc_cor_pkg_fiber +: public sc_cor_pkg +{ + public: + + // constructor + sc_cor_pkg_fiber( sc_simcontext* simc ); + + // destructor + virtual ~sc_cor_pkg_fiber(); + + // create a new coroutine + virtual sc_cor* create( std::size_t stack_size, sc_cor_fn* fn, void* arg ); + + // yield to the next coroutine + virtual void yield( sc_cor* next_cor ); + + // abort the current coroutine (and resume the next coroutine) + virtual void abort( sc_cor* next_cor ); + + // get the main coroutine + virtual sc_cor* get_main(); + +private: + + static int instance_count; + +private: + + // disabled + sc_cor_pkg_fiber(); + sc_cor_pkg_fiber( const sc_cor_pkg_fiber& ); + sc_cor_pkg_fiber& operator = ( const sc_cor_pkg_fiber& ); +}; + +} // namespace sc_core + +#endif // WIN32 + +// $Log: sc_cor_fiber.h,v $ +// Revision 1.6 2011/08/26 20:46:09 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +// Revision 1.5 2011/06/25 17:08:39 acg +// Andy Goodrich: Jerome Cornet's changes to use libtool to build the +// library. +// +// Revision 1.4 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.3 2011/02/13 21:47:37 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.2 2008/05/22 17:06:25 acg +// Andy Goodrich: updated copyright notice to include 2008. +// +// Revision 1.1.1.1 2006/12/15 20:20:05 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:44:29 acg +// Added $Log to record CVS changes into the source. +// + +#endif + +// Taf! diff --git a/ext/systemc/src/sysc/kernel/sc_cor_pthread.cpp b/ext/systemc/src/sysc/kernel/sc_cor_pthread.cpp new file mode 100644 index 000000000..d95eca93b --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_cor_pthread.cpp @@ -0,0 +1,313 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_cor_pthread.cpp -- Coroutine implementation with pthreads. + + Original Author: Andy Goodrich, Forte Design Systems, 2002-11-10 + + CHANGE LOG APPEARS AT THE END OF THE FILE + *****************************************************************************/ + +#if !defined(_WIN32) && !defined(WIN32) && defined(SC_USE_PTHREADS) + +// ORDER OF THE INCLUDES AND namespace sc_core IS IMPORTANT!!! + +#include "sysc/kernel/sc_cor_pthread.h" +#include "sysc/kernel/sc_simcontext.h" + +using namespace std; + +namespace sc_core { + +// MAKE SURE WE HAVE A NULL THAT WILL WORK: + +#if defined(__hpux) +# define PTHREAD_NULL cma_c_null +#else // !defined(__hpux) +# define PTHREAD_NULL NULL +#endif // !defined(__hpux) + +#define DEBUGF \ + if (0) std::cout << "sc_cor_pthread.cpp(" << __LINE__ << ") " + +// ---------------------------------------------------------------------------- +// File static variables. +// +// (1) The thread creation mutex and the creation condition are used to +// suspend the thread creating another one until the created thread +// reaches its invoke_module_method. This allows us to get control of +// thread scheduling away from the pthread package. +// ---------------------------------------------------------------------------- + +static sc_cor_pthread* active_cor_p=0; // Active co-routine. +static pthread_cond_t create_condition; // See note 1 above. +static pthread_mutex_t create_mutex; // See note 1 above. +static sc_cor_pthread main_cor; // Main coroutine. + + +// ---------------------------------------------------------------------------- +// CLASS : sc_cor_pthread +// +// Coroutine class implemented with Posix Threads. +// ---------------------------------------------------------------------------- + +// constructor + +sc_cor_pthread::sc_cor_pthread() + : m_cor_fn_arg( 0 ), m_pkg_p( 0 ) +{ + DEBUGF << this << ": sc_cor_pthread::sc_cor_pthread()" << std::endl; + pthread_cond_init( &m_pt_condition, PTHREAD_NULL ); + pthread_mutex_init( &m_mutex, PTHREAD_NULL ); +} + + +// destructor + +sc_cor_pthread::~sc_cor_pthread() +{ + DEBUGF << this << ": sc_cor_pthread::~sc_cor_pthread()" << std::endl; + pthread_cond_destroy( &m_pt_condition); + pthread_mutex_destroy( &m_mutex ); +} + + +// This static method is a Posix Threads helper callback and invokes a thread +// for the first time. It performs some synchronization and then invokes the +// actual sc_cor helper function. +// context_p -> thread to invoke module method of. +// Result is 0 and ignored. + +void* sc_cor_pthread::invoke_module_method(void* context_p) +{ + sc_cor_pthread* p = (sc_cor_pthread*)context_p; + DEBUGF << p << ": sc_cor_pthread::invoke_module_method()" << std::endl; + + + // SUSPEND THE THREAD SO WE CAN GAIN CONTROL FROM THE PTHREAD PACKAGE: + // + // Since pthread_create schedules each thread behind our back for its + // initial execution we immediately suspend a newly created thread + // here so we can control when its execution will occur. We also wake + // up the main thread which is waiting for this thread to execute to this + // wait point. + + pthread_mutex_lock( &create_mutex ); + DEBUGF << p << ": child signalling main thread " << endl; + pthread_cond_signal( &create_condition ); + pthread_mutex_lock( &p->m_mutex ); + pthread_mutex_unlock( &create_mutex ); + pthread_cond_wait( &p->m_pt_condition, &p->m_mutex ); + pthread_mutex_unlock( &p->m_mutex ); + + + // CALL THE SYSTEMC CODE THAT WILL ACTUALLY START THE THREAD OFF: + + active_cor_p = p; + DEBUGF << p << ": about to invoke real method " + << active_cor_p << std::endl; + (p->m_cor_fn)(p->m_cor_fn_arg); + + return 0; +} + + +// ---------------------------------------------------------------------------- +// CLASS : sc_cor_pkg_pthread +// +// Coroutine package class implemented with Posix Threads. +// ---------------------------------------------------------------------------- + +int sc_cor_pkg_pthread::instance_count = 0; + + +// constructor + +sc_cor_pkg_pthread::sc_cor_pkg_pthread( sc_simcontext* simc ) +: sc_cor_pkg( simc ) +{ + // initialize the current coroutine + if( ++ instance_count == 1 ) + { + pthread_cond_init( &create_condition, PTHREAD_NULL ); + pthread_mutex_init( &create_mutex, PTHREAD_NULL ); + assert( active_cor_p == 0 ); + main_cor.m_pkg_p = this; + DEBUGF << &main_cor << ": is main co-routine" << std::endl; + active_cor_p = &main_cor; + } +} + + +// destructor + +sc_cor_pkg_pthread::~sc_cor_pkg_pthread() +{ + if( -- instance_count == 0 ) { + // cleanup the main coroutine + } +} + + +// create a new coroutine + +sc_cor* +sc_cor_pkg_pthread::create( std::size_t stack_size, sc_cor_fn* fn, void* arg ) +{ + sc_cor_pthread* cor_p = new sc_cor_pthread; + DEBUGF << &main_cor << ": sc_cor_pkg_pthread::create(" + << cor_p << ")" << std::endl; + + + // INITIALIZE OBJECT'S FIELDS FROM ARGUMENT LIST: + + cor_p->m_pkg_p = this; + cor_p->m_cor_fn = fn; + cor_p->m_cor_fn_arg = arg; + + + // SET UP THREAD CREATION ATTRIBUTES: + // + // Use default values except for stack size. If stack size is non-zero + // set it. + + pthread_attr_t attr; + pthread_attr_init( &attr ); + if ( stack_size != 0 ) + { + pthread_attr_setstacksize( &attr, stack_size ); + } + + + // ALLOCATE THE POSIX THREAD TO USE AND FORCE SEQUENTIAL EXECUTION: + // + // Because pthread_create causes the created thread to be executed, + // we need to let it run until we can block in the invoke_module_method. + // So we: + // (1) Lock the creation mutex before creating the new thread. + // (2) Sleep on the creation condition, which will be signalled by + // the newly created thread just before it goes to sleep in + // invoke_module_method. + // This scheme results in the newly created thread being dormant before + // the main thread continues execution. + + pthread_mutex_lock( &create_mutex ); + DEBUGF << &main_cor << ": about to create actual thread " + << cor_p << std::endl; + if ( pthread_create( &cor_p->m_thread, &attr, + &sc_cor_pthread::invoke_module_method, (void*)cor_p ) ) + { + std::fprintf(stderr, "ERROR - could not create thread\n"); + } + + DEBUGF << &main_cor << ": main thread waiting for signal from " + << cor_p << std::endl; + pthread_cond_wait( &create_condition, &create_mutex ); + DEBUGF << &main_cor << ": main thread signaled by " + << cor_p << endl; + pthread_attr_destroy( &attr ); + pthread_mutex_unlock( &create_mutex ); + DEBUGF << &main_cor << ": exiting sc_cor_pkg_pthread::create(" + << cor_p << ")" << std::endl; + + return cor_p; +} + + +// yield to the next coroutine +// +// We don't do anything after the p_thread_cond_wait since it won't +// happen until the thread wakes up again! + +void +sc_cor_pkg_pthread::yield( sc_cor* next_cor_p ) +{ + sc_cor_pthread* from_p = active_cor_p; + sc_cor_pthread* to_p = (sc_cor_pthread*)next_cor_p; + + DEBUGF << from_p << ": switch to " << to_p << std::endl; + if ( to_p != from_p ) + { + pthread_mutex_lock( &to_p->m_mutex ); + pthread_cond_signal( &to_p->m_pt_condition ); + pthread_mutex_lock( &from_p->m_mutex ); + pthread_mutex_unlock( &to_p->m_mutex ); + pthread_cond_wait( &from_p->m_pt_condition, &from_p->m_mutex ); + pthread_mutex_unlock( &from_p->m_mutex ); + } + + active_cor_p = from_p; // When we come out of wait make ourselves active. + DEBUGF << from_p << " restarting after yield to " << to_p << std::endl; +} + + +// abort the current coroutine (and resume the next coroutine) + +void +sc_cor_pkg_pthread::abort( sc_cor* next_cor_p ) +{ + sc_cor_pthread* n_p = (sc_cor_pthread*)next_cor_p; + + DEBUGF << active_cor_p << ": aborting, switching to " << n_p << std::endl; + pthread_mutex_lock( &n_p->m_mutex ); + pthread_cond_signal( &n_p->m_pt_condition ); + pthread_mutex_unlock( &n_p->m_mutex ); +} + + +// get the main coroutine + +sc_cor* +sc_cor_pkg_pthread::get_main() +{ + return &main_cor; +} + +} // namespace sc_core + +#endif // !defined(_WIN32) && !defined(WIN32) && defined(SC_USE_PTHREADS) + + +// $Log: sc_cor_pthread.cpp,v $ +// Revision 1.6 2011/08/30 21:51:04 acg +// Jerome Cornet: auto processing of pthread configurations. +// +// Revision 1.5 2011/08/26 20:46:09 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +// Revision 1.4 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.3 2011/02/13 21:47:37 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.2 2008/05/22 17:06:25 acg +// Andy Goodrich: updated copyright notice to include 2008. +// +// Revision 1.1.1.1 2006/12/15 20:20:05 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:44:29 acg +// Added $Log to record CVS changes into the source. +// + +// Taf! diff --git a/ext/systemc/src/sysc/kernel/sc_cor_pthread.h b/ext/systemc/src/sysc/kernel/sc_cor_pthread.h new file mode 100644 index 000000000..f4d835de3 --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_cor_pthread.h @@ -0,0 +1,157 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_cor_pthread.h -- Coroutine implementation with pthreads. + + Original Author: Andy Goodrich, Forte Design Systems, 2002-11-10 + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + + +#ifndef SC_COR_PTHREAD_H +#define SC_COR_PTHREAD_H + + +#if defined(SC_USE_PTHREADS) + +#include "sysc/kernel/sc_cor.h" +#include "sysc/kernel/sc_cmnhdr.h" +#include <pthread.h> + +namespace sc_core { + +class sc_cor_pkg_pthread; +typedef sc_cor_pkg_pthread sc_cor_pkg_t; + +// ---------------------------------------------------------------------------- +// CLASS : sc_cor_pthread +// +// Coroutine class implemented with Posix Threads. +// +// Notes: +// (1) The thread creation mutex and the creation condition are used to +// suspend the thread creating another one until the created thread +// reaches its invoke_module_method. This allows us to get control of +// thread scheduling away from the pthread package. +// ---------------------------------------------------------------------------- + +class sc_cor_pthread : public sc_cor +{ + public: + + // constructor + sc_cor_pthread(); + + // destructor + virtual ~sc_cor_pthread(); + + // module method invocator (starts thread execution) + static void* invoke_module_method( void* context_p ); + + public: + static sc_cor_pthread* m_active_cor_p; // Active coroutine. + + public: + sc_cor_fn* m_cor_fn; // Core function. + void* m_cor_fn_arg; // Core function argument. + pthread_mutex_t m_mutex; // Mutex to suspend thread on. + sc_cor_pkg_pthread* m_pkg_p; // the creating coroutine package + pthread_cond_t m_pt_condition; // Condition waiting for. + pthread_t m_thread; // Our pthread storage. + +private: + + // disabled + sc_cor_pthread( const sc_cor_pthread& ); + sc_cor_pthread& operator = ( const sc_cor_pthread& ); +}; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_cor_pkg_pthread +// +// Coroutine package class implemented with Posix Threads. +// ---------------------------------------------------------------------------- + +class sc_cor_pkg_pthread +: public sc_cor_pkg +{ +public: + + // constructor + sc_cor_pkg_pthread( sc_simcontext* simc ); + + // destructor + virtual ~sc_cor_pkg_pthread(); + + // create a new coroutine + virtual sc_cor* create( std::size_t stack_size, sc_cor_fn* fn, void* arg ); + + // yield to the next coroutine + virtual void yield( sc_cor* next_cor ); + + // abort the current coroutine (and resume the next coroutine) + virtual void abort( sc_cor* next_cor ); + + // get the main coroutine + virtual sc_cor* get_main(); + +private: + + static int instance_count; + +private: + + // disabled + sc_cor_pkg_pthread(); + sc_cor_pkg_pthread( const sc_cor_pkg_pthread& ); + sc_cor_pkg_pthread& operator = ( const sc_cor_pkg_pthread& ); +}; + +} // namespace sc_core + +#endif + +// $Log: sc_cor_pthread.h,v $ +// Revision 1.5 2011/08/26 20:46:09 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +// Revision 1.4 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.3 2011/02/13 21:47:37 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.2 2008/05/22 17:06:25 acg +// Andy Goodrich: updated copyright notice to include 2008. +// +// Revision 1.1.1.1 2006/12/15 20:20:05 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:44:29 acg +// Added $Log to record CVS changes into the source. +// + +#endif // defined(SC_USE_PTHREADS) + +// Taf! diff --git a/ext/systemc/src/sysc/kernel/sc_cor_qt.cpp b/ext/systemc/src/sysc/kernel/sc_cor_qt.cpp new file mode 100644 index 000000000..d42298a62 --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_cor_qt.cpp @@ -0,0 +1,271 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_cor_qt.cpp -- Coroutine implementation with QuickThreads. + + Original Author: Martin Janssen, Synopsys, Inc., 2001-12-18 + + CHANGE LOG APPEARS AT THE END OF THE FILE + *****************************************************************************/ + +#if !defined(_WIN32) && !defined(WIN32) && !defined(SC_USE_PTHREADS) + +#include <unistd.h> +#include <sys/mman.h> +#include <sys/types.h> + +#include "sysc/kernel/sc_cor_qt.h" +#include "sysc/kernel/sc_simcontext.h" + +namespace sc_core { + +// ---------------------------------------------------------------------------- +// File static variables. +// ---------------------------------------------------------------------------- + +// main coroutine + +static sc_cor_qt main_cor; + +// current coroutine + +static sc_cor_qt* curr_cor = 0; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_cor_qt +// +// Coroutine class implemented with QuickThreads. +// ---------------------------------------------------------------------------- + +// switch stack protection on/off + +void +sc_cor_qt::stack_protect( bool enable ) +{ + // Code needs to be tested on HP-UX and disabled if it doesn't work there + // Code still needs to be ported to WIN32 + + static std::size_t pagesize; + + if( pagesize == 0 ) { +# if defined(__ppc__) + pagesize = getpagesize(); +# else + pagesize = sysconf( _SC_PAGESIZE ); +# endif + } + + assert( pagesize != 0 ); + assert( m_stack_size > ( 2 * pagesize ) ); + +#ifdef QUICKTHREADS_GROW_DOWN + // Stacks grow from high address down to low address + caddr_t redzone = caddr_t( ( ( std::size_t( m_stack ) + pagesize - 1 ) / + pagesize ) * pagesize ); +#else + // Stacks grow from low address up to high address + caddr_t redzone = caddr_t( ( ( std::size_t( m_stack ) + + m_stack_size - pagesize ) / + pagesize ) * pagesize ); +#endif + + int ret; + + // Enable the red zone at the end of the stack so that references within + // it will cause an interrupt. + + if( enable ) { + ret = mprotect( redzone, pagesize - 1, PROT_NONE ); + } + + // Revert the red zone to normal memory usage. Try to make it read - write - + // execute. If that does not work then settle for read - write + + else { + ret = mprotect( redzone, pagesize - 1, PROT_READ|PROT_WRITE|PROT_EXEC); + if ( ret != 0 ) + ret = mprotect( redzone, pagesize - 1, PROT_READ | PROT_WRITE ); + } + + assert( ret == 0 ); +} + + +// ---------------------------------------------------------------------------- +// CLASS : sc_cor_pkg_qt +// +// Coroutine package class implemented with QuickThreads. +// ---------------------------------------------------------------------------- + +int sc_cor_pkg_qt::instance_count = 0; + + +// support function + +inline +void* +stack_align( void* sp, int alignment, std::size_t* stack_size ) +{ + int round_up_mask = alignment - 1; + *stack_size = (*stack_size + round_up_mask) & ~round_up_mask; + return ( (void*)(((qt_word_t) sp + round_up_mask) & ~round_up_mask) ); +} + + +// constructor + +sc_cor_pkg_qt::sc_cor_pkg_qt( sc_simcontext* simc ) +: sc_cor_pkg( simc ) +{ + if( ++ instance_count == 1 ) { + // initialize the current coroutine + assert( curr_cor == 0 ); + curr_cor = &main_cor; + } +} + + +// destructor + +sc_cor_pkg_qt::~sc_cor_pkg_qt() +{ + if( -- instance_count == 0 ) { + // cleanup the current coroutine + curr_cor = 0; + } +} + + +// create a new coroutine + +extern "C" +void +sc_cor_qt_wrapper( void* arg, void* cor, qt_userf_t* fn ) +{ + curr_cor = RCAST<sc_cor_qt*>( cor ); + // invoke the user function + (*(sc_cor_fn*) fn)( arg ); + // not reached +} + +sc_cor* +sc_cor_pkg_qt::create( std::size_t stack_size, sc_cor_fn* fn, void* arg ) +{ + sc_cor_qt* cor = new sc_cor_qt(); + cor->m_pkg = this; + cor->m_stack_size = stack_size; + cor->m_stack = new char[cor->m_stack_size]; + void* sto = stack_align( cor->m_stack, QUICKTHREADS_STKALIGN, + &cor->m_stack_size ); + cor->m_sp = QUICKTHREADS_SP(sto, cor->m_stack_size - QUICKTHREADS_STKALIGN); + cor->m_sp = QUICKTHREADS_ARGS( cor->m_sp, arg, cor, (qt_userf_t*) fn, + sc_cor_qt_wrapper ); + return cor; +} + + +// yield to the next coroutine + +extern "C" +void* +sc_cor_qt_yieldhelp( qt_t* sp, void* old_cor, void* ) +{ + RCAST<sc_cor_qt*>( old_cor )->m_sp = sp; + return 0; +} + +void +sc_cor_pkg_qt::yield( sc_cor* next_cor ) +{ + sc_cor_qt* new_cor = SCAST<sc_cor_qt*>( next_cor ); + sc_cor_qt* old_cor = curr_cor; + curr_cor = new_cor; + QUICKTHREADS_BLOCK( sc_cor_qt_yieldhelp, old_cor, 0, new_cor->m_sp ); +} + + +// abort the current coroutine (and resume the next coroutine) + +extern "C" +void* +sc_cor_qt_aborthelp( qt_t*, void*, void* ) +{ + return 0; +} + +void +sc_cor_pkg_qt::abort( sc_cor* next_cor ) +{ + sc_cor_qt* new_cor = SCAST<sc_cor_qt*>( next_cor ); + sc_cor_qt* old_cor = curr_cor; + curr_cor = new_cor; + QUICKTHREADS_ABORT( sc_cor_qt_aborthelp, old_cor, 0, new_cor->m_sp ); +} + + +// get the main coroutine + +sc_cor* +sc_cor_pkg_qt::get_main() +{ + return &main_cor; +} + +} // namespace sc_core + +#endif + +// $Log: sc_cor_qt.cpp,v $ +// Revision 1.9 2011/08/29 18:04:32 acg +// Philipp A. Hartmann: miscellaneous clean ups. +// +// Revision 1.8 2011/08/26 20:46:09 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +// Revision 1.7 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.6 2011/02/13 21:47:37 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.5 2010/08/03 16:52:14 acg +// Andy Goodrich: line formatting. +// +// Revision 1.4 2008/11/11 14:03:07 acg +// Andy Goodrich: added execute access to the release of red zone storage +// per Ulli's suggestion. +// +// Revision 1.3 2008/05/22 17:06:25 acg +// Andy Goodrich: updated copyright notice to include 2008. +// +// Revision 1.2 2008/03/24 18:32:36 acg +// Andy Goodrich: added include of sys/types.h to pick up the declaration +// of caddr_t. +// +// Revision 1.1.1.1 2006/12/15 20:20:05 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:44:29 acg +// Added $Log to record CVS changes into the source. + +// Taf! diff --git a/ext/systemc/src/sysc/kernel/sc_cor_qt.h b/ext/systemc/src/sysc/kernel/sc_cor_qt.h new file mode 100644 index 000000000..644d39c3f --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_cor_qt.h @@ -0,0 +1,154 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_cor_qt.h -- Coroutine implementation with QuickThreads. + + Original Author: Martin Janssen, Synopsys, Inc., 2001-12-18 + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + + +#ifndef SC_COR_QT_H +#define SC_COR_QT_H + + +#if !defined(_WIN32) && !defined(WIN32) && !defined(WIN64) && !defined(SC_USE_PTHREADS) + +#include "sysc/kernel/sc_cor.h" +#include "sysc/qt/qt.h" + +namespace sc_core { + +class sc_cor_pkg_qt; +typedef sc_cor_pkg_qt sc_cor_pkg_t; + +// ---------------------------------------------------------------------------- +// CLASS : sc_cor_qt +// +// Coroutine class implemented with QuickThreads. +// ---------------------------------------------------------------------------- + +class sc_cor_qt +: public sc_cor +{ +public: + + // constructor + sc_cor_qt() + : m_stack_size( 0 ), m_stack( 0 ), m_sp( 0 ), m_pkg( 0 ) + {} + + // destructor + virtual ~sc_cor_qt() + { delete[] (char*) m_stack; } + + // switch stack protection on/off + virtual void stack_protect( bool enable ); + +public: + + std::size_t m_stack_size; // stack size + void* m_stack; // stack + qt_t* m_sp; // stack pointer + + sc_cor_pkg_qt* m_pkg; // the creating coroutine package + +private: + + // disabled + sc_cor_qt( const sc_cor_qt& ); + sc_cor_qt& operator = ( const sc_cor_qt& ); +}; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_cor_pkg_qt +// +// Coroutine package class implemented with QuickThreads. +// ---------------------------------------------------------------------------- + +class sc_cor_pkg_qt +: public sc_cor_pkg +{ +public: + + // constructor + sc_cor_pkg_qt( sc_simcontext* simc ); + + // destructor + virtual ~sc_cor_pkg_qt(); + + // create a new coroutine + virtual sc_cor* create( std::size_t stack_size, sc_cor_fn* fn, void* arg ); + + // yield to the next coroutine + virtual void yield( sc_cor* next_cor ); + + // abort the current coroutine (and resume the next coroutine) + virtual void abort( sc_cor* next_cor ); + + // get the main coroutine + virtual sc_cor* get_main(); + +private: + + static int instance_count; + +private: + + // disabled + sc_cor_pkg_qt(); + sc_cor_pkg_qt( const sc_cor_pkg_qt& ); + sc_cor_pkg_qt& operator = ( const sc_cor_pkg_qt& ); +}; + +} // namespace sc_core + +#endif + +// $Log: sc_cor_qt.h,v $ +// Revision 1.6 2011/08/29 18:04:32 acg +// Philipp A. Hartmann: miscellaneous clean ups. +// +// Revision 1.5 2011/08/26 20:46:09 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +// Revision 1.4 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.3 2011/02/13 21:47:37 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.2 2008/05/22 17:06:25 acg +// Andy Goodrich: updated copyright notice to include 2008. +// +// Revision 1.1.1.1 2006/12/15 20:20:05 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:44:29 acg +// Added $Log to record CVS changes into the source. +// + +#endif + +// Taf! diff --git a/ext/systemc/src/sysc/kernel/sc_cthread_process.cpp b/ext/systemc/src/sysc/kernel/sc_cthread_process.cpp new file mode 100644 index 000000000..fef5cc8d8 --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_cthread_process.cpp @@ -0,0 +1,123 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_cthread_process.cpp -- Clocked thread implementation. + + Original Author: Andy Goodrich, Forte Design Systems, 4 August 2005 + + + CHANGE LOG APPEARS AT THE END OF THE FILE + *****************************************************************************/ + +#include "sysc/kernel/sc_cthread_process.h" +#include "sysc/kernel/sc_simcontext_int.h" + +namespace sc_core { + +//------------------------------------------------------------------------------ +//"sc_cthread_process::dont_initialize" +// +// This virtual method sets the initialization switch for this object instance. +//------------------------------------------------------------------------------ +void sc_cthread_process::dont_initialize( bool /* dont */ ) +{ + SC_REPORT_WARNING( SC_ID_DONT_INITIALIZE_, 0 ); +} + +//------------------------------------------------------------------------------ +//"sc_cthread_process::sc_cthread_process" +// +// This is the object instance constructor for this class. +//------------------------------------------------------------------------------ +sc_cthread_process::sc_cthread_process( const char* name_p, + bool free_host, SC_ENTRY_FUNC method_p, + sc_process_host* host_p, const sc_spawn_options* opt_p +): + sc_thread_process(name_p, free_host, method_p, host_p, opt_p) +{ + m_dont_init = true; + m_process_kind = SC_CTHREAD_PROC_; +} + +//------------------------------------------------------------------------------ +//"sc_cthread_process::~sc_cthread_process" +// +// This is the object instance constructor for this class. +//------------------------------------------------------------------------------ +sc_cthread_process::~sc_cthread_process() +{ +} + +} // namespace sc_core + +// $Log: sc_cthread_process.cpp,v $ +// Revision 1.11 2011/08/26 20:46:09 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +// Revision 1.10 2011/08/15 16:43:24 acg +// Torsten Maehne: changes to remove unused argument warnings. +// +// Revision 1.9 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.8 2011/02/13 21:47:37 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.7 2011/02/11 13:25:24 acg +// Andy Goodrich: Philipp A. Hartmann's changes: +// (1) Removal of SC_CTHREAD method overloads. +// (2) New exception processing code. +// +// Revision 1.6 2011/02/01 21:00:35 acg +// Andy Goodrich: removed throw_reset as it is now handled by parent +// sc_thread_process::throw_reset(). +// +// Revision 1.5 2011/01/18 20:10:44 acg +// Andy Goodrich: changes for IEEE1666_2011 semantics. +// +// Revision 1.4 2009/07/28 01:10:53 acg +// Andy Goodrich: updates for 2.3 release candidate. +// +// Revision 1.3 2009/05/22 16:06:29 acg +// Andy Goodrich: process control updates. +// +// Revision 1.2 2008/05/22 17:06:25 acg +// Andy Goodrich: updated copyright notice to include 2008. +// +// Revision 1.1.1.1 2006/12/15 20:20:05 acg +// SystemC 2.3 +// +// Revision 1.6 2006/04/20 17:08:16 acg +// Andy Goodrich: 3.0 style process changes. +// +// Revision 1.5 2006/04/11 23:13:20 acg +// Andy Goodrich: Changes for reduced reset support that only includes +// sc_cthread, but has preliminary hooks for expanding to method and thread +// processes also. +// +// Revision 1.4 2006/01/24 20:49:04 acg +// Andy Goodrich: changes to remove the use of deprecated features within the +// simulator, and to issue warning messages when deprecated features are used. +// +// Revision 1.3 2006/01/13 18:44:29 acg +// Added $Log to record CVS changes into the source. +// diff --git a/ext/systemc/src/sysc/kernel/sc_cthread_process.h b/ext/systemc/src/sysc/kernel/sc_cthread_process.h new file mode 100644 index 000000000..6d35ece0d --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_cthread_process.h @@ -0,0 +1,144 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_cthread_process.h -- Clocked thread declarations + + Original Author: Andy Goodrich, Forte Design Systems, 4 August 2005 + + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + + +#if !defined(sc_cthread_process_h_INCLUDED) +#define sc_cthread_process_h_INCLUDED + +#include "sysc/kernel/sc_thread_process.h" + +namespace sc_core { + +// friend function declarations: + +void halt( sc_simcontext* ); +void wait( int, sc_simcontext* ); + + +//============================================================================== +// sc_cthread_process - +// +//============================================================================== +class sc_cthread_process : public sc_thread_process { + + friend class sc_module; + friend class sc_process_handle; + friend class sc_process_table; + friend class sc_thread_process; + friend class sc_simcontext; + + friend void sc_cthread_cor_fn( void* ); + + friend void halt( sc_simcontext* ); + friend void wait( int, sc_simcontext* ); + + public: + sc_cthread_process( const char* name_p, bool free_host, + SC_ENTRY_FUNC method_p, sc_process_host* host_p, + const sc_spawn_options* opt_p ); + + virtual void dont_initialize( bool dont ); + virtual const char* kind() const + { return "sc_cthread_process"; } + +private: + + sc_cthread_process( const char* nm, + SC_ENTRY_FUNC fn, + sc_process_host* host ); + + // may not be deleted manually (called from sc_process_b) + virtual ~sc_cthread_process(); + + bool eval_watchlist(); + bool eval_watchlist_curr_level(); + + void wait_halt(); + +}; + +//------------------------------------------------------------------------------ +//"sc_cthread_process::wait_halt" +// +//------------------------------------------------------------------------------ +inline void sc_cthread_process::wait_halt() +{ + m_wait_cycle_n = 0; + suspend_me(); + throw sc_halt(); +} + +} // namespace sc_core + +// $Log: sc_cthread_process.h,v $ +// Revision 1.8 2011/08/26 20:46:09 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +// Revision 1.7 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.6 2011/02/13 21:47:37 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.5 2011/02/11 13:25:24 acg +// Andy Goodrich: Philipp A. Hartmann's changes: +// (1) Removal of SC_CTHREAD method overloads. +// (2) New exception processing code. +// +// Revision 1.4 2011/02/01 21:01:41 acg +// Andy Goodrich: removed throw_reset() as it is now handled by the parent +// method sc_thread_process::throw_reset(). +// +// Revision 1.3 2011/01/18 20:10:44 acg +// Andy Goodrich: changes for IEEE1666_2011 semantics. +// +// Revision 1.2 2008/05/22 17:06:25 acg +// Andy Goodrich: updated copyright notice to include 2008. +// +// Revision 1.1.1.1 2006/12/15 20:20:05 acg +// SystemC 2.3 +// +// Revision 1.6 2006/05/08 17:57:13 acg +// Andy Goodrich: Added David Long's forward declarations for friend functions +// to keep the Microsoft C++ compiler happy. +// +// Revision 1.5 2006/04/20 17:08:16 acg +// Andy Goodrich: 3.0 style process changes. +// +// Revision 1.4 2006/04/11 23:13:20 acg +// Andy Goodrich: Changes for reduced reset support that only includes +// sc_cthread, but has preliminary hooks for expanding to method and thread +// processes also. +// +// Revision 1.3 2006/01/13 18:44:29 acg +// Added $Log to record CVS changes into the source. +// + +#endif // !defined(sc_cthread_process_h_INCLUDED) diff --git a/ext/systemc/src/sysc/kernel/sc_dynamic_processes.h b/ext/systemc/src/sysc/kernel/sc_dynamic_processes.h new file mode 100644 index 000000000..628c3300a --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_dynamic_processes.h @@ -0,0 +1,67 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_dynamic_process.h -- Dynamic Process Package Definitions + + Original Author: Andy Goodrich, Forte Design Systems, 5 May 2003 + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + + +#ifndef SC_DYNAMIC_PROCESSES_H +#define SC_DYNAMIC_PROCESSES_H + +#include "sysc/kernel/sc_except.h" +#include "sysc/kernel/sc_spawn.h" +#include "sysc/kernel/sc_join.h" +#include "sysc/kernel/sc_boost.h" + +// $Log: sc_dynamic_processes.h,v $ +// Revision 1.5 2011/08/26 20:46:09 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +// Revision 1.4 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.3 2011/02/13 21:47:37 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.2 2008/05/22 17:06:25 acg +// Andy Goodrich: updated copyright notice to include 2008. +// +// Revision 1.1.1.1 2006/12/15 20:20:05 acg +// SystemC 2.3 +// +// Revision 1.5 2006/04/20 17:08:16 acg +// Andy Goodrich: 3.0 style process changes. +// +// Revision 1.4 2006/04/11 23:13:20 acg +// Andy Goodrich: Changes for reduced reset support that only includes +// sc_cthread, but has preliminary hooks for expanding to method and thread +// processes also. +// +// Revision 1.3 2006/01/13 18:44:29 acg +// Added $Log to record CVS changes into the source. +// + +#endif // SC_DYNAMIC_PROCESSES_H diff --git a/ext/systemc/src/sysc/kernel/sc_event.cpp b/ext/systemc/src/sysc/kernel/sc_event.cpp new file mode 100644 index 000000000..488210ee9 --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_event.cpp @@ -0,0 +1,759 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_event.cpp -- + + Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21 + + CHANGE LOG APPEARS AT THE END OF THE FILE + *****************************************************************************/ + +#include <stdlib.h> +#include <string.h> + +#include "sysc/kernel/sc_event.h" +#include "sysc/kernel/sc_kernel_ids.h" +#include "sysc/kernel/sc_phase_callback_registry.h" +#include "sysc/kernel/sc_process.h" +#include "sysc/kernel/sc_process_handle.h" +#include "sysc/kernel/sc_simcontext_int.h" +#include "sysc/kernel/sc_object_manager.h" +#include "sysc/utils/sc_utils_ids.h" + +namespace sc_core { + +// ---------------------------------------------------------------------------- +// CLASS : sc_event +// +// The event class. +// ---------------------------------------------------------------------------- + +const char* +sc_event::basename() const +{ + const char* p = strrchr( m_name.c_str(), SC_HIERARCHY_CHAR ); + return p ? (p + 1) : m_name.c_str(); +} + +void +sc_event::cancel() +{ + // cancel a delta or timed notification + switch( m_notify_type ) { + case DELTA: { + // remove this event from the delta events set + m_simc->remove_delta_event( this ); + m_notify_type = NONE; + break; + } + case TIMED: { + // remove this event from the timed events set + sc_assert( m_timed != 0 ); + m_timed->m_event = 0; + m_timed = 0; + m_notify_type = NONE; + break; + } + default: + ; + } +} + + +void +sc_event::notify() +{ + // immediate notification + if( + // coming from sc_prim_channel::update + m_simc->update_phase() +#if SC_HAS_PHASE_CALLBACKS_ + // coming from phase callbacks + || m_simc->notify_phase() +#endif + ) + { + SC_REPORT_ERROR( SC_ID_IMMEDIATE_NOTIFICATION_, "" ); + return; + } + cancel(); + trigger(); +} + +void +sc_event::notify( const sc_time& t ) +{ + if( m_notify_type == DELTA ) { + return; + } + if( t == SC_ZERO_TIME ) { +# if SC_HAS_PHASE_CALLBACKS_ + if( SC_UNLIKELY_( m_simc->get_status() + & (SC_END_OF_UPDATE|SC_BEFORE_TIMESTEP) ) ) + { + std::stringstream msg; + msg << m_simc->get_status() + << ":\n\t delta notification of `" + << name() << "' ignored"; + SC_REPORT_WARNING( SC_ID_PHASE_CALLBACK_FORBIDDEN_ + , msg.str().c_str() ); + return; + } +# endif + if( m_notify_type == TIMED ) { + // remove this event from the timed events set + sc_assert( m_timed != 0 ); + m_timed->m_event = 0; + m_timed = 0; + } + // add this event to the delta events set + m_delta_event_index = m_simc->add_delta_event( this ); + m_notify_type = DELTA; + return; + } +# if SC_HAS_PHASE_CALLBACKS_ + if( SC_UNLIKELY_( m_simc->get_status() + & (SC_END_OF_UPDATE|SC_BEFORE_TIMESTEP) ) ) + { + std::stringstream msg; + msg << m_simc->get_status() + << ":\n\t timed notification of `" + << name() << "' ignored"; + SC_REPORT_WARNING( SC_ID_PHASE_CALLBACK_FORBIDDEN_ + , msg.str().c_str() ); + return; + } +# endif + if( m_notify_type == TIMED ) { + sc_assert( m_timed != 0 ); + if( m_timed->m_notify_time <= m_simc->time_stamp() + t ) { + return; + } + // remove this event from the timed events set + m_timed->m_event = 0; + m_timed = 0; + } + // add this event to the timed events set + sc_event_timed* et = new sc_event_timed( this, m_simc->time_stamp() + t ); + m_simc->add_timed_event( et ); + m_timed = et; + m_notify_type = TIMED; +} + +static void sc_warn_notify_delayed() +{ + static bool warn_notify_delayed=true; + if ( warn_notify_delayed ) + { + warn_notify_delayed = false; + SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, + "notify_delayed(...) is deprecated, use notify(sc_time) instead" ); + } +} + +void +sc_event::notify_delayed() +{ + sc_warn_notify_delayed(); + if( m_notify_type != NONE ) { + SC_REPORT_ERROR( SC_ID_NOTIFY_DELAYED_, 0 ); + } + // add this event to the delta events set + m_delta_event_index = m_simc->add_delta_event( this ); + m_notify_type = DELTA; +} + +void +sc_event::notify_delayed( const sc_time& t ) +{ + sc_warn_notify_delayed(); + if( m_notify_type != NONE ) { + SC_REPORT_ERROR( SC_ID_NOTIFY_DELAYED_, 0 ); + } + if( t == SC_ZERO_TIME ) { + // add this event to the delta events set + m_delta_event_index = m_simc->add_delta_event( this ); + m_notify_type = DELTA; + } else { + // add this event to the timed events set + sc_event_timed* et = new sc_event_timed( this, + m_simc->time_stamp() + t ); + m_simc->add_timed_event( et ); + m_timed = et; + m_notify_type = TIMED; + } +} + +// +---------------------------------------------------------------------------- +// |"sc_event::register_event" +// | +// | This method sets the name of this object instance and optionally adds +// | it to the object manager's hierarchy. The object instance will be +// | inserted into the object manager's hierarchy if one of the following is +// | true: +// | (a) the leaf name is non-null and does not start with +// | SC_KERNEL_EVENT_PREFIX. +// | (b) the event is being created before the start of simulation. +// | +// | Arguments: +// | leaf_name = leaf name of the object or NULL. +// +---------------------------------------------------------------------------- +void sc_event::register_event( const char* leaf_name ) +{ + sc_object_manager* object_manager = m_simc->get_object_manager(); + m_parent_p = m_simc->active_object(); + + // No name provided, if we are not executing then create a name: + + if( !leaf_name || !leaf_name[0] ) + { + if ( sc_is_running( m_simc ) ) return; + leaf_name = sc_gen_unique_name("event"); + } + + // Create a hierarchichal name and place it into the object manager if + // its not a kernel event: + + object_manager->create_name( leaf_name ).swap( m_name ); + + if ( strncmp( leaf_name, SC_KERNEL_EVENT_PREFIX, + strlen(SC_KERNEL_EVENT_PREFIX) ) ) + { + object_manager->insert_event(m_name, this); + if ( m_parent_p ) + m_parent_p->add_child_event( this ); + else + m_simc->add_child_event( this ); + } +} + +void +sc_event::reset() +{ + m_notify_type = NONE; + m_delta_event_index = -1; + m_timed = 0; + // clear the dynamic sensitive methods + m_methods_dynamic.resize(0); + // clear the dynamic sensitive threads + m_threads_dynamic.resize(0); +} + +// +---------------------------------------------------------------------------- +// |"sc_event::sc_event(name)" +// | +// | This is the object instance constructor for named sc_event instances. +// | If the name is non-null or the this is during elaboration add the +// | event to the object hierarchy. +// | +// | Arguments: +// | name = name of the event. +// +---------------------------------------------------------------------------- +sc_event::sc_event( const char* name ) : + m_name(), + m_parent_p(NULL), + m_simc( sc_get_curr_simcontext() ), + m_notify_type( NONE ), + m_delta_event_index( -1 ), + m_timed( 0 ), + m_methods_static(), + m_methods_dynamic(), + m_threads_static(), + m_threads_dynamic() +{ + // Skip simulator's internally defined events. + + register_event( name ); +} + +// +---------------------------------------------------------------------------- +// |"sc_event::sc_event(name)" +// | +// | This is the object instance constructor for non-named sc_event instances. +// | If this is during elaboration add create a name and add it to the object +// | hierarchy. +// +---------------------------------------------------------------------------- +sc_event::sc_event() : + m_name(), + m_parent_p(NULL), + m_simc( sc_get_curr_simcontext() ), + m_notify_type( NONE ), + m_delta_event_index( -1 ), + m_timed( 0 ), + m_methods_static(), + m_methods_dynamic(), + m_threads_static(), + m_threads_dynamic() +{ + + register_event( NULL ); +} + +// +---------------------------------------------------------------------------- +// |"sc_event::~sc_event" +// | +// | This is the object instance destructor for this class. It cancels any +// | outstanding waits and removes the event from the object manager's +// | instance table if it has a name. +// +---------------------------------------------------------------------------- +sc_event::~sc_event() +{ + cancel(); + if ( m_name.length() != 0 ) + { + sc_object_manager* object_manager_p = m_simc->get_object_manager(); + object_manager_p->remove_event( m_name ); + } +} + +// +---------------------------------------------------------------------------- +// |"sc_event::trigger" +// | +// | This method "triggers" this object instance. This consists of scheduling +// | for execution all the processes that are schedulable and waiting on this +// | event. +// +---------------------------------------------------------------------------- +void +sc_event::trigger() +{ + int last_i; // index of last element in vector now accessing. + int size; // size of vector now accessing. + + + // trigger the static sensitive methods + + if( ( size = m_methods_static.size() ) != 0 ) + { + sc_method_handle* l_methods_static = &m_methods_static[0]; + int i = size - 1; + do { + sc_method_handle method_h = l_methods_static[i]; + method_h->trigger_static(); + } while( -- i >= 0 ); + } + + // trigger the dynamic sensitive methods + + + if( ( size = m_methods_dynamic.size() ) != 0 ) + { + last_i = size - 1; + sc_method_handle* l_methods_dynamic = &m_methods_dynamic[0]; + for ( int i = 0; i <= last_i; i++ ) + { + sc_method_handle method_h = l_methods_dynamic[i]; + if ( method_h->trigger_dynamic( this ) ) + { + l_methods_dynamic[i] = l_methods_dynamic[last_i]; + last_i--; + i--; + } + } + m_methods_dynamic.resize(last_i+1); + } + + + // trigger the static sensitive threads + + if( ( size = m_threads_static.size() ) != 0 ) + { + sc_thread_handle* l_threads_static = &m_threads_static[0]; + int i = size - 1; + do { + sc_thread_handle thread_h = l_threads_static[i]; + thread_h->trigger_static(); + } while( -- i >= 0 ); + } + + // trigger the dynamic sensitive threads + + if( ( size = m_threads_dynamic.size() ) != 0 ) + { + last_i = size - 1; + sc_thread_handle* l_threads_dynamic = &m_threads_dynamic[0]; + for ( int i = 0; i <= last_i; i++ ) + { + sc_thread_handle thread_h = l_threads_dynamic[i]; + if ( thread_h->trigger_dynamic( this ) ) + { + l_threads_dynamic[i] = l_threads_dynamic[last_i]; + i--; + last_i--; + } + } + m_threads_dynamic.resize(last_i+1); + } + + m_notify_type = NONE; + m_delta_event_index = -1; + m_timed = 0; +} + + +bool +sc_event::remove_static( sc_method_handle method_h_ ) const +{ + int size; + if ( ( size = m_methods_static.size() ) != 0 ) { + sc_method_handle* l_methods_static = &m_methods_static[0]; + for( int i = size - 1; i >= 0; -- i ) { + if( l_methods_static[i] == method_h_ ) { + l_methods_static[i] = l_methods_static[size - 1]; + m_methods_static.resize(size-1); + return true; + } + } + } + return false; +} + +bool +sc_event::remove_static( sc_thread_handle thread_h_ ) const +{ + int size; + if ( ( size = m_threads_static.size() ) != 0 ) { + sc_thread_handle* l_threads_static = &m_threads_static[0]; + for( int i = size - 1; i >= 0; -- i ) { + if( l_threads_static[i] == thread_h_ ) { + l_threads_static[i] = l_threads_static[size - 1]; + m_threads_static.resize(size-1); + return true; + } + } + } + return false; +} + +bool +sc_event::remove_dynamic( sc_method_handle method_h_ ) const +{ + int size; + if ( ( size = m_methods_dynamic.size() ) != 0 ) { + sc_method_handle* l_methods_dynamic = &m_methods_dynamic[0]; + for( int i = size - 1; i >= 0; -- i ) { + if( l_methods_dynamic[i] == method_h_ ) { + l_methods_dynamic[i] = l_methods_dynamic[size - 1]; + m_methods_dynamic.resize(size-1); + return true; + } + } + } + return false; +} + +bool +sc_event::remove_dynamic( sc_thread_handle thread_h_ ) const +{ + int size; + if ( ( size= m_threads_dynamic.size() ) != 0 ) { + sc_thread_handle* l_threads_dynamic = &m_threads_dynamic[0]; + for( int i = size - 1; i >= 0; -- i ) { + if( l_threads_dynamic[i] == thread_h_ ) { + l_threads_dynamic[i] = l_threads_dynamic[size - 1]; + m_threads_dynamic.resize(size-1); + return true; + } + } + } + return false; +} + + +// ---------------------------------------------------------------------------- +// CLASS : sc_event_timed +// +// Class for storing the time to notify a timed event. +// ---------------------------------------------------------------------------- + +// dedicated memory management; not MT-Safe + +union sc_event_timed_u +{ + sc_event_timed_u* next; + char dummy[sizeof( sc_event_timed )]; +}; + +static +sc_event_timed_u* free_list = 0; + +void* +sc_event_timed::allocate() +{ + const int ALLOC_SIZE = 64; + + if( free_list == 0 ) { + free_list = (sc_event_timed_u*) malloc( ALLOC_SIZE * + sizeof( sc_event_timed ) ); + int i = 0; + for( ; i < ALLOC_SIZE - 1; ++ i ) { + free_list[i].next = &free_list[i + 1]; + } + free_list[i].next = 0; + } + + sc_event_timed_u* q = free_list; + free_list = free_list->next; + return q; +} + +void +sc_event_timed::deallocate( void* p ) +{ + if( p != 0 ) { + sc_event_timed_u* q = RCAST<sc_event_timed_u*>( p ); + q->next = free_list; + free_list = q; + } +} + + +// ---------------------------------------------------------------------------- +// CLASS : sc_event_list +// +// Base class for lists of events. +// ---------------------------------------------------------------------------- + +void +sc_event_list::push_back( const sc_event& e ) +{ + // make sure e is not already in the list + if ( m_events.size() != 0 ) { + const sc_event** l_events = &m_events[0]; + for( int i = m_events.size() - 1; i >= 0; -- i ) { + if( &e == l_events[i] ) { + // event already in the list; ignore + return; + } + } + } + m_events.push_back( &e ); +} + +void +sc_event_list::push_back( const sc_event_list& el ) +{ + m_events.reserve( size() + el.size() ); + for ( int i = el.m_events.size() - 1; i >= 0; --i ) + { + push_back( *el.m_events[i] ); + } + el.auto_delete(); +} + +void +sc_event_list::add_dynamic( sc_method_handle method_h ) const +{ + m_busy++; + if ( m_events.size() != 0 ) { + const sc_event* const * l_events = &m_events[0]; + for( int i = m_events.size() - 1; i >= 0; -- i ) { + l_events[i]->add_dynamic( method_h ); + } + } +} + +void +sc_event_list::add_dynamic( sc_thread_handle thread_h ) const +{ + m_busy++; + if ( m_events.size() != 0 ) { + const sc_event* const* l_events = &m_events[0]; + for( int i = m_events.size() - 1; i >= 0; -- i ) { + l_events[i]->add_dynamic( thread_h ); + } + } +} + +void +sc_event_list::remove_dynamic( sc_method_handle method_h, + const sc_event* e_not ) const +{ + if ( m_events.size() != 0 ) { + const sc_event* const* l_events = &m_events[0]; + for( int i = m_events.size() - 1; i >= 0; -- i ) { + const sc_event* e = l_events[i]; + if( e != e_not ) { + e->remove_dynamic( method_h ); + } + } + } +} + +void +sc_event_list::remove_dynamic( sc_thread_handle thread_h, + const sc_event* e_not ) const +{ + if ( m_events.size() != 0 ) { + const sc_event* const* l_events = &m_events[0]; + for( int i = m_events.size() - 1; i >= 0; -- i ) { + const sc_event* e = l_events[i]; + if( e != e_not ) { + e->remove_dynamic( thread_h ); + } + } + } +} + +void +sc_event_list::report_premature_destruction() const +{ + // TDB: reliably detect premature destruction + // + // If an event list is used as a member of a module, + // its lifetime may (correctly) end, although there + // are processes currently waiting for it. + // + // Detecting (and ignoring) this corner-case is quite + // difficult for similar reasons to the sc_is_running() + // return value during the destruction of the module + // hierarchy. + // + // Ignoring the lifetime checks for now, if no process + // is currently running (which is only part of the story): + + if( sc_get_current_process_handle().valid() ) { + // FIXME: improve error-handling + sc_assert( false && "sc_event_list prematurely destroyed" ); + } + +} + +void +sc_event_list::report_invalid_modification() const +{ + // FIXME: improve error-handling + sc_assert( false && "sc_event_list modfied while being waited on" ); +} + +// ---------------------------------------------------------------------------- +// Deprecated functional notation for notifying events. +// ---------------------------------------------------------------------------- + +static void sc_warn_notify() +{ + static bool warn_notify=true; + if ( warn_notify ) + { + SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, + "the notify() function is deprecated use sc_event::notify()" ); + warn_notify = false; + } +} + +void +notify( sc_event& e ) +{ + sc_warn_notify(); + e.notify(); +} + +void +notify( const sc_time& t, sc_event& e ) +{ + sc_warn_notify(); + e.notify( t ); +} + +void +notify( double v, sc_time_unit tu, sc_event& e ) +{ + sc_warn_notify(); + e.notify( v, tu ); +} + +} // namespace sc_core + +// $Log: sc_event.cpp,v $ +// Revision 1.17 2011/08/26 20:46:09 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +// Revision 1.16 2011/08/24 22:05:50 acg +// Torsten Maehne: initialization changes to remove warnings. +// +// Revision 1.15 2011/03/12 21:07:51 acg +// Andy Goodrich: changes to kernel generated event support. +// +// Revision 1.14 2011/03/06 15:55:52 acg +// Andy Goodrich: changes for named events. +// +// Revision 1.13 2011/03/05 01:39:21 acg +// Andy Goodrich: changes for named events. +// +// Revision 1.12 2011/02/19 08:33:25 acg +// Andy Goodrich: remove }'s that should have been removed before. +// +// Revision 1.11 2011/02/19 08:30:53 acg +// Andy Goodrich: Moved process queueing into trigger_static from +// sc_event::notify. +// +// Revision 1.10 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.9 2011/02/17 19:49:51 acg +// Andy Goodrich: +// (1) Changed signature of trigger_dynamic() to return a bool again. +// (2) Moved process run queue processing into trigger_dynamic(). +// +// Revision 1.8 2011/02/16 22:37:30 acg +// Andy Goodrich: clean up to remove need for ps_disable_pending. +// +// Revision 1.7 2011/02/13 21:47:37 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.6 2011/02/01 21:02:28 acg +// Andy Goodrich: new return code for trigger_dynamic() calls. +// +// Revision 1.5 2011/01/18 20:10:44 acg +// Andy Goodrich: changes for IEEE1666_2011 semantics. +// +// Revision 1.4 2011/01/06 18:04:05 acg +// Andy Goodrich: added code to leave disabled processes on the dynamic +// method and thread queues. +// +// Revision 1.3 2008/05/22 17:06:25 acg +// Andy Goodrich: updated copyright notice to include 2008. +// +// Revision 1.2 2007/01/17 22:44:30 acg +// Andy Goodrich: fix for Microsoft compiler. +// +// Revision 1.7 2006/04/11 23:13:20 acg +// Andy Goodrich: Changes for reduced reset support that only includes +// sc_cthread, but has preliminary hooks for expanding to method and thread +// processes also. +// +// Revision 1.6 2006/01/25 00:31:19 acg +// Andy Goodrich: Changed over to use a standard message id of +// SC_ID_IEEE_1666_DEPRECATION for all deprecation messages. +// +// Revision 1.5 2006/01/24 20:59:11 acg +// Andy Goodrich: fix up of CVS comments, new version roll. +// +// Revision 1.4 2006/01/24 20:48:14 acg +// Andy Goodrich: added deprecation warnings for notify_delayed(). Added two +// new implementation-dependent methods, notify_next_delta() & notify_internal() +// to replace calls to notify_delayed() from within the simulator. These two +// new methods are simpler than notify_delayed() and should speed up simulations +// +// Revision 1.3 2006/01/13 18:44:29 acg +// Added $Log to record CVS changes into the source. + +// Taf! diff --git a/ext/systemc/src/sysc/kernel/sc_event.h b/ext/systemc/src/sysc/kernel/sc_event.h new file mode 100644 index 000000000..9633752ce --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_event.h @@ -0,0 +1,884 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_event.h -- + + Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21 + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + + +#ifndef SC_EVENT_H +#define SC_EVENT_H + +#include "sysc/kernel/sc_cmnhdr.h" +#include "sysc/kernel/sc_kernel_ids.h" +#include "sysc/kernel/sc_simcontext.h" +#include "sysc/communication/sc_writer_policy.h" + +namespace sc_core { + +// forward declarations +class sc_event; +class sc_event_timed; +class sc_event_list; +class sc_event_or_list; +class sc_event_and_list; +class sc_object; + +// friend function declarations + int sc_notify_time_compare( const void*, const void* ); + +// ---------------------------------------------------------------------------- +// CLASS : sc_event_expr +// +// The event expression class. +// ---------------------------------------------------------------------------- + +template< typename T > +class sc_event_expr +{ + friend class sc_event; + friend class sc_event_and_list; + friend class sc_event_or_list; + + typedef T type; + + inline sc_event_expr() + : m_expr( new T(true) ) + {} + +public: + + inline sc_event_expr( sc_event_expr const & e) // move semantics + : m_expr(e.m_expr) + { + e.m_expr = 0; + } + + T const & release() const + { + sc_assert( m_expr ); + T* expr = m_expr; + m_expr=0; + return *expr; + } + + void push_back( sc_event const & e) const + { + sc_assert( m_expr ); + m_expr->push_back(e); + } + + void push_back( type const & el) const + { + sc_assert( m_expr ); + m_expr->push_back(el); + } + operator T const &() const + { + return release(); + } + + ~sc_event_expr() + { + delete m_expr; + } + +private: + mutable type * m_expr; + + // disabled + void operator=( sc_event_expr const & ); +}; + +// ---------------------------------------------------------------------------- +// CLASS : sc_event_list +// +// Base class for lists of events. +// ---------------------------------------------------------------------------- + +class sc_event_list +{ + friend class sc_process_b; + friend class sc_method_process; + friend class sc_thread_process; + friend void sc_thread_cor_fn( void* arg ); + +public: + sc_event_list( const sc_event_list& ); + sc_event_list& operator = ( const sc_event_list& ); + + int size() const; + +protected: + + void push_back( const sc_event& ); + void push_back( const sc_event_list& ); + + explicit + sc_event_list( bool and_list_, bool auto_delete_ = false ); + + sc_event_list( const sc_event&, + bool and_list_, + bool auto_delete_ = false ); + + ~sc_event_list(); + + void swap( sc_event_list& ); + void move_from( const sc_event_list& ); + + bool and_list() const; + + void add_dynamic( sc_method_handle ) const; + void add_dynamic( sc_thread_handle ) const; + void remove_dynamic( sc_method_handle, const sc_event* ) const; + void remove_dynamic( sc_thread_handle, const sc_event* ) const; + + bool busy() const; + bool temporary() const; + void auto_delete() const; + + void report_premature_destruction() const; + void report_invalid_modification() const; + +private: + + std::vector<const sc_event*> m_events; + bool m_and_list; + bool m_auto_delete; + mutable unsigned m_busy; +}; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_event_and_list +// +// AND list of events. +// ---------------------------------------------------------------------------- + +class sc_event_and_list +: public sc_event_list +{ + friend class sc_event; + friend class sc_event_expr<sc_event_and_list>; + friend class sc_process_b; + friend class sc_method_process; + friend class sc_thread_process; + +protected: + + explicit + sc_event_and_list( bool auto_delete_ ); + +public: + + sc_event_and_list(); + sc_event_and_list( const sc_event& ); + + void swap( sc_event_and_list& ); + sc_event_and_list& operator &= ( const sc_event& ); + sc_event_and_list& operator &= ( const sc_event_and_list & ); + + sc_event_expr<sc_event_and_list> operator & ( const sc_event& ); + sc_event_expr<sc_event_and_list> operator & ( const sc_event_and_list& ); +}; + +typedef sc_event_expr<sc_event_and_list> sc_event_and_expr; + +// ---------------------------------------------------------------------------- +// CLASS : sc_event_or_list +// +// OR list of events. +// ---------------------------------------------------------------------------- + +class sc_event_or_list +: public sc_event_list +{ + friend class sc_event; + friend class sc_event_expr<sc_event_or_list>; + friend class sc_process_b; + friend class sc_method_process; + friend class sc_thread_process; + +protected: + + explicit + sc_event_or_list( bool auto_delete_ ); + +public: + sc_event_or_list(); + sc_event_or_list( const sc_event& ); + void swap( sc_event_or_list& ); + sc_event_or_list& operator |= ( const sc_event& ); + sc_event_or_list& operator |= ( const sc_event_or_list & ); + sc_event_expr<sc_event_or_list> operator | ( const sc_event& ) const; + sc_event_expr<sc_event_or_list> operator | ( const sc_event_or_list& ) const; +}; + +typedef sc_event_expr<sc_event_or_list> sc_event_or_expr; + +// ---------------------------------------------------------------------------- +// CLASS : sc_event +// +// The event class. +// ---------------------------------------------------------------------------- + +class sc_event +{ + friend class sc_clock; + friend class sc_event_list; + friend class sc_event_timed; + friend class sc_simcontext; + friend class sc_object; + friend class sc_process_b; + friend class sc_method_process; + friend class sc_thread_process; + template<typename IF, sc_writer_policy POL> friend class sc_signal; + friend void sc_thread_cor_fn( void* arg ); + +public: + + sc_event(); + sc_event( const char* name ); + ~sc_event(); + + void cancel(); + + const char* name() const { return m_name.c_str(); } + const char* basename() const; + sc_object* get_parent_object() const { return m_parent_p; } + bool in_hierarchy() const { return m_name.length() != 0; } + + void notify(); + void notify( const sc_time& ); + void notify( double, sc_time_unit ); + + void notify_delayed(); + void notify_delayed( const sc_time& ); + void notify_delayed( double, sc_time_unit ); + + sc_event_or_expr operator | ( const sc_event& ) const; + sc_event_or_expr operator | ( const sc_event_or_list& ) const; + sc_event_and_expr operator & ( const sc_event& ) const; + sc_event_and_expr operator & ( const sc_event_and_list& ) const; + + +private: + + void add_static( sc_method_handle ) const; + void add_static( sc_thread_handle ) const; + void add_dynamic( sc_method_handle ) const; + void add_dynamic( sc_thread_handle ) const; + + void notify_internal( const sc_time& ); + void notify_next_delta(); + + bool remove_static( sc_method_handle ) const; + bool remove_static( sc_thread_handle ) const; + bool remove_dynamic( sc_method_handle ) const; + bool remove_dynamic( sc_thread_handle ) const; + + void register_event( const char* name ); + void reset(); + + void trigger(); + +private: + + enum notify_t { NONE, DELTA, TIMED }; + + std::string m_name; // name of object. + sc_object* m_parent_p; // parent sc_object for this event. + sc_simcontext* m_simc; + notify_t m_notify_type; + int m_delta_event_index; + sc_event_timed* m_timed; + + mutable std::vector<sc_method_handle> m_methods_static; + mutable std::vector<sc_method_handle> m_methods_dynamic; + mutable std::vector<sc_thread_handle> m_threads_static; + mutable std::vector<sc_thread_handle> m_threads_dynamic; + +private: + + // disabled + sc_event( const sc_event& ); + sc_event& operator = ( const sc_event& ); +}; + +#define SC_KERNEL_EVENT_PREFIX "$$$$kernel_event$$$$_" + +extern sc_event sc_non_event; // Event that never happens. + +// ---------------------------------------------------------------------------- +// CLASS : sc_event_timed +// +// Class for storing the time to notify a timed event. +// ---------------------------------------------------------------------------- + +class sc_event_timed +{ + friend class sc_event; + friend class sc_simcontext; + + friend int sc_notify_time_compare( const void*, const void* ); + +private: + + sc_event_timed( sc_event* e, const sc_time& t ) + : m_event( e ), m_notify_time( t ) + {} + + ~sc_event_timed() + { if( m_event != 0 ) { m_event->m_timed = 0; } } + + sc_event* event() const + { return m_event; } + + const sc_time& notify_time() const + { return m_notify_time; } + + static void* operator new( std::size_t ) + { return allocate(); } + + static void operator delete( void* p, std::size_t ) + { deallocate( p ); } + +private: + + // dedicated memory management + static void* allocate(); + static void deallocate( void* ); + +private: + + sc_event* m_event; + sc_time m_notify_time; + +private: + + // disabled + sc_event_timed(); + sc_event_timed( const sc_event_timed& ); + sc_event_timed& operator = ( const sc_event_timed& ); +}; + + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + +inline +void +sc_event::notify( double v, sc_time_unit tu ) +{ + notify( sc_time( v, tu, m_simc ) ); +} + + +inline +void +sc_event::notify_internal( const sc_time& t ) +{ + if( t == SC_ZERO_TIME ) { + // add this event to the delta events set + m_delta_event_index = m_simc->add_delta_event( this ); + m_notify_type = DELTA; + } else { + sc_event_timed* et = + new sc_event_timed( this, m_simc->time_stamp() + t ); + m_simc->add_timed_event( et ); + m_timed = et; + m_notify_type = TIMED; + } +} + +inline +void +sc_event::notify_next_delta() +{ + if( m_notify_type != NONE ) { + SC_REPORT_ERROR( SC_ID_NOTIFY_DELAYED_, 0 ); + } + // add this event to the delta events set + m_delta_event_index = m_simc->add_delta_event( this ); + m_notify_type = DELTA; +} + +inline +void +sc_event::notify_delayed( double v, sc_time_unit tu ) +{ + notify_delayed( sc_time( v, tu, m_simc ) ); +} + + +inline +void +sc_event::add_static( sc_method_handle method_h ) const +{ + m_methods_static.push_back( method_h ); +} + +inline +void +sc_event::add_static( sc_thread_handle thread_h ) const +{ + m_threads_static.push_back( thread_h ); +} + +inline +void +sc_event::add_dynamic( sc_method_handle method_h ) const +{ + m_methods_dynamic.push_back( method_h ); +} + +inline +void +sc_event::add_dynamic( sc_thread_handle thread_h ) const +{ + m_threads_dynamic.push_back( thread_h ); +} + + +// ---------------------------------------------------------------------------- +// Deprecated functional notation for notifying events. +// ---------------------------------------------------------------------------- + +extern void notify( sc_event& e ); +extern void notify( const sc_time& t, sc_event& e ); +extern void notify( double v, sc_time_unit tu, sc_event& e ); + + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + +inline +sc_event_list::sc_event_list( bool and_list_, bool auto_delete_ ) + : m_events() + , m_and_list( and_list_ ) + , m_auto_delete( auto_delete_ ) + , m_busy( 0 ) +{ +} + +inline +sc_event_list::sc_event_list( const sc_event& e, + bool and_list_, + bool auto_delete_ ) + : m_events() + , m_and_list( and_list_ ) + , m_auto_delete( auto_delete_ ) + , m_busy(0) +{ + m_events.push_back( &e ); +} + +inline +sc_event_list::sc_event_list( sc_event_list const & that ) + : m_events() + , m_and_list( that.m_and_list ) + , m_auto_delete( false ) + , m_busy( 0 ) +{ + move_from( that ); + that.auto_delete(); // free automatic lists +} + +inline +sc_event_list& +sc_event_list::operator=( sc_event_list const & that ) +{ + if( m_busy ) + report_invalid_modification(); + + move_from( that ); + that.auto_delete(); // free automatic lists + + return *this; +} + +inline +sc_event_list::~sc_event_list() +{ + if( m_busy ) + report_premature_destruction(); +} + +inline +void +sc_event_list::swap( sc_event_list& that ) +{ + if( busy() || that.busy() ) + report_invalid_modification(); + m_events.swap( that.m_events ); +} + +inline +void +sc_event_list::move_from( sc_event_list const& that ) +{ + if( that.temporary() ) { + swap( const_cast<sc_event_list&>(that) ); // move from source + } else { + m_events = that.m_events; // copy from source + } +} + +inline +int +sc_event_list::size() const +{ + return m_events.size(); +} + +inline +bool +sc_event_list::and_list() const +{ + return m_and_list; +} + + +inline +bool +sc_event_list::busy() const +{ + return m_busy != 0; +} + + +inline +bool +sc_event_list::temporary() const +{ + return m_auto_delete && ! m_busy; +} + +inline +void +sc_event_list::auto_delete() const +{ + if( m_busy ) { + --m_busy; + } + if( ! m_busy && m_auto_delete ) { + delete this; + } +} + + + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + +inline +sc_event_or_list::sc_event_or_list() + : sc_event_list( false ) +{} + +inline +sc_event_or_list::sc_event_or_list( const sc_event& e ) +: sc_event_list( false ) +{ + push_back( e ); +} + +inline +sc_event_or_list::sc_event_or_list( bool auto_delete_ ) +: sc_event_list( false, auto_delete_ ) +{} + +inline +sc_event_or_list& +sc_event_or_list::operator |= ( const sc_event& e ) +{ + if( busy() ) + report_invalid_modification(); + + push_back( e ); + return *this; +} + +inline +sc_event_or_list& +sc_event_or_list::operator |= ( const sc_event_or_list& el ) +{ + if( busy() ) + report_invalid_modification(); + + push_back( el ); + return *this; +} + +inline +sc_event_or_expr +sc_event_or_list::operator | ( const sc_event& e2 ) const +{ + sc_event_or_expr expr; + expr.push_back( *this ); + expr.push_back( e2 ); + return expr; +} + +inline +sc_event_or_expr +sc_event_or_list::operator | ( const sc_event_or_list& e2 ) const +{ + sc_event_or_expr expr; + expr.push_back( *this ); + expr.push_back( e2 ); + return expr; +} + + +// sc_event + +inline +sc_event_or_expr +sc_event::operator | ( const sc_event& e2 ) const +{ + sc_event_or_expr expr; + expr.push_back( *this ); + expr.push_back( e2 ); + return expr; +} + +inline +sc_event_or_expr +sc_event::operator | ( const sc_event_or_list& e2 ) const +{ + sc_event_or_expr expr; + expr.push_back( *this ); + expr.push_back( e2 ); + return expr; +} + +// sc_event_expr + +inline +sc_event_or_expr +operator | ( sc_event_or_expr expr, sc_event const & e ) +{ + expr.push_back( e ); + return expr; +} + +inline +sc_event_or_expr +operator | ( sc_event_or_expr expr, sc_event_or_list const & el ) +{ + expr.push_back( el ); + return expr; +} + +inline +void +sc_event_or_list::swap( sc_event_or_list & that ) +{ + sc_event_list::swap( that ); +} + + + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + +inline +sc_event_and_list::sc_event_and_list() + : sc_event_list( true ) +{} + +inline +sc_event_and_list::sc_event_and_list( const sc_event& e ) +: sc_event_list( true ) +{ + push_back( e ); +} + +inline +sc_event_and_list::sc_event_and_list( bool auto_delete_ ) +: sc_event_list( true, auto_delete_ ) +{} + +inline +void +sc_event_and_list::swap( sc_event_and_list & that ) +{ + sc_event_list::swap( that ); +} + + +inline +sc_event_and_list& +sc_event_and_list::operator &= ( const sc_event& e ) +{ + if( busy() ) + report_invalid_modification(); + + push_back( e ); + return *this; +} + +inline +sc_event_and_list& +sc_event_and_list::operator &= ( const sc_event_and_list& el ) +{ + if( busy() ) + report_invalid_modification(); + + push_back( el ); + return *this; +} + +inline +sc_event_and_expr +sc_event_and_list::operator & ( const sc_event& e ) +{ + sc_event_and_expr expr; + expr.push_back( *this ); + expr.push_back( e ); + return expr; +} + +inline +sc_event_and_expr +sc_event_and_list::operator & ( const sc_event_and_list& el ) +{ + sc_event_and_expr expr; + expr.push_back( *this ); + expr.push_back( el ); + return expr; +} + +// sc_event + +inline +sc_event_and_expr +sc_event::operator & ( const sc_event& e2 ) const +{ + sc_event_and_expr expr; + expr.push_back( *this ); + expr.push_back( e2 ); + return expr; +} + +inline +sc_event_and_expr +sc_event::operator & ( const sc_event_and_list& e2 ) const +{ + sc_event_and_expr expr; + expr.push_back( *this ); + expr.push_back( e2 ); + return expr; +} + +// sc_event_expr + +inline +sc_event_and_expr +operator & ( sc_event_and_expr expr, sc_event const & e ) +{ + expr.push_back( e ); + return expr; +} + +inline +sc_event_and_expr +operator & ( sc_event_and_expr expr, sc_event_and_list const & el ) +{ + expr.push_back( el ); + return expr; +} + +} // namespace sc_core + +// $Log: sc_event.h,v $ +// Revision 1.14 2011/08/29 18:04:32 acg +// Philipp A. Hartmann: miscellaneous clean ups. +// +// Revision 1.13 2011/08/26 20:46:09 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +// Revision 1.12 2011/08/24 22:05:50 acg +// Torsten Maehne: initialization changes to remove warnings. +// +// Revision 1.11 2011/03/12 21:07:51 acg +// Andy Goodrich: changes to kernel generated event support. +// +// Revision 1.10 2011/03/06 15:55:11 acg +// Andy Goodrich: Changes for named events. +// +// Revision 1.9 2011/03/05 01:39:21 acg +// Andy Goodrich: changes for named events. +// +// Revision 1.8 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.7 2011/02/13 21:47:37 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.6 2011/02/01 21:03:23 acg +// Andy Goodrich: new return codes for trigger_dynamic calls. +// +// Revision 1.5 2011/01/18 20:10:44 acg +// Andy Goodrich: changes for IEEE1666_2011 semantics. +// +// Revision 1.4 2010/12/07 20:09:11 acg +// Andy Goodrich: writer policy fix. +// +// Revision 1.3 2009/05/22 16:06:29 acg +// Andy Goodrich: process control updates. +// +// Revision 1.2 2008/05/22 17:06:25 acg +// Andy Goodrich: updated copyright notice to include 2008. +// +// Revision 1.1.1.1 2006/12/15 20:20:05 acg +// SystemC 2.3 +// +// Revision 1.8 2006/05/26 20:33:16 acg +// Andy Goodrich: changes required by additional platform compilers (i.e., +// Microsoft VC++, Sun Forte, HP aCC). +// +// Revision 1.7 2006/05/08 17:57:51 acg +// Andy Goodrich: added David Long's forward declarations for friend +// functions, methods, and operators to keep the Microsoft compiler happy. +// +// Revision 1.6 2006/04/11 23:13:20 acg +// Andy Goodrich: Changes for reduced reset support that only includes +// sc_cthread, but has preliminary hooks for expanding to method and thread +// processes also. +// +// Revision 1.5 2006/01/24 20:56:00 acg +// Andy Goodrich: fixed up CVS comment. +// +// Revision 1.4 2006/01/24 20:48:14 acg +// Andy Goodrich: added deprecation warnings for notify_delayed(). Added two +// new implementation-dependent methods, notify_next_delta() & notify_internal() +// to replace calls to notify_delayed() from within the simulator. These two +// new methods are simpler than notify_delayed() and should speed up simulations +// +// Revision 1.3 2006/01/13 18:44:29 acg +// Added $Log to record CVS changes into the source. +// + +#endif + +// Taf! diff --git a/ext/systemc/src/sysc/kernel/sc_except.cpp b/ext/systemc/src/sysc/kernel/sc_except.cpp new file mode 100644 index 000000000..2699f8daf --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_except.cpp @@ -0,0 +1,142 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_except.cpp -- kill/reset exception handling + + Original Author: Philipp A. Hartmann, OFFIS + + CHANGE LOG APPEARS AT THE END OF THE FILE + *****************************************************************************/ + +#include "sysc/kernel/sc_cmnhdr.h" +// +#include "sysc/kernel/sc_except.h" +#include "sysc/kernel/sc_process.h" +// +#include "sysc/utils/sc_report.h" + +namespace sc_core { + +sc_unwind_exception::sc_unwind_exception( sc_process_b* proc_p, bool is_reset ) + : m_proc_p(proc_p), m_is_reset( is_reset ) +{ + sc_assert( m_proc_p ); + m_proc_p->start_unwinding(); +} + +bool +sc_unwind_exception::active() const +{ + return m_proc_p && m_proc_p->is_unwinding(); +} + +void +sc_unwind_exception::clear() const +{ + sc_assert( m_proc_p ); + m_proc_p->clear_unwinding(); +} + +const char* +sc_unwind_exception::what() const throw() +{ + return ( m_is_reset ) ? "RESET" : "KILL"; +} + +sc_unwind_exception::~sc_unwind_exception() throw() +{ + if( active() ) { + // can't throw an exception, since we're already throwing + // -> abort instead + SC_REPORT_FATAL( SC_ID_RETHROW_UNWINDING_, m_proc_p->name() ); + } +} + +// handle and translate uncaught exceptions here +// +// These exceptions can either escape from sc_main() directly, +// indirectly from an SC_METHOD(), or are thrown from within +// an SC_(C)THREAD() +// +// returns a pointer to a dynamically allocated sc_report object, +// containing the caught message + +sc_report* +sc_handle_exception() +{ + try { + + // re-throw exception here + try { throw; } + + catch( sc_report & ) // to be on the safe side + { + throw; // continue + } + catch( sc_unwind_exception const & ) + { + sc_assert( false && "Unhandled kill/reset, should never happen" ); + } + catch( std::exception const & x ) + { + SC_REPORT_ERROR( SC_ID_SIMULATION_UNCAUGHT_EXCEPTION_, x.what() ); + } + catch( char const * x ) + { + SC_REPORT_ERROR( SC_ID_SIMULATION_UNCAUGHT_EXCEPTION_, x ); + } + catch( ... ) + { + SC_REPORT_ERROR( SC_ID_SIMULATION_UNCAUGHT_EXCEPTION_, + "UNKNOWN EXCEPTION" ); + } + } + // everything is an sc_report now + catch( sc_report & rpt ) + { + sc_report* rpt_p = new sc_report; + rpt_p->swap( rpt ); + return rpt_p; + } + return 0; +} + +} // namespace sc_core + +// $Log: sc_except.cpp,v $ +// Revision 1.4 2011/08/26 20:46:09 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +// Revision 1.3 2011/05/09 04:07:48 acg +// Philipp A. Hartmann: +// (1) Restore hierarchy in all phase callbacks. +// (2) Ensure calls to before_end_of_elaboration. +// +// Revision 1.2 2011/02/13 21:47:37 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.1 2011/02/10 22:47:38 acg +// Andy Goodrich: first check in of Philipp A. Hartmann's new exception +// processing code. +// + +// Taf! diff --git a/ext/systemc/src/sysc/kernel/sc_except.h b/ext/systemc/src/sysc/kernel/sc_except.h new file mode 100644 index 000000000..e3bacbd9c --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_except.h @@ -0,0 +1,178 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_except.h - Exception classes to be handled by SystemC. + + Original Author: Stan Y. Liao, Synopsys, Inc. + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + + +#ifndef SC_EXCEPT_H +#define SC_EXCEPT_H + +#include <exception> + +namespace sc_core { + +class sc_simcontext; +class sc_process_b; +class sc_method_process; +class sc_thread_process; +void sc_thread_cor_fn( void* arg ); + +/* + * These classes are intentionally empty. Their raison d'etre is for + * the implementation of various SystemC throws. + */ + +class sc_user +{ + /*EMPTY*/ +public: + sc_user() {} + sc_user( const sc_user& ) {} +}; + +class sc_halt +{ +public: + sc_halt() {} + sc_halt( const sc_halt& ) {} +}; + +class sc_kill +{ +public: + sc_kill() {} + sc_kill( const sc_kill& ) {} +}; + +class sc_unwind_exception : public std::exception +{ + friend class sc_simcontext; + friend class sc_process_b; + friend class sc_method_process; + friend class sc_thread_process; + friend void sc_thread_cor_fn( void* arg ); + + public: + virtual bool is_reset() const { return m_is_reset; } + virtual const char* what() const throw(); + + public: + + // enable catch by value + sc_unwind_exception( const sc_unwind_exception& ); + virtual ~sc_unwind_exception() throw(); + + protected: + explicit + sc_unwind_exception( sc_process_b* target_p, bool is_reset = false ); + + bool active() const; + void clear() const; + + private: + // disabled + sc_unwind_exception& operator=( const sc_unwind_exception& ); + + mutable sc_process_b* m_proc_p; // used to check, if caught by the kernel + const bool m_is_reset; // true if this is an unwind of a reset + +}; + +inline +sc_unwind_exception::sc_unwind_exception( const sc_unwind_exception& that ) + : std::exception( that ) + , m_proc_p( that.m_proc_p ) + , m_is_reset( that.m_is_reset ) +{ + that.m_proc_p = 0; // move to new instance +} + +//------------------------------------------------------------------------------ +// global exception handling +//------------------------------------------------------------------------------ + +class sc_report; +sc_report* sc_handle_exception(); + +} // namespace sc_core + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: Gene Bushuyev. Synopsys, Inc. + Description of Modification: - Had to add empty public default and copy + constructors to satisfy VC6.0. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + +// $Log: sc_except.h,v $ +// Revision 1.11 2011/08/26 21:40:26 acg +// Philipp A. Hartmann: fix up sc_unwind_exception copy-ctor. +// +// Revision 1.10 2011/08/26 20:46:09 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +// Revision 1.9 2011/08/24 22:05:50 acg +// Torsten Maehne: initialization changes to remove warnings. +// +// Revision 1.8 2011/05/09 04:07:48 acg +// Philipp A. Hartmann: +// (1) Restore hierarchy in all phase callbacks. +// (2) Ensure calls to before_end_of_elaboration. +// +// Revision 1.7 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.6 2011/02/13 21:47:37 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.5 2011/02/11 13:25:24 acg +// Andy Goodrich: Philipp A. Hartmann's changes: +// (1) Removal of SC_CTHREAD method overloads. +// (2) New exception processing code. +// +// Revision 1.4 2011/01/18 20:10:44 acg +// Andy Goodrich: changes for IEEE1666_2011 semantics. +// +// Revision 1.3 2009/05/22 16:06:29 acg +// Andy Goodrich: process control updates. +// +// Revision 1.2 2008/05/22 17:06:25 acg +// Andy Goodrich: updated copyright notice to include 2008. +// +// Revision 1.1.1.1 2006/12/15 20:20:05 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:44:29 acg +// Added $Log to record CVS changes into the source. + +#endif diff --git a/ext/systemc/src/sysc/kernel/sc_externs.h b/ext/systemc/src/sysc/kernel/sc_externs.h new file mode 100644 index 000000000..1d1818089 --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_externs.h @@ -0,0 +1,65 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_externs.h -- Declaration of `sc_main' and other global variables. + + Original Author: Stan Y. Liao, Synopsys, Inc. + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + + +#ifndef SC_EXTERNS_H +#define SC_EXTERNS_H + + + +extern "C" int sc_main( int argc, char* argv[] ); + +namespace sc_core { + extern "C" int sc_elab_and_sim( int argc, char* argv[] ); + extern "C" int sc_argc(); + extern "C" const char* const* sc_argv(); + +} // namespace sc_core + +// $Log: sc_externs.h,v $ +// Revision 1.5 2011/08/26 20:46:09 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +// Revision 1.4 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.3 2011/02/13 21:47:37 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.2 2008/05/22 17:06:25 acg +// Andy Goodrich: updated copyright notice to include 2008. +// +// Revision 1.1.1.1 2006/12/15 20:20:05 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:44:29 acg +// Added $Log to record CVS changes into the source. +// + +#endif diff --git a/ext/systemc/src/sysc/kernel/sc_join.cpp b/ext/systemc/src/sysc/kernel/sc_join.cpp new file mode 100644 index 000000000..25f6f6cea --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_join.cpp @@ -0,0 +1,143 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_join.cpp -- Join Process Synchronization Implementation + + Original Author: Andy Goodrich, Forte Design Systems, 5 May 2003 + + CHANGE LOG APPEARS AT THE END OF THE FILE + *****************************************************************************/ + + +#include <cassert> +#include <cstdlib> +#include <cstddef> + +#include "sysc/kernel/sc_process_handle.h" +#include "sysc/kernel/sc_simcontext.h" +#include "sysc/kernel/sc_simcontext_int.h" +#include "sysc/kernel/sc_kernel_ids.h" +#include "sysc/kernel/sc_thread_process.h" +#include "sysc/kernel/sc_join.h" + +namespace sc_core { + +//------------------------------------------------------------------------------ +//"sc_join::sc_join" +// +// This is the object instance constructor for this class. +//------------------------------------------------------------------------------ +sc_join::sc_join() + : m_join_event( (std::string(SC_KERNEL_EVENT_PREFIX)+"_join_event").c_str() ) + , m_threads_n(0) +{} + +//------------------------------------------------------------------------------ +//"sc_join::add_process - sc_process_b*" +// +// This method adds a process to this join object instance. This consists of +// incrementing the count of processes in the join process and adding this +// object instance to the supplied thread's monitoring queue. +// process_p -> thread to be monitored. +//------------------------------------------------------------------------------ +void sc_join::add_process( sc_process_b* process_p ) +{ + sc_thread_handle handle = DCAST<sc_thread_handle>(process_p); + assert( handle != 0 ); + m_threads_n++; + handle->add_monitor( this ); +} + + +//------------------------------------------------------------------------------ +//"sc_join::add_process - sc_process_handle" +// +// This method adds a process to this join object instance. This consists of +// incrementing the count of processes in the join process and adding this +// object instance to the supplied thread's monitoring queue. +// process_h = handle for process to be monitored. +//------------------------------------------------------------------------------ +void sc_join::add_process( sc_process_handle process_h ) +{ + sc_thread_handle thread_p; // Thread within process_h. + + thread_p = process_h.operator sc_thread_handle(); + if ( thread_p ) + { + m_threads_n++; + thread_p->add_monitor( this ); + } + else + { + SC_REPORT_ERROR( SC_ID_JOIN_ON_METHOD_HANDLE_, 0 ); + } +} + + +//------------------------------------------------------------------------------ +//"sc_join::signal" +// +// This virtual method is called when a process being monitored by this object +// instance sends a signal. If the signal type is spm_exit and the count of +// threads that we are waiting to terminate on goes to zero we fire our join +// event. +// thread_p -> thread that is signalling. +// type = type of signal being sent. +//------------------------------------------------------------------------------ +void sc_join::signal(sc_thread_handle thread_p, int type) +{ + switch ( type ) + { + case sc_process_monitor::spm_exit: + thread_p->remove_monitor(this); + if ( --m_threads_n == 0 ) m_join_event.notify(); + break; + } +} + +} // namespace sc_core + +// $Log: sc_join.cpp,v $ +// Revision 1.7 2011/08/26 21:45:00 acg +// Andy Goodrich: fix internal event naming. +// +// Revision 1.6 2011/08/26 20:46:09 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +// Revision 1.5 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.4 2011/02/13 21:47:37 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.3 2009/07/28 01:10:53 acg +// Andy Goodrich: updates for 2.3 release candidate. +// +// Revision 1.2 2008/05/22 17:06:25 acg +// Andy Goodrich: updated copyright notice to include 2008. +// +// Revision 1.1.1.1 2006/12/15 20:20:05 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:44:29 acg +// Added $Log to record CVS changes into the source. +// diff --git a/ext/systemc/src/sysc/kernel/sc_join.h b/ext/systemc/src/sysc/kernel/sc_join.h new file mode 100644 index 000000000..e240f51a2 --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_join.h @@ -0,0 +1,136 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_join.h -- Join Process Synchronization Definition + + Original Author: Andy Goodrich, Forte Design Systems, 5 May 2003 + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + +// $Log: sc_join.h,v $ +// Revision 1.8 2011/08/26 21:45:00 acg +// Andy Goodrich: fix internal event naming. +// +// Revision 1.7 2011/08/26 20:46:09 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// + +#ifndef SC_JOIN_H +#define SC_JOIN_H + +#include "sysc/kernel/sc_process.h" +#include "sysc/kernel/sc_wait.h" + +namespace sc_core { + +//============================================================================== +// CLASS sc_join +// +// This class provides a way of waiting for a set of threads to complete their +// execution. The threads whose completion is to be monitored are registered, +// and upon their completion an event notification will occur. +//============================================================================== +class sc_join : public sc_process_monitor { + friend class sc_process_b; + friend class sc_process_handle; + public: + sc_join(); + void add_process( sc_process_handle process_h ); + inline int process_count(); + virtual void signal(sc_thread_handle thread_p, int type); + inline void wait(); + inline void wait_clocked(); + + protected: + void add_process( sc_process_b* process_p ); + + protected: + sc_event m_join_event; // Event to notify when all threads have reported. + int m_threads_n; // # of threads still need to wait for. +}; + +int sc_join::process_count() { return m_threads_n; } + +// suspend a thread that does not have a sensitivity list: + +inline void sc_join::wait() { ::sc_core::wait(m_join_event); } + +// suspend a thread that has a sensitivity list: + +inline void sc_join::wait_clocked() +{ + do { ::sc_core::wait(); } while (m_threads_n != 0); +} + +#define SC_CJOIN \ + }; \ + sc_core::sc_join join; \ + for ( unsigned int i = 0; \ + i < sizeof(forkees)/sizeof(sc_core::sc_process_handle); \ + i++ ) \ + join.add_process(forkees[i]); \ + join.wait_clocked(); \ +} + +#define SC_FORK \ +{ \ + sc_core::sc_process_handle forkees[] = { + +#define SC_JOIN \ + }; \ + sc_core::sc_join join; \ + for ( unsigned int i = 0; \ + i < sizeof(forkees)/sizeof(sc_core::sc_process_handle); \ + i++ ) \ + join.add_process(forkees[i]); \ + join.wait(); \ +} + +} // namespace sc_core + +// Revision 1.6 2011/08/24 22:05:50 acg +// Torsten Maehne: initialization changes to remove warnings. +// +// Revision 1.5 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.4 2011/02/13 21:47:37 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.3 2009/07/28 01:10:53 acg +// Andy Goodrich: updates for 2.3 release candidate. +// +// Revision 1.2 2008/05/22 17:06:25 acg +// Andy Goodrich: updated copyright notice to include 2008. +// +// Revision 1.1.1.1 2006/12/15 20:20:05 acg +// SystemC 2.3 +// +// Revision 1.5 2006/04/28 21:38:27 acg +// Andy Goodrich: fixed loop constraint that was using sizeof(sc_thread_handle) +// rather than sizeof(sc_process_handle). +// +// Revision 1.4 2006/01/13 18:44:29 acg +// Added $Log to record CVS changes into the source. + +#endif // SC_JOIN_H diff --git a/ext/systemc/src/sysc/kernel/sc_kernel_ids.h b/ext/systemc/src/sysc/kernel/sc_kernel_ids.h new file mode 100644 index 000000000..32846df12 --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_kernel_ids.h @@ -0,0 +1,321 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_kernel_ids.h -- Report ids for the kernel code. + + Original Author: Martin Janssen, Synopsys, Inc., 2002-01-17 + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + +#ifndef SC_KERNEL_IDS_H +#define SC_KERNEL_IDS_H + + +#include "sysc/utils/sc_report.h" + + +// ---------------------------------------------------------------------------- +// Report ids (kernel) +// +// Report ids in the range of 500-599. +// ---------------------------------------------------------------------------- + +#ifndef SC_DEFINE_MESSAGE +#define SC_DEFINE_MESSAGE(id,unused1,unused2) \ + namespace sc_core { extern const char id[]; } +namespace sc_core { + extern const char SC_ID_REGISTER_ID_FAILED_[]; // in sc_report_handler.cpp +} +#endif + +SC_DEFINE_MESSAGE(SC_ID_NO_BOOL_RETURNED_ , 500, + "operator does not return boolean") +SC_DEFINE_MESSAGE(SC_ID_NO_INT_RETURNED_ , 501, + "operator does not return int") +SC_DEFINE_MESSAGE(SC_ID_NO_SC_LOGIC_RETURNED_ , 502, + "operator does not return sc_logic") +SC_DEFINE_MESSAGE(SC_ID_OPERAND_NOT_SC_LOGIC_ , 503, + "operand is not sc_logic") +SC_DEFINE_MESSAGE(SC_ID_OPERAND_NOT_BOOL_ , 504, + "operand is not bool") +SC_DEFINE_MESSAGE(SC_ID_INSTANCE_EXISTS_ , 505, + "object already exists") +SC_DEFINE_MESSAGE(SC_ID_ILLEGAL_CHARACTERS_ , 506, + "illegal characters" ) +SC_DEFINE_MESSAGE(SC_ID_VC6_PROCESS_HELPER_ , 507, + "internal error: sc_vc6_process_helper" ) +SC_DEFINE_MESSAGE(SC_ID_VC6_MAX_PROCESSES_EXCEEDED_ , 508, + "maximum number of processes per module exceeded (VC6)" ) +SC_DEFINE_MESSAGE(SC_ID_END_MODULE_NOT_CALLED_ , 509, + "module construction not properly completed: did " + "you forget to add a sc_module_name parameter to " + "your module constructor?" ) +SC_DEFINE_MESSAGE(SC_ID_HIER_NAME_INCORRECT_ , 510, + "hierarchical name as shown may be incorrect due to previous errors" ) +SC_DEFINE_MESSAGE(SC_ID_SET_STACK_SIZE_ , 511, + "set_stack_size() is only allowed for SC_THREADs and SC_CTHREADs" ) +SC_DEFINE_MESSAGE(SC_ID_SC_MODULE_NAME_USE_ , 512, + "incorrect use of sc_module_name" ) +SC_DEFINE_MESSAGE(SC_ID_SC_MODULE_NAME_REQUIRED_ , 513, + "an sc_module_name parameter for your constructor is required" ) +SC_DEFINE_MESSAGE(SC_ID_SET_TIME_RESOLUTION_ , 514, + "set time resolution failed" ) +SC_DEFINE_MESSAGE(SC_ID_SET_DEFAULT_TIME_UNIT_ , 515, + "set default time unit failed" ) +SC_DEFINE_MESSAGE(SC_ID_DEFAULT_TIME_UNIT_CHANGED_ , 516, + "default time unit changed to time resolution" ) +SC_DEFINE_MESSAGE(SC_ID_INCONSISTENT_API_CONFIG_ , 517, + "inconsistent library configuration detected" ) +// available message number 518 +SC_DEFINE_MESSAGE(SC_ID_WAIT_NOT_ALLOWED_ , 519, + "wait() is only allowed in SC_THREADs and SC_CTHREADs" ) +SC_DEFINE_MESSAGE(SC_ID_NEXT_TRIGGER_NOT_ALLOWED_ , 520, + "next_trigger() is only allowed in SC_METHODs" ) +SC_DEFINE_MESSAGE(SC_ID_IMMEDIATE_NOTIFICATION_ , 521, + "immediate notification is not allowed during the update phase" ) +SC_DEFINE_MESSAGE(SC_ID_HALT_NOT_ALLOWED_ , 522, + "halt() is only allowed in SC_CTHREADs" ) +SC_DEFINE_MESSAGE(SC_ID_WATCHING_NOT_ALLOWED_ , 523, + "watching() has been deprecated, use reset_signal_is()" ) +SC_DEFINE_MESSAGE(SC_ID_DONT_INITIALIZE_ , 524, + "dont_initialize() has no effect for SC_CTHREADs" ) +SC_DEFINE_MESSAGE(SC_ID_WAIT_N_INVALID_ , 525, + "wait(n) is only valid for n > 0" ) +SC_DEFINE_MESSAGE(SC_ID_MAKE_SENSITIVE_ , 526, + "make sensitive failed" ) +SC_DEFINE_MESSAGE(SC_ID_MAKE_SENSITIVE_POS_ , 527, + "make sensitive pos failed" ) +SC_DEFINE_MESSAGE(SC_ID_MAKE_SENSITIVE_NEG_ , 528, + "make sensitive neg failed" ) +SC_DEFINE_MESSAGE(SC_ID_INSERT_MODULE_ , 529, + "insert module failed" ) +SC_DEFINE_MESSAGE(SC_ID_REMOVE_MODULE_ , 530, + "remove module failed" ) +SC_DEFINE_MESSAGE(SC_ID_NOTIFY_DELAYED_ , 531, + "notify_delayed() cannot be called on events " + "that have pending notifications" ) +SC_DEFINE_MESSAGE(SC_ID_GEN_UNIQUE_NAME_ , 532, + "cannot generate unique name from null string" ) +SC_DEFINE_MESSAGE(SC_ID_MODULE_NAME_STACK_EMPTY_ , 533, + "module name stack is empty: did you forget to " + "add a sc_module_name parameter to your module " + "constructor?" ) +// available message number 534 +// available message number 535 +SC_DEFINE_MESSAGE( SC_ID_IMMEDIATE_SELF_NOTIFICATION_, 536, + "immediate self-notification ignored as of IEEE 1666-2011" ) +SC_DEFINE_MESSAGE( SC_ID_WAIT_DURING_UNWINDING_ , 537, + "wait() not allowed during unwinding" ) +SC_DEFINE_MESSAGE(SC_ID_CYCLE_MISSES_EVENTS_ , 538, + "the simulation contains timed-events but they are " + "ignored by sc_cycle() ==> the simulation will be " + "incorrect" ) +SC_DEFINE_MESSAGE( SC_ID_RETHROW_UNWINDING_ , 539, + "sc_unwind_exception not re-thrown during kill/reset" ) +SC_DEFINE_MESSAGE( SC_ID_PROCESS_ALREADY_UNWINDING_ , 540, + "kill/reset ignored during unwinding" ) +SC_DEFINE_MESSAGE(SC_ID_MODULE_METHOD_AFTER_START_ , 541, + "call to SC_METHOD in sc_module while simulation running" ) +SC_DEFINE_MESSAGE(SC_ID_MODULE_THREAD_AFTER_START_ , 542, + "call to SC_THREAD in sc_module while simulation running" ) +SC_DEFINE_MESSAGE(SC_ID_MODULE_CTHREAD_AFTER_START_ , 543, + "call to SC_CTHREAD in sc_module while simulation running" ) +SC_DEFINE_MESSAGE(SC_ID_SIMULATION_TIME_OVERFLOW_ , 544, + "simulation time value overflow, simulation aborted" ) +SC_DEFINE_MESSAGE(SC_ID_SIMULATION_STOP_CALLED_TWICE_ , 545, + "sc_stop has already been called" ) +SC_DEFINE_MESSAGE(SC_ID_SIMULATION_START_AFTER_STOP_ , 546, + "sc_start called after sc_stop has been called" ) +SC_DEFINE_MESSAGE(SC_ID_STOP_MODE_AFTER_START_ , 547, + "attempt to set sc_stop mode after start will be ignored" ) +SC_DEFINE_MESSAGE( SC_ID_SIMULATION_START_AFTER_ERROR_, 548, + "attempt to restart simulation after error" ) +SC_DEFINE_MESSAGE( SC_ID_SIMULATION_UNCAUGHT_EXCEPTION_, 549, + "uncaught exception" ) +SC_DEFINE_MESSAGE(SC_ID_PHASE_CALLBACKS_UNSUPPORTED_ , 550, + "simulation phase callbacks not enabled") +SC_DEFINE_MESSAGE(SC_ID_PHASE_CALLBACK_NOT_IMPLEMENTED_, 551, + "empty simulation phase callback called" ) +SC_DEFINE_MESSAGE(SC_ID_PHASE_CALLBACK_REGISTER_, 552, + "register simulation phase callback" ) +SC_DEFINE_MESSAGE(SC_ID_PHASE_CALLBACK_FORBIDDEN_, 553, + "forbidden action in simulation phase callback" ) +// available message number 554 +// available message number 555 +SC_DEFINE_MESSAGE(SC_ID_THROW_IT_IGNORED_ , 556, + "throw_it on method/non-running process is being ignored " ) +SC_DEFINE_MESSAGE(SC_ID_NOT_EXPECTING_DYNAMIC_EVENT_NOTIFY_ , 557, + "dynamic event notification encountered when sensitivity is static" ) +SC_DEFINE_MESSAGE(SC_ID_DISABLE_WILL_ORPHAN_PROCESS_ , 558, + "disable() or dont_initialize() called on process with no static sensitivity, it will be orphaned" ) +SC_DEFINE_MESSAGE(SC_ID_PROCESS_CONTROL_CORNER_CASE_ , 559, + "Undefined process control interaction" ) +SC_DEFINE_MESSAGE(SC_ID_METHOD_TERMINATION_EVENT_ , 560, + "Attempt to get terminated event for a method process" ) +SC_DEFINE_MESSAGE(SC_ID_JOIN_ON_METHOD_HANDLE_ , 561, + "Attempt to register method process with sc_join object" ) +SC_DEFINE_MESSAGE(SC_ID_NO_PROCESS_SEMANTICS_ , 563, + "Attempt to invoke process with no semantics() method" ) +SC_DEFINE_MESSAGE(SC_ID_EVENT_ON_NULL_PROCESS_ , 564, + "Attempt to get an event for non-existent process" ) +// available message number 565 +SC_DEFINE_MESSAGE(SC_ID_UNKNOWN_PROCESS_TYPE_, 566, + "Unknown process type" ) +// available message number 567 +SC_DEFINE_MESSAGE(SC_ID_NEGATIVE_SIMULATION_TIME_, 568, + "negative simulation interval specified in sc_start call" ) +SC_DEFINE_MESSAGE(SC_ID_BAD_SC_MODULE_CONSTRUCTOR_ , 569, + "sc_module(const char*), sc_module(const std::string&) " + "have been deprecated, use sc_module(const sc_module_name&)" ) +SC_DEFINE_MESSAGE(SC_ID_EMPTY_PROCESS_HANDLE_ , 570, + "attempt to use an empty process handle ignored" ) +SC_DEFINE_MESSAGE(SC_ID_NO_SC_START_ACTIVITY_ , 571, + "no activity or clock movement for sc_start() invocation" ) +SC_DEFINE_MESSAGE(SC_ID_KILL_PROCESS_WHILE_UNITIALIZED_ , 572, + "a process may not be killed before it is initialized" ) +SC_DEFINE_MESSAGE(SC_ID_RESET_PROCESS_WHILE_NOT_RUNNING_ , 573, + "a process may not be asynchronously reset while the simulation is not running" ) +SC_DEFINE_MESSAGE(SC_ID_THROW_IT_WHILE_NOT_RUNNING_ , 574, + "throw_it not allowed unless simulation is running " ) + + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + +// $Log: sc_kernel_ids.h,v $ +// Revision 1.25 2011/08/26 22:06:34 acg +// Torsten Maehne: formating fix. +// +// Revision 1.24 2011/08/07 19:08:04 acg +// Andy Goodrich: moved logs to end of file so line number synching works +// better between versions. +// +// Revision 1.23 2011/07/24 11:15:47 acg +// Philipp A. Hartmann: Improvements to error/warning messages related to +// process control. +// +// Revision 1.22 2011/05/09 04:07:48 acg +// Philipp A. Hartmann: +// (1) Restore hierarchy in all phase callbacks. +// (2) Ensure calls to before_end_of_elaboration. +// +// Revision 1.21 2011/04/19 19:15:41 acg +// Andy Goodrich: fix so warning message is always issued for a throw_it() +// on a method process. +// +// Revision 1.20 2011/04/19 15:04:27 acg +// Philipp A. Hartmann: clean up SC_ID messages. +// +// Revision 1.19 2011/04/19 02:39:09 acg +// Philipp A. Hartmann: added checks for additional throws during stack unwinds. +// +// Revision 1.18 2011/04/05 06:23:45 acg +// Andy Goodrich: comments for throws while the simulator is not running. +// +// Revision 1.17 2011/04/01 22:30:39 acg +// Andy Goodrich: change hard assertion to warning for trigger_dynamic() +// getting called when there is only STATIC sensitivity. This can result +// because of sc_process_handle::throw_it(). +// +// Revision 1.16 2011/03/28 13:02:51 acg +// Andy Goodrich: Changes for disable() interactions. +// +// Revision 1.15 2011/03/07 17:34:21 acg +// Andy Goodrich: changed process control corner case message. Added more +// place holders for unused message numbers. +// +// Revision 1.14 2011/03/06 19:57:11 acg +// Andy Goodrich: refinements for the illegal suspend - synchronous reset +// interaction. +// +// Revision 1.13 2011/03/06 15:56:29 acg +// Andy Goodrich: added process control corner case error message, remove +// unused messages. +// +// Revision 1.12 2011/03/05 19:44:20 acg +// Andy Goodrich: changes for object and event naming and structures. +// +// Revision 1.11 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.10 2011/02/13 21:47:37 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.9 2011/02/13 21:29:16 acg +// Andy Goodrich: added error messages for throws that occur before +// simulator intialization. +// +// Revision 1.8 2011/02/11 13:25:24 acg +// Andy Goodrich: Philipp A. Hartmann's changes: +// (1) Removal of SC_CTHREAD method overloads. +// (2) New exception processing code. +// +// Revision 1.7 2011/02/07 19:17:20 acg +// Andy Goodrich: changes for IEEE 1666 compatibility. +// +// Revision 1.6 2011/01/19 23:21:50 acg +// Andy Goodrich: changes for IEEE 1666 2011 +// +// Revision 1.5 2010/07/30 05:21:22 acg +// Andy Goodrich: release 2.3 fixes. +// +// Revision 1.4 2009/02/28 00:26:58 acg +// Andy Goodrich: changed boost name space to sc_boost to allow use with +// full boost library applications. +// +// Revision 1.3 2008/11/17 15:57:15 acg +// Andy Goodrich: added deprecation message for sc_module(const char*) +// +// Revision 1.2 2008/05/22 17:06:25 acg +// Andy Goodrich: updated copyright notice to include 2008. +// +// Revision 1.1.1.1 2006/12/15 20:20:05 acg +// SystemC 2.3 +// +// Revision 1.7 2006/08/29 23:37:13 acg +// Andy Goodrich: Added check for negative time. +// +// Revision 1.6 2006/04/20 17:08:16 acg +// Andy Goodrich: 3.0 style process changes. +// +// Revision 1.5 2006/01/25 00:31:19 acg +// Andy Goodrich: Changed over to use a standard message id of +// SC_ID_IEEE_1666_DEPRECATION for all deprecation messages. +// +// Revision 1.4 2006/01/24 20:49:04 acg +// Andy Goodrich: changes to remove the use of deprecated features within the +// simulator, and to issue warning messages when deprecated features are used. +// +// Revision 1.3 2006/01/13 18:44:29 acg +// Added $Log to record CVS changes into the source. +// + +#endif + +// Taf! diff --git a/ext/systemc/src/sysc/kernel/sc_macros.h b/ext/systemc/src/sysc/kernel/sc_macros.h new file mode 100644 index 000000000..baa6d6e3b --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_macros.h @@ -0,0 +1,136 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_macros.h -- Miscellaneous definitions that are needed by the headers. + + Original Author: Stan Y. Liao, Synopsys, Inc. + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + + +#ifndef SC_MACROS_H +#define SC_MACROS_H + + +namespace sc_dt { + +template <class T> +inline +const T +sc_min( const T& a, const T& b ) +{ + return ( ( a <= b ) ? a : b ); +} + +template <class T> +inline +const T +sc_max( const T& a, const T& b ) +{ + return ( ( a >= b ) ? a : b ); +} + +template <class T> +inline +const T +sc_abs( const T& a ) +{ + // return ( a >= 0 ? a : -a ); + // the code below is functionaly the same as the code above; the + // difference is that the code below works for all arithmetic + // SystemC datatypes. + T z( a ); + z = 0; + if( a >= z ) { + return a; + } else { + T c( a ); + c = -a; + return c; + } +} + +} // namespace sc_dt + +namespace sc_core { + +// token stringification + +#define SC_STRINGIFY_HELPER_( Arg ) \ + SC_STRINGIFY_HELPER_DEFERRED_( Arg ) +#define SC_STRINGIFY_HELPER_DEFERRED_( Arg ) \ + SC_STRINGIFY_HELPER_MORE_DEFERRED_( Arg ) +#define SC_STRINGIFY_HELPER_MORE_DEFERRED_( Arg ) \ + #Arg + + +// token concatenation + +#define SC_CONCAT_HELPER_( a, b ) \ + SC_CONCAT_HELPER_DEFERRED_( a, b ) +#define SC_CONCAT_HELPER_DEFERRED_( a, b ) \ + SC_CONCAT_HELPER_MORE_DEFERRED_( a,b ) +#define SC_CONCAT_HELPER_MORE_DEFERRED_( a, b ) \ + a ## b +#define SC_CONCAT_UNDERSCORE_( a, b ) \ + SC_CONCAT_HELPER_( a, SC_CONCAT_HELPER_( _, b ) ) + +/* + * These help debugging -- + * -- user can find out where each process is stopped at. + */ + +#define WAIT() \ + ::sc_core::sc_set_location( __FILE__, __LINE__ ); \ + ::sc_core::wait() + +#define WAITN(n) \ + ::sc_core::sc_set_location( __FILE__, __LINE__ ); \ + ::sc_core::wait(n) + +#define WAIT_UNTIL(expr) \ + ::sc_core::sc_set_location( __FILE__, __LINE__ ); \ + do { ::sc_core::wait(); } while( !(expr) ) + +} // namespace sc_core + +// $Log: sc_macros.h,v $ +// Revision 1.5 2011/08/26 20:46:09 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +// Revision 1.4 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.3 2011/02/13 21:47:37 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.2 2008/05/22 17:06:25 acg +// Andy Goodrich: updated copyright notice to include 2008. +// +// Revision 1.1.1.1 2006/12/15 20:20:05 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:44:29 acg +// Added $Log to record CVS changes into the source. + +#endif diff --git a/ext/systemc/src/sysc/kernel/sc_main.cpp b/ext/systemc/src/sysc/kernel/sc_main.cpp new file mode 100644 index 000000000..a5f780d70 --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_main.cpp @@ -0,0 +1,58 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_main.cpp - Wrapper around user's toplevel routine `sc_main'. + + Original Author: Stan Y. Liao, Synopsys, Inc. + + CHANGE LOG APPEARS AT THE END OF THE FILE + *****************************************************************************/ + + +#include "sysc/kernel/sc_cmnhdr.h" +#include "sysc/kernel/sc_externs.h" + +int +main( int argc, char* argv[] ) +{ + return sc_core::sc_elab_and_sim( argc, argv ); +} + +// $Log: sc_main.cpp,v $ +// Revision 1.5 2011/08/26 20:46:09 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +// Revision 1.4 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.3 2011/02/13 21:47:37 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.2 2008/05/22 17:06:25 acg +// Andy Goodrich: updated copyright notice to include 2008. +// +// Revision 1.1.1.1 2006/12/15 20:20:05 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:44:29 acg +// Added $Log to record CVS changes into the source. +// diff --git a/ext/systemc/src/sysc/kernel/sc_main_main.cpp b/ext/systemc/src/sysc/kernel/sc_main_main.cpp new file mode 100644 index 000000000..1cdf1eb49 --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_main_main.cpp @@ -0,0 +1,167 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_main_main.cpp - Wrapper around user's toplevel routine `sc_main'. + + Original Author: Andy Goodrich, Forte Design Systems + + CHANGE LOG APPEARS AT THE END OF THE FILE + *****************************************************************************/ + + +#include "sysc/kernel/sc_cmnhdr.h" +#include "sysc/kernel/sc_externs.h" +#include "sysc/kernel/sc_except.h" +#include "sysc/utils/sc_iostream.h" +#include "sysc/utils/sc_report.h" +#include "sysc/utils/sc_report_handler.h" +#include "sysc/utils/sc_utils_ids.h" +#include <vector> + +namespace sc_core { + +extern void pln(); + +static int argc_copy; // Copy of argc value passed to sc_elab_and_sim. +static char** argv_copy; // Copy of argv value passed to sc_elab_and_sim. + +static +inline +void +message_function( const char* s ) +{ + ::std::cout << "\n" << s << ::std::endl; +} + +bool sc_in_action = false; + +int sc_argc() +{ + return argc_copy; +} + +const char* const* sc_argv() +{ + return argv_copy; +} + + +int +sc_elab_and_sim( int argc, char* argv[] ) +{ + int status = 1; + argc_copy = argc; + argv_copy = argv; + std::vector<char*> argv_call; + for ( int i = 0; i < argc; i++ ) + argv_call.push_back(argv[i]); + + try + { + pln(); + + // Perform initialization here + sc_in_action = true; + + status = sc_main( argc, &argv_call[0] ); + + // Perform cleanup here + sc_in_action = false; + } + catch( const sc_report& x ) + { + message_function( x.what() ); + } + catch( ... ) + { + // translate other escaping exceptions + sc_report* err_p = sc_handle_exception(); + if( err_p ) message_function( err_p->what() ); + delete err_p; + } + + // IF DEPRECATION WARNINGS WERE ISSUED TELL THE USER HOW TO TURN THEM OFF + + if ( sc_report_handler::get_count( SC_ID_IEEE_1666_DEPRECATION_ ) > 0 ) + { + std::stringstream ss; + +# define MSGNL "\n " +# define CODENL "\n " + + ss << + "You can turn off warnings about" MSGNL + "IEEE 1666 deprecated features by placing this method call" MSGNL + "as the first statement in your sc_main() function:\n" CODENL + "sc_core::sc_report_handler::set_actions( " + "\"" << SC_ID_IEEE_1666_DEPRECATION_ << "\"," CODENL + " " /* indent param */ + "sc_core::SC_DO_NOTHING );" + << std::endl; + + SC_REPORT_INFO( SC_ID_IEEE_1666_DEPRECATION_, ss.str().c_str() ); + } + + return status; +} + +} // namespace sc_core + +// $Log: sc_main_main.cpp,v $ +// Revision 1.9 2011/08/26 20:46:10 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +// Revision 1.8 2011/05/09 04:07:48 acg +// Philipp A. Hartmann: +// (1) Restore hierarchy in all phase callbacks. +// (2) Ensure calls to before_end_of_elaboration. +// +// Revision 1.7 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.6 2011/02/13 21:47:37 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.5 2010/03/15 18:29:25 acg +// Andy Goodrich: Changed the default stack size to 128K from 64K. +// +// Revision 1.4 2009/10/14 19:06:48 acg +// Andy Goodrich: changed the way the "copy" of argv is handled. It is +// now passed to sc_main, and the original is referenced via argv_copy. +// +// Revision 1.3 2008/05/22 17:06:25 acg +// Andy Goodrich: updated copyright notice to include 2008. +// +// Revision 1.2 2008/04/11 20:41:28 acg +// Andy Goodrich: changed the return value in sc_elab_and_sim() to be 1 +// when an exception occurs in sc_main() rather than 0. +// +// Revision 1.1.1.1 2006/12/15 20:20:05 acg +// SystemC 2.3 +// +// Revision 1.4 2006/01/25 00:31:19 acg +// Andy Goodrich: Changed over to use a standard message id of +// SC_ID_IEEE_1666_DEPRECATION for all deprecation messages. +// +// Revision 1.3 2006/01/13 18:44:29 acg +// Added $Log to record CVS changes into the source. +// diff --git a/ext/systemc/src/sysc/kernel/sc_method_process.cpp b/ext/systemc/src/sysc/kernel/sc_method_process.cpp new file mode 100644 index 000000000..994e495ad --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_method_process.cpp @@ -0,0 +1,1023 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_method_process.cpp -- Method process implementation + + Original Author: Andy Goodrich, Forte Design Systems, 4 August 2005 + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + +#include "sysc/kernel/sc_method_process.h" +#include "sysc/kernel/sc_simcontext_int.h" +#include "sysc/kernel/sc_module.h" +#include "sysc/kernel/sc_spawn_options.h" + +// DEBUGGING MACROS: +// +// DEBUG_MSG(NAME,P,MSG) +// MSG = message to print +// NAME = name that must match the process for the message to print, or +// null if the message should be printed unconditionally. +// P = pointer to process message is for, or NULL in which case the +// message will not print. +#if 0 +# define DEBUG_NAME "" +# define DEBUG_MSG(NAME,P,MSG) \ + { \ + if ( P && ( (strlen(NAME)==0) || !strcmp(NAME,P->name())) ) \ + std::cout << "**** " << sc_time_stamp() << " (" \ + << sc_get_current_process_name() << "): " << MSG \ + << " - " << P->name() << std::endl; \ + } +#else +# define DEBUG_MSG(NAME,P,MSG) +#endif + +namespace sc_core { + +// +---------------------------------------------------------------------------- +// |"sc_method_process::check_for_throws" +// | +// | This method checks to see if this method process should throw an exception +// | or not. It is called from sc_simcontext::preempt_with() to see if the +// | thread that was executed during the preemption did a kill or other +// | manipulation on this object instance that requires it to throw an +// | exception. +// +---------------------------------------------------------------------------- +void sc_method_process::check_for_throws() +{ + if ( !m_unwinding ) + { + switch( m_throw_status ) + { + case THROW_ASYNC_RESET: + simcontext()->preempt_with(this); + break; + case THROW_KILL: + throw sc_unwind_exception( this, false ); + default: + break; + } + } +} + +//------------------------------------------------------------------------------ +//"sc_method_process::clear_trigger" +// +// This method clears any pending trigger for this object instance. +//------------------------------------------------------------------------------ +void sc_method_process::clear_trigger() +{ + switch( m_trigger_type ) { + case STATIC: + return; + case EVENT: + m_event_p->remove_dynamic( this ); + m_event_p = 0; + break; + case OR_LIST: + m_event_list_p->remove_dynamic( this, 0 ); + m_event_list_p->auto_delete(); + m_event_list_p = 0; + break; + case AND_LIST: + m_event_list_p->remove_dynamic( this, 0 ); + m_event_list_p->auto_delete(); + m_event_list_p = 0; + m_event_count = 0; + break; + case TIMEOUT: + m_timeout_event_p->cancel(); + m_timeout_event_p->reset(); + break; + case EVENT_TIMEOUT: + m_timeout_event_p->cancel(); + m_timeout_event_p->reset(); + m_event_p->remove_dynamic( this ); + m_event_p = 0; + break; + case OR_LIST_TIMEOUT: + m_timeout_event_p->cancel(); + m_timeout_event_p->reset(); + m_event_list_p->remove_dynamic( this, 0 ); + m_event_list_p->auto_delete(); + m_event_list_p = 0; + break; + case AND_LIST_TIMEOUT: + m_timeout_event_p->cancel(); + m_timeout_event_p->reset(); + m_event_list_p->remove_dynamic( this, 0 ); + m_event_list_p->auto_delete(); + m_event_list_p = 0; + m_event_count = 0; + break; + } + m_trigger_type = STATIC; +} + +//------------------------------------------------------------------------------ +//"sc_method_process::disable_process" +// +// This virtual method disables this process and its children if requested to. +// descendants = indicator of whether this process' children should also +// be suspended +//------------------------------------------------------------------------------ +void sc_method_process::disable_process( + sc_descendant_inclusion_info descendants ) +{ + + // IF NEEDED PROPOGATE THE SUSPEND REQUEST THROUGH OUR DESCENDANTS: + + if ( descendants == SC_INCLUDE_DESCENDANTS ) + { + const std::vector<sc_object*>& children = get_child_objects(); + int child_n = children.size(); + + for ( int child_i = 0; child_i < child_n; child_i++ ) + { + sc_process_b* child_p = DCAST<sc_process_b*>(children[child_i]); + if ( child_p ) child_p->disable_process(descendants); + } + } + + // DON'T ALLOW CORNER CASE BY DEFAULT: + + if ( !sc_allow_process_control_corners ) + { + switch( m_trigger_type ) + { + case AND_LIST_TIMEOUT: + case EVENT_TIMEOUT: + case OR_LIST_TIMEOUT: + case TIMEOUT: + report_error( SC_ID_PROCESS_CONTROL_CORNER_CASE_, + "attempt to disable a method with timeout wait" ); + break; + default: + break; + } + } + + // DISABLE OUR OBJECT INSTANCE: + + m_state = m_state | ps_bit_disabled; + + // IF THIS CALL IS BEFORE THE SIMULATION DON'T RUN THE METHOD: + + if ( !sc_is_running() ) + { + sc_get_curr_simcontext()->remove_runnable_method(this); + } +} + + +//------------------------------------------------------------------------------ +//"sc_method_process::enable_process" +// +// This method enables the execution of this process, and if requested, its +// descendants. If the process was suspended and has a resumption pending it +// will be dispatched in the next delta cycle. Otherwise the state will be +// adjusted to indicate it is no longer suspended, but no immediate execution +// will occur. +//------------------------------------------------------------------------------ +void sc_method_process::enable_process( + sc_descendant_inclusion_info descendants ) +{ + + // IF NEEDED PROPOGATE THE RESUME REQUEST THROUGH OUR DESCENDANTS: + + if ( descendants == SC_INCLUDE_DESCENDANTS ) + { + const std::vector<sc_object*>& children = get_child_objects(); + int child_n = children.size(); + + for ( int child_i = 0; child_i < child_n; child_i++ ) + { + sc_process_b* child_p = DCAST<sc_process_b*>(children[child_i]); + if ( child_p ) child_p->enable_process(descendants); + } + } + + // ENABLE THIS OBJECT INSTANCE: + // + // If it was disabled and ready to run then put it on the run queue. + + m_state = m_state & ~ps_bit_disabled; + if ( m_state == ps_bit_ready_to_run ) + { + m_state = ps_normal; + if ( next_runnable() == 0 ) + simcontext()->push_runnable_method(this); + } +} + + +//------------------------------------------------------------------------------ +//"sc_method_process::kill_process" +// +// This method removes throws a kill for this object instance. It calls the +// sc_process_b::kill_process() method to perform low level clean up. +//------------------------------------------------------------------------------ +void sc_method_process::kill_process(sc_descendant_inclusion_info descendants) +{ + + // IF THE SIMULATION HAS NOT BEEN INITIALIZED YET THAT IS AN ERROR: + + if ( sc_get_status() == SC_ELABORATION ) + { + report_error( SC_ID_KILL_PROCESS_WHILE_UNITIALIZED_ ); + } + + // IF NEEDED, PROPOGATE THE KILL REQUEST THROUGH OUR DESCENDANTS: + + if ( descendants == SC_INCLUDE_DESCENDANTS ) + { + const std::vector<sc_object*> children = get_child_objects(); + int child_n = children.size(); + + for ( int child_i = 0; child_i < child_n; child_i++ ) + { + sc_process_b* child_p = DCAST<sc_process_b*>(children[child_i]); + if ( child_p ) child_p->kill_process(descendants); + } + } + + // IF THE PROCESS IS CURRENTLY UNWINDING OR IS ALREADY A ZOMBIE + // IGNORE THE KILL: + + if ( m_unwinding ) + { + SC_REPORT_WARNING( SC_ID_PROCESS_ALREADY_UNWINDING_, name() ); + return; + } + + if ( m_state & ps_bit_zombie ) + return; + + + // REMOVE OUR PROCESS FROM EVENTS, ETC., AND IF ITS THE ACTIVE PROCESS + // THROW ITS KILL. + // + // Note we set the throw status to kill regardless if we throw or not. + // That lets check_for_throws stumble across it if we were in the call + // chain when the kill call occurred. + + if ( next_runnable() != 0 ) + simcontext()->remove_runnable_method( this ); + disconnect_process(); + + m_throw_status = THROW_KILL; + if ( sc_get_current_process_b() == this ) + { + throw sc_unwind_exception( this, false ); + } +} + +//------------------------------------------------------------------------------ +//"sc_method_process::sc_method_process" +// +// This is the object instance constructor for this class. +//------------------------------------------------------------------------------ +sc_method_process::sc_method_process( const char* name_p, + bool free_host, SC_ENTRY_FUNC method_p, + sc_process_host* host_p, const sc_spawn_options* opt_p +): + sc_process_b( + name_p ? name_p : sc_gen_unique_name("method_p"), + false, free_host, method_p, host_p, opt_p), + m_cor(0), m_stack_size(0), m_monitor_q() +{ + + // CHECK IF THIS IS AN sc_module-BASED PROCESS AND SIMUALTION HAS STARTED: + + if ( DCAST<sc_module*>(host_p) != 0 && sc_is_running() ) + { + report_error( SC_ID_MODULE_METHOD_AFTER_START_, "" ); + } + + // INITIALIZE VALUES: + // + // If there are spawn options use them. + + m_process_kind = SC_METHOD_PROC_; + if (opt_p) { + m_dont_init = opt_p->m_dont_initialize; + + // traverse event sensitivity list + for (unsigned int i = 0; i < opt_p->m_sensitive_events.size(); i++) { + sc_sensitive::make_static_sensitivity( + this, *opt_p->m_sensitive_events[i]); + } + + // traverse port base sensitivity list + for ( unsigned int i = 0; i < opt_p->m_sensitive_port_bases.size(); i++) + { + sc_sensitive::make_static_sensitivity( + this, *opt_p->m_sensitive_port_bases[i]); + } + + // traverse interface sensitivity list + for ( unsigned int i = 0; i < opt_p->m_sensitive_interfaces.size(); i++) + { + sc_sensitive::make_static_sensitivity( + this, *opt_p->m_sensitive_interfaces[i]); + } + + // traverse event finder sensitivity list + for ( unsigned int i = 0; i < opt_p->m_sensitive_event_finders.size(); + i++) + { + sc_sensitive::make_static_sensitivity( + this, *opt_p->m_sensitive_event_finders[i]); + } + + // process any reset signal specification: + + opt_p->specify_resets(); + } + + else + { + m_dont_init = false; + } +} + +//------------------------------------------------------------------------------ +//"sc_method_process::sc_method_process" +// +// This is the object instance destructor for this class. +//------------------------------------------------------------------------------ +sc_method_process::~sc_method_process() +{ +} + + +//------------------------------------------------------------------------------ +//"sc_method_process::suspend_process" +// +// This virtual method suspends this process and its children if requested to. +// descendants = indicator of whether this process' children should also +// be suspended +//------------------------------------------------------------------------------ +void sc_method_process::suspend_process( + sc_descendant_inclusion_info descendants ) +{ + + // IF NEEDED PROPOGATE THE SUSPEND REQUEST THROUGH OUR DESCENDANTS: + + if ( descendants == SC_INCLUDE_DESCENDANTS ) + { + const std::vector<sc_object*>& children = get_child_objects(); + int child_n = children.size(); + + for ( int child_i = 0; child_i < child_n; child_i++ ) + { + sc_process_b* child_p = DCAST<sc_process_b*>(children[child_i]); + if ( child_p ) child_p->suspend_process(descendants); + } + } + + // CORNER CASE CHECKS, THE FOLLOWING ARE ERRORS: + // (a) if this method has a reset_signal_is specification + // (b) if this method is in synchronous reset + + if ( !sc_allow_process_control_corners && m_has_reset_signal ) + { + report_error(SC_ID_PROCESS_CONTROL_CORNER_CASE_, + "attempt to suspend a method that has a reset signal"); + } + else if ( !sc_allow_process_control_corners && m_sticky_reset ) + { + report_error(SC_ID_PROCESS_CONTROL_CORNER_CASE_, + "attempt to suspend a method in synchronous reset"); + } + + // SUSPEND OUR OBJECT INSTANCE: + // + // (1) If we are on the runnable queue then set suspended and ready_to_run, + // and remove ourselves from the run queue. + // (2) If this is a self-suspension then a resume should cause immediate + // scheduling of the process. + + m_state = m_state | ps_bit_suspended; + if ( next_runnable() != 0 ) + { + m_state = m_state | ps_bit_ready_to_run; + simcontext()->remove_runnable_method( this ); + } + if ( sc_get_current_process_b() == DCAST<sc_process_b*>(this) ) + { + m_state = m_state | ps_bit_ready_to_run; + } +} + +//------------------------------------------------------------------------------ +//"sc_method_process::resume_process" +// +// This method resumes the execution of this process, and if requested, its +// descendants. If the process was suspended and has a resumption pending it +// will be dispatched in the next delta cycle. Otherwise the state will be +// adjusted to indicate it is no longer suspended, but no immediate execution +// will occur. +//------------------------------------------------------------------------------ +void sc_method_process::resume_process( + sc_descendant_inclusion_info descendants ) +{ + + // IF NEEDED PROPOGATE THE RESUME REQUEST THROUGH OUR DESCENDANTS: + + if ( descendants == SC_INCLUDE_DESCENDANTS ) + { + const std::vector<sc_object*>& children = get_child_objects(); + int child_n = children.size(); + + for ( int child_i = 0; child_i < child_n; child_i++ ) + { + sc_process_b* child_p = DCAST<sc_process_b*>(children[child_i]); + if ( child_p ) child_p->resume_process(descendants); + } + } + + + // BY DEFAULT THE CORNER CASE IS AN ERROR: + + if ( !sc_allow_process_control_corners && (m_state & ps_bit_disabled) && + (m_state & ps_bit_suspended) ) + { + m_state = m_state & ~ps_bit_suspended; + report_error( SC_ID_PROCESS_CONTROL_CORNER_CASE_, + "call to resume() on a disabled suspended method"); + } + + // CLEAR THE SUSPENDED BIT: + + m_state = m_state & ~ps_bit_suspended; + + // RESUME OBJECT INSTANCE: + // + // If this is not a self-resume and the method is ready to run then + // put it on the runnable queue. + + if ( m_state & ps_bit_ready_to_run ) + { + m_state = m_state & ~ps_bit_ready_to_run; + if ( next_runnable() == 0 && + ( sc_get_current_process_b() != DCAST<sc_process_b*>(this) ) ) + { + simcontext()->push_runnable_method(this); + remove_dynamic_events(); + } + } +} + +//------------------------------------------------------------------------------ +//"sc_method_process::throw_reset" +// +// This virtual method is invoked to "throw" a reset. +// +// If the reset is synchronous this is a no-op, except for triggering the +// reset event if it is present. +// +// If the reset is asynchronous we: +// (a) cancel any dynamic waits +// (b) if it is the active process actually throw a reset exception. +// (c) if it was not the active process and does not have a static +// sensitivity emit an error if corner cases are to be considered +// errors. +// +// Notes: +// (1) If the process had a reset event it will have been triggered in +// sc_process_b::semantics() +// +// Arguments: +// async = true if this is an asynchronous reset. +//------------------------------------------------------------------------------ +void sc_method_process::throw_reset( bool async ) +{ + // IF THE PROCESS IS CURRENTLY UNWINDING OR IS ALREADY A ZOMBIE + // IGNORE THE RESET: + + if ( m_unwinding ) + { + SC_REPORT_WARNING( SC_ID_PROCESS_ALREADY_UNWINDING_, name() ); + return; + } + + if ( m_state & ps_bit_zombie ) + return; + + // Set the throw status and if its an asynchronous reset throw an + // exception: + + m_throw_status = async ? THROW_ASYNC_RESET : THROW_SYNC_RESET; + if ( async ) + { + remove_dynamic_events(); + if ( sc_get_current_process_b() == this ) + { + DEBUG_MSG(DEBUG_NAME,this,"throw_reset: throwing exception"); + m_throw_status = THROW_ASYNC_RESET; + throw sc_unwind_exception( this, true ); + } + else + { + DEBUG_MSG(DEBUG_NAME,this, + "throw_reset: queueing this method for execution"); + simcontext()->preempt_with(this); + } + } +} + + +//------------------------------------------------------------------------------ +//"sc_method_process::throw_user" +// +// This virtual method is invoked when a user exception is to be thrown. +// If requested it will also throw the exception to the children of this +// object instance. Since this is a method no throw will occur for this +// object instance. The children will be awakened from youngest child to +// eldest. +// helper_p -> object to use to throw the exception. +// descendants = indicator of whether this process' children should also +// be suspended +//------------------------------------------------------------------------------ +void sc_method_process::throw_user( const sc_throw_it_helper& helper, + sc_descendant_inclusion_info descendants ) +{ + + // IF THE SIMULATION IS NOT ACTUALLY RUNNING THIS IS AN ERROR: + + if ( sc_get_status() != SC_RUNNING ) + { + report_error( SC_ID_THROW_IT_WHILE_NOT_RUNNING_ ); + } + + // IF NEEDED PROPOGATE THE THROW REQUEST THROUGH OUR DESCENDANTS: + + if ( descendants == SC_INCLUDE_DESCENDANTS ) + { + const std::vector<sc_object*> children = get_child_objects(); + int child_n = children.size(); + + for ( int child_i = 0; child_i < child_n; child_i++ ) + { + sc_process_b* child_p = DCAST<sc_process_b*>(children[child_i]); + if ( child_p ) + { + DEBUG_MSG(DEBUG_NAME,child_p,"about to throw user on"); + child_p->throw_user(helper, descendants); + } + } + } + +#if 0 // shouldn't we throw, if we're currently running? + + if ( sc_get_current_process_b() == (sc_process_b*)this ) + { + remove_dynamic_events(); + m_throw_status = THROW_USER; + if ( m_throw_helper_p != 0 ) delete m_throw_helper_p; + m_throw_helper_p = helper.clone(); + m_throw_helper_p->throw_it(); + } + + // throw_it HAS NO EFFECT ON A METHOD, ISSUE A WARNING: + + else + +#endif + { + SC_REPORT_WARNING( SC_ID_THROW_IT_IGNORED_, name() ); + } + + +} + +//------------------------------------------------------------------------------ +//"sc_method_process::trigger_dynamic" +// +// This method sets up a dynamic trigger on an event. +// +// Notes: +// (1) This method is identical to sc_thread_process::trigger_dynamic(), +// but they cannot be combined as sc_process_b::trigger_dynamic() +// because the signatures things like sc_event::remove_dynamic() +// have different overloads for sc_method_process* and sc_thread_process*. +// So if you change code here you'll also need to change it in +// sc_thread_process.cpp. +// +// Result is true if this process should be removed from the event's list, +// false if not. +// +// If the triggering process is the same process, the trigger is +// ignored as well, unless SC_ENABLE_IMMEDIATE_SELF_NOTIFICATIONS +// is defined. +//------------------------------------------------------------------------------ +bool sc_method_process::trigger_dynamic( sc_event* e ) +{ + // No time outs yet, and keep gcc happy. + + m_timed_out = false; + + // Escape cases: + // (a) If this method issued the notify() don't schedule it for + // execution, but leave the sensitivity in place. + // (b) If this method is already runnable can't trigger an event. + +#if ! defined( SC_ENABLE_IMMEDIATE_SELF_NOTIFICATIONS ) + if( SC_UNLIKELY_( sc_get_current_process_b() == this ) ) + { + report_immediate_self_notification(); + return false; + } +#endif // SC_ENABLE_IMMEDIATE_SELF_NOTIFICATIONS + + if( is_runnable() ) + return true; + + // If a process is disabled then we ignore any events, leaving them enabled: + // + // But if this is a time out event we need to remove both it and the + // event that was being waited for. + + if ( m_state & ps_bit_disabled ) + { + if ( e == m_timeout_event_p ) + { + remove_dynamic_events( true ); + return true; + } + else + { + return false; + } + } + + + // Process based on the event type and current process state: + // + // Every case needs to set 'rc' and continue on to the end of + // this method to allow suspend processing to work correctly. + + switch( m_trigger_type ) + { + case EVENT: + m_event_p = 0; + m_trigger_type = STATIC; + break; + + case AND_LIST: + -- m_event_count; + if ( m_event_count == 0 ) + { + m_event_list_p->auto_delete(); + m_event_list_p = 0; + m_trigger_type = STATIC; + } + else + { + return true; + } + break; + + case OR_LIST: + m_event_list_p->remove_dynamic( this, e ); + m_event_list_p->auto_delete(); + m_event_list_p = 0; + m_trigger_type = STATIC; + break; + + case TIMEOUT: + m_trigger_type = STATIC; + break; + + case EVENT_TIMEOUT: + if ( e == m_timeout_event_p ) + { + m_timed_out = true; + m_event_p->remove_dynamic( this ); + m_event_p = 0; + m_trigger_type = STATIC; + } + else + { + m_timeout_event_p->cancel(); + m_timeout_event_p->reset(); + m_event_p = 0; + m_trigger_type = STATIC; + } + break; + + case OR_LIST_TIMEOUT: + if ( e == m_timeout_event_p ) + { + m_timed_out = true; + m_event_list_p->remove_dynamic( this, e ); + m_event_list_p->auto_delete(); + m_event_list_p = 0; + m_trigger_type = STATIC; + } + + else + { + m_timeout_event_p->cancel(); + m_timeout_event_p->reset(); + m_event_list_p->remove_dynamic( this, e ); + m_event_list_p->auto_delete(); + m_event_list_p = 0; + m_trigger_type = STATIC; + } + break; + + case AND_LIST_TIMEOUT: + if ( e == m_timeout_event_p ) + { + m_timed_out = true; + m_event_list_p->remove_dynamic( this, e ); + m_event_list_p->auto_delete(); + m_event_list_p = 0; + m_trigger_type = STATIC; + } + + else + { + -- m_event_count; + if ( m_event_count == 0 ) + { + m_timeout_event_p->cancel(); + m_timeout_event_p->reset(); + // no need to remove_dynamic + m_event_list_p->auto_delete(); + m_event_list_p = 0; + m_trigger_type = STATIC; + } + else + { + return true; + } + } + break; + + case STATIC: { + // we should never get here, but throw_it() can make it happen. + SC_REPORT_WARNING(SC_ID_NOT_EXPECTING_DYNAMIC_EVENT_NOTIFY_, name()); + return true; + } + } + + // If we get here then the method has satisfied its next_trigger, if its + // suspended mark its state as ready to run. If its not suspended then push + // it onto the runnable queue. + + if ( (m_state & ps_bit_suspended) ) + { + m_state = m_state | ps_bit_ready_to_run; + } + else + { + simcontext()->push_runnable_method(this); + } + + return true; +} + +} // namespace sc_core + + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + +// $Log: sc_method_process.cpp,v $ +// Revision 1.49 2011/08/29 18:24:47 acg +// Andy Goodrich: remove temporary comment flagging new preempt_with() call. +// +// Revision 1.48 2011/08/29 18:04:32 acg +// Philipp A. Hartmann: miscellaneous clean ups. +// +// Revision 1.47 2011/08/24 22:05:50 acg +// Torsten Maehne: initialization changes to remove warnings. +// +// Revision 1.46 2011/08/07 19:08:04 acg +// Andy Goodrich: moved logs to end of file so line number synching works +// better between versions. +// +// Revision 1.45 2011/07/29 22:42:45 acg +// Andy Goodrich: added check_for_throws() to fix case where a method is +// deleted by a process it resets or kills so that it can throw itself. +// Philipp A. Hartmann: changes to handle case where a process control +// invocation on a child process causes the list of child processes to change. +// +// Revision 1.44 2011/07/24 11:27:04 acg +// Andy Goodrich: moved the check for unwinding processes until after the +// descendants have been processed in throw_user and kill. +// +// Revision 1.43 2011/07/24 11:20:03 acg +// Philipp A. Hartmann: process control error message improvements: +// (1) Downgrade error to warning for re-kills of processes. +// (2) Add process name to process messages. +// (3) drop some superfluous colons in messages. +// +// Revision 1.42 2011/05/05 17:45:27 acg +// Philip A. Hartmann: changes in WIN64 support. +// Andy Goodrich: additional DEBUG_MSG instances to trace process handling. +// +// Revision 1.41 2011/04/19 19:15:41 acg +// Andy Goodrich: fix so warning message is always issued for a throw_it() +// on a method process. +// +// Revision 1.40 2011/04/19 15:04:27 acg +// Philipp A. Hartmann: clean up SC_ID messages. +// +// Revision 1.39 2011/04/19 02:39:09 acg +// Philipp A. Hartmann: added checks for additional throws during stack unwinds. +// +// Revision 1.38 2011/04/13 02:41:34 acg +// Andy Goodrich: eliminate warning messages generated when the DEBUG_MSG +// macro is used. +// +// Revision 1.37 2011/04/11 22:10:46 acg +// Andy Goodrich: +// (1) Add DEBUG_MSG macro and use it to generate a journal of method +// throws if it is enabled. +// (2) Trim down to the expected behavior of scheduling a method that +// is asynchronously reset in anticipation of IEEE 1666 being revised. +// +// Revision 1.36 2011/04/10 22:15:29 acg +// Andy Goodrich: change to call methods on asynchronous reset. +// +// Revision 1.35 2011/04/08 22:31:40 acg +// Andy Goodrich: removed unused code. +// +// Revision 1.34 2011/04/08 18:24:07 acg +// Andy Goodrich: fix asynchronous reset dispatch and when the reset_event() +// is fired. +// +// Revision 1.33 2011/04/05 20:50:56 acg +// Andy Goodrich: +// (1) changes to make sure that event(), posedge() and negedge() only +// return true if the clock has not moved. +// (2) fixes for method self-resumes. +// (3) added SC_PRERELEASE_VERSION +// (4) removed kernel events from the object hierarchy, added +// sc_hierarchy_name_exists(). +// +// Revision 1.32 2011/04/01 22:30:39 acg +// Andy Goodrich: change hard assertion to warning for trigger_dynamic() +// getting called when there is only STATIC sensitivity. This can result +// because of sc_process_handle::throw_it(). +// +// Revision 1.31 2011/03/28 13:02:51 acg +// Andy Goodrich: Changes for disable() interactions. +// +// Revision 1.30 2011/03/23 16:17:52 acg +// Andy Goodrich: don't emit an error message for a resume on a disabled +// process that is not suspended. +// +// Revision 1.29 2011/03/20 13:43:23 acg +// Andy Goodrich: added async_signal_is() plus suspend() as a corner case. +// +// Revision 1.28 2011/03/08 20:49:30 acg +// Andy Goodrich: implement coarse checking for synchronous reset - suspend +// interaction. +// +// Revision 1.27 2011/03/08 20:32:28 acg +// Andy Goodrich: implemented "coarse" checking for undefined process +// control interactions. +// +// Revision 1.26 2011/03/07 18:25:19 acg +// Andy Goodrich: tightening of check for resume on a disabled process to +// only produce an error if it is ready to run. +// +// Revision 1.25 2011/03/07 17:38:43 acg +// Andy Goodrich: tightening up of checks for undefined interaction between +// synchronous reset and suspend. +// +// Revision 1.24 2011/03/06 23:30:13 acg +// Andy Goodrich: refining suspend - sync reset corner case checking so that +// the following are error situations: +// (1) Calling suspend on a process with a reset_signal_is() specification +// or sync_reset_on() is active. +// (2) Calling sync_reset_on() on a suspended process. +// +// Revision 1.23 2011/03/06 19:57:11 acg +// Andy Goodrich: refinements for the illegal suspend - synchronous reset +// interaction. +// +// Revision 1.22 2011/03/06 16:47:09 acg +// Andy Goodrich: changes for testing sync_reset - suspend corner cases. +// +// Revision 1.21 2011/03/06 15:57:08 acg +// Andy Goodrich: added process control corner case checks. +// +// Revision 1.20 2011/03/05 19:44:20 acg +// Andy Goodrich: changes for object and event naming and structures. +// +// Revision 1.19 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.18 2011/02/17 19:50:43 acg +// Andy Goodrich: +// (1) Changed signature of trigger_dynamic back to a bool. +// (2) Added run queue processing into trigger dynamic. +// (3) Simplified process control support. +// +// Revision 1.17 2011/02/16 22:37:30 acg +// Andy Goodrich: clean up to remove need for ps_disable_pending. +// +// Revision 1.16 2011/02/13 23:09:58 acg +// Andy Goodrich: only remove dynamic events for asynchronous resets. +// +// Revision 1.15 2011/02/13 21:47:37 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.14 2011/02/13 21:31:02 acg +// Andy Goodrich: added error messages for throws when simulator has not +// been initialized. Added missing remove_dynamic_events() call to the +// reset code. +// +// Revision 1.13 2011/02/11 13:25:24 acg +// Andy Goodrich: Philipp A. Hartmann's changes: +// (1) Removal of SC_CTHREAD method overloads. +// (2) New exception processing code. +// +// Revision 1.12 2011/02/07 19:17:20 acg +// Andy Goodrich: changes for IEEE 1666 compatibility. +// +// Revision 1.11 2011/02/04 15:27:36 acg +// Andy Goodrich: changes for suspend-resume semantics. +// +// Revision 1.10 2011/02/01 23:01:53 acg +// Andy Goodrich: removed dead code. +// +// Revision 1.9 2011/02/01 21:05:05 acg +// Andy Goodrich: Changes in trigger_dynamic methods to handle new +// process control rules about event sensitivity. +// +// Revision 1.8 2011/01/25 20:50:37 acg +// Andy Goodrich: changes for IEEE 1666 2011. +// +// Revision 1.7 2011/01/18 20:10:44 acg +// Andy Goodrich: changes for IEEE1666_2011 semantics. +// +// Revision 1.6 2011/01/06 18:02:43 acg +// Andy Goodrich: added check for ps_disabled to method_dynamic(). +// +// Revision 1.5 2010/11/20 17:10:56 acg +// Andy Goodrich: reset processing changes for new IEEE 1666 standard. +// +// Revision 1.4 2010/07/22 20:02:33 acg +// Andy Goodrich: bug fixes. +// +// Revision 1.3 2009/05/22 16:06:29 acg +// Andy Goodrich: process control updates. +// +// Revision 1.2 2008/05/22 17:06:25 acg +// Andy Goodrich: updated copyright notice to include 2008. +// +// Revision 1.1.1.1 2006/12/15 20:20:05 acg +// SystemC 2.3 +// +// Revision 1.7 2006/04/20 17:08:16 acg +// Andy Goodrich: 3.0 style process changes. +// +// Revision 1.6 2006/04/11 23:13:20 acg +// Andy Goodrich: Changes for reduced reset support that only includes +// sc_cthread, but has preliminary hooks for expanding to method and thread +// processes also. +// +// Revision 1.5 2006/01/26 21:04:54 acg +// Andy Goodrich: deprecation message changes and additional messages. +// +// Revision 1.4 2006/01/24 20:49:05 acg +// Andy Goodrich: changes to remove the use of deprecated features within the +// simulator, and to issue warning messages when deprecated features are used. +// +// Revision 1.3 2006/01/13 18:44:29 acg +// Added $Log to record CVS changes into the source. +// diff --git a/ext/systemc/src/sysc/kernel/sc_method_process.h b/ext/systemc/src/sysc/kernel/sc_method_process.h new file mode 100644 index 000000000..00f6e37e7 --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_method_process.h @@ -0,0 +1,467 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_method_process.h -- Method process declarations + + Original Author: Andy Goodrich, Forte Design Systems, 4 August 2005 + + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + +// $Log: sc_method_process.h,v $ +// Revision 1.23 2011/09/05 21:20:22 acg +// Andy Goodrich: result of automake invocation. +// +// Revision 1.22 2011/08/29 18:04:32 acg +// Philipp A. Hartmann: miscellaneous clean ups. +// +// Revision 1.21 2011/08/26 20:46:10 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// + +#if !defined(sc_method_process_h_INCLUDED) +#define sc_method_process_h_INCLUDED + +#include "sysc/kernel/sc_process.h" +#include "sysc/kernel/sc_spawn_options.h" +#include "sysc/kernel/sc_cor.h" +#include "sysc/kernel/sc_event.h" +#include "sysc/kernel/sc_except.h" + + +// DEBUGGING MACROS: +// +// DEBUG_MSG(NAME,P,MSG) +// MSG = message to print +// NAME = name that must match the process for the message to print, or +// null if the message should be printed unconditionally. +// P = pointer to process message is for, or NULL in which case the +// message will not print. +#if 0 +# define DEBUG_NAME "" +# define DEBUG_MSG(NAME,P,MSG) \ + { \ + if ( P && ( (strlen(NAME)==0) || !strcmp(NAME,P->name())) ) \ + std::cout << "**** " << sc_time_stamp() << " (" \ + << sc_get_current_process_name() << "): " << MSG \ + << " - " << P->name() << std::endl; \ + } +#else +# define DEBUG_MSG(NAME,P,MSG) +#endif + + +namespace sc_core { + +// forward function and class declarations: + +void sc_method_cor_fn( void* ); +void sc_cmethod_cor_fn( void* ); +void sc_set_stack_size( sc_method_handle, std::size_t ); +class sc_event; +class sc_module; +class sc_process_table; +class sc_process_handle; +class sc_simcontext; +class sc_runnable; + +void next_trigger( sc_simcontext* ); +void next_trigger( const sc_event&, sc_simcontext* ); +void next_trigger( const sc_event_or_list&, sc_simcontext* ); +void next_trigger( const sc_event_and_list&, sc_simcontext* ); +void next_trigger( const sc_time&, sc_simcontext* ); +void next_trigger( const sc_time&, const sc_event&, sc_simcontext* ); +void next_trigger( const sc_time&, const sc_event_or_list&, sc_simcontext* ); +void next_trigger( const sc_time&, const sc_event_and_list&, sc_simcontext* ); + +struct sc_invoke_method; +//============================================================================== +// sc_method_process - +// +//============================================================================== +class sc_method_process : public sc_process_b { + friend struct sc_invoke_method; + friend void sc_method_cor_fn( void* ); + friend void sc_cmethod_cor_fn( void* ); + friend void sc_set_stack_size( sc_method_handle, std::size_t ); + friend class sc_event; + friend class sc_module; + friend class sc_process_table; + friend class sc_process_handle; + friend class sc_simcontext; + friend class sc_runnable; + + friend void next_trigger( sc_simcontext* ); + friend void next_trigger( const sc_event&, + sc_simcontext* ); + friend void next_trigger( const sc_event_or_list&, + sc_simcontext* ); + friend void next_trigger( const sc_event_and_list&, + sc_simcontext* ); + friend void next_trigger( const sc_time&, + sc_simcontext* ); + friend void next_trigger( const sc_time&, const sc_event&, + sc_simcontext* ); + friend void next_trigger( const sc_time&, const sc_event_or_list&, + sc_simcontext* ); + friend void next_trigger( const sc_time&, const sc_event_and_list&, + sc_simcontext* ); + + public: + sc_method_process( const char* name_p, bool free_host, + SC_ENTRY_FUNC method_p, sc_process_host* host_p, + const sc_spawn_options* opt_p ); + + virtual const char* kind() const + { return "sc_method_process"; } + + protected: + void check_for_throws(); + virtual void disable_process( + sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS ); + virtual void enable_process( + sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS ); + inline bool run_process(); + virtual void kill_process( + sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS ); + sc_method_handle next_exist(); + sc_method_handle next_runnable(); + void clear_trigger(); + void next_trigger( const sc_event& ); + void next_trigger( const sc_event_or_list& ); + void next_trigger( const sc_event_and_list& ); + void next_trigger( const sc_time& ); + void next_trigger( const sc_time&, const sc_event& ); + void next_trigger( const sc_time&, const sc_event_or_list& ); + void next_trigger( const sc_time&, const sc_event_and_list& ); + virtual void resume_process( + sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS ); + void set_next_exist( sc_method_handle next_p ); + void set_next_runnable( sc_method_handle next_p ); + void set_stack_size( std::size_t size ); + virtual void suspend_process( + sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS ); + virtual void throw_reset( bool async ); + virtual void throw_user( const sc_throw_it_helper& helper, + sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS ); + bool trigger_dynamic( sc_event* ); + inline void trigger_static(); + + protected: + sc_cor* m_cor; // Thread's coroutine. + std::size_t m_stack_size; // Thread stack size. + std::vector<sc_process_monitor*> m_monitor_q; // Thread monitors. + + private: + // may not be deleted manually (called from sc_process_b) + virtual ~sc_method_process(); + + private: // disabled + sc_method_process( const sc_method_process& ); + const sc_method_process& operator = ( const sc_method_process& ); + +}; + +inline +void +sc_method_process::next_trigger( const sc_event& e ) +{ + clear_trigger(); + e.add_dynamic( this ); + m_event_p = &e; + m_trigger_type = EVENT; +} + +inline +void +sc_method_process::next_trigger( const sc_event_or_list& el ) +{ + clear_trigger(); + el.add_dynamic( this ); + m_event_list_p = ⪙ + m_trigger_type = OR_LIST; +} + +inline +void +sc_method_process::next_trigger( const sc_event_and_list& el ) +{ + clear_trigger(); + el.add_dynamic( this ); + m_event_list_p = ⪙ + m_event_count = el.size(); + m_trigger_type = AND_LIST; +} + +inline +void +sc_method_process::next_trigger( const sc_time& t ) +{ + clear_trigger(); + m_timeout_event_p->notify_internal( t ); + m_timeout_event_p->add_dynamic( this ); + m_trigger_type = TIMEOUT; +} + +inline +void +sc_method_process::next_trigger( const sc_time& t, const sc_event& e ) +{ + clear_trigger(); + m_timeout_event_p->notify_internal( t ); + m_timeout_event_p->add_dynamic( this ); + e.add_dynamic( this ); + m_event_p = &e; + m_trigger_type = EVENT_TIMEOUT; +} + +inline +void +sc_method_process::next_trigger( const sc_time& t, const sc_event_or_list& el ) +{ + clear_trigger(); + m_timeout_event_p->notify_internal( t ); + m_timeout_event_p->add_dynamic( this ); + el.add_dynamic( this ); + m_event_list_p = ⪙ + m_trigger_type = OR_LIST_TIMEOUT; +} + +inline +void +sc_method_process::next_trigger( const sc_time& t, const sc_event_and_list& el ) +{ + clear_trigger(); + m_timeout_event_p->notify_internal( t ); + m_timeout_event_p->add_dynamic( this ); + el.add_dynamic( this ); + m_event_list_p = ⪙ + m_event_count = el.size(); + m_trigger_type = AND_LIST_TIMEOUT; +} + +inline +void sc_method_process::set_next_exist(sc_method_handle next_p) +{ + m_exist_p = next_p; +} + +inline +sc_method_handle sc_method_process::next_exist() +{ + return (sc_method_handle)m_exist_p; +} + + +inline +void sc_method_process::set_next_runnable(sc_method_handle next_p) +{ + m_runnable_p = next_p; +} + +inline +sc_method_handle sc_method_process::next_runnable() +{ + return (sc_method_handle)m_runnable_p; +} + +// +---------------------------------------------------------------------------- +// |"sc_method_process::run_process" +// | +// | This method executes this object instance, including fielding exceptions. +// | +// | Result is false if an unfielded exception occurred, true if not. +// +---------------------------------------------------------------------------- +inline bool sc_method_process::run_process() +{ + // Execute this object instance's semantics and catch any exceptions that + // are generated: + + bool restart = false; + do { + try { + DEBUG_MSG(DEBUG_NAME,this,"executing method semantics"); + semantics(); + restart = false; + } + catch( sc_unwind_exception& ex ) { + DEBUG_MSG(DEBUG_NAME,this,"caught unwind exception"); + ex.clear(); + restart = ex.is_reset(); + } + catch( ... ) { + sc_report* err_p = sc_handle_exception(); + simcontext()->set_error( err_p ); + return false; + } + } while( restart ); + + return true; +} + +//------------------------------------------------------------------------------ +//"sc_method_process::trigger_static" +// +// This inline method adds the current method to the queue of runnable +// processes, if required. This is the case if the following criteria +// are met: +// (1) The process is in a runnable state. +// (2) The process is not already on the run queue. +// (3) The process is expecting a static trigger, +// dynamic event waits take priority. +// +// +// If the triggering process is the same process, the trigger is +// ignored as well, unless SC_ENABLE_IMMEDIATE_SELF_NOTIFICATIONS +// is defined. +//------------------------------------------------------------------------------ +inline +void +sc_method_process::trigger_static() +{ + if ( (m_state & ps_bit_disabled) || is_runnable() || + m_trigger_type != STATIC ) + return; + +#if ! defined( SC_ENABLE_IMMEDIATE_SELF_NOTIFICATIONS ) + if( SC_UNLIKELY_( sc_get_current_process_b() == this ) ) + { + report_immediate_self_notification(); + return; + } +#endif // SC_ENABLE_IMMEDIATE_SELF_NOTIFICATIONS + + // If we get here then the method is has satisfied its wait, if its + // suspended mark its state as ready to run. If its not suspended then + // push it onto the runnable queue. + + if ( m_state & ps_bit_suspended ) + { + m_state = m_state | ps_bit_ready_to_run; + } + else + { + simcontext()->push_runnable_method(this); + } +} + +#undef DEBUG_MSG + +} // namespace sc_core + +// Revision 1.20 2011/08/24 22:05:50 acg +// Torsten Maehne: initialization changes to remove warnings. +// +// Revision 1.19 2011/07/29 22:43:15 acg +// Andy Goodrich: addition of check_for_throws() method. +// +// Revision 1.18 2011/07/24 11:18:09 acg +// Philipp A. Hartmann: add code to restart a method process after a +// self-reset. +// +// Revision 1.17 2011/05/09 04:07:48 acg +// Philipp A. Hartmann: +// (1) Restore hierarchy in all phase callbacks. +// (2) Ensure calls to before_end_of_elaboration. +// +// Revision 1.16 2011/04/13 02:41:34 acg +// Andy Goodrich: eliminate warning messages generated when the DEBUG_MSG +// macro is used. +// +// Revision 1.15 2011/04/10 22:12:32 acg +// Andy Goodrich: adding debugging macros. +// +// Revision 1.14 2011/04/08 22:31:21 acg +// Andy Goodrich: added new inline method run_process() to hide the process +// implementation for sc_simcontext. +// +// Revision 1.13 2011/04/05 20:50:56 acg +// Andy Goodrich: +// (1) changes to make sure that event(), posedge() and negedge() only +// return true if the clock has not moved. +// (2) fixes for method self-resumes. +// (3) added SC_PRERELEASE_VERSION +// (4) removed kernel events from the object hierarchy, added +// sc_hierarchy_name_exists(). +// +// Revision 1.12 2011/04/01 21:24:57 acg +// Andy Goodrich: removed unused code. +// +// Revision 1.11 2011/02/19 08:30:53 acg +// Andy Goodrich: Moved process queueing into trigger_static from +// sc_event::notify. +// +// Revision 1.10 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.9 2011/02/17 19:51:34 acg +// Andy Goodrich: +// (1) Changed the signature of trigger_dynamic back to a bool. +// (2) Removed ready_to_run(). +// (3) Simplified process control usage. +// +// Revision 1.8 2011/02/16 22:37:30 acg +// Andy Goodrich: clean up to remove need for ps_disable_pending. +// +// Revision 1.7 2011/02/13 21:47:37 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.6 2011/02/01 21:05:05 acg +// Andy Goodrich: Changes in trigger_dynamic methods to handle new +// process control rules about event sensitivity. +// +// Revision 1.5 2011/01/18 20:10:44 acg +// Andy Goodrich: changes for IEEE1666_2011 semantics. +// +// Revision 1.4 2009/07/28 01:10:53 acg +// Andy Goodrich: updates for 2.3 release candidate. +// +// Revision 1.3 2009/05/22 16:06:29 acg +// Andy Goodrich: process control updates. +// +// Revision 1.2 2008/05/22 17:06:25 acg +// Andy Goodrich: updated copyright notice to include 2008. +// +// Revision 1.1.1.1 2006/12/15 20:20:05 acg +// SystemC 2.3 +// +// Revision 1.7 2006/05/08 17:57:13 acg +// Andy Goodrich: Added David Long's forward declarations for friend functions +// to keep the Microsoft C++ compiler happy. +// +// Revision 1.6 2006/04/20 17:08:17 acg +// Andy Goodrich: 3.0 style process changes. +// +// Revision 1.5 2006/04/11 23:13:21 acg +// Andy Goodrich: Changes for reduced reset support that only includes +// sc_cthread, but has preliminary hooks for expanding to method and thread +// processes also. +// +// Revision 1.4 2006/01/24 20:49:05 acg +// Andy Goodrich: changes to remove the use of deprecated features within the +// simulator, and to issue warning messages when deprecated features are used. +// +// Revision 1.3 2006/01/13 18:44:29 acg +// Added $Log to record CVS changes into the source. + +#endif // !defined(sc_method_process_h_INCLUDED) diff --git a/ext/systemc/src/sysc/kernel/sc_module.cpp b/ext/systemc/src/sysc/kernel/sc_module.cpp new file mode 100644 index 000000000..efca2a4dc --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_module.cpp @@ -0,0 +1,846 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_module.cpp -- Base class of all sequential and combinational processes. + + Original Author: Stan Y. Liao, Synopsys, Inc. + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + + +#include <cassert> +#include <math.h> +#include <stddef.h> +#include <stdio.h> + +#include "sysc/kernel/sc_event.h" +#include "sysc/kernel/sc_kernel_ids.h" +#include "sysc/kernel/sc_module.h" +#include "sysc/kernel/sc_module_registry.h" +#include "sysc/kernel/sc_name_gen.h" +#include "sysc/kernel/sc_object_manager.h" +#include "sysc/kernel/sc_process.h" +#include "sysc/kernel/sc_process_handle.h" +#include "sysc/kernel/sc_simcontext.h" +#include "sysc/kernel/sc_simcontext_int.h" +#include "sysc/kernel/sc_object_int.h" +#include "sysc/kernel/sc_reset.h" +#include "sysc/communication/sc_communication_ids.h" +#include "sysc/communication/sc_interface.h" +#include "sysc/communication/sc_port.h" +#include "sysc/communication/sc_signal.h" +#include "sysc/communication/sc_signal_ports.h" +#include "sysc/utils/sc_utils_ids.h" +#include "sysc/utils/sc_iostream.h" + +namespace sc_core { + +// ---------------------------------------------------------------------------- +// CLASS : sc_module_dynalloc_list +// +// Garbage collection for modules dynamically allocated with SC_NEW. +// ---------------------------------------------------------------------------- + +class sc_module_dynalloc_list +{ +public: + + sc_module_dynalloc_list() : m_list() + {} + + ~sc_module_dynalloc_list(); + + void add( sc_module* p ) + { m_list.push_back( p ); } + +private: + + sc_plist<sc_module*> m_list; +}; + + +//------------------------------------------------------------------------------ +//"~sc_module_dynalloc_list" +// +// Note we clear the m_parent field for the module being deleted. This because +// we process the list front to back so the parent has already been deleted, +// and we don't want ~sc_object() to try to access the parent which may +// contain garbage. +//------------------------------------------------------------------------------ +sc_module_dynalloc_list::~sc_module_dynalloc_list() +{ + sc_plist<sc_module*>::iterator it( m_list ); + while( ! it.empty() ) { + (*it)->m_parent = 0; + delete *it; + it ++; + } +} + + +// ---------------------------------------------------------------------------- + +sc_module* +sc_module_dynalloc( sc_module* module_ ) +{ + static sc_module_dynalloc_list dynalloc_list; + dynalloc_list.add( module_ ); + return module_; +} + + +// ---------------------------------------------------------------------------- +// STRUCT : sc_bind_proxy +// +// Struct for temporarily storing a pointer to an interface or port. +// Used for positional binding. +// ---------------------------------------------------------------------------- + +sc_bind_proxy::sc_bind_proxy() +: iface( 0 ), + port( 0 ) +{} + +sc_bind_proxy::sc_bind_proxy( sc_interface& iface_ ) +: iface( &iface_ ), + port( 0 ) +{} + +sc_bind_proxy::sc_bind_proxy( sc_port_base& port_ ) +: iface( 0 ), + port( &port_ ) +{} + + +const sc_bind_proxy SC_BIND_PROXY_NIL; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_module +// +// Base class for all structural entities. +// ---------------------------------------------------------------------------- + +void +sc_module::sc_module_init() +{ + simcontext()->get_module_registry()->insert( *this ); + simcontext()->hierarchy_push( this ); + m_end_module_called = false; + m_module_name_p = 0; + m_port_vec = new std::vector<sc_port_base*>; + m_port_index = 0; + m_name_gen = new sc_name_gen; +} + +/* + * This form of the constructor assumes that the user has + * used an sc_module_name parameter for his/her constructor. + * That parameter object has been pushed onto the stack, + * and can be looked up by calling the + * top_of_module_name_stack() function of the object manager. + * This technique has two advantages: + * + * 1) The user no longer has to write sc_module(name) in the + * constructor initializer. + * 2) The user no longer has to call end_module() at the end + * of the constructor -- a common negligence. + * + * But it is important to note that sc_module_name may be used + * in the user's constructor's parameter. If it is used anywhere + * else, unexpected things will happen. The error-checking + * mechanism builtin here cannot hope to catch all misuses. + * + */ + +sc_module::sc_module() +: sc_object(::sc_core::sc_get_curr_simcontext() + ->get_object_manager() + ->top_of_module_name_stack() + ->operator const char*()), + sensitive(this), + sensitive_pos(this), + sensitive_neg(this), + m_end_module_called(false), + m_port_vec(), + m_port_index(0), + m_name_gen(0), + m_module_name_p(0) +{ + /* When this form is used, we better have a fresh sc_module_name + on the top of the stack */ + sc_module_name* mod_name = + simcontext()->get_object_manager()->top_of_module_name_stack(); + if (0 == mod_name || 0 != mod_name->m_module_p) + SC_REPORT_ERROR( SC_ID_SC_MODULE_NAME_REQUIRED_, 0 ); + sc_module_init(); + mod_name->set_module( this ); + m_module_name_p = mod_name; // must come after sc_module_init call. +} + +sc_module::sc_module( const sc_module_name& ) +: sc_object(::sc_core::sc_get_curr_simcontext() + ->get_object_manager() + ->top_of_module_name_stack() + ->operator const char*()), + sensitive(this), + sensitive_pos(this), + sensitive_neg(this), + m_end_module_called(false), + m_port_vec(), + m_port_index(0), + m_name_gen(0), + m_module_name_p(0) +{ + /* For those used to the old style of passing a name to sc_module, + this constructor will reduce the chance of making a mistake */ + + /* When this form is used, we better have a fresh sc_module_name + on the top of the stack */ + sc_module_name* mod_name = + simcontext()->get_object_manager()->top_of_module_name_stack(); + if (0 == mod_name || 0 != mod_name->m_module_p) + SC_REPORT_ERROR( SC_ID_SC_MODULE_NAME_REQUIRED_, 0 ); + sc_module_init(); + mod_name->set_module( this ); + m_module_name_p = mod_name; // must come after sc_module_init call. +} + +/* -------------------------------------------------------------------- + * + * Deprecated constructors: + * sc_module( const char* ) + * sc_module( const std::string& ) + */ +sc_module::sc_module( const char* nm ) +: sc_object(nm), + sensitive(this), + sensitive_pos(this), + sensitive_neg(this), + m_end_module_called(false), + m_port_vec(), + m_port_index(0), + m_name_gen(0), + m_module_name_p(0) +{ + SC_REPORT_WARNING( SC_ID_BAD_SC_MODULE_CONSTRUCTOR_, nm ); + sc_module_init(); +} + +sc_module::sc_module( const std::string& s ) +: sc_object( s.c_str() ), + sensitive(this), + sensitive_pos(this), + sensitive_neg(this), + m_end_module_called(false), + m_port_vec(), + m_port_index(0), + m_name_gen(0), + m_module_name_p(0) +{ + SC_REPORT_WARNING( SC_ID_BAD_SC_MODULE_CONSTRUCTOR_, s.c_str() ); + sc_module_init(); +} + +/* -------------------------------------------------------------------- */ + +sc_module::~sc_module() +{ + delete m_port_vec; + delete m_name_gen; + orphan_child_objects(); + if ( m_module_name_p ) + { + m_module_name_p->clear_module( this ); // must be before end_module() + end_module(); + } + simcontext()->get_module_registry()->remove( *this ); +} + + +const ::std::vector<sc_object*>& +sc_module::get_child_objects() const +{ + return m_child_objects; +} + +// set SC_THREAD asynchronous reset sensitivity + +void +sc_module::async_reset_signal_is( const sc_in<bool>& port, bool level ) +{ + sc_reset::reset_signal_is(true, port, level); +} + +void +sc_module::async_reset_signal_is( const sc_inout<bool>& port, bool level ) +{ + sc_reset::reset_signal_is(true, port, level); +} + +void +sc_module::async_reset_signal_is( const sc_out<bool>& port, bool level ) +{ + sc_reset::reset_signal_is(true, port, level); +} + +void +sc_module::async_reset_signal_is(const sc_signal_in_if<bool>& iface, bool level) +{ + sc_reset::reset_signal_is(true, iface, level); +} + +void +sc_module::end_module() +{ + if( ! m_end_module_called ) { + /* TBD: Can check here to alert the user that end_module + was not called for a previous module. */ + (void)sc_get_curr_simcontext()->hierarchy_pop(); + sc_get_curr_simcontext()->reset_curr_proc(); + sensitive.reset(); + sensitive_pos.reset(); + sensitive_neg.reset(); + m_end_module_called = true; + m_module_name_p = 0; // make sure we are not called in ~sc_module(). + } +} + + +// to prevent initialization for SC_METHODs and SC_THREADs + +void +sc_module::dont_initialize() +{ + sc_process_handle last_proc = sc_get_last_created_process_handle(); + last_proc.dont_initialize( true ); +} + +// set SC_THREAD synchronous reset sensitivity + +void +sc_module::reset_signal_is( const sc_in<bool>& port, bool level ) +{ + sc_reset::reset_signal_is(false, port, level); +} + +void +sc_module::reset_signal_is( const sc_inout<bool>& port, bool level ) +{ + sc_reset::reset_signal_is(false, port, level); +} + +void +sc_module::reset_signal_is( const sc_out<bool>& port, bool level ) +{ + sc_reset::reset_signal_is(false, port, level); +} + +void +sc_module::reset_signal_is( const sc_signal_in_if<bool>& iface, bool level ) +{ + sc_reset::reset_signal_is(false, iface, level); +} + +// to generate unique names for objects in an MT-Safe way + +const char* +sc_module::gen_unique_name( const char* basename_, bool preserve_first ) +{ + return m_name_gen->gen_unique_name( basename_, preserve_first ); +} + + +// called by construction_done + +void +sc_module::before_end_of_elaboration() +{} + +// We push the sc_module instance onto the stack of open objects so +// that any objects that are created in before_end_of_elaboration have +// the proper parent. After the call we pop the hierarchy. +void +sc_module::construction_done() +{ + hierarchy_scope scope(this); + before_end_of_elaboration(); +} + +// called by elaboration_done (does nothing by default) + +void +sc_module::end_of_elaboration() +{} + + +// We push the sc_module instance onto the stack of open objects so +// that any objects that are created in end_of_elaboration have +// the proper parent. After the call we pop the hierarchy. +void +sc_module::elaboration_done( bool& error_ ) +{ + if( ! m_end_module_called ) { + char msg[BUFSIZ]; + std::sprintf( msg, "module '%s'", name() ); + SC_REPORT_WARNING( SC_ID_END_MODULE_NOT_CALLED_, msg ); + if( error_ ) { + SC_REPORT_WARNING( SC_ID_HIER_NAME_INCORRECT_, 0 ); + } + error_ = true; + } + hierarchy_scope scope(this); + end_of_elaboration(); +} + +// called by start_simulation (does nothing by default) + +void +sc_module::start_of_simulation() +{} + +void +sc_module::start_simulation() +{ + hierarchy_scope scope(this); + start_of_simulation(); +} + +// called by simulation_done (does nothing by default) + +void +sc_module::end_of_simulation() +{} + +void +sc_module::simulation_done() +{ + hierarchy_scope scope(this); + end_of_simulation(); +} + +void +sc_module::set_stack_size( std::size_t size ) +{ + sc_process_handle proc_h( + sc_is_running() ? + sc_get_current_process_handle() : + sc_get_last_created_process_handle() + ); + sc_thread_handle thread_h; // Current process as thread. + + + thread_h = (sc_thread_handle)proc_h; + if ( thread_h ) + { + thread_h->set_stack_size( size ); + } + else + { + SC_REPORT_WARNING( SC_ID_SET_STACK_SIZE_, 0 ); + } +} + + +int +sc_module::append_port( sc_port_base* port_ ) +{ + int index = m_port_vec->size(); + m_port_vec->push_back( port_ ); + return index; +} + + +// positional binding methods + +static void sc_warn_arrow_arrow_bind() +{ + static bool warn_arrow_arrow_bind=true; + if ( warn_arrow_arrow_bind ) + { + warn_arrow_arrow_bind = false; + SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, + "positional binding using << or , is deprecated, use () instead."); + } +} + +sc_module& +sc_module::operator << ( sc_interface& interface_ ) +{ + sc_warn_arrow_arrow_bind(); + positional_bind(interface_); + return *this; +} + +sc_module& +sc_module::operator << ( sc_port_base& port_ ) +{ + sc_warn_arrow_arrow_bind(); + positional_bind(port_); + return *this; +} + + +void +sc_module::positional_bind( sc_interface& interface_ ) +{ + if( m_port_index == (int)m_port_vec->size() ) { + char msg[BUFSIZ]; + if( m_port_index == 0 ) { + std::sprintf( msg, "module `%s' has no ports", name() ); + } else { + std::sprintf( msg, "all ports of module `%s' are bound", name() ); + } + SC_REPORT_ERROR( SC_ID_BIND_IF_TO_PORT_, msg ); + } + int status = (*m_port_vec)[m_port_index]->pbind( interface_ ); + if( status != 0 ) { + char msg[BUFSIZ]; + switch( status ) { + case 1: + std::sprintf( msg, "port %d of module `%s' is already bound", + m_port_index, name() ); + break; + case 2: + std::sprintf( msg, "type mismatch on port %d of module `%s'", + m_port_index, name() ); + break; + default: + std::sprintf( msg, "unknown error" ); + break; + } + SC_REPORT_ERROR( SC_ID_BIND_IF_TO_PORT_, msg ); + } + ++ m_port_index; +} + +void +sc_module::positional_bind( sc_port_base& port_ ) +{ + if( m_port_index == (int)m_port_vec->size() ) { + char msg[BUFSIZ]; + if( m_port_index == 0 ) { + std::sprintf( msg, "module `%s' has no ports", name() ); + } else { + std::sprintf( msg, "all ports of module `%s' are bound", name() ); + } + SC_REPORT_ERROR( SC_ID_BIND_PORT_TO_PORT_, msg ); + } + int status = (*m_port_vec)[m_port_index]->pbind( port_ ); + if( status != 0 ) { + char msg[BUFSIZ]; + switch( status ) { + case 1: + std::sprintf( msg, "port %d of module `%s' is already bound", + m_port_index, name() ); + break; + case 2: + std::sprintf( msg, "type mismatch on port %d of module `%s'", + m_port_index, name() ); + break; + default: + std::sprintf( msg, "unknown error" ); + break; + } + SC_REPORT_ERROR( SC_ID_BIND_PORT_TO_PORT_, msg ); + } + ++ m_port_index; +} + + +#define TRY_BIND( p ) \ + if( (p).iface != 0 ) { \ + positional_bind( *(p).iface ); \ + } else if( (p).port != 0 ) { \ + positional_bind( *(p).port ); \ + } else { \ + return; \ + } + + +void +sc_module::operator () ( const sc_bind_proxy& p001, + const sc_bind_proxy& p002, + const sc_bind_proxy& p003, + const sc_bind_proxy& p004, + const sc_bind_proxy& p005, + const sc_bind_proxy& p006, + const sc_bind_proxy& p007, + const sc_bind_proxy& p008, + const sc_bind_proxy& p009, + const sc_bind_proxy& p010, + const sc_bind_proxy& p011, + const sc_bind_proxy& p012, + const sc_bind_proxy& p013, + const sc_bind_proxy& p014, + const sc_bind_proxy& p015, + const sc_bind_proxy& p016, + const sc_bind_proxy& p017, + const sc_bind_proxy& p018, + const sc_bind_proxy& p019, + const sc_bind_proxy& p020, + const sc_bind_proxy& p021, + const sc_bind_proxy& p022, + const sc_bind_proxy& p023, + const sc_bind_proxy& p024, + const sc_bind_proxy& p025, + const sc_bind_proxy& p026, + const sc_bind_proxy& p027, + const sc_bind_proxy& p028, + const sc_bind_proxy& p029, + const sc_bind_proxy& p030, + const sc_bind_proxy& p031, + const sc_bind_proxy& p032, + const sc_bind_proxy& p033, + const sc_bind_proxy& p034, + const sc_bind_proxy& p035, + const sc_bind_proxy& p036, + const sc_bind_proxy& p037, + const sc_bind_proxy& p038, + const sc_bind_proxy& p039, + const sc_bind_proxy& p040, + const sc_bind_proxy& p041, + const sc_bind_proxy& p042, + const sc_bind_proxy& p043, + const sc_bind_proxy& p044, + const sc_bind_proxy& p045, + const sc_bind_proxy& p046, + const sc_bind_proxy& p047, + const sc_bind_proxy& p048, + const sc_bind_proxy& p049, + const sc_bind_proxy& p050, + const sc_bind_proxy& p051, + const sc_bind_proxy& p052, + const sc_bind_proxy& p053, + const sc_bind_proxy& p054, + const sc_bind_proxy& p055, + const sc_bind_proxy& p056, + const sc_bind_proxy& p057, + const sc_bind_proxy& p058, + const sc_bind_proxy& p059, + const sc_bind_proxy& p060, + const sc_bind_proxy& p061, + const sc_bind_proxy& p062, + const sc_bind_proxy& p063, + const sc_bind_proxy& p064 ) +{ + static bool warn_only_once=true; + if ( m_port_index > 0 && warn_only_once ) + { + warn_only_once = false; + SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, + "multiple () binding deprecated, use explicit port binding instead." ); + } + + TRY_BIND( p001 ); + TRY_BIND( p002 ); + TRY_BIND( p003 ); + TRY_BIND( p004 ); + TRY_BIND( p005 ); + TRY_BIND( p006 ); + TRY_BIND( p007 ); + TRY_BIND( p008 ); + TRY_BIND( p009 ); + TRY_BIND( p010 ); + TRY_BIND( p011 ); + TRY_BIND( p012 ); + TRY_BIND( p013 ); + TRY_BIND( p014 ); + TRY_BIND( p015 ); + TRY_BIND( p016 ); + TRY_BIND( p017 ); + TRY_BIND( p018 ); + TRY_BIND( p019 ); + TRY_BIND( p020 ); + TRY_BIND( p021 ); + TRY_BIND( p022 ); + TRY_BIND( p023 ); + TRY_BIND( p024 ); + TRY_BIND( p025 ); + TRY_BIND( p026 ); + TRY_BIND( p027 ); + TRY_BIND( p028 ); + TRY_BIND( p029 ); + TRY_BIND( p030 ); + TRY_BIND( p031 ); + TRY_BIND( p032 ); + TRY_BIND( p033 ); + TRY_BIND( p034 ); + TRY_BIND( p035 ); + TRY_BIND( p036 ); + TRY_BIND( p037 ); + TRY_BIND( p038 ); + TRY_BIND( p039 ); + TRY_BIND( p040 ); + TRY_BIND( p041 ); + TRY_BIND( p042 ); + TRY_BIND( p043 ); + TRY_BIND( p044 ); + TRY_BIND( p045 ); + TRY_BIND( p046 ); + TRY_BIND( p047 ); + TRY_BIND( p048 ); + TRY_BIND( p049 ); + TRY_BIND( p050 ); + TRY_BIND( p051 ); + TRY_BIND( p052 ); + TRY_BIND( p053 ); + TRY_BIND( p054 ); + TRY_BIND( p055 ); + TRY_BIND( p056 ); + TRY_BIND( p057 ); + TRY_BIND( p058 ); + TRY_BIND( p059 ); + TRY_BIND( p060 ); + TRY_BIND( p061 ); + TRY_BIND( p062 ); + TRY_BIND( p063 ); + TRY_BIND( p064 ); +} + +} // namespace sc_core + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: Ali Dasdan, Synopsys, Inc. + Description of Modification: - Implementation of operator() and operator, + positional connection method. + - Implementation of error checking in + operator<<'s. + - Implementation of the function test_module_prm. + - Implementation of set_stack_size(). + + Name, Affiliation, Date: Andy Goodrich, Forte Design Systems 20 May 2003 + Description of Modification: Inherit from sc_process_host + + Name, Affiliation, Date: Bishnupriya Bhattacharya, Cadence Design Systems, + 25 August, 2003 + Description of Modification: dont_initialize() uses + sc_get_last_created_process_handle() instead of + sc_get_current_process_b() + + Name, Affiliation, Date: Andy Goodrich, Forte Design Systems 25 Mar 2003 + Description of Modification: Fixed bug in SC_NEW, see comments on + ~sc_module_dynalloc_list below. + + + *****************************************************************************/ + + +// $Log: sc_module.cpp,v $ +// Revision 1.14 2011/08/29 18:04:32 acg +// Philipp A. Hartmann: miscellaneous clean ups. +// +// Revision 1.13 2011/08/26 20:46:10 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +// Revision 1.12 2011/08/24 22:05:51 acg +// Torsten Maehne: initialization changes to remove warnings. +// +// Revision 1.11 2011/03/05 19:44:20 acg +// Andy Goodrich: changes for object and event naming and structures. +// +// Revision 1.10 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.9 2011/02/16 22:37:30 acg +// Andy Goodrich: clean up to remove need for ps_disable_pending. +// +// Revision 1.8 2011/02/14 17:51:40 acg +// Andy Goodrich: proper pushing an poppping of the module hierarchy for +// start_of_simulation() and end_of_simulation. +// +// Revision 1.7 2011/02/13 21:47:37 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.6 2011/01/25 20:50:37 acg +// Andy Goodrich: changes for IEEE 1666 2011. +// +// Revision 1.5 2009/05/22 16:06:29 acg +// Andy Goodrich: process control updates. +// +// Revision 1.4 2008/11/17 15:57:15 acg +// Andy Goodrich: added deprecation message for sc_module(const char*) +// +// Revision 1.3 2008/05/22 17:06:25 acg +// Andy Goodrich: updated copyright notice to include 2008. +// +// Revision 1.2 2007/05/17 20:16:33 acg +// Andy Goodrich: changes for beta release to LWG. +// +// Revision 1.1.1.1 2006/12/15 20:20:05 acg +// SystemC 2.3 +// +// Revision 1.9 2006/12/02 20:58:18 acg +// Andy Goodrich: updates from 2.2 for IEEE 1666 support. +// +// Revision 1.8 2006/03/21 00:00:34 acg +// Andy Goodrich: changed name of sc_get_current_process_base() to be +// sc_get_current_process_b() since its returning an sc_process_b instance. +// +// Revision 1.7 2006/03/14 23:56:58 acg +// Andy Goodrich: This fixes a bug when an exception is thrown in +// sc_module::sc_module() for a dynamically allocated sc_module +// object. We are calling sc_module::end_module() on a module that has +// already been deleted. The scenario runs like this: +// +// a) the sc_module constructor is entered +// b) the exception is thrown +// c) the exception processor deletes the storage for the sc_module +// d) the stack is unrolled causing the sc_module_name instance to be deleted +// e) ~sc_module_name() calls end_module() with its pointer to the sc_module +// f) because the sc_module has been deleted its storage is corrupted, +// either by linking it to a free space chain, or by reuse of some sort +// g) the m_simc field is garbage +// h) the m_object_manager field is also garbage +// i) an exception occurs +// +// This does not happen for automatic sc_module instances since the +// storage for the module is not reclaimed its just part of the stack. +// +// I am fixing this by having the destructor for sc_module clear the +// module pointer in its sc_module_name instance. That cuts things at +// step (e) above, since the pointer will be null if the module has +// already been deleted. To make sure the module stack is okay, I call +// end-module() in ~sc_module in the case where there is an +// sc_module_name pointer lying around. +// +// Revision 1.6 2006/01/26 21:04:54 acg +// Andy Goodrich: deprecation message changes and additional messages. +// +// Revision 1.5 2006/01/25 00:31:19 acg +// Andy Goodrich: Changed over to use a standard message id of +// SC_ID_IEEE_1666_DEPRECATION for all deprecation messages. +// +// Revision 1.4 2006/01/24 20:49:05 acg +// Andy Goodrich: changes to remove the use of deprecated features within the +// simulator, and to issue warning messages when deprecated features are used. +// +// Revision 1.3 2006/01/13 18:44:29 acg +// Added $Log to record CVS changes into the source. +// + +// Taf! diff --git a/ext/systemc/src/sysc/kernel/sc_module.h b/ext/systemc/src/sysc/kernel/sc_module.h new file mode 100644 index 000000000..8a68cb049 --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_module.h @@ -0,0 +1,583 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_module.h -- Base class of all hierarchical modules and channels. + + Original Author: Stan Y. Liao, Synopsys, Inc. + Martin Janssen, Synopsys, Inc. + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + + +#ifndef SC_MODULE_H +#define SC_MODULE_H + +#include "sysc/kernel/sc_kernel_ids.h" +#include "sysc/kernel/sc_process.h" +#include "sysc/kernel/sc_module_name.h" +#include "sysc/kernel/sc_sensitive.h" +#include "sysc/kernel/sc_time.h" +#include "sysc/kernel/sc_wait.h" +#include "sysc/kernel/sc_wait_cthread.h" +#include "sysc/kernel/sc_process.h" +#include "sysc/kernel/sc_process_handle.h" +#include "sysc/utils/sc_list.h" + +namespace sc_core { + +class sc_name_gen; +template<class T> class sc_in; +template<class T> class sc_inout; +template<class T> class sc_out; + +// ---------------------------------------------------------------------------- +// STRUCT : sc_bind_proxy +// +// Struct for temporarily storing a pointer to an interface or port. +// Used for positional binding. +// ---------------------------------------------------------------------------- + +struct sc_bind_proxy +{ + sc_interface* iface; + sc_port_base* port; + + sc_bind_proxy(); + sc_bind_proxy( sc_interface& ); + sc_bind_proxy( sc_port_base& ); +}; + + +extern const sc_bind_proxy SC_BIND_PROXY_NIL; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_module +// +// Base class for all structural entities. +// ---------------------------------------------------------------------------- + +class sc_module +: public sc_object, public sc_process_host +{ + friend class sc_module_name; + friend class sc_module_registry; + friend class sc_object; + friend class sc_port_registry; + friend class sc_process_b; + friend class sc_simcontext; + +public: + + sc_simcontext* sc_get_curr_simcontext() + { return simcontext(); } + + // to generate unique names for objects in an MT-Safe way + const char* gen_unique_name( const char* basename_, bool preserve_first ); + + virtual const char* kind() const + { return "sc_module"; } + +protected: + + // called by construction_done + virtual void before_end_of_elaboration(); + + void construction_done(); + + // called by elaboration_done (does nothing by default) + virtual void end_of_elaboration(); + + void elaboration_done( bool& ); + + // called by start_simulation (does nothing by default) + virtual void start_of_simulation(); + + void start_simulation(); + + // called by simulation_done (does nothing by default) + virtual void end_of_simulation(); + + void simulation_done(); + + void sc_module_init(); + + // constructor + sc_module(); + sc_module( const sc_module_name& nm ); /* for those used to old style */ + + /* DEPRECATED */ sc_module( const char* nm ); + /* DEPRECATED */ sc_module( const std::string& nm ); + +public: + + // destructor + virtual ~sc_module(); + + // positional binding methods + + sc_module& operator << ( sc_interface& ); + sc_module& operator << ( sc_port_base& ); + + sc_module& operator , ( sc_interface& interface_ ) + { return operator << ( interface_ ); } + + sc_module& operator , ( sc_port_base& port_ ) + { return operator << ( port_ ); } + + // operator() is declared at the end of the class. + + const ::std::vector<sc_object*>& get_child_objects() const; + +protected: + + // this must be called by user-defined modules + void end_module(); + + + // to prevent initialization for SC_METHODs and SC_THREADs + void dont_initialize(); + + // positional binding code - used by operator () + + void positional_bind( sc_interface& ); + void positional_bind( sc_port_base& ); + + // set reset sensitivity for SC_xTHREADs + void async_reset_signal_is( const sc_in<bool>& port, bool level ); + void async_reset_signal_is( const sc_inout<bool>& port, bool level ); + void async_reset_signal_is( const sc_out<bool>& port, bool level ); + void async_reset_signal_is( const sc_signal_in_if<bool>& iface, bool level); + void reset_signal_is( const sc_in<bool>& port, bool level ); + void reset_signal_is( const sc_inout<bool>& port, bool level ); + void reset_signal_is( const sc_out<bool>& port, bool level ); + void reset_signal_is( const sc_signal_in_if<bool>& iface, bool level ); + + // static sensitivity for SC_THREADs and SC_CTHREADs + + void wait() + { ::sc_core::wait( simcontext() ); } + + // dynamic sensitivity for SC_THREADs and SC_CTHREADs + + void wait( const sc_event& e ) + { ::sc_core::wait( e, simcontext() ); } + + void wait( const sc_event_or_list& el ) + { ::sc_core::wait( el, simcontext() ); } + + void wait( const sc_event_and_list& el ) + { ::sc_core::wait( el, simcontext() ); } + + void wait( const sc_time& t ) + { ::sc_core::wait( t, simcontext() ); } + + void wait( double v, sc_time_unit tu ) + { ::sc_core::wait( sc_time( v, tu, simcontext() ), simcontext() ); } + + void wait( const sc_time& t, const sc_event& e ) + { ::sc_core::wait( t, e, simcontext() ); } + + void wait( double v, sc_time_unit tu, const sc_event& e ) + { ::sc_core::wait( + sc_time( v, tu, simcontext() ), e, simcontext() ); } + + void wait( const sc_time& t, const sc_event_or_list& el ) + { ::sc_core::wait( t, el, simcontext() ); } + + void wait( double v, sc_time_unit tu, const sc_event_or_list& el ) + { ::sc_core::wait( sc_time( v, tu, simcontext() ), el, simcontext() ); } + + void wait( const sc_time& t, const sc_event_and_list& el ) + { ::sc_core::wait( t, el, simcontext() ); } + + void wait( double v, sc_time_unit tu, const sc_event_and_list& el ) + { ::sc_core::wait( sc_time( v, tu, simcontext() ), el, simcontext() ); } + + + // static sensitivity for SC_METHODs + + void next_trigger() + { ::sc_core::next_trigger( simcontext() ); } + + + // dynamic sensitivty for SC_METHODs + + void next_trigger( const sc_event& e ) + { ::sc_core::next_trigger( e, simcontext() ); } + + void next_trigger( const sc_event_or_list& el ) + { ::sc_core::next_trigger( el, simcontext() ); } + + void next_trigger( const sc_event_and_list& el ) + { ::sc_core::next_trigger( el, simcontext() ); } + + void next_trigger( const sc_time& t ) + { ::sc_core::next_trigger( t, simcontext() ); } + + void next_trigger( double v, sc_time_unit tu ) + { ::sc_core::next_trigger( + sc_time( v, tu, simcontext() ), simcontext() ); } + + void next_trigger( const sc_time& t, const sc_event& e ) + { ::sc_core::next_trigger( t, e, simcontext() ); } + + void next_trigger( double v, sc_time_unit tu, const sc_event& e ) + { ::sc_core::next_trigger( + sc_time( v, tu, simcontext() ), e, simcontext() ); } + + void next_trigger( const sc_time& t, const sc_event_or_list& el ) + { ::sc_core::next_trigger( t, el, simcontext() ); } + + void next_trigger( double v, sc_time_unit tu, const sc_event_or_list& el ) + { ::sc_core::next_trigger( + sc_time( v, tu, simcontext() ), el, simcontext() ); } + + void next_trigger( const sc_time& t, const sc_event_and_list& el ) + { ::sc_core::next_trigger( t, el, simcontext() ); } + + void next_trigger( double v, sc_time_unit tu, const sc_event_and_list& el ) + { ::sc_core::next_trigger( + sc_time( v, tu, simcontext() ), el, simcontext() ); } + + + // for SC_METHODs and SC_THREADs and SC_CTHREADs + + bool timed_out() + { return ::sc_core::timed_out(); } + + + // for SC_CTHREADs + + void halt() + { ::sc_core::halt( simcontext() ); } + + void wait( int n ) + { ::sc_core::wait( n, simcontext() ); } + + void at_posedge( const sc_signal_in_if<bool>& s ) + { ::sc_core::at_posedge( s, simcontext() ); } + + void at_posedge( const sc_signal_in_if<sc_dt::sc_logic>& s ) + { ::sc_core::at_posedge( s, simcontext() ); } + + void at_negedge( const sc_signal_in_if<bool>& s ) + { ::sc_core::at_negedge( s, simcontext() ); } + + void at_negedge( const sc_signal_in_if<sc_dt::sc_logic>& s ) + { ::sc_core::at_negedge( s, simcontext() ); } + + // Catch uses of watching: + void watching( bool /* expr */ ) + { SC_REPORT_ERROR(SC_ID_WATCHING_NOT_ALLOWED_,""); } + + // These are protected so that user derived classes can refer to them. + sc_sensitive sensitive; + sc_sensitive_pos sensitive_pos; + sc_sensitive_neg sensitive_neg; + + // Function to set the stack size of the current (c)thread process. + void set_stack_size( std::size_t ); + + int append_port( sc_port_base* ); + +private: + sc_module( const sc_module& ); + const sc_module& operator = ( const sc_module& ); + +private: + + bool m_end_module_called; + std::vector<sc_port_base*>* m_port_vec; + int m_port_index; + sc_name_gen* m_name_gen; + sc_module_name* m_module_name_p; + +public: + + void defunct() { } + + // positional binding methods (cont'd) + + void operator () ( const sc_bind_proxy& p001, + const sc_bind_proxy& p002 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p003 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p004 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p005 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p006 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p007 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p008 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p009 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p010 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p011 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p012 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p013 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p014 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p015 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p016 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p017 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p018 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p019 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p020 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p021 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p022 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p023 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p024 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p025 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p026 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p027 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p028 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p029 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p030 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p031 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p032 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p033 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p034 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p035 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p036 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p037 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p038 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p039 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p040 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p041 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p042 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p043 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p044 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p045 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p046 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p047 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p048 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p049 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p050 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p051 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p052 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p053 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p054 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p055 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p056 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p057 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p058 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p059 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p060 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p061 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p062 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p063 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p064 = SC_BIND_PROXY_NIL ); + +}; + +extern sc_module* sc_module_dynalloc(sc_module*); +#define SC_NEW(x) ::sc_core::sc_module_dynalloc(new x); + + +// ----------------------------------------------------------------------------- +// SOME MACROS TO SIMPLIFY SYNTAX: +// ----------------------------------------------------------------------------- + +#define SC_MODULE(user_module_name) \ + struct user_module_name : ::sc_core::sc_module + +#define SC_CTOR(user_module_name) \ + typedef user_module_name SC_CURRENT_USER_MODULE; \ + user_module_name( ::sc_core::sc_module_name ) + +// the SC_HAS_PROCESS macro call must be followed by a ; +#define SC_HAS_PROCESS(user_module_name) \ + typedef user_module_name SC_CURRENT_USER_MODULE + +// The this-> construct on sensitive operators in the macros below is +// required for gcc 4.x when a templated class has a templated parent that is +// derived from sc_module: +// +// template<typename X> +// class B : public sc_module; +// template<typename X> +// class A : public B<X> + +#define declare_method_process(handle, name, host_tag, func) \ + { \ + ::sc_core::sc_process_handle handle = \ + sc_core::sc_get_curr_simcontext()->create_method_process( \ + name, false, SC_MAKE_FUNC_PTR( host_tag, func ), \ + this, 0 ); \ + this->sensitive << handle; \ + this->sensitive_pos << handle; \ + this->sensitive_neg << handle; \ + } + +#define declare_thread_process(handle, name, host_tag, func) \ + { \ + ::sc_core::sc_process_handle handle = \ + sc_core::sc_get_curr_simcontext()->create_thread_process( \ + name, false, \ + SC_MAKE_FUNC_PTR( host_tag, func ), this, 0 ); \ + this->sensitive << handle; \ + this->sensitive_pos << handle; \ + this->sensitive_neg << handle; \ + } + +#define declare_cthread_process(handle, name, host_tag, func, edge) \ + { \ + ::sc_core::sc_process_handle handle = \ + sc_core::sc_get_curr_simcontext()->create_cthread_process( \ + name, false, \ + SC_MAKE_FUNC_PTR( host_tag, func ), this, 0 ); \ + this->sensitive.operator() ( handle, edge );\ + } + +#define SC_CTHREAD(func, edge) \ + declare_cthread_process( func ## _handle, \ + #func, \ + SC_CURRENT_USER_MODULE, \ + func, \ + edge ) + +#define SC_METHOD(func) \ + declare_method_process( func ## _handle, \ + #func, \ + SC_CURRENT_USER_MODULE, \ + func ) + +#define SC_THREAD(func) \ + declare_thread_process( func ## _handle, \ + #func, \ + SC_CURRENT_USER_MODULE, \ + func ) + + + +// ---------------------------------------------------------------------------- +// TYPEDEFS +// ---------------------------------------------------------------------------- + +typedef sc_module sc_channel; +typedef sc_module sc_behavior; + +} // namespace sc_core + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: Ali Dasdan, Synopsys, Inc. + Description of Modification: - Implementation of operator() and operator, + positional connection method. + - Implementation of error checking in + operator<<'s. + - Implementation of the function test_module_prm. + - Implementation of set_stack_size(). + + Name, Affiliation, Date: Gene Bushuyev, Synopsys, Inc. + Description of Modification: - Change implementation for VC6. + + Name, Affiliation, Date: Andy Godorich, Forte + Bishnupriya Bhattacharya, Cadence Design Systems, + 25 August, 2003 + Description of Modification: inherit from sc_process_host as a part of + implementing dynamic processes + + *****************************************************************************/ + +// $Log: sc_module.h,v $ +// Revision 1.11 2011/08/26 20:46:10 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +// Revision 1.10 2011/08/15 16:43:24 acg +// Torsten Maehne: changes to remove unused argument warnings. +// +// Revision 1.9 2011/03/05 19:44:20 acg +// Andy Goodrich: changes for object and event naming and structures. +// +// Revision 1.8 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.7 2011/02/13 21:47:37 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.6 2011/01/18 20:10:44 acg +// Andy Goodrich: changes for IEEE1666_2011 semantics. +// +// Revision 1.5 2010/12/07 20:09:12 acg +// Andy Goodrich: remove unused signal declaration +// +// Revision 1.4 2009/05/22 16:06:29 acg +// Andy Goodrich: process control updates. +// +// Revision 1.3 2008/05/22 17:06:25 acg +// Andy Goodrich: updated copyright notice to include 2008. +// +// Revision 1.2 2007/01/24 20:14:40 acg +// Andy Goodrich: improved comments about the use of this-> in the macros +// that access sensitive. +// +// Revision 1.1.1.1 2006/12/15 20:20:05 acg +// SystemC 2.3 +// +// Revision 1.10 2006/12/02 20:58:18 acg +// Andy Goodrich: updates from 2.2 for IEEE 1666 support. +// +// Revision 1.7 2006/04/11 23:13:21 acg +// Andy Goodrich: Changes for reduced reset support that only includes +// sc_cthread, but has preliminary hooks for expanding to method and thread +// processes also. +// +// Revision 1.6 2006/03/15 17:53:34 acg +// Andy Goodrich, Forte Design +// Reordered includes to pick up <cassert> for use by sc_process_name.h +// +// Revision 1.5 2006/03/14 23:56:58 acg +// Andy Goodrich: This fixes a bug when an exception is thrown in +// sc_module::sc_module() for a dynamically allocated sc_module +// object. We are calling sc_module::end_module() on a module that has +// already been deleted. The scenario runs like this: +// +// a) the sc_module constructor is entered +// b) the exception is thrown +// c) the exception processor deletes the storage for the sc_module +// d) the stack is unrolled causing the sc_module_name instance to be deleted +// e) ~sc_module_name() calls end_module() with its pointer to the sc_module +// f) because the sc_module has been deleted its storage is corrupted, +// either by linking it to a free space chain, or by reuse of some sort +// g) the m_simc field is garbage +// h) the m_object_manager field is also garbage +// i) an exception occurs +// +// This does not happen for automatic sc_module instances since the +// storage for the module is not reclaimed its just part of the stack. +// +// I am fixing this by having the destructor for sc_module clear the +// module pointer in its sc_module_name instance. That cuts things at +// step (e) above, since the pointer will be null if the module has +// already been deleted. To make sure the module stack is okay, I call +// end-module() in ~sc_module in the case where there is an +// sc_module_name pointer lying around. +// +// Revision 1.4 2006/01/24 20:49:05 acg +// Andy Goodrich: changes to remove the use of deprecated features within the +// simulator, and to issue warning messages when deprecated features are used. +// +// Revision 1.3 2006/01/13 18:44:30 acg +// Added $Log to record CVS changes into the source. + +#endif diff --git a/ext/systemc/src/sysc/kernel/sc_module_name.cpp b/ext/systemc/src/sysc/kernel/sc_module_name.cpp new file mode 100644 index 000000000..a5352690f --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_module_name.cpp @@ -0,0 +1,123 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_module_name.cpp -- An object used to help manage object names + and hierarchy + + Original Author: Stan Y. Liao, Synopsys, Inc. + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + +#include <cstdlib> + +#include "sysc/kernel/sc_kernel_ids.h" +#include "sysc/kernel/sc_module.h" +#include "sysc/kernel/sc_module_name.h" +#include "sysc/kernel/sc_object_manager.h" +#include "sysc/kernel/sc_simcontext.h" +#include "sysc/utils/sc_iostream.h" + +namespace sc_core { + +sc_module_name::sc_module_name( const char* name_ ) +: m_name( name_ ), + m_module_p( 0 ), + m_next( 0 ), + m_simc( sc_get_curr_simcontext() ), + m_pushed( true ) +{ + m_simc->get_object_manager()->push_module_name( this ); +} + +sc_module_name::sc_module_name( const sc_module_name& name_ ) +: m_name( name_.m_name ), + m_module_p( 0 ), + m_next( 0 ), + m_simc( name_.m_simc ), + m_pushed( false ) +{} + +sc_module_name::~sc_module_name() +{ + if( m_pushed ) { + sc_module_name* smn = m_simc->get_object_manager()->pop_module_name(); + if( this != smn ) { + SC_REPORT_ERROR( SC_ID_SC_MODULE_NAME_USE_, 0 ); + } + if ( m_module_p ) m_module_p->end_module(); + } +} + +sc_module_name::operator const char*() const +{ + return m_name; +} + +} // namespace sc_core + +// $Log: sc_module_name.cpp,v $ +// Revision 1.5 2011/08/26 20:46:10 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +// Revision 1.4 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.3 2011/02/13 21:47:37 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.2 2008/05/22 17:06:26 acg +// Andy Goodrich: updated copyright notice to include 2008. +// +// Revision 1.1.1.1 2006/12/15 20:20:05 acg +// SystemC 2.3 +// +// Revision 1.4 2006/03/14 23:56:58 acg +// Andy Goodrich: This fixes a bug when an exception is thrown in +// sc_module::sc_module() for a dynamically allocated sc_module +// object. We are calling sc_module::end_module() on a module that has +// already been deleted. The scenario runs like this: +// +// a) the sc_module constructor is entered +// b) the exception is thrown +// c) the exception processor deletes the storage for the sc_module +// d) the stack is unrolled causing the sc_module_name instance to be deleted +// e) ~sc_module_name() calls end_module() with its pointer to the sc_module +// f) because the sc_module has been deleted its storage is corrupted, +// either by linking it to a free space chain, or by reuse of some sort +// g) the m_simc field is garbage +// h) the m_object_manager field is also garbage +// i) an exception occurs +// +// This does not happen for automatic sc_module instances since the +// storage for the module is not reclaimed its just part of the stack. +// +// I am fixing this by having the destructor for sc_module clear the +// module pointer in its sc_module_name instance. That cuts things at +// step (e) above, since the pointer will be null if the module has +// already been deleted. To make sure the module stack is okay, I call +// end-module() in ~sc_module in the case where there is an +// sc_module_name pointer lying around. +// +// Revision 1.3 2006/01/13 18:44:30 acg +// Added $Log to record CVS changes into the source. +// diff --git a/ext/systemc/src/sysc/kernel/sc_module_name.h b/ext/systemc/src/sysc/kernel/sc_module_name.h new file mode 100644 index 000000000..a2149cc6a --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_module_name.h @@ -0,0 +1,140 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_module_name.h -- An object used to help manage object names + and hierarchy. + + Original Author: Stan Y. Liao, Synopsys, Inc. + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + +// $Log: sc_module_name.h,v $ +// Revision 1.5 2011/08/26 20:46:10 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// + +#ifndef SC_MODULE_NAME_H +#define SC_MODULE_NAME_H + + +namespace sc_core { + +class sc_module; +class sc_simcontext; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_module_name +// +// Module name class. +// ---------------------------------------------------------------------------- + +class sc_module_name +{ + friend class sc_module; + friend class sc_object_manager; + +public: + + sc_module_name( const char* ); + sc_module_name( const sc_module_name& ); + + ~sc_module_name(); + + operator const char*() const; + +protected: + inline void clear_module( sc_module* module_p ); + inline void set_module( sc_module* module_p ); + +private: + + const char* m_name; + sc_module* m_module_p; + sc_module_name* m_next; + sc_simcontext* m_simc; + bool m_pushed; + +private: + + // disabled + sc_module_name(); + sc_module_name& operator = ( const sc_module_name& ); +}; + +inline void sc_module_name::clear_module( sc_module* module_p ) +{ + assert( m_module_p == module_p ); + m_module_p = 0; +} + +inline void sc_module_name::set_module( sc_module* module_p ) +{ + m_module_p = module_p; +} + +} // namespace sc_core + +// Revision 1.4 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.3 2011/02/13 21:47:37 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.2 2008/05/22 17:06:26 acg +// Andy Goodrich: updated copyright notice to include 2008. +// +// Revision 1.1.1.1 2006/12/15 20:20:05 acg +// SystemC 2.3 +// +// Revision 1.4 2006/03/14 23:56:58 acg +// Andy Goodrich: This fixes a bug when an exception is thrown in +// sc_module::sc_module() for a dynamically allocated sc_module +// object. We are calling sc_module::end_module() on a module that has +// already been deleted. The scenario runs like this: +// +// a) the sc_module constructor is entered +// b) the exception is thrown +// c) the exception processor deletes the storage for the sc_module +// d) the stack is unrolled causing the sc_module_name instance to be deleted +// e) ~sc_module_name() calls end_module() with its pointer to the sc_module +// f) because the sc_module has been deleted its storage is corrupted, +// either by linking it to a free space chain, or by reuse of some sort +// g) the m_simc field is garbage +// h) the m_object_manager field is also garbage +// i) an exception occurs +// +// This does not happen for automatic sc_module instances since the +// storage for the module is not reclaimed its just part of the stack. +// +// I am fixing this by having the destructor for sc_module clear the +// module pointer in its sc_module_name instance. That cuts things at +// step (e) above, since the pointer will be null if the module has +// already been deleted. To make sure the module stack is okay, I call +// end-module() in ~sc_module in the case where there is an +// sc_module_name pointer lying around. +// +// Revision 1.3 2006/01/13 18:44:30 acg +// Added $Log to record CVS changes into the source. + +#endif diff --git a/ext/systemc/src/sysc/kernel/sc_module_registry.cpp b/ext/systemc/src/sysc/kernel/sc_module_registry.cpp new file mode 100644 index 000000000..2d8b02c34 --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_module_registry.cpp @@ -0,0 +1,184 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_module_registry.cpp -- Registry for all modules. + FOR INTERNAL USE ONLY. + + Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21 + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + + +#include "sysc/kernel/sc_kernel_ids.h" +#include "sysc/kernel/sc_module.h" +#include "sysc/kernel/sc_module_registry.h" +#include "sysc/kernel/sc_simcontext.h" + +namespace sc_core { + +// ---------------------------------------------------------------------------- +// CLASS : sc_module_registry +// +// Registry for all modules. +// FOR INTERNAL USE ONLY! +// ---------------------------------------------------------------------------- + +void +sc_module_registry::insert( sc_module& module_ ) +{ + if( sc_is_running() ) { + SC_REPORT_ERROR( SC_ID_INSERT_MODULE_, "simulation running" ); + } + + if( m_simc->elaboration_done() ) { + SC_REPORT_ERROR( SC_ID_INSERT_MODULE_, "elaboration done" ); + } + +#ifdef DEBUG_SYSTEMC + // check if module_ is already inserted + for( int i = size() - 1; i >= 0; -- i ) { + if( &module_ == m_module_vec[i] ) { + SC_REPORT_ERROR( SC_ID_INSERT_MODULE_, "already inserted" ); + } + } +#endif + + // insert + m_module_vec.push_back( &module_ ); +} + +void +sc_module_registry::remove( sc_module& module_ ) +{ + int i; + for( i = 0; i < size(); ++ i ) { + if( &module_ == m_module_vec[i] ) { + break; + } + } + if( i == size() ) { + SC_REPORT_ERROR( SC_ID_REMOVE_MODULE_, 0 ); + } + + // remove + m_module_vec[i] = m_module_vec[size() - 1]; + m_module_vec.resize(m_module_vec.size()-1); +} + + +// constructor + +sc_module_registry::sc_module_registry( sc_simcontext& simc_ ) + : m_construction_done(0), m_module_vec(), m_simc( &simc_ ) +{} + + +// destructor + +sc_module_registry::~sc_module_registry() +{} + +// called when construction is done + +bool +sc_module_registry::construction_done() +{ + if( size() == m_construction_done ) + // nothing has been updated + return true; + + for( ; m_construction_done < size(); ++m_construction_done ) { + m_module_vec[m_construction_done]->construction_done(); + } + return false; +} + +// called when elaboration is done + +void +sc_module_registry::elaboration_done() +{ + bool error = false; + for( int i = 0; i < size(); ++ i ) { + m_module_vec[i]->elaboration_done( error ); + } +} + +// called before simulation begins + +void +sc_module_registry::start_simulation() +{ + for( int i = 0; i < size(); ++ i ) { + m_module_vec[i]->start_simulation(); + } +} + +// called after simulation ends + +void +sc_module_registry::simulation_done() +{ + for( int i = 0; i < size(); ++ i ) { + m_module_vec[i]->simulation_done(); + } +} + +} // namespace sc_core + +// $Log: sc_module_registry.cpp,v $ +// Revision 1.8 2011/08/26 20:46:10 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +// Revision 1.7 2011/08/24 22:05:51 acg +// Torsten Maehne: initialization changes to remove warnings. +// +// Revision 1.6 2011/05/09 04:07:49 acg +// Philipp A. Hartmann: +// (1) Restore hierarchy in all phase callbacks. +// (2) Ensure calls to before_end_of_elaboration. +// +// Revision 1.5 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.4 2011/02/14 17:51:40 acg +// Andy Goodrich: proper pushing an poppping of the module hierarchy for +// start_of_simulation() and end_of_simulation. +// +// Revision 1.3 2011/02/13 21:47:37 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.2 2008/05/22 17:06:26 acg +// Andy Goodrich: updated copyright notice to include 2008. +// +// Revision 1.1.1.1 2006/12/15 20:20:05 acg +// SystemC 2.3 +// +// Revision 1.4 2006/01/26 21:04:54 acg +// Andy Goodrich: deprecation message changes and additional messages. +// +// Revision 1.3 2006/01/13 18:44:30 acg +// Added $Log to record CVS changes into the source. +// + +// Taf! diff --git a/ext/systemc/src/sysc/kernel/sc_module_registry.h b/ext/systemc/src/sysc/kernel/sc_module_registry.h new file mode 100644 index 000000000..3e1bb5dff --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_module_registry.h @@ -0,0 +1,124 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_module_registry.h -- Registry for all modules. + FOR INTERNAL USE ONLY. + + Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21 + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + + +#ifndef SC_MODULE_REGISTRY_H +#define SC_MODULE_REGISTRY_H + + +namespace sc_core { + +class sc_module; +class sc_simcontext; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_module_registry +// +// Registry for all modules. +// FOR INTERNAL USE ONLY! +// ---------------------------------------------------------------------------- + +class sc_module_registry +{ + friend class sc_simcontext; + +public: + + void insert( sc_module& ); + void remove( sc_module& ); + + int size() const + { return m_module_vec.size(); } + +private: + + // constructor + explicit sc_module_registry( sc_simcontext& simc_ ); + + // destructor + ~sc_module_registry(); + + // called when construction is done + bool construction_done(); + + // called when elaboration is done + void elaboration_done(); + + // called before simulation begins + void start_simulation(); + + // called after simulation ends + void simulation_done(); + + +private: + + int m_construction_done; + std::vector<sc_module*> m_module_vec; + sc_simcontext* m_simc; + +private: + + // disabled + sc_module_registry(); + sc_module_registry( const sc_module_registry& ); + sc_module_registry& operator = ( const sc_module_registry& ); +}; + +} // namespace sc_core + +#endif + +// $Log: sc_module_registry.h,v $ +// Revision 1.6 2011/08/26 20:46:10 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +// Revision 1.5 2011/05/09 04:07:49 acg +// Philipp A. Hartmann: +// (1) Restore hierarchy in all phase callbacks. +// (2) Ensure calls to before_end_of_elaboration. +// +// Revision 1.4 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.3 2011/02/13 21:47:37 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.2 2008/05/22 17:06:26 acg +// Andy Goodrich: updated copyright notice to include 2008. +// +// Revision 1.1.1.1 2006/12/15 20:20:05 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:44:30 acg +// Added $Log to record CVS changes into the source. + +// Taf! diff --git a/ext/systemc/src/sysc/kernel/sc_name_gen.cpp b/ext/systemc/src/sysc/kernel/sc_name_gen.cpp new file mode 100644 index 000000000..16f6ad78f --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_name_gen.cpp @@ -0,0 +1,109 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_name_gen.cpp -- Unique name generator. + + Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21 + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + + +#include "sysc/kernel/sc_kernel_ids.h" +#include "sysc/kernel/sc_name_gen.h" +#include "sysc/utils/sc_iostream.h" + +#if defined(_MSC_VER) && _MSC_VER >= 1310 +// "C4351: new behavior: elements of array will be default initialized" +#pragma warning(disable: 4351) +#endif + +namespace sc_core { + +// ---------------------------------------------------------------------------- +// CLASS : sc_name_gen +// +// Unique name generator class. +// ---------------------------------------------------------------------------- + +sc_name_gen::sc_name_gen() : m_unique_name_map(), m_unique_name() +{} + +sc_name_gen::~sc_name_gen() +{ + sc_strhash<int*>::iterator it( m_unique_name_map ); + for( ; ! it.empty(); it ++ ) { + delete it.contents(); + } + m_unique_name_map.erase(); +} + + +// to generate unique names for objects in an MT-Safe way + +const char* +sc_name_gen::gen_unique_name( const char* basename_, bool preserve_first ) +{ + if( basename_ == 0 ) { + SC_REPORT_ERROR( SC_ID_GEN_UNIQUE_NAME_, 0 ); + } + int* c = m_unique_name_map[basename_]; + if( c == 0 ) { + c = new int( 0 ); + m_unique_name_map.insert( CCAST<char*>( basename_ ), c ); + if (preserve_first) { + std::sprintf( m_unique_name, "%s", basename_ ); + } else { + std::sprintf( m_unique_name, "%s_%d", basename_, *c ); + } + } else { + std::sprintf( m_unique_name, "%s_%d", basename_, ++ (*c) ); + } + return m_unique_name; +} + +} // namespace sc_core + +// $Log: sc_name_gen.cpp,v $ +// Revision 1.6 2011/08/26 20:46:10 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +// Revision 1.5 2011/08/24 22:05:51 acg +// Torsten Maehne: initialization changes to remove warnings. +// +// Revision 1.4 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.3 2011/02/13 21:47:37 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.2 2008/05/22 17:06:26 acg +// Andy Goodrich: updated copyright notice to include 2008. +// +// Revision 1.1.1.1 2006/12/15 20:20:05 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:44:30 acg +// Added $Log to record CVS changes into the source. +// + +// Taf! diff --git a/ext/systemc/src/sysc/kernel/sc_name_gen.h b/ext/systemc/src/sysc/kernel/sc_name_gen.h new file mode 100644 index 000000000..0910e014a --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_name_gen.h @@ -0,0 +1,93 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_name_gen.h -- Unique name generator. + + Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21 + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + + +#ifndef SC_NAME_GEN +#define SC_NAME_GEN + + +#include <cstdio> + +#include "sysc/utils/sc_hash.h" + +namespace sc_core{ + +// ---------------------------------------------------------------------------- +// CLASS : sc_name_gen +// +// Unique name generator class. +// ---------------------------------------------------------------------------- + +class sc_name_gen +{ +public: + + sc_name_gen(); + ~sc_name_gen(); + + const char* gen_unique_name( const char* basename_, + bool preserve_first = false + ); + +private: + + sc_strhash<int*> m_unique_name_map; + char m_unique_name[BUFSIZ]; + +private: + + // disabled + sc_name_gen( const sc_name_gen& ); + sc_name_gen& operator = ( const sc_name_gen& ); +}; + +} // namespace sc_core + +// $Log: sc_name_gen.h,v $ +// Revision 1.5 2011/08/26 20:46:10 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +// Revision 1.4 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.3 2011/02/13 21:47:37 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.2 2008/05/22 17:06:26 acg +// Andy Goodrich: updated copyright notice to include 2008. +// +// Revision 1.1.1.1 2006/12/15 20:20:05 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:44:30 acg +// Added $Log to record CVS changes into the source. + +#endif + +// Taf! diff --git a/ext/systemc/src/sysc/kernel/sc_object.cpp b/ext/systemc/src/sysc/kernel/sc_object.cpp new file mode 100644 index 000000000..e624d12b5 --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_object.cpp @@ -0,0 +1,568 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_object.cpp -- Abstract base class of all SystemC objects. + + Original Author: Stan Y. Liao, Synopsys, Inc. + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + + +#include <cstdlib> +#include <cassert> +#include <stddef.h> +#include <cstdio> +#include <string.h> +#include <ctype.h> + +#include "sysc/kernel/sc_externs.h" +#include "sysc/kernel/sc_kernel_ids.h" +#include "sysc/kernel/sc_module.h" +#include "sysc/kernel/sc_object.h" +#include "sysc/kernel/sc_object_manager.h" +#include "sysc/kernel/sc_phase_callback_registry.h" +#include "sysc/kernel/sc_process_handle.h" +#include "sysc/kernel/sc_simcontext.h" +#include "sysc/kernel/sc_event.h" +#include "sysc/utils/sc_hash.h" +#include "sysc/utils/sc_iostream.h" +#include "sysc/utils/sc_list.h" +#include "sysc/utils/sc_utils_ids.h" +#include "sysc/utils/sc_mempool.h" + +namespace sc_core { + +typedef int (*STRCMP)(const void*, const void*); + +const char SC_HIERARCHY_CHAR = '.'; + +/* This will be gotten rid after multiple-processes + are implemented. This is to fix some regression + problems. */ +bool sc_enable_name_checking = true; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_object +// +// Abstract base class of all SystemC `simulation' objects. +// ---------------------------------------------------------------------------- + +void +sc_object::add_child_event( sc_event* event_p ) +{ + // no check if event_p is already in the set + m_child_events.push_back( event_p ); +} + +void +sc_object::add_child_object( sc_object* object_ ) +{ + // no check if object_ is already in the set + m_child_objects.push_back( object_ ); +} + +const char* +sc_object::basename() const +{ + size_t pos; // position of last SC_HIERARCHY_CHAR. + pos = m_name.rfind( (char)SC_HIERARCHY_CHAR ); + return ( pos == m_name.npos ) ? m_name.c_str() : &(m_name.c_str()[pos+1]); +} + +void +sc_object::print(::std::ostream& os) const +{ + os << name(); +} + +void +sc_object::dump(::std::ostream& os) const +{ + os << "name = " << name() << "\n"; + os << "kind = " << kind() << "\n"; +} + +static int sc_object_num = 0; + +static std::string +sc_object_newname() +{ + char buffer[64]; + std::string result; + + std::sprintf(buffer, "{%d}", sc_object_num); + sc_object_num++; + result = buffer; + + return result; +} + +// +---------------------------------------------------------------------------- +// |"sc_object::remove_child_event" +// | +// | This virtual method removes the supplied event from the list of child +// | events if it is present. +// | +// | Arguments: +// | event_p -> event to be removed. +// | Returns true if the event was present, false if not. +// +---------------------------------------------------------------------------- +bool +sc_object::remove_child_event( sc_event* event_p ) +{ + int size = m_child_events.size(); + for( int i = 0; i < size; ++ i ) { + if( event_p == m_child_events[i] ) { + m_child_events[i] = m_child_events[size - 1]; + m_child_events.pop_back(); + return true; + } + } + return false; +} + +// +---------------------------------------------------------------------------- +// |"sc_object::remove_child_object" +// | +// | This virtual method removes the supplied object from the list of child +// | objects if it is present. +// | +// | Arguments: +// | object_p -> object to be removed. +// | Returns true if the object was present, false if not. +// +---------------------------------------------------------------------------- +bool +sc_object::remove_child_object( sc_object* object_p ) +{ + int size = m_child_objects.size(); + for( int i = 0; i < size; ++ i ) { + if( object_p == m_child_objects[i] ) { + m_child_objects[i] = m_child_objects[size - 1]; + m_child_objects.pop_back(); + object_p->m_parent = NULL; + return true; + } + } + return false; +} + +// +---------------------------------------------------------------------------- +// |"sc_object::sc_object_init" +// | +// | This method initializes this object instance and places it in to the +// | object hierarchy if the supplied name is not NULL. +// | +// | Arguments: +// | nm = leaf name for the object. +// +---------------------------------------------------------------------------- +void +sc_object::sc_object_init(const char* nm) +{ + // SET UP POINTERS TO OBJECT MANAGER, PARENT, AND SIMULATION CONTEXT: + // + // Make the current simcontext the simcontext for this object + + m_simc = sc_get_curr_simcontext(); + m_attr_cltn_p = 0; + sc_object_manager* object_manager = m_simc->get_object_manager(); + m_parent = m_simc->active_object(); + + // CONSTRUCT PATHNAME TO OBJECT BEING CREATED: + // + // If there is not a leaf name generate one. + + m_name = object_manager->create_name(nm ? nm : sc_object_newname().c_str()); + + + // PLACE THE OBJECT INTO THE HIERARCHY + + object_manager->insert_object(m_name, this); + if ( m_parent ) + m_parent->add_child_object( this ); + else + m_simc->add_child_object( this ); +} + +sc_object::sc_object() : + m_attr_cltn_p(0), m_child_events(), m_child_objects(), m_name(), + m_parent(0), m_simc(0) +{ + sc_object_init( sc_gen_unique_name("object") ); +} + +sc_object::sc_object( const sc_object& that ) : + m_attr_cltn_p(0), m_child_events(), m_child_objects(), m_name(), + m_parent(0), m_simc(0) +{ + sc_object_init( sc_gen_unique_name( that.basename() ) ); +} + + +static bool +object_name_illegal_char(char ch) +{ + return (ch == SC_HIERARCHY_CHAR) || isspace(ch); +} + +sc_object::sc_object(const char* nm) : + m_attr_cltn_p(0), m_child_events(), m_child_objects(), m_name(), + m_parent(0), m_simc(0) +{ + int namebuf_alloc = 0; + char* namebuf = 0; + const char* p; + + // null name or "" uses machine generated name. + + if ( !nm || !*nm ) + nm = sc_gen_unique_name("object"); + p = nm; + + if (nm && sc_enable_name_checking) { + namebuf_alloc = 1 + strlen(nm); + namebuf = (char*) sc_mempool::allocate(namebuf_alloc); + char* q = namebuf; + const char* r = nm; + bool has_illegal_char = false; + while (*r) { + if (object_name_illegal_char(*r)) { + has_illegal_char = true; + *q = '_'; + } else { + *q = *r; + } + r++; + q++; + } + *q = '\0'; + p = namebuf; + if (has_illegal_char) + { + std::string message = nm; + message += " substituted by "; + message += namebuf; + SC_REPORT_WARNING( SC_ID_ILLEGAL_CHARACTERS_, message.c_str()); + } + } + sc_object_init(p); + sc_mempool::release( namebuf, namebuf_alloc ); +} + +sc_object::~sc_object() +{ +#if SC_HAS_PHASE_CALLBACKS_ + unregister_simulation_phase_callback( SC_STATUS_ANY ); +#endif + detach(); + delete m_attr_cltn_p; +} + +//------------------------------------------------------------------------------ +//"sc_object::detach" +// +// This method detaches this object instance from the object hierarchy. +// It is called in two places: ~sc_object() and sc_process_b::kill_process(). +//------------------------------------------------------------------------------ +void sc_object::detach() +{ + if (m_simc) { + + // REMOVE OBJECT FROM THE OBJECT MANAGER: + + sc_object_manager* object_manager = m_simc->get_object_manager(); + object_manager->remove_object(m_name); + + // REMOVE OBJECT FROM PARENT'S LIST OF OBJECTS: + + if ( m_parent ) + m_parent->remove_child_object( this ); + else + m_simc->remove_child_object( this ); + + // ORPHAN THIS OBJECT'S CHILDREN: + +#if 0 // #### + ::std::<sc_object*> children_p = &get_child_objects(); + int child_n = children_p->size(); + sc_object* parent_p; + + for ( int child_i = 0; child_i < child_n; child_i++ ) + { + (*children_p)[child_i]->m_parent = 0; + } +#endif + + } +} + +// +---------------------------------------------------------------------------- +// |"sc_object::orphan_child_events" +// | +// | This method moves the children of this object instance to be children +// | of the simulator. +// +---------------------------------------------------------------------------- +void sc_object::orphan_child_events() +{ + std::vector< sc_event* > const & events = get_child_events(); + + std::vector< sc_event* >::const_iterator + it = events.begin(), end = events.end(); + + for( ; it != end; ++it ) + { + (*it)->m_parent_p = NULL; + simcontext()->add_child_event(*it); + } +} + +// +---------------------------------------------------------------------------- +// |"sc_object::orphan_child_objects" +// | +// | This method moves the children of this object instance to be children +// | of the simulator. +// +---------------------------------------------------------------------------- +void sc_object::orphan_child_objects() +{ + std::vector< sc_object* > const & children = get_child_objects(); + + std::vector< sc_object* >::const_iterator + it = children.begin(), end = children.end(); + + for( ; it != end; ++it ) + { + (*it)->m_parent = NULL; + simcontext()->add_child_object(*it); + } +} + +void +sc_object::trace( sc_trace_file * /* unused */) const +{ + /* This space is intentionally left blank */ +} + + +// add attribute + +bool +sc_object::add_attribute( sc_attr_base& attribute_ ) +{ + if ( !m_attr_cltn_p ) m_attr_cltn_p = new sc_attr_cltn; + return ( m_attr_cltn_p->push_back( &attribute_ ) ); +} + + +// get attribute by name + +sc_attr_base* +sc_object::get_attribute( const std::string& name_ ) +{ + if ( !m_attr_cltn_p ) m_attr_cltn_p = new sc_attr_cltn; + return ( (*m_attr_cltn_p)[name_] ); +} + +const sc_attr_base* +sc_object::get_attribute( const std::string& name_ ) const +{ + if ( !m_attr_cltn_p ) m_attr_cltn_p = new sc_attr_cltn; + return ( (*m_attr_cltn_p)[name_] ); +} + + +// remove attribute by name + +sc_attr_base* +sc_object::remove_attribute( const std::string& name_ ) +{ + if ( m_attr_cltn_p ) + return ( m_attr_cltn_p->remove( name_ ) ); + else + return 0; +} + + +// remove all attributes + +void +sc_object::remove_all_attributes() +{ + if ( m_attr_cltn_p ) + m_attr_cltn_p->remove_all(); +} + + +// get the number of attributes + +int +sc_object::num_attributes() const +{ + if ( m_attr_cltn_p ) + return ( m_attr_cltn_p->size() ); + else + return 0; +} + + +// get the attribute collection + +sc_attr_cltn& +sc_object::attr_cltn() +{ + if ( !m_attr_cltn_p ) m_attr_cltn_p = new sc_attr_cltn; + return *m_attr_cltn_p; +} + +const sc_attr_cltn& +sc_object::attr_cltn() const +{ + if ( !m_attr_cltn_p ) m_attr_cltn_p = new sc_attr_cltn; + return *m_attr_cltn_p; +} + +sc_object* +sc_object::get_parent() const +{ + static bool warn_sc_get_parent_deprecated=true; + if ( warn_sc_get_parent_deprecated ) + { + warn_sc_get_parent_deprecated=false; + SC_REPORT_INFO(sc_core::SC_ID_IEEE_1666_DEPRECATION_, + "sc_object::get_parent() is deprecated, " + "use get_parent_object() instead"); + } + return get_parent_object(); +} + +// ---------------------------------------------------------------------------- +// simulation phase callbacks + + +sc_object::phase_cb_mask +sc_object::register_simulation_phase_callback( phase_cb_mask mask ) +{ + mask = simcontext()->m_phase_cb_registry + ->register_callback(*this, mask); + return mask; +} + + +sc_object::phase_cb_mask +sc_object::unregister_simulation_phase_callback( phase_cb_mask mask ) +{ + mask = simcontext()->m_phase_cb_registry + ->unregister_callback(*this, mask); + return mask; +} + + +void +sc_object::simulation_phase_callback() +{ + SC_REPORT_WARNING( SC_ID_PHASE_CALLBACK_NOT_IMPLEMENTED_, name() ); +} + + +} // namespace sc_core + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: Bishnupriya Bhattacharya, Cadence Design Systems, + 25 August, 2003 + Description of Modification: if module name hierarchy is empty, sc_object + ctor assumes the currently executing process + as the parent object to support dynamic process + creation similar to other sc_objects + + Name, Affiliation, Date: Andy Goodrich, Forte Design Systems + 5 September 2003 + Description of Modification: - Made creation of attributes structure + conditional on its being used. This eliminates + 100 bytes of storage for each normal sc_object. + + *****************************************************************************/ + + +// $Log: sc_object.cpp,v $ +// Revision 1.16 2011/08/29 18:04:32 acg +// Philipp A. Hartmann: miscellaneous clean ups. +// +// Revision 1.15 2011/08/26 20:46:10 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +// Revision 1.14 2011/08/24 22:05:51 acg +// Torsten Maehne: initialization changes to remove warnings. +// +// Revision 1.13 2011/04/01 21:24:57 acg +// Andy Goodrich: removed unused code. +// +// Revision 1.12 2011/03/06 15:55:11 acg +// Andy Goodrich: Changes for named events. +// +// Revision 1.11 2011/03/05 19:44:20 acg +// Andy Goodrich: changes for object and event naming and structures. +// +// Revision 1.10 2011/03/05 04:45:16 acg +// Andy Goodrich: moved active process calculation to the sc_simcontext class. +// +// Revision 1.9 2011/03/05 01:39:21 acg +// Andy Goodrich: changes for named events. +// +// Revision 1.8 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.7 2011/02/13 21:47:37 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.6 2011/01/25 20:50:37 acg +// Andy Goodrich: changes for IEEE 1666 2011. +// +// Revision 1.5 2011/01/18 20:10:44 acg +// Andy Goodrich: changes for IEEE1666_2011 semantics. +// +// Revision 1.4 2010/08/03 17:02:39 acg +// Andy Goodrich: formatting changes. +// +// Revision 1.3 2009/02/28 00:26:58 acg +// Andy Goodrich: changed boost name space to sc_boost to allow use with +// full boost library applications. +// +// Revision 1.2 2008/05/22 17:06:26 acg +// Andy Goodrich: updated copyright notice to include 2008. +// +// Revision 1.1.1.1 2006/12/15 20:20:05 acg +// SystemC 2.3 +// +// Revision 1.5 2006/04/20 17:08:17 acg +// Andy Goodrich: 3.0 style process changes. +// +// Revision 1.4 2006/03/21 00:00:34 acg +// Andy Goodrich: changed name of sc_get_current_process_base() to be +// sc_get_current_process_b() since its returning an sc_process_b instance. +// +// Revision 1.3 2006/01/13 18:44:30 acg +// Added $Log to record CVS changes into the source. +// diff --git a/ext/systemc/src/sysc/kernel/sc_object.h b/ext/systemc/src/sysc/kernel/sc_object.h new file mode 100644 index 000000000..c6e0957a8 --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_object.h @@ -0,0 +1,244 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_object.h -- Abstract base class of all SystemC `simulation' objects. + + Original Author: Stan Y. Liao, Synopsys, Inc. + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + + +#ifndef SC_OBJECT_H +#define SC_OBJECT_H + + +#include "sysc/utils/sc_iostream.h" +#include "sysc/kernel/sc_attribute.h" + +namespace sc_core { + +class sc_event; +class sc_module; +class sc_phase_callback_registry; +class sc_runnable; +class sc_simcontext; +class sc_trace_file; +class sc_trace_file_base; + +// ---------------------------------------------------------------------------- +// CLASS : sc_object +// +// Abstract base class of all SystemC `simulation' objects. +// ---------------------------------------------------------------------------- + +class sc_object +{ + friend class sc_event; + friend class sc_module; + friend struct sc_invoke_method; + friend class sc_module_dynalloc_list; + friend class sc_object_manager; + friend class sc_phase_callback_registry; + friend class sc_process_b; + friend class sc_runnable; + friend class sc_simcontext; + friend class sc_trace_file_base; + +public: + typedef unsigned phase_cb_mask; + + const char* name() const + { return m_name.c_str(); } + + const char* basename() const; + + virtual void print(::std::ostream& os=::std::cout ) const; + + // dump() is more detailed than print() + virtual void dump(::std::ostream& os=::std::cout ) const; + + virtual void trace( sc_trace_file* tf ) const; + + virtual const char* kind() const { return "sc_object"; } + + sc_simcontext* simcontext() const + { return m_simc; } + + // add attribute + bool add_attribute( sc_attr_base& ); + + // get attribute by name + sc_attr_base* get_attribute( const std::string& name_ ); + const sc_attr_base* get_attribute( const std::string& name_ ) const; + + // remove attribute by name + sc_attr_base* remove_attribute( const std::string& name_ ); + + // remove all attributes + void remove_all_attributes(); + + // get the number of attributes + int num_attributes() const; + + // get the attribute collection + sc_attr_cltn& attr_cltn(); + const sc_attr_cltn& attr_cltn() const; + + virtual const std::vector<sc_event*>& get_child_events() const + { return m_child_events; } + + virtual const std::vector<sc_object*>& get_child_objects() const + { return m_child_objects; } + + sc_object* get_parent() const; + sc_object* get_parent_object() const { return m_parent; } + +protected: + + sc_object(); + sc_object(const char* nm); + + sc_object( const sc_object& ); + sc_object& operator=( const sc_object& ); + + + virtual ~sc_object(); + + virtual void add_child_event( sc_event* event_p ); + virtual void add_child_object( sc_object* object_p ); + virtual bool remove_child_event( sc_event* event_p ); + virtual bool remove_child_object( sc_object* object_p ); + + phase_cb_mask register_simulation_phase_callback( phase_cb_mask ); + phase_cb_mask unregister_simulation_phase_callback( phase_cb_mask ); + + class hierarchy_scope; + +private: + void do_simulation_phase_callback(); + virtual void simulation_phase_callback(); + + void detach(); + virtual void orphan_child_events(); + virtual void orphan_child_objects(); + void sc_object_init(const char* nm); + +private: + + /* Each simulation object is associated with a simulation context */ + mutable sc_attr_cltn* m_attr_cltn_p; // attributes for this object. + std::vector<sc_event*> m_child_events; // list of child events. + std::vector<sc_object*> m_child_objects; // list of child objects. + std::string m_name; // name of this object. + sc_object* m_parent; // parent for this object. + sc_simcontext* m_simc; // simcontext ptr / empty indicator +}; + +inline +sc_object& +sc_object::operator=( sc_object const & ) +{ + // deliberately do nothing + return *this; +} + +// ---------------------------------------------------------------------------- + +extern const char SC_HIERARCHY_CHAR; +extern bool sc_enable_name_checking; + + +inline +sc_object* sc_get_parent( const sc_object* obj_p ) +{ + return obj_p->get_parent_object(); +} + +} // namespace sc_core + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: Andy Goodrich, Forte Design Systems + 5 September 2003 + Description of Modification: - Made creation of attributes structure + conditional on its being used. This eliminates + 100 bytes of storage for each normal sc_object. + + *****************************************************************************/ + +// $Log: sc_object.h,v $ +// Revision 1.13 2011/08/29 18:04:32 acg +// Philipp A. Hartmann: miscellaneous clean ups. +// +// Revision 1.12 2011/08/26 20:46:10 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +// Revision 1.11 2011/03/06 15:55:11 acg +// Andy Goodrich: Changes for named events. +// +// Revision 1.10 2011/03/05 19:44:20 acg +// Andy Goodrich: changes for object and event naming and structures. +// +// Revision 1.9 2011/03/05 01:39:21 acg +// Andy Goodrich: changes for named events. +// +// Revision 1.8 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.7 2011/02/13 21:47:37 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.6 2011/01/25 20:50:37 acg +// Andy Goodrich: changes for IEEE 1666 2011. +// +// Revision 1.5 2011/01/18 20:10:44 acg +// Andy Goodrich: changes for IEEE1666_2011 semantics. +// +// Revision 1.4 2010/07/22 20:02:33 acg +// Andy Goodrich: bug fixes. +// +// Revision 1.3 2009/02/28 00:26:58 acg +// Andy Goodrich: changed boost name space to sc_boost to allow use with +// full boost library applications. +// +// Revision 1.2 2008/05/22 17:06:26 acg +// Andy Goodrich: updated copyright notice to include 2008. +// +// Revision 1.1.1.1 2006/12/15 20:20:05 acg +// SystemC 2.3 +// +// Revision 1.5 2006/04/20 17:08:17 acg +// Andy Goodrich: 3.0 style process changes. +// +// Revision 1.4 2006/04/11 23:13:21 acg +// Andy Goodrich: Changes for reduced reset support that only includes +// sc_cthread, but has preliminary hooks for expanding to method and thread +// processes also. +// +// Revision 1.3 2006/01/13 18:44:30 acg +// Added $Log to record CVS changes into the source. + +#endif // SC_OBJECT_H diff --git a/ext/systemc/src/sysc/kernel/sc_object_int.h b/ext/systemc/src/sysc/kernel/sc_object_int.h new file mode 100644 index 000000000..aca230f8b --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_object_int.h @@ -0,0 +1,99 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_object_int.h -- For inline definitions of some utility functions. + DO NOT EXPORT THIS INCLUDE FILE. + + Original Author: Philipp A. Hartmann, OFFIS, 2013-02-10 + + *****************************************************************************/ + +#ifndef SC_OBJECT_INT_H_INCLUDED_ +#define SC_OBJECT_INT_H_INCLUDED_ + +#include "sysc/kernel/sc_object.h" +#include "sysc/kernel/sc_module.h" +#include "sysc/kernel/sc_simcontext_int.h" +#include "sysc/kernel/sc_phase_callback_registry.h" + +namespace sc_core { + +class sc_object::hierarchy_scope +{ +public: + explicit hierarchy_scope(sc_object* obj); + explicit hierarchy_scope(sc_module* mod); + ~hierarchy_scope(); + +private: + sc_module * scope_; + +private: + hierarchy_scope( hierarchy_scope const & other ) /* = delete */; + hierarchy_scope& operator=(hierarchy_scope const&) /* = delete */; +}; + + +inline +sc_object::hierarchy_scope::hierarchy_scope( sc_object* obj ) + : scope_(0) +{ + if( !obj ) return; + + scope_ = dynamic_cast<sc_module*>(obj); + if( !scope_ ) + scope_ = dynamic_cast<sc_module*>(obj->get_parent_object()); + if( scope_ ) + scope_->simcontext()->hierarchy_push(scope_); +} + + +inline +sc_object::hierarchy_scope::hierarchy_scope( sc_module* mod ) + : scope_(mod) +{ + if( scope_ ) + scope_->simcontext()->hierarchy_push(scope_); +} + + +inline +sc_object::hierarchy_scope::~hierarchy_scope() +{ + if( scope_ ) + scope_->simcontext()->hierarchy_pop(); +} + + +// ----------------------------------------------------------------------- + +inline void +sc_object::do_simulation_phase_callback() +{ + simulation_phase_callback(); +} + +// ----------------------------------------------------------------------- + +} // namespace sc_core + +#endif // SC_OBJECT_INT_H_INCLUDED_ +// Taf! diff --git a/ext/systemc/src/sysc/kernel/sc_object_manager.cpp b/ext/systemc/src/sysc/kernel/sc_object_manager.cpp new file mode 100644 index 000000000..e46413928 --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_object_manager.cpp @@ -0,0 +1,462 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_object_manager.cpp -- Manager of objects (naming, &c.) + + Original Author: Stan Y. Liao, Synopsys, Inc. + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + + +#include <stdio.h> +#include <cstdlib> +#include <cassert> +#include <ctype.h> +#include <stddef.h> +#include <algorithm> // pick up std::sort. + +#include "sysc/utils/sc_iostream.h" +#include "sysc/kernel/sc_object.h" +#include "sysc/utils/sc_hash.h" +#include "sysc/utils/sc_list.h" +#include "sysc/utils/sc_mempool.h" +#include "sysc/kernel/sc_simcontext.h" +#include "sysc/kernel/sc_object_manager.h" +#include "sysc/kernel/sc_kernel_ids.h" +#include "sysc/kernel/sc_process.h" +#include "sysc/kernel/sc_module_name.h" + +namespace sc_core { + +// ---------------------------------------------------------------------------- +// CLASS : sc_object_manager +// +// Manager of objects. +// ---------------------------------------------------------------------------- + +sc_object_manager::sc_object_manager() : + m_event_it(), + m_event_walk_ok(0), + m_instance_table(), + m_module_name_stack(0), + m_object_it(), + m_object_stack(), + m_object_walk_ok() +{ +} + +// +---------------------------------------------------------------------------- +// |"sc_object_manager::~sc_object_manager" +// | +// | This is the object instance destructor for this class. It goes through +// | each sc_object instance in the instance table and sets its m_simc field +// | to NULL. +// +---------------------------------------------------------------------------- +sc_object_manager::~sc_object_manager() +{ + instance_table_t::iterator it; // instance table iterator. + + for ( it = m_instance_table.begin(); it != m_instance_table.end(); it++) + { + sc_object* obj_p = it->second.m_object_p; + if ( obj_p ) obj_p->m_simc = 0; + } +} + +// +---------------------------------------------------------------------------- +// |"sc_object_manager::create_name" +// | +// | This method creates a hierarchical name based on the name of the active +// | object and the supplied leaf name. If the resultant name is not unique it +// | will be made unique and a warning message issued. +// | +// | Arguments: +// | leaf_name = name to use for the leaf of the hierarchy. +// | Result is an std::string containing the name. +// +---------------------------------------------------------------------------- +std::string sc_object_manager::create_name(const char* leaf_name) +{ + bool clash; // true if path name exists in obj table + std::string leafname_string; // string containing the leaf name. + std::string parentname_string; // parent path name + sc_object* parent_p; // parent for this instance or NULL. + std::string result_orig_string; // save for warning message. + std::string result_string; // name to return. + + // CONSTRUCT PATHNAME TO THE NAME TO BE RETURNED: + // + // If there is not a leaf name generate one. + + parent_p = sc_get_curr_simcontext()->active_object(); + parentname_string = parent_p ? parent_p->name() : ""; + leafname_string = leaf_name; + if (parent_p) { + result_string = parentname_string; + result_string += SC_HIERARCHY_CHAR; + result_string += leafname_string; + } else { + result_string = leafname_string; + } + + // SAVE the original path name + + result_orig_string = result_string; + + // MAKE SURE THE ENTITY NAME IS UNIQUE: + // + // If not use unique name generator to make it unique. + + clash = false; + for (;;) + { + instance_table_t::iterator it = m_instance_table.find(result_string); + if ( it == m_instance_table.end() || + (it->second.m_event_p == NULL && it->second.m_object_p == NULL ) ) + { + break; + } + clash = true; + leafname_string = sc_gen_unique_name(leafname_string.c_str(), false); + if (parent_p) { + result_string = parentname_string; + result_string += SC_HIERARCHY_CHAR; + result_string += leafname_string; + } else { + result_string = leafname_string; + } + } + if (clash) { + std::string message = result_orig_string; + message += ". Latter declaration will be renamed to "; + message += result_string; + SC_REPORT_WARNING( SC_ID_INSTANCE_EXISTS_, message.c_str()); + } + + return result_string; +} + +// +---------------------------------------------------------------------------- +// |"sc_object_manager::find_event" +// | +// | This method returns the sc_event with the supplied name, or a NULL if +// | the event does not exist. +// | +// | Arguments: +// | name = name of the event +// | Result is a pointer to the event or NULL if it does not exist. +// +---------------------------------------------------------------------------- +sc_event* +sc_object_manager::find_event(const char* name) +{ + instance_table_t::iterator it; + it = m_instance_table.find(name); + return it == m_instance_table.end() ? NULL : it->second.m_event_p; +} + +// +---------------------------------------------------------------------------- +// |"sc_object_manager::find_object" +// | +// | This method returns the sc_object with the supplied name, or a NULL if +// | the object does not exist. +// | +// | Arguments: +// | name = name of the object +// | Result is a pointer to the object or NULL if it does not exist. +// +---------------------------------------------------------------------------- +sc_object* +sc_object_manager::find_object(const char* name) +{ + instance_table_t::iterator it; + it = m_instance_table.find(name); + return it == m_instance_table.end() ? NULL : it->second.m_object_p; +} + + +// +---------------------------------------------------------------------------- +// |"sc_object_manager::first_object" +// | +// | This method initializes the object iterator to point to the first object +// | in the instance table, and returns its address. If there are no objects +// | in the table a NULL value is returned. +// +---------------------------------------------------------------------------- +sc_object* +sc_object_manager::first_object() +{ + sc_object* result_p; // result to return. + + m_object_walk_ok = true; + result_p = NULL; + for ( m_object_it = m_instance_table.begin(); + m_object_it != m_instance_table.end(); + m_object_it++ ) + { + result_p = m_object_it->second.m_object_p; + if ( result_p ) break; + } + return result_p; +} + +// +---------------------------------------------------------------------------- +// |"sc_object_manager::hierarchy_curr" +// | +// | This method returns the current object in the object hierarchy or NULL +// | if it does not exist. +// +---------------------------------------------------------------------------- +sc_object* +sc_object_manager::hierarchy_curr() +{ + size_t hierarchy_n; // current size of the hierarchy. + + hierarchy_n = m_object_stack.size(); + return hierarchy_n ? m_object_stack[hierarchy_n-1] : 0; +} + +// +---------------------------------------------------------------------------- +// |"sc_object_manager::hierarchy_pop" +// | +// | This method pops the current object off the object hierarchy and returns +// | it. +// +---------------------------------------------------------------------------- +sc_object* +sc_object_manager::hierarchy_pop() +{ + size_t hierarchy_n; // current size of the hierarchy. + sc_object* result_p; // object to return. + + hierarchy_n = m_object_stack.size(); + if ( hierarchy_n == 0 ) return NULL; + hierarchy_n--; + result_p = m_object_stack[hierarchy_n]; + m_object_stack.pop_back(); + return result_p; +} + +// +---------------------------------------------------------------------------- +// |"sc_object_manager::hierarchy_push" +// | +// | This method pushes down the sc_object hierarchy to make the supplied +// | object the current object in the hierarchy. +// | +// | Arguments: +// | object_p -> object to become the new current object in the hierarchy. +// +---------------------------------------------------------------------------- +void +sc_object_manager::hierarchy_push(sc_object* object_p) +{ + m_object_stack.push_back(object_p); +} + + +// +---------------------------------------------------------------------------- +// |"sc_object_manager::hierarchy_size" +// | +// | This method returns the current size of the object hierarchy stack. +// +---------------------------------------------------------------------------- +int +sc_object_manager::hierarchy_size() +{ + return m_object_stack.size(); +} + +// +---------------------------------------------------------------------------- +// |"sc_object_manager::insert_event" +// | +// | This method inserts the supplied sc_event instance into the instance +// | table using the supplied name. +// | +// | Arguments: +// | name = name of the event to be inserted. +// | event_p -> event to be inserted. +// +---------------------------------------------------------------------------- +void +sc_object_manager::insert_event(const std::string& name, sc_event* event_p) +{ + m_instance_table[name].m_event_p = event_p; +} + +// +---------------------------------------------------------------------------- +// |"sc_object_manager::insert_object" +// | +// | This method inserts the supplied sc_object instance into the instance +// | table using the supplied name. +// | +// | Arguments: +// | name = name of the event to be inserted. +// | object_p -> object to be inserted. +// +---------------------------------------------------------------------------- +void +sc_object_manager::insert_object(const std::string& name, sc_object* object_p) +{ + m_instance_table[name].m_object_p = object_p; +} + +// +---------------------------------------------------------------------------- +// |"sc_object_manager::next_object" +// | +// | This method returns the next object pointed to by the instance iterator. +// +---------------------------------------------------------------------------- +sc_object* +sc_object_manager::next_object() +{ + sc_object* result_p; // result to return. + + assert( m_object_walk_ok ); + + if ( m_object_it == m_instance_table.end() ) return NULL; + m_object_it++; + + for ( result_p = NULL; m_object_it != m_instance_table.end(); + m_object_it++ ) + { + result_p = m_object_it->second.m_object_p; + if ( result_p ) break; + } + return result_p; +} + +// +---------------------------------------------------------------------------- +// |"sc_object_manager::pop_module_name" +// | +// | This method pops an entry off the module name stack and returns it. +// +---------------------------------------------------------------------------- +sc_module_name* +sc_object_manager::pop_module_name() +{ + sc_module_name* mod_name = m_module_name_stack; + m_module_name_stack = m_module_name_stack->m_next; + mod_name->m_next = 0; + return mod_name; +} + +// +---------------------------------------------------------------------------- +// |"sc_object_manager::push_module_name" +// | +// | This method pushes the supplied entry onto the module name stack. +// | +// | Arguments: +// | mod_name_p -> entry to push onto the module name stack. +// +---------------------------------------------------------------------------- +void +sc_object_manager::push_module_name(sc_module_name* mod_name_p) +{ + mod_name_p->m_next = m_module_name_stack; + m_module_name_stack = mod_name_p; +} + +// +---------------------------------------------------------------------------- +// |"sc_object_manager::top_of_module_name_stack" +// | +// | This method returns the module name that is on the top of the module +// | name stack. +// +---------------------------------------------------------------------------- +sc_module_name* +sc_object_manager::top_of_module_name_stack() +{ + if( m_module_name_stack == 0 ) { + SC_REPORT_ERROR( SC_ID_MODULE_NAME_STACK_EMPTY_, 0 ); + } + return m_module_name_stack; +} + +// +---------------------------------------------------------------------------- +// |"sc_object_manager::remove_event" +// | +// | This method removes the sc_event instance with the supplied name from +// | the table of instances. Note we just clear the pointer since if the name +// | was for an sc_object the m_event_p pointer will be null anyway. +// | +// | Arguments: +// | name = name of the event to be removed. +// +---------------------------------------------------------------------------- +void +sc_object_manager::remove_event(const std::string& name) +{ + instance_table_t::iterator it; // instance table iterator. + it = m_instance_table.find(name); + if ( it != m_instance_table.end() ) it->second.m_event_p = NULL; +} + +// +---------------------------------------------------------------------------- +// |"sc_object_manager::remove_object" +// | +// | This method removes the sc_object instance with the supplied name from +// | the table of instances. Note we just clear the pointer since if the name +// | was for an sc_event the m_object_p pointer will be null anyway. +// | +// | Arguments: +// | name = name of the object to be removed. +// +---------------------------------------------------------------------------- +void +sc_object_manager::remove_object(const std::string& name) +{ + instance_table_t::iterator it; // instance table iterator. + it = m_instance_table.find(name); + if ( it != m_instance_table.end() ) it->second.m_object_p = NULL; +} + +} // namespace sc_core + +// $Log: sc_object_manager.cpp,v $ +// Revision 1.13 2011/08/26 20:46:10 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +// Revision 1.12 2011/08/24 22:05:51 acg +// Torsten Maehne: initialization changes to remove warnings. +// +// Revision 1.11 2011/06/25 17:08:39 acg +// Andy Goodrich: Jerome Cornet's changes to use libtool to build the +// library. +// +// Revision 1.10 2011/04/01 21:27:54 acg +// Andy Goodrich: documentation of event and object insertion methods. +// +// Revision 1.9 2011/03/06 15:55:11 acg +// Andy Goodrich: Changes for named events. +// +// Revision 1.8 2011/03/05 19:44:20 acg +// Andy Goodrich: changes for object and event naming and structures. +// +// Revision 1.7 2011/03/05 04:45:16 acg +// Andy Goodrich: moved active process calculation to the sc_simcontext class. +// +// Revision 1.6 2011/03/05 01:39:21 acg +// Andy Goodrich: changes for named events. +// +// Revision 1.5 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.4 2011/02/13 21:47:37 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.3 2010/07/22 20:02:33 acg +// Andy Goodrich: bug fixes. +// +// Revision 1.2 2008/05/22 17:06:26 acg +// Andy Goodrich: updated copyright notice to include 2008. +// +// Revision 1.1.1.1 2006/12/15 20:20:05 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:44:30 acg +// Added $Log to record CVS changes into the source. +// diff --git a/ext/systemc/src/sysc/kernel/sc_object_manager.h b/ext/systemc/src/sysc/kernel/sc_object_manager.h new file mode 100644 index 000000000..753252c33 --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_object_manager.h @@ -0,0 +1,139 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_object_manager.h -- Manager of objects (naming, &c.) + + Original Author: Stan Y. Liao, Synopsys, Inc. + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + + +#ifndef SC_OBJECT_MANAGER_H +#define SC_OBJECT_MANAGER_H + +#include <map> +#include <vector> + +namespace sc_core { + +class sc_event; +class sc_object; +class sc_module_name; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_object_manager +// +// Manager of objects. +// ---------------------------------------------------------------------------- + +class sc_object_manager +{ + friend class sc_event; + friend class sc_object; + friend class sc_simcontext; + +protected: + struct table_entry + { + table_entry() : m_event_p(NULL), m_object_p(NULL) {} + + sc_event* m_event_p; // if non-null this is an sc_event. + sc_object* m_object_p; // if non-null this is an sc_object. + }; + +public: + typedef std::map<std::string,table_entry> instance_table_t; + typedef std::vector<sc_object*> object_vector_t; + + sc_object_manager(); + ~sc_object_manager(); + + sc_event* find_event(const char* name); + + sc_object* find_object(const char* name); + sc_object* first_object(); + sc_object* next_object(); + + void hierarchy_push(sc_object* mdl); + sc_object* hierarchy_pop(); + sc_object* hierarchy_curr(); + int hierarchy_size(); + + void push_module_name(sc_module_name* mod_name); + sc_module_name* pop_module_name(); + sc_module_name* top_of_module_name_stack(); + + +private: + std::string create_name( const char* leaf_name ); + void insert_event(const std::string& name, sc_event* obj); + void insert_object(const std::string& name, sc_object* obj); + void remove_event(const std::string& name); + void remove_object(const std::string& name); + +private: + + instance_table_t::iterator m_event_it; // event instance iterator. + bool m_event_walk_ok; // true if can walk events. + instance_table_t m_instance_table; // table of instances. + sc_module_name* m_module_name_stack; // sc_module_name stack. + instance_table_t::iterator m_object_it; // object instance iterator. + object_vector_t m_object_stack; // sc_object stack. + bool m_object_walk_ok; // true if can walk objects. +}; + +} // namespace sc_core + +// $Log: sc_object_manager.h,v $ +// Revision 1.9 2011/08/26 20:46:10 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +// Revision 1.8 2011/03/06 15:55:11 acg +// Andy Goodrich: Changes for named events. +// +// Revision 1.7 2011/03/05 19:44:20 acg +// Andy Goodrich: changes for object and event naming and structures. +// +// Revision 1.6 2011/03/05 01:39:21 acg +// Andy Goodrich: changes for named events. +// +// Revision 1.5 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.4 2011/02/13 21:47:37 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.3 2010/07/22 20:02:33 acg +// Andy Goodrich: bug fixes. +// +// Revision 1.2 2008/05/22 17:06:26 acg +// Andy Goodrich: updated copyright notice to include 2008. +// +// Revision 1.1.1.1 2006/12/15 20:20:05 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:44:30 acg +// Added $Log to record CVS changes into the source. + +#endif diff --git a/ext/systemc/src/sysc/kernel/sc_phase_callback_registry.cpp b/ext/systemc/src/sysc/kernel/sc_phase_callback_registry.cpp new file mode 100644 index 000000000..84f15c93f --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_phase_callback_registry.cpp @@ -0,0 +1,301 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_phase_callback_registry.cpp -- Implementation of phase callback registry + + Original Author: Philipp A. Hartmann, OFFIS, 2013-02-15 + + CHANGE LOG AT END OF FILE + *****************************************************************************/ + +#include "sysc/kernel/sc_object.h" +#include "sysc/kernel/sc_phase_callback_registry.h" +#include "sysc/kernel/sc_kernel_ids.h" +#include "sysc/utils/sc_report.h" + +#include <algorithm> +#include <functional> + +namespace sc_core { + +#if SC_HAS_PHASE_CALLBACKS_ + +sc_phase_callback_registry::sc_phase_callback_registry( sc_simcontext& simc ) + : m_simc( &simc ) +#if 0 + , m_cb_eval_vec() +#endif + , m_cb_update_vec() + , m_cb_timestep_vec() +{} + +sc_phase_callback_registry::~sc_phase_callback_registry() +{} + +static const sc_phase_callback_registry::mask_type + SC_PHASE_CALLBACK_MASK = SC_STATUS_ANY; + +namespace /* anonymous */ { + +struct entry_match + : std::unary_function< sc_phase_callback_registry::entry, bool > +{ + typedef sc_phase_callback_registry::cb_type* ref_type; + + explicit + entry_match( ref_type ref ) + : ref_(ref) + {} + + result_type operator()( argument_type e ) + { return e.target == ref_; } +private: + sc_phase_callback_registry::cb_type * ref_; + +}; // entry_match + +template< typename T > +inline void +erase_remove( std::vector<T>* vec, T const& t ) +{ + vec->erase( std::remove( vec->begin(), vec->end(), t ) ); +} + +} // namespace anonymous + + +sc_phase_callback_registry::mask_type +sc_phase_callback_registry::validate_mask( cb_type& cb + , mask_type m + , bool warn = false ) +{ + if( SC_UNLIKELY_(m & ~SC_PHASE_CALLBACK_MASK) ) + { + if( warn ) + { + std::stringstream ss; + ss << cb.name() << ": invalid phase callback mask: " + << (sc_status)m; + SC_REPORT_WARNING( SC_ID_PHASE_CALLBACK_REGISTER_ + , ss.str().c_str() ); + } + m &= SC_PHASE_CALLBACK_MASK; + } + + mask_type check_mask; + + // elaboration callbacks + check_mask = ( SC_ELABORATION + | SC_BEFORE_END_OF_ELABORATION + | SC_END_OF_ELABORATION ); + if( SC_UNLIKELY_( (m & check_mask ) && m_simc->elaboration_done() ) ) + { + if( warn ) + { + std::stringstream ss; + ss << cb.name() << ": elaboration done\n\t " + << (sc_status)( m & check_mask ) << " callback(s) ignored"; + SC_REPORT_WARNING(SC_ID_PHASE_CALLBACK_REGISTER_ + , ss.str().c_str() ); + } + m &= ~check_mask; + } + + check_mask = (SC_BEFORE_END_OF_ELABORATION | SC_END_OF_ELABORATION); + if( SC_UNLIKELY_(m & SC_ELABORATION) ) + { + if( warn ) + { + std::stringstream ss; + ss << cb.name() << ": " << SC_ELABORATION + << ":\n\t substituted by " << (sc_status)(check_mask); + SC_REPORT_WARNING( SC_ID_PHASE_CALLBACK_REGISTER_ + , ss.str().c_str() ); + } + m &= ~SC_ELABORATION; + m |= check_mask; + } + + check_mask = ( SC_END_OF_INITIALIZATION +#if 0 + | SC_END_OF_EVALUATION +#endif + | SC_END_OF_UPDATE + | SC_BEFORE_TIMESTEP ); + if( SC_UNLIKELY_(m & SC_RUNNING) ) + { + if( warn ) + { + std::stringstream ss; + ss << cb.name() << ": " << SC_RUNNING + << ":\n\t substituted by " << (sc_status)(check_mask); + SC_REPORT_WARNING( SC_ID_PHASE_CALLBACK_REGISTER_ + , ss.str().c_str() ); + } + m &= ~SC_RUNNING; + m |= check_mask; + } + return m; +} + + +sc_phase_callback_registry::mask_type +sc_phase_callback_registry::register_callback( cb_type& cb, mask_type m ) +{ + storage_type::iterator it = + find_if( m_cb_vec.begin(), m_cb_vec.end(), entry_match(&cb) ); + + m = validate_mask(cb, m, /* warn */ true ); + + mask_type diff_mask = m; + mask_type new_mask = m; + + if( it != m_cb_vec.end() ) // update existing entry + { + // update masks + new_mask = (*it).mask | m; + diff_mask = ~(*it).mask & m; + (*it).mask = new_mask; + } + else // new entry + { + if( !m ) // empty, do nothing + return SC_UNITIALIZED; + + entry new_entry = { &cb, new_mask }; + m_cb_vec.push_back( new_entry ); + } + + // add to callback shortcut sets +#if 0 + if( diff_mask & SC_END_OF_EVALUATION ) + m_cb_eval_vec.push_back( &cb ); +#endif + if( diff_mask & SC_END_OF_UPDATE ) + m_cb_update_vec.push_back( &cb ); + if( diff_mask & SC_BEFORE_TIMESTEP ) + m_cb_timestep_vec.push_back( &cb ); + + return new_mask; +} + + +sc_phase_callback_registry::mask_type +sc_phase_callback_registry::unregister_callback( cb_type& cb, mask_type m ) +{ + storage_type::iterator it = + find_if( m_cb_vec.begin(), m_cb_vec.end(), entry_match(&cb) ); + + m = validate_mask(cb, m); + + mask_type diff_mask = m; + mask_type new_mask = m; + + if( it == m_cb_vec.end() ) { // not registered + return SC_UNITIALIZED; + } + + // update masks + new_mask = (*it).mask & ~m; + diff_mask = (*it).mask & m; + (*it).mask = new_mask; + + if( !new_mask ) + m_cb_vec.erase(it); + + // drop from callback shortcut sets +#if 0 + if( diff_mask & SC_END_OF_EVALUATION ) + erase_remove( &m_cb_eval_vec, &cb ); +#endif + if( diff_mask & SC_END_OF_UPDATE ) + erase_remove( &m_cb_update_vec, &cb ); + if( diff_mask & SC_BEFORE_TIMESTEP ) + erase_remove( &m_cb_timestep_vec, &cb ); + + return new_mask; +} + + +// generic implementation (for non-critical callbacks) +// - also restores hierarchy around callback object +void +sc_phase_callback_registry::do_callback( sc_status s ) const +{ + typedef storage_type::const_iterator it_type; + storage_type const & vec = m_cb_vec; + + for(it_type it = vec.begin(), end = vec.end(); it != end; ++it) { + if( s & it->mask ) { + sc_object::hierarchy_scope scope(it->target); + it->target->do_simulation_phase_callback(); + } + } +} + +#else // ! SC_HAS_PHASE_CALLBACKS_ + +sc_phase_callback_registry::sc_phase_callback_registry( sc_simcontext& ){} +sc_phase_callback_registry::~sc_phase_callback_registry(){} + +static inline void +warn_phase_callbacks( sc_core::sc_object const& obj ) +{ + static bool warned = false; + if (!warned) + { + std::stringstream ss; + ss << obj.name() << ".\n" + << "Please recompile SystemC with " + "\"SC_ENABLE_SIMULATION_PHASE_CALLBACKS\" defined."; + SC_REPORT_WARNING( SC_ID_PHASE_CALLBACKS_UNSUPPORTED_ + , ss.str().c_str() ); + } +} + +sc_phase_callback_registry::mask_type +sc_phase_callback_registry::register_callback( cb_type& cb, mask_type ) +{ + warn_phase_callbacks( cb ); + return SC_UNITIALIZED; +} + +sc_phase_callback_registry::mask_type +sc_phase_callback_registry::unregister_callback( cb_type& cb, mask_type ) +{ + warn_phase_callbacks( cb ); + return SC_UNITIALIZED; +} + +#endif // ! SC_HAS_PHASE_CALLBACKS_ + +} // namespace sc_core + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ +// Taf! diff --git a/ext/systemc/src/sysc/kernel/sc_phase_callback_registry.h b/ext/systemc/src/sysc/kernel/sc_phase_callback_registry.h new file mode 100644 index 000000000..9510c0d3f --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_phase_callback_registry.h @@ -0,0 +1,276 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_phase_callback_registry.h -- Definition of the simulation phase callbacks + + The most critical functions are defined inline in this file. Only active, + if SC_ENABLE_SIMULATION_PHASE_CALLBACKS[_TRACING] is defined during the + SystemC library build. + + Original Author: Philipp A. Hartmann, OFFIS, 2013-02-15 + + CHANGE LOG AT END OF FILE + *****************************************************************************/ + +#ifndef SC_PHASE_CALLBACK_REGISTRY_H_INCLUDED_ +#define SC_PHASE_CALLBACK_REGISTRY_H_INCLUDED_ + +#if defined( SC_ENABLE_SIMULATION_PHASE_CALLBACKS ) \ + || defined( SC_ENABLE_SIMULATION_PHASE_CALLBACKS_TRACING ) +# define SC_HAS_PHASE_CALLBACKS_ 1 +#else +# define SC_HAS_PHASE_CALLBACKS_ 0 +#endif + +#include "sysc/kernel/sc_simcontext.h" +#include "sysc/kernel/sc_object_int.h" +#include "sysc/kernel/sc_status.h" + +#include <vector> + +namespace sc_core { + +class sc_simcontext; +class sc_object; + +class sc_phase_callback_registry +{ +public: + typedef sc_phase_callback_registry this_type; + typedef sc_object cb_type; + typedef cb_type::phase_cb_mask mask_type; + + struct entry + { + cb_type* target; + mask_type mask; + }; + + friend class sc_simcontext; + friend class sc_object; + +private: // interface completely internal + + explicit + sc_phase_callback_registry( sc_simcontext& simc ); + + ~sc_phase_callback_registry(); + + // --- callback forwarders + + bool construction_done() const; //< returns false + void elaboration_done() const; + void initialization_done() const; + void start_simulation() const; + + void evaluation_done() const; + void update_done() const; + void before_timestep() const; + + void simulation_paused() const; + void simulation_stopped() const; + void simulation_done() const; + + + // --- callback registration and implementation + + mask_type register_callback( cb_type&, mask_type mask ); + mask_type unregister_callback( cb_type&, mask_type mask ); + + // generic caller + void do_callback( sc_status ) const; + +private: + typedef std::vector<entry> storage_type; + typedef std::vector<cb_type*> single_storage_type; + +#if SC_HAS_PHASE_CALLBACKS_ + + // set and restore simulation status + struct scoped_status + { + scoped_status( sc_status& ref, sc_status s ) + : ref_(ref), prev_(ref) { ref_ = s;} + ~scoped_status() { ref_ = prev_; } + private: + sc_status& ref_; + sc_status prev_; + }; // scoped_status + + mask_type validate_mask( cb_type&, mask_type, bool warn ); + +private: + + sc_simcontext* m_simc; + storage_type m_cb_vec; // all callbacks +#if 0 + single_storage_type m_cb_eval_vec; // - eval cb shortcut +#endif + single_storage_type m_cb_update_vec; // - update cb shortcut + single_storage_type m_cb_timestep_vec; // - timestep cb shortcut + +#endif // SC_HAS_PHASE_CALLBACKS_ + +private: + // disabled + sc_phase_callback_registry( const this_type& ); + this_type& operator=(const this_type&); + +}; // sc_phase_callback_registry + + +// -------------------- callback implementations -------------------- +// (empty, if feature is disabled) + +inline bool +sc_phase_callback_registry::construction_done() const +{ +#if SC_HAS_PHASE_CALLBACKS_ + do_callback( SC_BEFORE_END_OF_ELABORATION ); +#endif + return false; +} + +inline void +sc_phase_callback_registry::elaboration_done() const +{ +#if SC_HAS_PHASE_CALLBACKS_ + do_callback( SC_END_OF_ELABORATION ); +#endif +} + +inline void +sc_phase_callback_registry::start_simulation() const +{ +#if SC_HAS_PHASE_CALLBACKS_ + do_callback( SC_START_OF_SIMULATION ); +#endif +} + +inline void +sc_phase_callback_registry::initialization_done() const +{ +#if SC_HAS_PHASE_CALLBACKS_ + scoped_status scope( m_simc->m_simulation_status + , SC_END_OF_INITIALIZATION ); + + do_callback( SC_END_OF_INITIALIZATION ); +#endif +} + +inline void +sc_phase_callback_registry::simulation_paused() const +{ +#if SC_HAS_PHASE_CALLBACKS_ + do_callback( SC_PAUSED ); +#endif +} + +inline void +sc_phase_callback_registry::simulation_stopped() const +{ +#if SC_HAS_PHASE_CALLBACKS_ + do_callback( SC_STOPPED ); +#endif +} + +inline void +sc_phase_callback_registry::simulation_done() const +{ +#if SC_HAS_PHASE_CALLBACKS_ + do_callback( SC_END_OF_SIMULATION ); +#endif +} + +// -------------- specialized callback implementations -------------- + +#if 0 +inline void +sc_phase_callback_registry::evaluation_done() const +{ +#if SC_HAS_PHASE_CALLBACKS_ + + if( !m_cb_eval_vec.size() ) return; + + typedef single_storage_type::const_iterator it_type; + single_storage_type const & vec = m_cb_eval_vec; + + scoped_status scope( m_simc->m_simulation_status + , SC_END_OF_EVALUATION ); + + for(it_type it = vec.begin(), end = vec.end(); it != end; ++it) + (*it)->do_simulation_phase_callback(); +#endif +} +#endif + +inline void +sc_phase_callback_registry::update_done() const +{ +#if SC_HAS_PHASE_CALLBACKS_ + + if( !m_cb_update_vec.size() ) return; + + typedef single_storage_type::const_iterator it_type; + single_storage_type const & vec = m_cb_update_vec; + + scoped_status scope( m_simc->m_simulation_status + , SC_END_OF_UPDATE ); + + for(it_type it = vec.begin(), end = vec.end(); it != end; ++it) + (*it)->do_simulation_phase_callback(); +#endif +} + +inline void +sc_phase_callback_registry::before_timestep() const +{ +#if SC_HAS_PHASE_CALLBACKS_ + + if( !m_cb_timestep_vec.size() ) return; + + typedef single_storage_type::const_iterator it_type; + single_storage_type const & vec = m_cb_timestep_vec; + + scoped_status scope( m_simc->m_simulation_status + , SC_BEFORE_TIMESTEP ); + + for(it_type it = vec.begin(), end = vec.end(); it != end; ++it) + (*it)->do_simulation_phase_callback(); +#endif +} + +// ------------------------------------------------------------------ + +} // namespace sc_core + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ +#endif /* SC_PHASE_CALLBACK_REGISTRY_H_INCLUDED_ */ +// Taf! + diff --git a/ext/systemc/src/sysc/kernel/sc_process.cpp b/ext/systemc/src/sysc/kernel/sc_process.cpp new file mode 100644 index 000000000..353eddd6a --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_process.cpp @@ -0,0 +1,854 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_process.cpp -- Base process implementation. + + Original Authors: Andy Goodrich, Forte Design Systems, 17 June 2003 + Stuart Swan, Cadence + Bishnupriya Bhattacharya, Cadence Design Systems, + 25 August, 2003 + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + +#include "sysc/kernel/sc_name_gen.h" +#include "sysc/kernel/sc_cthread_process.h" +#include "sysc/kernel/sc_method_process.h" +#include "sysc/kernel/sc_thread_process.h" +#include "sysc/kernel/sc_sensitive.h" +#include "sysc/kernel/sc_process_handle.h" +#include "sysc/kernel/sc_event.h" +#include <sstream> + +namespace sc_core { + +// sc_process_handle entities that are returned for null pointer instances: +// +// Note the special name for 'non_event' - this makes sure it does not +// appear as a named event. + +std::vector<sc_event*> sc_process_handle::empty_event_vector; +std::vector<sc_object*> sc_process_handle::empty_object_vector; +sc_event sc_process_handle::non_event(SC_KERNEL_EVENT_PREFIX); + +// Last process that was created: + +sc_process_b* sc_process_b::m_last_created_process_p = 0; + +//------------------------------------------------------------------------------ +//"sc_process_b::add_static_event" +// +// This method adds an event to the list of static events, and sets the +// event up to call back this process when it fires. +//------------------------------------------------------------------------------ +void sc_process_b::add_static_event( const sc_event& e ) +{ + sc_method_handle method_h; // This process as a method. + sc_thread_handle thread_h; // This process as a thread. + + + // CHECK TO SEE IF WE ARE ALREADY REGISTERED WITH THE EVENT: + + for( int i = m_static_events.size() - 1; i >= 0; -- i ) { + if( &e == m_static_events[i] ) { + return; + } + } + + // REMEMBER THE EVENT AND THEN REGISTER OUR OBJECT INSTANCE WITH IT: + + m_static_events.push_back( &e ); + + switch ( m_process_kind ) + { + case SC_THREAD_PROC_: + case SC_CTHREAD_PROC_: + thread_h = SCAST<sc_thread_handle>( this ); + e.add_static( thread_h ); + break; + case SC_METHOD_PROC_: + method_h = SCAST<sc_method_handle>( this ); + e.add_static( method_h ); + break; + default: + assert( false ); + break; + } +} + +//------------------------------------------------------------------------------ +//"sc_process_b::disconnect_process" +// +// This method removes this object instance from use. It will be called by +// the kill_process() methods of classes derived from it. This object instance +// will be removed from any data structures it resides, other than existence. +//------------------------------------------------------------------------------ +void sc_process_b::disconnect_process() +{ + int mon_n; // monitor queue size. + sc_thread_handle thread_h; // This process as a thread. + + // IF THIS OBJECT IS PINING FOR THE FJORDS WE ARE DONE: + + if ( m_state & ps_bit_zombie ) return; + + // IF THIS IS A THREAD SIGNAL ANY MONITORS WAITING FOR IT TO EXIT: + + switch ( m_process_kind ) + { + case SC_THREAD_PROC_: + case SC_CTHREAD_PROC_: + thread_h = SCAST<sc_thread_handle>(this); + mon_n = thread_h->m_monitor_q.size(); + if ( mon_n ) + { + for ( int mon_i = 0; mon_i < mon_n; mon_i++ ) + { + thread_h->m_monitor_q[mon_i]->signal( thread_h, + sc_process_monitor::spm_exit); + } + } + break; + default: + break; + } + + // REMOVE EVENT WAITS, AND REMOVE THE PROCESS FROM ITS SC_RESET: + + remove_dynamic_events(); + remove_static_events(); + + for ( std::vector<sc_reset*>::size_type rst_i = 0; rst_i < m_resets.size(); rst_i++ ) + { + m_resets[rst_i]->remove_process( this ); + } + m_resets.resize(0); + + + // FIRE THE TERMINATION EVENT, MARK AS TERMINATED, AND DECREMENT THE COUNT: + // + // (1) We wait to set the process kind until after doing the removals + // above. + // (2) Decrementing the reference count will result in actual object + // deletion if we hit zero. + + m_state = ps_bit_zombie; + if ( m_term_event_p ) m_term_event_p->notify(); + reference_decrement(); +} + +//------------------------------------------------------------------------------ +//"sc_process_b::delete_process" +// +// This method deletes the current instance, if it is not the running +// process. Otherwise, it is put in the simcontext's process deletion +// queue. +// +// The reason for the two step deletion process is that the process from which +// reference_decrement() is called may be the running process, so we may need +// to wait until it goes idle. +//------------------------------------------------------------------------------ +void sc_process_b::delete_process() +{ + assert( m_references_n == 0 ); + + // Immediate deletion: + + if ( this != sc_get_current_process_b() ) + { + delete this; + } + + // Deferred deletion: note we set the reference count to one for the call + // to reference_decrement that occurs in sc_simcontext::crunch(). + + else + { + m_references_n = 1; + detach(); + simcontext()->mark_to_collect_process( this ); + } +} + + +//------------------------------------------------------------------------------ +//"sc_process_b::dont_initialize" +// +// This virtual method sets the initialization switch for this object instance. +//------------------------------------------------------------------------------ +void sc_process_b::dont_initialize( bool dont ) +{ + m_dont_init = dont; +} + +//------------------------------------------------------------------------------ +//"sc_process_b::dump_state" +// +// This method returns the process state as a string. +//------------------------------------------------------------------------------ +std::string sc_process_b::dump_state() const +{ + std::string result; + result = "["; + if ( m_state == ps_normal ) + { + result += " normal"; + } + else + { + if ( m_state & ps_bit_disabled ) + result += "disabled "; + if ( m_state & ps_bit_suspended ) + result += "suspended "; + if ( m_state & ps_bit_ready_to_run ) + result += "ready_to_run "; + if ( m_state & ps_bit_zombie ) + result += "zombie "; + } + result += "]"; + return result; +} + + +//------------------------------------------------------------------------------ +//"sc_process_b::gen_unique_name" +// +// This method generates a unique name within this object instance's namespace. +//------------------------------------------------------------------------------ +const char* sc_process_b::gen_unique_name( const char* basename_, + bool preserve_first ) +{ + if ( ! m_name_gen_p ) m_name_gen_p = new sc_name_gen; + return m_name_gen_p->gen_unique_name( basename_, preserve_first ); +} + +//------------------------------------------------------------------------------ +//"sc_process_b::remove_dynamic_events" +// +// This method removes this object instance from the events in its dynamic +// event lists. +// +// Arguments: +// skip_timeout = skip cleaning up the timeout event, it will be done +// by sc_event_notify(). +//------------------------------------------------------------------------------ +void +sc_process_b::remove_dynamic_events( bool skip_timeout ) +{ + sc_method_handle method_h; // This process as a method. + sc_thread_handle thread_h; // This process as a thread. + + m_trigger_type = STATIC; + switch ( m_process_kind ) + { + case SC_THREAD_PROC_: + case SC_CTHREAD_PROC_: + thread_h = SCAST<sc_thread_handle>(this); + if ( thread_h->m_timeout_event_p && !skip_timeout ) { + thread_h->m_timeout_event_p->remove_dynamic(thread_h); + thread_h->m_timeout_event_p->cancel(); + } + if ( m_event_p ) m_event_p->remove_dynamic( thread_h ); + if ( m_event_list_p ) + { + m_event_list_p->remove_dynamic( thread_h, 0 ); + m_event_list_p->auto_delete(); + m_event_list_p = 0; + } + break; + case SC_METHOD_PROC_: + method_h = SCAST<sc_method_handle>(this); + if ( method_h->m_timeout_event_p && !skip_timeout ) { + method_h->m_timeout_event_p->remove_dynamic(method_h); + method_h->m_timeout_event_p->cancel(); + } + if ( m_event_p ) m_event_p->remove_dynamic( method_h ); + if ( m_event_list_p ) + { + m_event_list_p->remove_dynamic( method_h, 0 ); + m_event_list_p->auto_delete(); + m_event_list_p = 0; + } + break; + default: // Some other type, it needs to clean up itself. + // std::cout << "Check " << __FILE__ << ":" << __LINE__ << std::endl; + break; + } +} + +//------------------------------------------------------------------------------ +//"sc_process_b::remove_static_events" +// +// This method removes this object instance from the events in its static +// event list. +//------------------------------------------------------------------------------ +void +sc_process_b::remove_static_events() +{ + sc_method_handle method_h; // This process as a method. + sc_thread_handle thread_h; // This process as a thread. + + switch ( m_process_kind ) + { + case SC_THREAD_PROC_: + case SC_CTHREAD_PROC_: + thread_h = SCAST<sc_thread_handle>( this ); + for( int i = m_static_events.size() - 1; i >= 0; -- i ) { + m_static_events[i]->remove_static( thread_h ); + } + m_static_events.resize(0); + break; + case SC_METHOD_PROC_: + method_h = DCAST<sc_method_handle>( this ); + assert( method_h != 0 ); + for( int i = m_static_events.size() - 1; i >= 0; -- i ) { + m_static_events[i]->remove_static( method_h ); + } + m_static_events.resize(0); + break; + default: // Some other type, it needs to clean up itself. + // std::cout << "Check " << __FILE__ << ":" << __LINE__ << std::endl; + break; + } +} + +//------------------------------------------------------------------------------ +// "sc_process_b::report_error" +// +// This method can be used to issue a report from within a process. +// The error of the given ID is reported with the given message and +// the process' name() appended to the report. +//------------------------------------------------------------------------------ +void +sc_process_b::report_error( const char* msgid, const char* msg ) const +{ + std::stringstream sstr; + if( msg && msg[0] ) + sstr << msg << ": "; + sstr << name(); + SC_REPORT_ERROR( msgid, sstr.str().c_str() ); +} + + +//------------------------------------------------------------------------------ +// "sc_process_b::report_immediate_self_notification" +// +// This method is used to report an immediate self-notification +// that used to trigger the process before the clarification in 1666-2011. +// The warning is only reported once. +//------------------------------------------------------------------------------ +void +sc_process_b::report_immediate_self_notification() const +{ + static bool once = false; + if( !once ) { + SC_REPORT_WARNING( SC_ID_IMMEDIATE_SELF_NOTIFICATION_, name() ); + once = true; + } +} + +//------------------------------------------------------------------------------ +//"sc_process_b::reset_changed" +// +// This method is called when there is a change in the value of the +// signal that was specified via reset_signal_is, or the value of the +// m_sticky_reset field. We get called any time m_sticky_reset changes +// or a signal value changes since, since we may need to throw an exception +// or clear one. Note that this method may be called when there is no +// active process, but rather the main simulator is executing so we must +// check for that case. +// +// Arguments: +// async = true if this is an asynchronous reset. +// asserted = true if reset being asserted, false if being deasserted. +//------------------------------------------------------------------------------ +void sc_process_b::reset_changed( bool async, bool asserted ) +{ + + // Error out on the corner case: + + if ( !sc_allow_process_control_corners && !async && + (m_state & ps_bit_suspended) ) + { + report_error( SC_ID_PROCESS_CONTROL_CORNER_CASE_, + "synchronous reset changed on a suspended process" ); + } + + // IF THIS OBJECT IS PUSHING UP DAISIES WE ARE DONE: + + if ( m_state & ps_bit_zombie ) return; + + // Reset is being asserted: + + if ( asserted ) + { + // if ( m_reset_event_p ) m_reset_event_p->notify(); + if ( async ) + { + m_active_areset_n++; + if ( sc_is_running() ) throw_reset(true); + } + else + { + m_active_reset_n++; + if ( sc_is_running() ) throw_reset(false); + } + } + + // Reset is being deasserted: + + else + { + if ( async ) + { + m_active_areset_n--; + } + else + { + m_active_reset_n--; + } + } + + // Clear the throw type if there are no active resets. + + if ( (m_throw_status == THROW_SYNC_RESET || + m_throw_status == THROW_ASYNC_RESET) && + m_active_areset_n == 0 && m_active_reset_n == 0 && !m_sticky_reset ) + { + m_throw_status = THROW_NONE; + } +} + +//------------------------------------------------------------------------------ +//"sc_process_b::reset_event" +// +// This method returns a reference to the reset event for this object +// instance. If no event exists one is allocated. +//------------------------------------------------------------------------------ +sc_event& sc_process_b::reset_event() +{ + if ( !m_reset_event_p ) + { + m_reset_event_p = new sc_event( + (std::string(SC_KERNEL_EVENT_PREFIX)+"_reset_event").c_str() ); + } + return *m_reset_event_p; +} + +//------------------------------------------------------------------------------ +//"sc_process_b::reset_process" +// +// This inline method changes the reset state of this object instance and +// conditionally its descendants. +// +// Notes: +// (1) It is called for sync_reset_on() and sync_reset_off(). It is not used +// for signal sensitive resets, though all reset flow ends up in +// reset_changed(). +// +// Arguments: +// rt = source of the reset: +// * reset_asynchronous - sc_process_handle::reset() +// * reset_synchronous_off - sc_process_handle::sync_reset_off() +// * reset_synchronous_on - sc_process_handle::sync_reset_on() +// descendants = indication of how to process descendants. +//------------------------------------------------------------------------------ +void sc_process_b::reset_process( reset_type rt, + sc_descendant_inclusion_info descendants ) +{ + + // PROCESS THIS OBJECT INSTANCE'S DESCENDANTS IF REQUESTED TO: + + if ( descendants == SC_INCLUDE_DESCENDANTS ) + { + const std::vector<sc_object*> children = get_child_objects(); + int child_n = children.size(); + + for ( int child_i = 0; child_i < child_n; child_i++ ) + { + sc_process_b* child_p = DCAST<sc_process_b*>(children[child_i]); + if ( child_p ) child_p->reset_process(rt, descendants); + } + } + + // PROCESS THIS OBJECT INSTANCE: + + switch (rt) + { + // One-shot asynchronous reset: remove dynamic sensitivity and throw: + // + // If this is an sc_method only throw if it is active. + + case reset_asynchronous: + if ( sc_get_status() != SC_RUNNING ) + { + report_error(SC_ID_RESET_PROCESS_WHILE_NOT_RUNNING_); + } + else + { + remove_dynamic_events(); + throw_reset(true); + } + break; + + // Turn on sticky synchronous reset: use standard reset mechanism. + + case reset_synchronous_on: + if ( m_sticky_reset == false ) + { + m_sticky_reset = true; + reset_changed( false, true ); + } + break; + + // Turn off sticky synchronous reset: use standard reset mechanism. + + default: + if ( m_sticky_reset == true ) + { + m_sticky_reset = false; + reset_changed( false, false ); + } + break; + } +} + +//------------------------------------------------------------------------------ +//"sc_process_b::sc_process_b" +// +// This is the object instance constructor for this class. +//------------------------------------------------------------------------------ +sc_process_b::sc_process_b( const char* name_p, bool is_thread, bool free_host, + SC_ENTRY_FUNC method_p, sc_process_host* host_p, + const sc_spawn_options* /* opt_p */ +) : + sc_object( name_p ), + file(0), + lineno(0), + proc_id( simcontext()->next_proc_id()), + m_active_areset_n(0), + m_active_reset_n(0), + m_dont_init( false ), + m_dynamic_proc( simcontext()->elaboration_done() ), + m_event_p(0), + m_event_count(0), + m_event_list_p(0), + m_exist_p(0), + m_free_host( free_host ), + m_has_reset_signal( false ), + m_has_stack(false), + m_is_thread(is_thread), + m_last_report_p(0), + m_name_gen_p(0), + m_process_kind(SC_NO_PROC_), + m_references_n(1), + m_resets(), + m_reset_event_p(0), + m_resume_event_p(0), + m_runnable_p(0), + m_semantics_host_p( host_p ), + m_semantics_method_p ( method_p ), + m_state(ps_normal), + m_static_events(), + m_sticky_reset(false), + m_term_event_p(0), + m_throw_helper_p(0), + m_throw_status( THROW_NONE ), + m_timed_out(false), + m_timeout_event_p(0), + m_trigger_type(STATIC), + m_unwinding(false) +{ + + // THIS OBJECT INSTANCE IS NOW THE LAST CREATED PROCESS: + + m_last_created_process_p = this; + m_timeout_event_p = new sc_event( + (std::string(SC_KERNEL_EVENT_PREFIX)+"_free_event").c_str() ); +} + +//------------------------------------------------------------------------------ +//"sc_process_b::~sc_process_b" +// +// This is the object instance destructor for this class. +//------------------------------------------------------------------------------ +sc_process_b::~sc_process_b() +{ + + // REDIRECT ANY CHILDREN AS CHILDREN OF THE SIMULATION CONTEXT: + + orphan_child_objects(); + + + // DELETE SEMANTICS OBJECTS IF NEED BE: + + if ( m_free_host ) delete m_semantics_host_p; +# if !defined(SC_USE_MEMBER_FUNC_PTR) // Remove invocation object. + delete m_semantics_method_p; +# endif + + + // REMOVE ANY STRUCTURES THAT MAY HAVE BEEN BUILT: + + delete m_last_report_p; + delete m_name_gen_p; + delete m_reset_event_p; + delete m_resume_event_p; + delete m_term_event_p; + delete m_throw_helper_p; + delete m_timeout_event_p; + +} + +//------------------------------------------------------------------------------ +//"sc_process_b::terminated_event" +// +// This method returns a reference to the terminated event for this object +// instance. If no event exists one is allocated. +//------------------------------------------------------------------------------ +sc_event& sc_process_b::terminated_event() +{ + if ( !m_term_event_p ) + { + m_term_event_p = new sc_event( + (std::string(SC_KERNEL_EVENT_PREFIX)+"_term_event").c_str() ); + } + return *m_term_event_p; +} + +// +---------------------------------------------------------------------------- +// |"sc_process_b::trigger_reset_event" +// | +// | This method triggers the notify event. It exists because we can't get +// | sc_event context in sc_process.h because the includes would be +// | circular... sigh... +// +---------------------------------------------------------------------------- +void sc_process_b::trigger_reset_event() +{ + if ( m_reset_event_p ) m_reset_event_p->notify(); +} + +//------------------------------------------------------------------------------ +//"sc_process_handle::operator sc_cthread_handle" +// +//------------------------------------------------------------------------------ +sc_process_handle::operator sc_cthread_handle() +{ + return DCAST<sc_cthread_handle>(m_target_p); +} + +//------------------------------------------------------------------------------ +//"sc_process_handle::sc_method_handle" +// +//------------------------------------------------------------------------------ +sc_process_handle::operator sc_method_handle() +{ + return DCAST<sc_method_handle>(m_target_p); +} + +//------------------------------------------------------------------------------ +//"sc_process_handle::sc_thread_handle" +// +//------------------------------------------------------------------------------ +sc_process_handle::operator sc_thread_handle() +{ + return DCAST<sc_thread_handle>(m_target_p); +} + +} // namespace sc_core + + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: Andy Goodrich, Forte Design Systems, 12 Aug 05 + Description of Modification: This is the rewrite of process support. It + contains some code from the now-defunct + sc_process_b.cpp, as well as the former + version of sc_process_b.cpp. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + +// $Log: sc_process.cpp,v $ +// Revision 1.37 2011/08/24 22:05:51 acg +// Torsten Maehne: initialization changes to remove warnings. +// +// Revision 1.36 2011/08/15 16:43:24 acg +// Torsten Maehne: changes to remove unused argument warnings. +// +// Revision 1.35 2011/08/07 19:08:04 acg +// Andy Goodrich: moved logs to end of file so line number synching works +// better between versions. +// +// Revision 1.34 2011/07/29 22:55:01 acg +// Philipp A. Hartmann: add missing include. +// +// Revision 1.33 2011/07/29 22:43:41 acg +// Philipp A. Hartmann: changes to handle case where a process control +// invocation on a child process causes the list of child processes to change. +// +// Revision 1.32 2011/07/24 11:20:03 acg +// Philipp A. Hartmann: process control error message improvements: +// (1) Downgrade error to warning for re-kills of processes. +// (2) Add process name to process messages. +// (3) drop some superfluous colons in messages. +// +// Revision 1.31 2011/04/19 15:04:27 acg +// Philipp A. Hartmann: clean up SC_ID messages. +// +// Revision 1.30 2011/04/14 22:33:43 acg +// Andy Goodrich: added missing checks for a process being a zombie. +// +// Revision 1.29 2011/04/13 05:00:43 acg +// Andy Goodrich: removed check for method process in termination_event() +// since with the new IEEE 1666 2011 its legal. +// +// Revision 1.28 2011/04/13 02:44:26 acg +// Andy Goodrich: added m_unwinding flag in place of THROW_NOW because the +// throw status will be set back to THROW_*_RESET if reset is active and +// the check for an unwind being complete was expecting THROW_NONE as the +// clearing of THROW_NOW. +// +// Revision 1.27 2011/04/10 22:17:35 acg +// Andy Goodrich: added trigger_reset_event() to allow sc_process.h to +// contain the run_process() inline method. sc_process.h cannot have +// sc_simcontext information because of recursive includes. +// +// Revision 1.26 2011/04/08 22:33:08 acg +// Andy Goodrich: moved the semantics() method to the header file and made +// it an inline method. +// +// Revision 1.25 2011/04/08 18:24:48 acg +// Andy Goodrich: moved reset_changed() to .cpp since it needs visibility +// to sc_simcontext. +// +// Revision 1.24 2011/04/05 20:50:57 acg +// Andy Goodrich: +// (1) changes to make sure that event(), posedge() and negedge() only +// return true if the clock has not moved. +// (2) fixes for method self-resumes. +// (3) added SC_PRERELEASE_VERSION +// (4) removed kernel events from the object hierarchy, added +// sc_hierarchy_name_exists(). +// +// Revision 1.23 2011/04/05 06:25:38 acg +// Andy Goodrich: new checks for simulation running in reset_process(). +// +// Revision 1.22 2011/03/20 13:43:23 acg +// Andy Goodrich: added async_signal_is() plus suspend() as a corner case. +// +// Revision 1.21 2011/03/12 21:07:51 acg +// Andy Goodrich: changes to kernel generated event support. +// +// Revision 1.20 2011/03/07 17:38:43 acg +// Andy Goodrich: tightening up of checks for undefined interaction between +// synchronous reset and suspend. +// +// Revision 1.19 2011/03/06 23:30:13 acg +// Andy Goodrich: refining suspend - sync reset corner case checking so that +// the following are error situations: +// (1) Calling suspend on a process with a reset_signal_is() specification +// or sync_reset_on() is active. +// (2) Calling sync_reset_on() on a suspended process. +// +// Revision 1.18 2011/03/06 19:57:11 acg +// Andy Goodrich: refinements for the illegal suspend - synchronous reset +// interaction. +// +// Revision 1.17 2011/03/06 16:47:09 acg +// Andy Goodrich: changes for testing sync_reset - suspend corner cases. +// +// Revision 1.16 2011/03/06 15:57:57 acg +// Andy Goodrich: added process control corner case checks. Changes for +// named events. +// +// Revision 1.15 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.14 2011/02/17 19:52:13 acg +// Andy Goodrich: +// (1) Simplfied process control usage. +// (2) Changed dump_status() to dump_state with new signature. +// +// Revision 1.13 2011/02/13 21:47:37 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.12 2011/02/13 21:41:34 acg +// Andy Goodrich: get the log messages for the previous check in correct. +// +// Revision 1.11 2011/02/13 21:32:24 acg +// Andy Goodrich: moved sc_process_b::reset_process() from header file +// to cpp file. Added dump_status() to print out the status of a +// process. +// +// Revision 1.10 2011/02/04 15:27:36 acg +// Andy Goodrich: changes for suspend-resume semantics. +// +// Revision 1.9 2011/02/01 21:06:12 acg +// Andy Goodrich: new layout for the process_state enum. +// +// Revision 1.8 2011/01/25 20:50:37 acg +// Andy Goodrich: changes for IEEE 1666 2011. +// +// Revision 1.7 2011/01/19 23:21:50 acg +// Andy Goodrich: changes for IEEE 1666 2011 +// +// Revision 1.6 2011/01/18 20:10:45 acg +// Andy Goodrich: changes for IEEE1666_2011 semantics. +// +// Revision 1.5 2010/07/22 20:02:33 acg +// Andy Goodrich: bug fixes. +// +// Revision 1.4 2009/05/22 16:06:29 acg +// Andy Goodrich: process control updates. +// +// Revision 1.3 2008/05/22 17:06:26 acg +// Andy Goodrich: updated copyright notice to include 2008. +// +// Revision 1.2 2007/09/20 20:32:35 acg +// Andy Goodrich: changes to the semantics of throw_it() to match the +// specification. A call to throw_it() will immediately suspend the calling +// thread until all the throwees have executed. At that point the calling +// thread will be restarted before the execution of any other threads. +// +// Revision 1.1.1.1 2006/12/15 20:20:05 acg +// SystemC 2.3 +// +// Revision 1.6 2006/04/20 17:08:17 acg +// Andy Goodrich: 3.0 style process changes. +// +// Revision 1.5 2006/04/11 23:13:21 acg +// Andy Goodrich: Changes for reduced reset support that only includes +// sc_cthread, but has preliminary hooks for expanding to method and thread +// processes also. +// +// Revision 1.4 2006/01/24 20:49:05 acg +// Andy Goodrich: changes to remove the use of deprecated features within the +// simulator, and to issue warning messages when deprecated features are used. +// +// Revision 1.3 2006/01/13 18:44:30 acg +// Added $Log to record CVS changes into the source. +// diff --git a/ext/systemc/src/sysc/kernel/sc_process.h b/ext/systemc/src/sysc/kernel/sc_process.h new file mode 100644 index 000000000..298e2462f --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_process.h @@ -0,0 +1,887 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_process.h -- Process base class support. + + Original Author: Andy Goodrich, Forte Design Systems, 04 August 2005 + + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + + +#if !defined(sc_process_h_INCLUDED) +#define sc_process_h_INCLUDED + +#include <cassert> +#include "sysc/utils/sc_iostream.h" +#include "sysc/kernel/sc_constants.h" +#include "sysc/kernel/sc_object.h" +#include "sysc/kernel/sc_kernel_ids.h" +#include "sysc/communication/sc_export.h" + +namespace sc_core { + +// Forward declarations: +class sc_process_handle; +class sc_thread_process; +class sc_reset; + +const char* sc_gen_unique_name( const char*, bool preserve_first ); +sc_process_handle sc_get_current_process_handle(); +void sc_thread_cor_fn( void* arg ); +bool timed_out( sc_simcontext* ); + +extern bool sc_allow_process_control_corners; // see sc_simcontext.cpp. + + +// Process handles as forward references: + +typedef class sc_cthread_process* sc_cthread_handle; +typedef class sc_method_process* sc_method_handle; +typedef class sc_thread_process* sc_thread_handle; + + +// Standard process types: + +enum sc_curr_proc_kind +{ + SC_NO_PROC_, + SC_METHOD_PROC_, + SC_THREAD_PROC_, + SC_CTHREAD_PROC_ +}; + +// Descendant information for process hierarchy operations: + +enum sc_descendant_inclusion_info { + SC_NO_DESCENDANTS=0, + SC_INCLUDE_DESCENDANTS, + SC_INVALID_DESCENDANTS +}; + +//============================================================================== +// CLASS sc_process_host +// +// This is the base class for objects which may have processes defined for +// their methods (e.g., sc_module) +//============================================================================== + +class sc_process_host +{ + public: + sc_process_host() {} + virtual ~sc_process_host() { } // Needed for cast check for sc_module. + void defunct() {} +}; + + +//============================================================================== +// CLASS sc_process_monitor +// +// This class provides a way of monitoring a process' status (e.g., waiting +// for a thread to complete its execution.) This class is intended to be a base +// class for classes which need to monitor a process or processes (e.g., +// sc_join.) Its methods should be overloaded where notifications are desired. +//============================================================================== + +class sc_process_monitor { + public: + enum { + spm_exit = 0 + }; + virtual ~sc_process_monitor() {} + virtual void signal(sc_thread_handle thread_p, int type); +}; +inline void sc_process_monitor::signal(sc_thread_handle , int ) {} + +//------------------------------------------------------------------------------ +// PROCESS INVOCATION METHOD OR FUNCTION: +// +// Define SC_USE_MEMBER_FUNC_PTR if we want to use member function pointers +// to implement process dispatch. Otherwise, we'll use a hack that involves +// creating a templated invocation object which will invoke the member +// function. This should not be necessary, but some compilers (e.g., VC++) +// do not allow the conversion from `void (callback_tag::*)()' to +// `void (sc_process_host::*)()'. This is supposed to be OK as long as the +// dynamic type is correct. C++ Standard 5.4 "Explicit type conversion", +// clause 7: a pointer to member of derived class type may be explicitly +// converted to a pointer to member of an unambiguous non-virtual base class +// type. +//----------------------------------------------------------------------------- + +#if defined(_MSC_VER) +#if ( _MSC_VER > 1200 ) +# define SC_USE_MEMBER_FUNC_PTR +#endif +#else +# define SC_USE_MEMBER_FUNC_PTR +#endif + + +// COMPILER DOES SUPPORT CAST TO void (sc_process_host::*)() from (T::*)(): + +#if defined(SC_USE_MEMBER_FUNC_PTR) + + typedef void (sc_process_host::*SC_ENTRY_FUNC)(); +# define SC_DECL_HELPER_STRUCT(callback_tag, func) /*EMPTY*/ +# define SC_MAKE_FUNC_PTR(callback_tag, func) \ + static_cast<sc_core::SC_ENTRY_FUNC>(&callback_tag::func) + + +// COMPILER NOT DOES SUPPORT CAST TO void (sc_process_host::*)() from (T::*)(): + +#else // !defined(SC_USE_MEMBER_FUNC_PTR) + class sc_process_call_base { + public: + inline sc_process_call_base() + { + } + + virtual ~sc_process_call_base() + { + } + + virtual void invoke(sc_process_host* host_p) + { + } + }; + extern sc_process_call_base sc_process_defunct; + + template<class T> + class sc_process_call : public sc_process_call_base { + public: + sc_process_call( void (T::*method_p)() ) : + sc_process_call_base() + { + m_method_p = method_p; + } + + virtual ~sc_process_call() + { + } + + virtual void invoke(sc_process_host* host_p) + { + (((T*)host_p)->*m_method_p)(); + } + + protected: + void (T::*m_method_p)(); // Method implementing the process. + }; + + typedef sc_process_call_base* SC_ENTRY_FUNC; +# define SC_DECL_HELPER_STRUCT(callback_tag, func) /*EMPTY*/ +# define SC_MAKE_FUNC_PTR(callback_tag, func) \ + (::sc_core::SC_ENTRY_FUNC) (new \ + ::sc_core::sc_process_call<callback_tag>(&callback_tag::func)) + +#endif // !defined(SC_USE_MEMBER_FUNC_PTR) + + +extern void sc_set_stack_size( sc_thread_handle, std::size_t ); + +class sc_event; +class sc_event_list; +class sc_name_gen; +class sc_spawn_options; +class sc_unwind_exception; + +//============================================================================== +// CLASS sc_throw_it<EXCEPT> - ARBITRARY EXCEPTION CLASS +// +// This class serves as a way of throwing an execption for an aribtrary type +// without knowing what that type is. A true virtual method in the base +// class is used to actually throw the execption. A pointer to the base +// class is used internally removing the necessity of knowing what the type +// of EXCEPT is for code internal to the library. +// +// Note the clone() true virtual method. This is used to allow instances +// of the sc_throw_it<EXCEPT> class to be easily garbage collected. Since +// an exception may be propogated to more than one process knowing when +// to garbage collect is non-trivial. So when a call is made to +// sc_process_handle::throw_it() an instance of sc_throw_it<EXCEPT> is +// allocated on the stack. For each process throwing the exception a copy is +// made via clone(). That allows those objects to be deleted by the individual +// processes when they are no longer needed (in this implementation of SystemC +// that deletion will occur each time a new exception is thrown ( see +// sc_thread_process::suspend_me() ). +//============================================================================== +class sc_throw_it_helper { + public: + virtual sc_throw_it_helper* clone() const = 0; + virtual void throw_it() = 0; + sc_throw_it_helper() {} + virtual ~sc_throw_it_helper() {} +}; + +template<typename EXCEPT> +class sc_throw_it : public sc_throw_it_helper +{ + typedef sc_throw_it<EXCEPT> this_type; + public: + sc_throw_it( const EXCEPT& value ) : m_value(value) { } + virtual ~sc_throw_it() {} + virtual inline this_type* clone() const { return new this_type(m_value); } + virtual inline void throw_it() { throw m_value; } + protected: + EXCEPT m_value; // value to be thrown. +}; + +//============================================================================== +// CLASS sc_process_b - USER INITIATED DYNAMIC PROCESS SUPPORT: +// +// This class implements the base class for a threaded process_base process +// whose semantics are provided by the true virtual method semantics(). +// Classes derived from this one will provide a version of semantics which +// implements the desired semantics. See the sc_spawn_xxx classes below. +// +// Notes: +// (1) Object instances of this class maintain a reference count of +// outstanding handles. When the handle count goes to zero the +// object will be deleted. +// (2) Descriptions of the methods and operators in this class appear with +// their implementations. +// (3) The m_sticky_reset field is used to handle synchronous resets that +// are enabled via the sc_process_handle::sync_reset_on() method. These +// resets are not generated by a signal, but rather are modal by +// method call: sync_reset_on - sync_reset_off. +// +//============================================================================== +class sc_process_b : public sc_object { + friend class sc_simcontext; // Allow static processes to have base. + friend class sc_cthread_process; // Child can access parent. + friend class sc_method_process; // Child can access parent. + friend class sc_process_handle; // Allow handles to modify ref. count. + friend class sc_thread_process; // Child can access parent. + + friend class sc_object; + friend class sc_port_base; + friend class sc_runnable; + friend class sc_sensitive; + friend class sc_sensitive_pos; + friend class sc_sensitive_neg; + friend class sc_module; + friend class sc_report_handler; + friend class sc_reset; + friend class sc_reset_finder; + friend class sc_unwind_exception; + + friend const char* sc_gen_unique_name( const char*, bool preserve_first ); + friend sc_process_handle sc_get_current_process_handle(); + friend void sc_thread_cor_fn( void* arg ); + friend bool timed_out( sc_simcontext* ); + + public: + enum process_throw_type { + THROW_NONE = 0, + THROW_KILL, + THROW_USER, + THROW_ASYNC_RESET, + THROW_SYNC_RESET + }; + + enum process_state { + ps_bit_disabled = 1, // process is disabled. + ps_bit_ready_to_run = 2, // process is ready to run. + ps_bit_suspended = 4, // process is suspended. + ps_bit_zombie = 8, // process is a zombie. + ps_normal = 0 // must be zero. + }; + + enum reset_type { // types for sc_process_b::reset_process() + reset_asynchronous = 0, // asynchronous reset. + reset_synchronous_off, // turn off synchronous reset sticky bit. + reset_synchronous_on // turn on synchronous reset sticky bit. + }; + + enum trigger_t + { + STATIC, + EVENT, + OR_LIST, + AND_LIST, + TIMEOUT, + EVENT_TIMEOUT, + OR_LIST_TIMEOUT, + AND_LIST_TIMEOUT + }; + + public: + sc_process_b( const char* name_p, bool is_thread, bool free_host, + SC_ENTRY_FUNC method_p, sc_process_host* host_p, + const sc_spawn_options* opt_p ); + + protected: + // may not be deleted manually (called from destroy_process()) + virtual ~sc_process_b(); + + public: + inline int current_state() { return m_state; } + bool dont_initialize() const { return m_dont_init; } + virtual void dont_initialize( bool dont ); + std::string dump_state() const; + const ::std::vector<sc_object*>& get_child_objects() const; + inline sc_curr_proc_kind proc_kind() const; + sc_event& reset_event(); + sc_event& terminated_event(); + + public: + static inline sc_process_handle last_created_process_handle(); + + protected: + virtual void add_child_object( sc_object* ); + void add_static_event( const sc_event& ); + bool dynamic() const { return m_dynamic_proc; } + const char* gen_unique_name( const char* basename_, bool preserve_first ); + inline sc_report* get_last_report() { return m_last_report_p; } + inline bool is_disabled() const; + inline bool is_runnable() const; + static inline sc_process_b* last_created_process_base(); + virtual bool remove_child_object( sc_object* ); + void remove_dynamic_events( bool skip_timeout = false ); + void remove_static_events(); + inline void set_last_report( sc_report* last_p ) + { + delete m_last_report_p; + m_last_report_p = last_p; + } + inline bool timed_out() const; + void report_error( const char* msgid, const char* msg = "" ) const; + void report_immediate_self_notification() const; + + protected: // process control methods: + virtual void disable_process( + sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS ) = 0; + void disconnect_process(); + virtual void enable_process( + sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS ) = 0; + inline void initially_in_reset( bool async ); + inline bool is_unwinding() const; + inline bool start_unwinding(); + inline bool clear_unwinding(); + virtual void kill_process( + sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS ) = 0; + void reset_changed( bool async, bool asserted ); + void reset_process( reset_type rt, + sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS ); + virtual void resume_process( + sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS ) = 0; + virtual void suspend_process( + sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS ) = 0; + virtual void throw_user( const sc_throw_it_helper& helper, + sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS ) = 0; + virtual void throw_reset( bool async ) = 0; + virtual bool terminated() const; + void trigger_reset_event(); + + private: + void delete_process(); + inline void reference_decrement(); + inline void reference_increment(); + + protected: + inline void semantics(); + + // debugging stuff: + + public: + const char* file; + int lineno; + int proc_id; + + protected: + int m_active_areset_n; // number of aresets active. + int m_active_reset_n; // number of resets active. + bool m_dont_init; // true: no initialize call. + bool m_dynamic_proc; // true: after elaboration. + const sc_event* m_event_p; // Dynamic event waiting on. + int m_event_count; // number of events. + const sc_event_list* m_event_list_p; // event list waiting on. + sc_process_b* m_exist_p; // process existence link. + bool m_free_host; // free sc_semantic_host_p. + bool m_has_reset_signal; // has reset_signal_is. + bool m_has_stack; // true is stack present. + bool m_is_thread; // true if this is thread. + sc_report* m_last_report_p; // last report this process. + sc_name_gen* m_name_gen_p; // subprocess name generator + sc_curr_proc_kind m_process_kind; // type of process. + int m_references_n; // outstanding handles. + std::vector<sc_reset*> m_resets; // resets for process. + sc_event* m_reset_event_p; // reset event. + sc_event* m_resume_event_p; // resume event. + sc_process_b* m_runnable_p; // sc_runnable link + sc_process_host* m_semantics_host_p; // host for semantics. + SC_ENTRY_FUNC m_semantics_method_p; // method for semantics. + int m_state; // process state. + std::vector<const sc_event*> m_static_events; // static events waiting on. + bool m_sticky_reset; // see note 3 above. + sc_event* m_term_event_p; // terminated event. + sc_throw_it_helper* m_throw_helper_p; // what to throw. + process_throw_type m_throw_status; // exception throwing status + bool m_timed_out; // true if we timed out. + sc_event* m_timeout_event_p; // timeout event. + trigger_t m_trigger_type; // type of trigger using. + bool m_unwinding; // true if unwinding stack. + + protected: + static sc_process_b* m_last_created_process_p; // Last process created. +}; + +typedef sc_process_b sc_process_b; // For compatibility. + + +//------------------------------------------------------------------------------ +//"sc_process_b::XXXX_child_YYYYY" +// +// These methods provide child object support. +//------------------------------------------------------------------------------ +inline void +sc_process_b::add_child_object( sc_object* object_p ) +{ + sc_object::add_child_object( object_p ); + reference_increment(); +} + +inline bool +sc_process_b::remove_child_object( sc_object* object_p ) +{ + if ( sc_object::remove_child_object( object_p ) ) { + reference_decrement(); + return true; + } + else + { + return false; + } +} + +inline const ::std::vector<sc_object*>& +sc_process_b::get_child_objects() const +{ + return m_child_objects; +} + + +//------------------------------------------------------------------------------ +//"sc_process_b::initially_in_reset" +// +// This inline method is a callback to indicate that a reset is active at +// start up. This is because the signal will have been initialized before +// a reset linkage for it is set up, so we won't get a reset_changed() +// callback. +// async = true if this an asynchronous reset. +//------------------------------------------------------------------------------ +inline void sc_process_b::initially_in_reset( bool async ) +{ + if ( async ) + m_active_areset_n++; + else + m_active_reset_n++; +} + +//------------------------------------------------------------------------------ +//"sc_process_b::is_disabled" +// +// This method returns true if this process is disabled. +//------------------------------------------------------------------------------ +inline bool sc_process_b::is_disabled() const +{ + return (m_state & ps_bit_disabled) ? true : false; +} + +//------------------------------------------------------------------------------ +//"sc_process_b::is_runnable" +// +// This method returns true if this process is runnable. That is indicated +// by a non-zero m_runnable_p field. +//------------------------------------------------------------------------------ +inline bool sc_process_b::is_runnable() const +{ + return m_runnable_p != 0; +} + +//------------------------------------------------------------------------------ +//"sc_process_b::is_unwinding" +// +// This method returns true if this process is unwinding from a kill or reset. +//------------------------------------------------------------------------------ +inline bool sc_process_b::is_unwinding() const +{ + return m_unwinding; +} + +//------------------------------------------------------------------------------ +//"sc_process_b::start_unwinding" +// +// This method flags that this object instance should start unwinding if the +// current throw status requires an unwind. +// +// Result is true if the flag is set, false if the flag is already set. +//------------------------------------------------------------------------------ +inline bool sc_process_b::start_unwinding() +{ + if ( !m_unwinding ) + { + switch( m_throw_status ) + { + case THROW_KILL: + case THROW_ASYNC_RESET: + case THROW_SYNC_RESET: + m_unwinding = true; + return true; + case THROW_USER: + default: + break; + } + } + return false; +} + +//------------------------------------------------------------------------------ +//"sc_process_b::clear_unwinding" +// +// This method clears this object instance's throw status and always returns +// true. +//------------------------------------------------------------------------------ +inline bool sc_process_b::clear_unwinding() +{ + m_unwinding = false; + return true; +} + + +//------------------------------------------------------------------------------ +//"sc_process_b::last_created_process_base" +// +// This virtual method returns the sc_process_b pointer for the last +// created process. It is only used internally by the simulator. +//------------------------------------------------------------------------------ +inline sc_process_b* sc_process_b::last_created_process_base() +{ + return m_last_created_process_p; +} + + + +//------------------------------------------------------------------------------ +//"sc_process_b::proc_kind" +// +// This method returns the kind of this process. +//------------------------------------------------------------------------------ +inline sc_curr_proc_kind sc_process_b::proc_kind() const +{ + return m_process_kind; +} + + +//------------------------------------------------------------------------------ +//"sc_process_b::reference_decrement" +// +// This inline method decrements the number of outstanding references to this +// object instance. If the number of references goes to zero, this object +// can be deleted in "sc_process_b::delete_process()". +//------------------------------------------------------------------------------ +inline void sc_process_b::reference_decrement() +{ + m_references_n--; + if ( m_references_n == 0 ) delete_process(); +} + + +//------------------------------------------------------------------------------ +//"sc_process_b::reference_increment" +// +// This inline method increments the number of outstanding references to this +// object instance. +//------------------------------------------------------------------------------ +inline void sc_process_b::reference_increment() +{ + assert(m_references_n != 0); + m_references_n++; +} + +//------------------------------------------------------------------------------ +//"sc_process_b::semantics" +// +// This inline method invokes the semantics for this object instance. +// We check to see if we are initially in reset and then invoke the +// process semantics. +// +// Notes: +// (1) For a description of the process reset mechanism see the top of +// the file sc_reset.cpp. +//------------------------------------------------------------------------------ +struct scoped_flag +{ + scoped_flag( bool& b ) : ref(b){ ref = true; } + ~scoped_flag() { ref = false; } + bool& ref; +}; +inline void sc_process_b::semantics() +{ + + // within this function, the process has a stack associated + + scoped_flag scoped_stack_flag( m_has_stack ); + + assert( m_process_kind != SC_NO_PROC_ ); + + // Determine the reset status of this object instance and potentially + // trigger its notify event: + + // See if we need to trigger the notify event: + + if ( m_reset_event_p && + ( (m_throw_status == THROW_SYNC_RESET) || + (m_throw_status == THROW_ASYNC_RESET) ) + ) { + trigger_reset_event(); + } + + // Set the new reset status of this object based on the reset counts: + + m_throw_status = m_active_areset_n ? THROW_ASYNC_RESET : + ( m_active_reset_n ? THROW_SYNC_RESET : THROW_NONE); + + // Dispatch the actual semantics for the process: + +# ifndef SC_USE_MEMBER_FUNC_PTR + m_semantics_method_p->invoke( m_semantics_host_p ); +# else + (m_semantics_host_p->*m_semantics_method_p)(); +# endif +} + + +//------------------------------------------------------------------------------ +//"sc_process_b::terminated" +// +// This inline method returns true if this object has terminated. +//------------------------------------------------------------------------------ +inline bool sc_process_b::terminated() const +{ + return (m_state & ps_bit_zombie) != 0; +} + + +//------------------------------------------------------------------------------ +//"sc_process_b::timed_out" +// +// This inline method returns true if this object instance timed out. +//------------------------------------------------------------------------------ +inline bool sc_process_b::timed_out() const +{ + return m_timed_out; +} + +} // namespace sc_core + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: Andy Goodrich, Forte Design Systems, 12 Aug 05 + Description of Modification: This is the rewrite of process support. It + contains some code from the original + sc_process.h by Stan Liao, and the now-defunct + sc_process_b.h by Stan Liao and Martin + Janssen, all of Synopsys, Inc., It also contains + code from the original sc_process_b.h by + Andy Goodrich of Forte Design Systems and + Bishnupriya Bhattacharya of Cadence Design + Systems. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + +// $Log: sc_process.h,v $ +// Revision 1.36 2011/08/26 22:44:30 acg +// Torsten Maehne: eliminate unused argument warning. +// +// Revision 1.35 2011/08/26 20:46:10 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +// Revision 1.34 2011/08/24 22:05:51 acg +// Torsten Maehne: initialization changes to remove warnings. +// +// Revision 1.33 2011/08/15 16:43:24 acg +// Torsten Maehne: changes to remove unused argument warnings. +// +// Revision 1.32 2011/07/24 11:20:03 acg +// Philipp A. Hartmann: process control error message improvements: +// (1) Downgrade error to warning for re-kills of processes. +// (2) Add process name to process messages. +// (3) drop some superfluous colons in messages. +// +// Revision 1.31 2011/04/13 02:44:26 acg +// Andy Goodrich: added m_unwinding flag in place of THROW_NOW because the +// throw status will be set back to THROW_*_RESET if reset is active and +// the check for an unwind being complete was expecting THROW_NONE as the +// clearing of THROW_NOW. +// +// Revision 1.30 2011/04/11 22:07:27 acg +// Andy Goodrich: check for reset event notification before resetting the +// throw_status value. +// +// Revision 1.29 2011/04/10 22:17:36 acg +// Andy Goodrich: added trigger_reset_event() to allow sc_process.h to +// contain the run_process() inline method. sc_process.h cannot have +// sc_simcontext information because of recursive includes. +// +// Revision 1.28 2011/04/08 22:34:06 acg +// Andy Goodrich: moved the semantics() method to this file and made it +// an inline method. Added reset processing to the semantics() method. +// +// Revision 1.27 2011/04/08 18:24:48 acg +// Andy Goodrich: moved reset_changed() to .cpp since it needs visibility +// to sc_simcontext. +// +// Revision 1.26 2011/04/01 21:24:57 acg +// Andy Goodrich: removed unused code. +// +// Revision 1.25 2011/03/28 13:02:51 acg +// Andy Goodrich: Changes for disable() interactions. +// +// Revision 1.24 2011/03/20 13:43:23 acg +// Andy Goodrich: added async_signal_is() plus suspend() as a corner case. +// +// Revision 1.23 2011/03/12 21:07:51 acg +// Andy Goodrich: changes to kernel generated event support. +// +// Revision 1.22 2011/03/08 20:49:31 acg +// Andy Goodrich: implement coarse checking for synchronous reset - suspend +// interaction. +// +// Revision 1.21 2011/03/07 17:38:43 acg +// Andy Goodrich: tightening up of checks for undefined interaction between +// synchronous reset and suspend. +// +// Revision 1.20 2011/03/06 19:57:11 acg +// Andy Goodrich: refinements for the illegal suspend - synchronous reset +// interaction. +// +// Revision 1.19 2011/03/05 19:44:20 acg +// Andy Goodrich: changes for object and event naming and structures. +// +// Revision 1.18 2011/02/19 08:30:53 acg +// Andy Goodrich: Moved process queueing into trigger_static from +// sc_event::notify. +// +// Revision 1.17 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.16 2011/02/18 20:10:44 acg +// Philipp A. Hartmann: force return expression to be a bool to keep MSVC +// happy. +// +// Revision 1.15 2011/02/17 19:52:45 acg +// Andy Goodrich: +// (1) Simplified process control usage. +// (2) Changed dump_status() to dump_state() with new signature. +// +// Revision 1.14 2011/02/16 22:37:30 acg +// Andy Goodrich: clean up to remove need for ps_disable_pending. +// +// Revision 1.13 2011/02/13 21:47:37 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.12 2011/02/13 21:41:34 acg +// Andy Goodrich: get the log messages for the previous check in correct. +// +// Revision 1.11 2011/02/13 21:32:24 acg +// Andy Goodrich: moved sc_process_b::reset_process() implementation +// from header to cpp file . Added dump_status() to print out the status of a +// process. +// +// Revision 1.10 2011/02/11 13:25:24 acg +// Andy Goodrich: Philipp A. Hartmann's changes: +// (1) Removal of SC_CTHREAD method overloads. +// (2) New exception processing code. +// +// Revision 1.9 2011/02/04 15:27:36 acg +// Andy Goodrich: changes for suspend-resume semantics. +// +// Revision 1.8 2011/02/01 21:06:12 acg +// Andy Goodrich: new layout for the process_state enum. +// +// Revision 1.7 2011/01/25 20:50:37 acg +// Andy Goodrich: changes for IEEE 1666 2011. +// +// Revision 1.6 2011/01/19 23:21:50 acg +// Andy Goodrich: changes for IEEE 1666 2011 +// +// Revision 1.5 2011/01/18 20:10:45 acg +// Andy Goodrich: changes for IEEE1666_2011 semantics. +// +// Revision 1.4 2010/07/22 20:02:33 acg +// Andy Goodrich: bug fixes. +// +// Revision 1.3 2009/05/22 16:06:29 acg +// Andy Goodrich: process control updates. +// +// Revision 1.2 2008/05/22 17:06:26 acg +// Andy Goodrich: updated copyright notice to include 2008. +// +// Revision 1.1.1.1 2006/12/15 20:20:05 acg +// SystemC 2.3 +// +// Revision 1.11 2006/05/08 17:58:10 acg +// Andy Goodrich: added David Long's forward declarations for friend +// functions, methods, and operators to keep the Microsoft compiler happy. +// +// Revision 1.10 2006/04/28 23:29:01 acg +// Andy Goodrich: added an sc_core:: prefix to SC_FUNC_PTR in the +// SC_MAKE_FUNC_PTR macro to allow its transpareuse outside of the sc_core +// namespace. +// +// Revision 1.9 2006/04/28 21:52:57 acg +// Andy Goodrich: changed SC_MAKE_FUNC_PTR to use a static cast to address +// and AIX issue wrt sc_module's inherited classes. +// +// Revision 1.8 2006/04/20 17:08:17 acg +// Andy Goodrich: 3.0 style process changes. +// +// Revision 1.7 2006/04/11 23:13:21 acg +// Andy Goodrich: Changes for reduced reset support that only includes +// sc_cthread, but has preliminary hooks for expanding to method and thread +// processes also. +// +// Revision 1.6 2006/03/13 20:26:50 acg +// Andy Goodrich: Addition of forward class declarations, e.g., +// sc_reset, to keep gcc 4.x happy. +// +// Revision 1.5 2006/01/31 20:09:10 acg +// Andy Goodrich: added explaination of static vs dynamic waits to +// sc_process_b::trigger_static. +// +// Revision 1.4 2006/01/24 20:49:05 acg +// Andy Goodrich: changes to remove the use of deprecated features within the +// simulator, and to issue warning messages when deprecated features are used. +// +// Revision 1.3 2006/01/13 18:44:30 acg +// Added $Log to record CVS changes into the source. + +#endif // !defined(sc_process_h_INCLUDED) diff --git a/ext/systemc/src/sysc/kernel/sc_process_handle.h b/ext/systemc/src/sysc/kernel/sc_process_handle.h new file mode 100644 index 000000000..c219f5fad --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_process_handle.h @@ -0,0 +1,608 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_process_handle.h -- Process access support. + + Original Author: Andy Goodrich, Forte Design Systems, 17 June 2003 + + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + +// $Log: sc_process_handle.h,v $ +// Revision 1.21 2011/08/26 21:54:04 acg +// Torsten Maehne: Simplify use of dynamic_cast<> for initializing m_target. +// +// Revision 1.20 2011/08/26 20:46:10 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// + +#if !defined(sc_process_handle_h_INCLUDED) +#define sc_process_handle_h_INCLUDED + +#include "sysc/kernel/sc_module.h" + +namespace sc_core { + +// forward operator declarations: + +class sc_process_handle; +bool +operator == ( const sc_process_handle& left, const sc_process_handle& right ); +bool +operator != ( const sc_process_handle& left, const sc_process_handle& right ); +bool +operator < ( const sc_process_handle& left, const sc_process_handle& right ); + + + +//============================================================================= +// CLASS sc_process_handle +// +// This class provides access to an sc_process_b object instance in a +// manner which allows some persistence after the deletion of the actual +// process. +//============================================================================= +class sc_simcontext; +class sc_process_handle { + typedef sc_process_handle this_type; + + friend bool operator == ( const this_type& left, const this_type& right ); + friend bool operator != ( const this_type& left, const this_type& right ); + friend bool operator < ( const this_type& left, const this_type& right ); + friend class sc_object; + friend class sc_join; + friend class sc_module; + friend class sc_reset; + friend class sc_sensitive; + friend class sc_sensitive_pos; + friend class sc_sensitive_neg; + friend class sc_thread_process; + + public: + inline sc_process_handle(); + inline explicit sc_process_handle( sc_object* object_p ); + inline explicit sc_process_handle( sc_process_b* process_p ); + inline sc_process_handle( const sc_process_handle& orig ); + inline ~sc_process_handle(); + inline sc_process_handle& operator = ( sc_process_handle src ); + inline void swap( sc_process_handle& other ); + + public: + inline void disable( + sc_descendant_inclusion_info descendants=SC_NO_DESCENDANTS ); + inline bool dynamic() const; + inline void enable( + sc_descendant_inclusion_info descendants=SC_NO_DESCENDANTS ); + inline const std::vector<sc_event*>& get_child_events() const; + inline const std::vector<sc_object*>& get_child_objects() const; + inline sc_object* get_parent_object() const; + inline sc_object* get_process_object() const; + inline bool is_unwinding() const; + inline void kill( + sc_descendant_inclusion_info descendants=SC_NO_DESCENDANTS ); + inline const char* name() const; + inline sc_curr_proc_kind proc_kind() const; + inline void reset( + sc_descendant_inclusion_info descendants=SC_NO_DESCENDANTS ); + inline sc_event& reset_event() const; + inline void resume( + sc_descendant_inclusion_info descendants=SC_NO_DESCENDANTS ); + inline void suspend( + sc_descendant_inclusion_info descendants=SC_NO_DESCENDANTS ); + inline void sync_reset_off( + sc_descendant_inclusion_info descendants=SC_NO_DESCENDANTS ); + inline void sync_reset_on( + sc_descendant_inclusion_info descendants=SC_NO_DESCENDANTS ); + inline sc_event& terminated_event(); + inline bool terminated() const; + template<typename EXCEPT> + inline void throw_it( const EXCEPT& exception, + sc_descendant_inclusion_info descendants=SC_NO_DESCENDANTS ); + inline bool valid() const; + + public: // implementation specific methods: + inline std::string dump_state() const; + + protected: + inline bool dont_initialize() const + { return m_target_p ? m_target_p->dont_initialize() : false; } + inline void dont_initialize( bool dont ); + + public: + operator sc_process_b* () + { return m_target_p; } + operator sc_cthread_handle (); + operator sc_method_handle (); + operator sc_thread_handle (); + + protected: + sc_process_b* m_target_p; // Target for this object instance. + + protected: + static std::vector<sc_event*> empty_event_vector; // If m_target_p == 0. + static std::vector<sc_object*> empty_object_vector; // If m_target_p == 0. + static sc_event non_event; // If m_target_p == 0. +}; + +inline bool operator == ( + const sc_process_handle& left, const sc_process_handle& right ) +{ + return (left.m_target_p != 0) && (right.m_target_p != 0) && + (left.m_target_p == right.m_target_p); +} + +inline bool operator != ( + const sc_process_handle& left, const sc_process_handle& right ) +{ + return (left.m_target_p == 0) || (right.m_target_p == 0) || + (left.m_target_p != right.m_target_p); +} + +inline bool operator < ( + const sc_process_handle& left, const sc_process_handle& right ) +{ + return left.m_target_p < right.m_target_p; +} + +//------------------------------------------------------------------------------ +//"sc_process_handle::sc_process_handle - non-pointer constructor" +// +// This version of the object instance constructor for this class creates +// an object instance whose target needs to be supplied via an assignment. +//------------------------------------------------------------------------------ +inline sc_process_handle::sc_process_handle() : m_target_p(0) +{ +} + +//------------------------------------------------------------------------------ +//"sc_process_handle::sc_process_handle - pointer constructor" +// +// This version of the object instance constructor for this class creates +// an object instance whose target is the supplied sc_object instance. +// The supplied sc_object must in fact be an sc_process_b instance. +// object_p -> sc_object instance this is handle for. +//------------------------------------------------------------------------------ +inline sc_process_handle::sc_process_handle( sc_object* object_p ) : + m_target_p(DCAST<sc_process_b*>(object_p)) +{ + if ( m_target_p ) m_target_p->reference_increment(); +} + +//------------------------------------------------------------------------------ +//"sc_process_handle::sc_process_handle - pointer constructor" +// +// This version of the object instance constructor for this class creates +// an object instance whose target is the supplied sc_process_b instance. +// This saves a dynamic cast compared to the sc_object* case. +// process_p -> process instance this is handle for. +//------------------------------------------------------------------------------ +inline sc_process_handle::sc_process_handle( sc_process_b* process_p ) : + m_target_p(process_p) +{ + if ( m_target_p ) m_target_p->reference_increment(); +} + +//------------------------------------------------------------------------------ +//"sc_process_handle::sc_process_handle - copy constructor" +// +// This version of the object instance constructor for this class provides +// the copy constructor for the class. It clones the supplied original +// handle and increments the references to its target. +// orig = sc_process_handle object instance to be copied from. +//------------------------------------------------------------------------------ +inline sc_process_handle::sc_process_handle( const sc_process_handle& orig ) : + m_target_p(orig.m_target_p) +{ + if ( m_target_p ) m_target_p->reference_increment(); +} + + +//------------------------------------------------------------------------------ +//"sc_process_handle::operator =" +// +// This assignment operator signature is call by value rather than reference. +// This means that an sc_process_handle instance will be created and the +// target for that instance will be incremented before the assignment is done. +// The assignment is done using the swap() method, which simply swaps the +// targets of 'orig' and this object instance. We don't need to increment +// the reference count for our new target since that was done when 'orig' +// was created. Our old target's reference count will be decremented when +// 'orig' is deleted. +// orig = sc_process_handle object instance to be copied from. +// Result is a reference for this object instance. +//------------------------------------------------------------------------------ +inline sc_process_handle& +sc_process_handle::operator = ( sc_process_handle orig ) +{ + swap( orig ); + return *this; +} + + +//------------------------------------------------------------------------------ +//"sc_process_handle::~sc_process_handle" +// +// This is the object instance destructor for this class. It decrements +// the reference count for its target. +//------------------------------------------------------------------------------ +inline sc_process_handle::~sc_process_handle() +{ + if ( m_target_p ) m_target_p->reference_decrement(); +} + +//------------------------------------------------------------------------------ +//"sc_process_handle::inline methods" +// +// These are short inline methods. +//------------------------------------------------------------------------------ + +// disable this object instance's target. + +inline void sc_process_handle::disable(sc_descendant_inclusion_info descendants) +{ + if ( m_target_p ) + m_target_p->disable_process(descendants); + else + SC_REPORT_WARNING( SC_ID_EMPTY_PROCESS_HANDLE_, "disable()"); +} + +// call dont_initialize() on this object instance's target. + +inline void sc_process_handle::dont_initialize( bool dont ) +{ + if ( m_target_p ) + m_target_p->dont_initialize( dont ); + else + SC_REPORT_WARNING( SC_ID_EMPTY_PROCESS_HANDLE_, "dont_initialize()"); +} + +// dump the status of this object instance's target: + +inline std::string sc_process_handle::dump_state() const +{ + return m_target_p ? m_target_p->dump_state() : std::string("NO TARGET"); +} + +// return whether this object instance's target is dynamic or not. + +inline bool sc_process_handle::dynamic() const +{ + return m_target_p ? m_target_p->dynamic() : false; +} + +// enable this object instance's target. + +inline void sc_process_handle::enable(sc_descendant_inclusion_info descendants) +{ + if ( m_target_p ) + m_target_p->enable_process(descendants); + else + SC_REPORT_WARNING( SC_ID_EMPTY_PROCESS_HANDLE_, "enable()"); +} + +// return the child objects for this object instance's target. + +inline +const std::vector<sc_event*>& sc_process_handle::get_child_events() const +{ + return m_target_p ? m_target_p->get_child_events() : empty_event_vector; +} + +// return the child objects for this object instance's target. + +inline +const std::vector<sc_object*>& sc_process_handle::get_child_objects() const +{ + return m_target_p ? m_target_p->get_child_objects() : empty_object_vector; +} + +// return the parent object for this object instance's target. + +inline sc_object* sc_process_handle::get_parent_object() const +{ + return m_target_p ? m_target_p->get_parent_object() : NULL; +} + +// return this object instance's target. + +inline sc_object* sc_process_handle::get_process_object() const +{ + return m_target_p; +} + +// return whether this object instance is unwinding or not. + +inline bool sc_process_handle::is_unwinding() const +{ + if ( m_target_p ) + return m_target_p->is_unwinding(); + else { + SC_REPORT_WARNING( SC_ID_EMPTY_PROCESS_HANDLE_, "is_unwinding()"); + return false; + } +} + +// kill this object instance's target. + +inline void sc_process_handle::kill( sc_descendant_inclusion_info descendants ) +{ + if ( m_target_p ) + m_target_p->kill_process( descendants ); + else + SC_REPORT_WARNING( SC_ID_EMPTY_PROCESS_HANDLE_, "kill()"); +} + +// return the name of this object instance's target. + +inline const char* sc_process_handle::name() const +{ + return m_target_p ? m_target_p->name() : ""; +} + +// return the process kind for this object instance's target. + +inline sc_curr_proc_kind sc_process_handle::proc_kind() const +{ + return m_target_p ? m_target_p->proc_kind() : SC_NO_PROC_; +} + +// reset this object instance's target. + +inline void sc_process_handle::reset( sc_descendant_inclusion_info descendants ) +{ + if ( m_target_p ) + m_target_p->reset_process( sc_process_b::reset_asynchronous, + descendants ); + else + SC_REPORT_WARNING( SC_ID_EMPTY_PROCESS_HANDLE_, "reset()"); +} + +// return the reset event for this object instance's target. + +inline sc_event& sc_process_handle::reset_event() const +{ + if ( m_target_p ) + return m_target_p->reset_event(); + else + { + SC_REPORT_WARNING( SC_ID_EMPTY_PROCESS_HANDLE_, "reset()"); + return sc_process_handle::non_event; + } +} + +// resume this object instance's target. + +inline void sc_process_handle::resume(sc_descendant_inclusion_info descendants) +{ + if ( m_target_p ) + m_target_p->resume_process(descendants); + else + SC_REPORT_WARNING( SC_ID_EMPTY_PROCESS_HANDLE_, "resume()"); +} + +// suspend this object instance's target. + +inline void sc_process_handle::suspend(sc_descendant_inclusion_info descendants) +{ + if ( m_target_p ) + m_target_p->suspend_process(descendants); + else + SC_REPORT_WARNING( SC_ID_EMPTY_PROCESS_HANDLE_, "suspend()"); +} + +// swap targets of this process handle with the supplied one. + +inline void sc_process_handle::swap( sc_process_handle& other ) +{ + sc_process_b* tmp = m_target_p; + m_target_p = other.m_target_p; + other.m_target_p = tmp; +} + +// turn sync_reset off for this object instance's target. + +inline void sc_process_handle::sync_reset_off( + sc_descendant_inclusion_info descendants) +{ + if ( m_target_p ) + m_target_p->reset_process( sc_process_b::reset_synchronous_off, + descendants); + else + SC_REPORT_WARNING( SC_ID_EMPTY_PROCESS_HANDLE_, "sync_reset_off()"); +} + +// turn sync_reset on for this object instance's target. + +inline void sc_process_handle::sync_reset_on( + sc_descendant_inclusion_info descendants) +{ + if ( m_target_p ) + { + m_target_p->reset_process(sc_process_b::reset_synchronous_on, + descendants); + } + else + { + SC_REPORT_WARNING( SC_ID_EMPTY_PROCESS_HANDLE_, "sync_reset_on()"); + } +} + +// terminate this object instance's target. + +inline bool sc_process_handle::terminated() const +{ + return m_target_p ? m_target_p->terminated() : false; +} + +// return the termination event for this object instance's target. + +inline sc_event& sc_process_handle::terminated_event() +{ + if ( m_target_p ) + return m_target_p->terminated_event(); + else + { + SC_REPORT_WARNING( SC_ID_EMPTY_PROCESS_HANDLE_, "terminated_event()"); + return sc_process_handle::non_event; + } +} + +// return true if this object instance has a target, false it not. + +inline bool sc_process_handle::valid() const +{ + return m_target_p ? true : false; +} + +//------------------------------------------------------------------------------ +//"sc_process_handle::sc_throw_it" +// +// This method throws the supplied exception to the process whose handle this +// object instance is, and optionally to the process' descendants. Once the +// exception is thrown the currently executed process will suspend to allow +// the exception to be propagated. Once the propagation has occurred the +// current process will be resumed. +// +// Notes: +// (1) We allocate the helper function on the stack, see the description of +// sc_throw_it<EXCEPT>, in sc_process.h, for why. +// +// Arguments: +// exception = exception to be thrown +// descendants = indication of whether descendant processes should also +// receive the throw. +//------------------------------------------------------------------------------ +template<typename EXCEPT> +inline void sc_process_handle::throw_it( const EXCEPT& exception, + sc_descendant_inclusion_info descendants) +{ + sc_throw_it<EXCEPT> helper(exception); // helper to throw the exception. + + if ( !m_target_p ) + { + SC_REPORT_WARNING( SC_ID_EMPTY_PROCESS_HANDLE_, "throw_it()"); + return; + } + m_target_p->throw_user(helper, descendants); +} + + +//------------------------------------------------------------------------------ +//"sc_process_b::last_created_process_handle" +// +// This method returns the kind of this process. +//------------------------------------------------------------------------------ +inline sc_process_handle sc_process_b::last_created_process_handle() +{ + return sc_process_handle(m_last_created_process_p); +} + +inline sc_process_handle sc_get_last_created_process_handle() +{ + return sc_process_b::last_created_process_handle(); +} + +} // namespace sc_core + +// Revision 1.19 2011/08/24 22:05:51 acg +// Torsten Maehne: initialization changes to remove warnings. +// +// Revision 1.18 2011/04/01 22:08:26 acg +// Andy Goodrich: remove unused variable. +// +// Revision 1.17 2011/03/12 21:07:51 acg +// Andy Goodrich: changes to kernel generated event support. +// +// Revision 1.16 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.15 2011/02/17 19:53:03 acg +// Andy Goodrich: changed dump_status() to dump_state() with new signature. +// +// Revision 1.14 2011/02/13 21:47:37 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.13 2011/02/13 21:33:30 acg +// Andy Goodrich: added dump_status() to allow the dumping of the status +// of a process handle's target. +// +// Revision 1.12 2011/02/01 23:01:53 acg +// Andy Goodrich: removed dead code. +// +// Revision 1.11 2011/02/01 21:07:36 acg +// Andy Goodrich: defering of run queue manipulations to the +// sc_thread_process::throw_it() method. +// +// Revision 1.10 2011/01/25 20:50:37 acg +// Andy Goodrich: changes for IEEE 1666 2011. +// +// Revision 1.9 2011/01/20 16:52:20 acg +// Andy Goodrich: changes for IEEE 1666 2011. +// +// Revision 1.8 2011/01/19 23:21:50 acg +// Andy Goodrich: changes for IEEE 1666 2011 +// +// Revision 1.7 2011/01/18 20:10:45 acg +// Andy Goodrich: changes for IEEE1666_2011 semantics. +// +// Revision 1.6 2010/07/30 05:21:22 acg +// Andy Goodrich: release 2.3 fixes. +// +// Revision 1.5 2010/07/22 20:02:33 acg +// Andy Goodrich: bug fixes. +// +// Revision 1.4 2009/05/22 16:06:29 acg +// Andy Goodrich: process control updates. +// +// Revision 1.3 2008/05/22 17:06:26 acg +// Andy Goodrich: updated copyright notice to include 2008. +// +// Revision 1.2 2007/09/20 20:32:35 acg +// Andy Goodrich: changes to the semantics of throw_it() to match the +// specification. A call to throw_it() will immediately suspend the calling +// thread until all the throwees have executed. At that point the calling +// thread will be restarted before the execution of any other threads. +// +// Revision 1.1.1.1 2006/12/15 20:20:05 acg +// SystemC 2.3 +// +// Revision 1.7 2006/05/08 17:58:24 acg +// Andy Goodrich: added David Long's forward declarations for friend +// functions, methods, and operators to keep the Microsoft compiler happy. +// +// Revision 1.6 2006/04/20 17:08:17 acg +// Andy Goodrich: 3.0 style process changes. +// +// Revision 1.5 2006/04/11 23:13:21 acg +// Andy Goodrich: Changes for reduced reset support that only includes +// sc_cthread, but has preliminary hooks for expanding to method and thread +// processes also. +// +// Revision 1.4 2006/01/24 20:49:05 acg +// Andy Goodrich: changes to remove the use of deprecated features within the +// simulator, and to issue warning messages when deprecated features are used. +// +// Revision 1.3 2006/01/13 18:44:30 acg +// Added $Log to record CVS changes into the source. + +#endif // !defined(sc_spawn_h_INCLUDED) diff --git a/ext/systemc/src/sysc/kernel/sc_reset.cpp b/ext/systemc/src/sysc/kernel/sc_reset.cpp new file mode 100644 index 000000000..2e4bc6c6e --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_reset.cpp @@ -0,0 +1,440 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_reset.cpp -- Support for reset. + + Original Author: Andy Goodrich, Forte Design Systems + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + + +#include "sysc/kernel/sc_simcontext.h" +#include "sysc/kernel/sc_reset.h" +#include "sysc/kernel/sc_process_handle.h" +#include "sysc/communication/sc_signal.h" +#include "sysc/communication/sc_signal_ports.h" + + +// THE SYSTEMC PROOF OF CONCEPT SIMULATOR RESET SIGNAL IMPLEMENTATION: +// +// (1) An instance of the sc_reset class is attached to each sc_signal<bool> +// that is used as a reset signal. +// +// (2) Each process that is senstive to a reset signal will be registered in the +// sc_reset class attached to that reset signal. +// +// (3) When a change in the value of a reset signal occurs it invokes the +// notify_processes() method of its sc_reset object instance. The +// notify_processes() method will call the reset_changed() method of each +// process that is registered with it to inform the process that +// state of the reset signal has changed. +// +// (4) A process may have multiple reset signals, so counters are kept for the +// number of active asynchronous, and synchronous, reset signals that are +// active. Those counters are incremented and decremented in the process' +// reset_changed() method. +// +// (5) When a process' semantics() method is called the current reset state is +// checked, and a reset sequence is initiated if the process is in reset. +// This will occur every time an SC_METHOD is dispatched. SC_CTHREAD and +// and SC_THREAD instances, only go through the semantics() method they +// initially start up. So the reset check is duplicated in the suspend_me() +// method, the tail of which will execute each time the thread is +// dispatched. + +namespace sc_core { + +class sc_reset_finder; +static sc_reset_finder* reset_finder_q=0; // Q of reset finders to reconcile. + +//============================================================================== +// sc_reset_finder - place holder class for a port reset signal until it is +// bound and an interface class is available. When the port +// has been bound the information in this class will be used +// to initialize its sc_reset object instance. +//============================================================================== +class sc_reset_finder { + friend class sc_reset; + public: + sc_reset_finder( bool async, const sc_in<bool>* port_p, bool level, + sc_process_b* target_p); + sc_reset_finder( bool async, const sc_inout<bool>* port_p, bool level, + sc_process_b* target_p); + sc_reset_finder( bool async, const sc_out<bool>* port_p, bool level, + sc_process_b* target_p); + + protected: + bool m_async; // True if asynchronous reset. + bool m_level; // Level for reset. + sc_reset_finder* m_next_p; // Next reset finder in list. + const sc_in<bool>* m_in_p; // Port for which reset is needed. + const sc_inout<bool>* m_inout_p; // Port for which reset is needed. + const sc_out<bool>* m_out_p; // Port for which reset is needed. + sc_process_b* m_target_p; // Process to reset. + + private: // disabled + sc_reset_finder( const sc_reset_finder& ); + const sc_reset_finder& operator = ( const sc_reset_finder& ); +}; + +inline sc_reset_finder::sc_reset_finder( + bool async, const sc_in<bool>* port_p, bool level, sc_process_b* target_p) : + m_async(async), m_level(level), m_next_p(0), m_in_p(port_p), m_inout_p(0), + m_out_p(0), m_target_p(target_p) +{ + m_next_p = reset_finder_q; + reset_finder_q = this; +} + +inline sc_reset_finder::sc_reset_finder( + bool async, const sc_inout<bool>* port_p, bool level, sc_process_b* target_p +) : + m_async(async), m_level(level), m_next_p(0), m_in_p(0), m_inout_p(port_p), + m_out_p(0), m_target_p(target_p) +{ + m_next_p = reset_finder_q; + reset_finder_q = this; +} + +inline sc_reset_finder::sc_reset_finder( + bool async, const sc_out<bool>* port_p, bool level, sc_process_b* target_p +) : + m_async(async), m_level(level), m_next_p(0), m_in_p(0), m_inout_p(0), + m_out_p(port_p), m_target_p(target_p) +{ + m_next_p = reset_finder_q; + reset_finder_q = this; +} + + +//------------------------------------------------------------------------------ +//"sc_reset::notify_processes" +// +// Notify processes that there is a change in the reset signal value. +//------------------------------------------------------------------------------ +void sc_reset::notify_processes() +{ + bool active; // true if reset is active. + sc_reset_target* entry_p; // reset entry processing. + std::vector<sc_reset_target>::size_type process_i; // index of process resetting. + std::vector<sc_reset_target>::size_type process_n; // # of processes to reset. + bool value; // value of our signal. + + value = m_iface_p->read(); + process_n = m_targets.size(); + for ( process_i = 0; process_i < process_n; process_i++ ) + { + entry_p = &m_targets[process_i]; + active = ( entry_p->m_level == value ); + entry_p->m_process_p->reset_changed( entry_p->m_async, active ); + } +} + + +//------------------------------------------------------------------------------ +//"sc_reset::reconcile_resets" +// +// This static method processes the sc_reset_finders to establish the actual +// reset connections. +// +// Notes: +// (1) If reset is asserted we tell the process that it is in reset. +//------------------------------------------------------------------------------ +void sc_reset::reconcile_resets() +{ + const sc_signal_in_if<bool>* iface_p; // Interface to reset signal. + sc_reset_finder* next_p; // Next finder to process. + sc_reset_finder* now_p; // Finder currently processing. + sc_reset_target reset_target; // Target's reset entry. + sc_reset* reset_p; // Reset object to use. + + for ( now_p = reset_finder_q; now_p; now_p = next_p ) + { + next_p = now_p->m_next_p; + if ( now_p->m_in_p ) + { + iface_p = DCAST<const sc_signal_in_if<bool>*>( + now_p->m_in_p->get_interface()); + } + else if ( now_p->m_inout_p ) + { + iface_p = DCAST<const sc_signal_in_if<bool>*>( + now_p->m_inout_p->get_interface()); + } + else + { + iface_p = DCAST<const sc_signal_in_if<bool>*>( + now_p->m_out_p->get_interface()); + } + assert( iface_p != 0 ); + reset_p = iface_p->is_reset(); + now_p->m_target_p->m_resets.push_back(reset_p); + reset_target.m_async = now_p->m_async; + reset_target.m_level = now_p->m_level; + reset_target.m_process_p = now_p->m_target_p; + reset_p->m_targets.push_back(reset_target); + if ( iface_p->read() == now_p->m_level ) // see note 1 above + now_p->m_target_p->initially_in_reset( now_p->m_async ); + delete now_p; + } +} + + +//------------------------------------------------------------------------------ +//"sc_reset::remove_process" +// +// This method removes the supplied process from the list of processes that +// should be notified when there is a change in the value of the reset signal. +// +// Arguments: +// process_p -> process to be removed. +//------------------------------------------------------------------------------ +void sc_reset::remove_process( sc_process_b* process_p ) +{ + int process_i; // Index of process resetting. + int process_n; // # of processes to reset. + + process_n = m_targets.size(); + for ( process_i = 0; process_i < process_n; ) + { + if ( m_targets[process_i].m_process_p == process_p ) + { + m_targets[process_i] = m_targets[process_n-1]; + process_n--; + m_targets.resize(process_n); + } + else + { + process_i++; + } + } +} + +//------------------------------------------------------------------------------ +//"sc_reset::reset_signal_is - ports" +// +// These overloads of the reset_signal_is() method will register the active +// process with the sc_reset object instance associated with the supplied port. +// If the port does not yet have a pointer to its sc_signal<bool> instance it +// will create an sc_reset_finder class object instance that will be used +// to set the process' reset information when the port has been bound. +// +// Arguments: +// async = true if the reset signal is asynchronous, false if not. +// port = port for sc_signal<bool> that will provide the reset signal. +// level = level at which reset is active, either true or false. +//------------------------------------------------------------------------------ +void sc_reset::reset_signal_is( bool async, const sc_in<bool>& port, bool level) +{ + const sc_signal_in_if<bool>* iface_p; + sc_process_b* process_p; + + process_p = (sc_process_b*)sc_get_current_process_handle(); + assert( process_p ); + process_p->m_has_reset_signal = true; + switch ( process_p->proc_kind() ) + { + case SC_THREAD_PROC_: + case SC_METHOD_PROC_: + case SC_CTHREAD_PROC_: + iface_p = DCAST<const sc_signal_in_if<bool>*>(port.get_interface()); + if ( iface_p ) + reset_signal_is( async, *iface_p, level ); + else + new sc_reset_finder( async, &port, level, process_p ); + break; + default: + SC_REPORT_ERROR(SC_ID_UNKNOWN_PROCESS_TYPE_, process_p->name()); + break; + } +} + +void sc_reset::reset_signal_is( + bool async, const sc_inout<bool>& port, bool level ) +{ + const sc_signal_in_if<bool>* iface_p; + sc_process_b* process_p; + + process_p = (sc_process_b*)sc_get_current_process_handle(); + assert( process_p ); + process_p->m_has_reset_signal = true; + switch ( process_p->proc_kind() ) + { + case SC_THREAD_PROC_: + case SC_METHOD_PROC_: + case SC_CTHREAD_PROC_: + iface_p = DCAST<const sc_signal_in_if<bool>*>(port.get_interface()); + if ( iface_p ) + reset_signal_is( async, *iface_p, level ); + else + new sc_reset_finder( async, &port, level, process_p ); + break; + default: + SC_REPORT_ERROR(SC_ID_UNKNOWN_PROCESS_TYPE_, process_p->name()); + break; + } +} + +void sc_reset::reset_signal_is( + bool async, const sc_out<bool>& port, bool level ) +{ + const sc_signal_in_if<bool>* iface_p; + sc_process_b* process_p; + + process_p = (sc_process_b*)sc_get_current_process_handle(); + assert( process_p ); + process_p->m_has_reset_signal = true; + switch ( process_p->proc_kind() ) + { + case SC_THREAD_PROC_: + case SC_METHOD_PROC_: + case SC_CTHREAD_PROC_: + iface_p = DCAST<const sc_signal_in_if<bool>*>(port.get_interface()); + if ( iface_p ) + reset_signal_is( async, *iface_p, level ); + else + new sc_reset_finder( async, &port, level, process_p ); + break; + default: + SC_REPORT_ERROR(SC_ID_UNKNOWN_PROCESS_TYPE_, process_p->name()); + break; + } +} + +//------------------------------------------------------------------------------ +//"sc_reset::reset_signal_is" +// +// This static method will register the active process instance as being +// reset by the sc_signal<bool> whose interface has been supplied. If no +// sc_reset object instance has been attached to the sc_signal<bool> yet, it +// will be created and attached. The active process instance is pushed into +// the list of processes that the sc_reset object instance should notify if +// the value of the reset signal changes. +// +// Arguments: +// async = true if the reset signal is asynchronous, false if not. +// iface = interface for the reset signal. +// level = is the level at which reset is active, either true or false. +// Notes: +// (1) If reset is asserted we tell the process that it is in reset +// initially. +//------------------------------------------------------------------------------ +void sc_reset::reset_signal_is( + bool async, const sc_signal_in_if<bool>& iface, bool level ) +{ + sc_process_b* process_p; // process adding reset for. + sc_reset_target reset_target; // entry to build for the process. + sc_reset* reset_p; // reset object. + + process_p = sc_process_b::last_created_process_base(); + assert( process_p ); + process_p->m_has_reset_signal = true; + switch ( process_p->proc_kind() ) + { + case SC_METHOD_PROC_: + case SC_CTHREAD_PROC_: + case SC_THREAD_PROC_: + reset_p = iface.is_reset(); + process_p->m_resets.push_back(reset_p); + reset_target.m_async = async; + reset_target.m_level = level; + reset_target.m_process_p = process_p; + reset_p->m_targets.push_back(reset_target); + if ( iface.read() == level ) process_p->initially_in_reset( async ); + break; + default: + SC_REPORT_ERROR(SC_ID_UNKNOWN_PROCESS_TYPE_, process_p->name()); + break; + } +} + +} // namespace sc_core + +// $Log: sc_reset.cpp,v $ +// Revision 1.16 2011/08/26 20:46:10 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +// Revision 1.15 2011/08/24 22:05:51 acg +// Torsten Maehne: initialization changes to remove warnings. +// +// Revision 1.14 2011/04/08 22:37:34 acg +// Andy Goodrich: documentation of the reset mechanism and additional +// documentation of methods. Removal of check for SC_METHODs in +// sc_reset_signal_is() that should not have been there. +// +// Revision 1.13 2011/03/20 15:13:01 acg +// Andy Goodrich: set the reset flag for async_reset_signal_is to catch +// the suspend() corner case. +// +// Revision 1.12 2011/03/20 13:43:23 acg +// Andy Goodrich: added async_signal_is() plus suspend() as a corner case. +// +// Revision 1.11 2011/03/06 19:57:11 acg +// Andy Goodrich: refinements for the illegal suspend - synchronous reset +// interaction. +// +// Revision 1.10 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.9 2011/02/13 21:47:37 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.8 2011/02/01 21:08:26 acg +// Andy Goodrich: new multiple reset support. +// +// Revision 1.7 2011/01/06 18:04:38 acg +// Andy Goodrich: removed commented out code. +// +// Revision 1.6 2010/12/07 20:09:13 acg +// Andy Goodrich: removed sc_signal overloads since already have sc_signal_in_if overloads. +// +// Revision 1.5 2010/11/20 17:10:56 acg +// Andy Goodrich: reset processing changes for new IEEE 1666 standard. +// +// Revision 1.4 2009/05/22 16:06:29 acg +// Andy Goodrich: process control updates. +// +// Revision 1.3 2009/03/12 22:59:58 acg +// Andy Goodrich: updates for 2.4 stuff. +// +// Revision 1.2 2008/05/22 17:06:26 acg +// Andy Goodrich: updated copyright notice to include 2008. +// +// Revision 1.1.1.1 2006/12/15 20:20:05 acg +// SystemC 2.3 +// +// Revision 1.7 2006/12/02 20:58:19 acg +// Andy Goodrich: updates from 2.2 for IEEE 1666 support. +// +// Revision 1.5 2006/04/11 23:13:21 acg +// Andy Goodrich: Changes for reduced reset support that only includes +// sc_cthread, but has preliminary hooks for expanding to method and thread +// processes also. +// +// Revision 1.4 2006/01/24 20:49:05 acg +// Andy Goodrich: changes to remove the use of deprecated features within the +// simulator, and to issue warning messages when deprecated features are used. +// +// Revision 1.3 2006/01/13 18:44:30 acg +// Added $Log to record CVS changes into the source. +// diff --git a/ext/systemc/src/sysc/kernel/sc_reset.h b/ext/systemc/src/sysc/kernel/sc_reset.h new file mode 100644 index 000000000..f0992bb16 --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_reset.h @@ -0,0 +1,164 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_reset.h -- Process reset support. + + Original Author: Andy Goodrich, Forte Design Systems, 17 June 2003 + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + +#if !defined(sc_reset_h_INCLUDED) +#define sc_reset_h_INCLUDED + +#include "sysc/communication/sc_writer_policy.h" + +namespace sc_core { + +// FORWARD CLASS REFERENCES: + +template<typename DATA> class sc_signal_in_if; +template<typename IF, sc_writer_policy POL> class sc_signal; +template<typename DATA> class sc_in; +template<typename DATA> class sc_inout; +template<typename DATA> class sc_out; +template<typename SOURCE> class sc_spawn_reset; +class sc_reset; +class sc_process_b; + +//============================================================================== +// CLASS sc_reset_target - RESET ENTRY FOR AN sc_process_b TARGET +// +// This class describes a reset condition associated with an sc_process_b +// instance. +//============================================================================== +class sc_reset_target { + public: + bool m_async; // true asynchronous reset, false synchronous. + bool m_level; // level for reset. + sc_process_b* m_process_p; // process this reset entry is for. +}; + +inline std::ostream& operator << ( std::ostream& os, + const sc_reset_target& target ) +{ + os << "["; + os << target.m_async << ","; + os << target.m_level << ","; + os << target.m_process_p << ","; + return os; +} + +//============================================================================== +// CLASS sc_reset - RESET INFORMATION FOR A RESET SIGNAL +// +// See the top of sc_reset.cpp for an explaination of how the reset mechanism +// is implemented. +//============================================================================== +class sc_reset { + friend class sc_cthread_process; + friend class sc_method_process; + friend class sc_module; + friend class sc_process_b; + friend class sc_signal<bool, SC_ONE_WRITER>; + friend class sc_signal<bool, SC_MANY_WRITERS>; + friend class sc_signal<bool, SC_UNCHECKED_WRITERS>; + friend class sc_simcontext; + template<typename SOURCE> friend class sc_spawn_reset; + friend class sc_thread_process; + + protected: + static void reconcile_resets(); + static void + reset_signal_is(bool async, const sc_signal_in_if<bool>& iface, + bool level); + static void + reset_signal_is( bool async, const sc_in<bool>& iface, bool level); + static void + reset_signal_is( bool async, const sc_inout<bool>& iface, bool level); + static void + reset_signal_is( bool async, const sc_out<bool>& iface, bool level); + + protected: + sc_reset( const sc_signal_in_if<bool>* iface_p ) : + m_iface_p(iface_p), m_targets() {} + void notify_processes(); + void remove_process( sc_process_b* ); + + protected: + const sc_signal_in_if<bool>* m_iface_p; // Interface to read. + std::vector<sc_reset_target> m_targets; // List of processes to reset. + + private: // disabled + sc_reset( const sc_reset& ); + const sc_reset& operator = ( const sc_reset& ); +}; + +// $Log: sc_reset.h,v $ +// Revision 1.11 2011/08/26 20:46:10 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +// Revision 1.10 2011/08/24 22:05:51 acg +// Torsten Maehne: initialization changes to remove warnings. +// +// Revision 1.9 2011/04/08 22:38:30 acg +// Andy Goodrich: added comment pointing to the description of how the +// reset mechanism works that is in sc_reset.cpp. +// +// Revision 1.8 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.7 2011/02/13 21:47:37 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.6 2011/01/06 18:00:32 acg +// Andy Goodrich: Removed commented out code. +// +// Revision 1.5 2010/12/07 20:09:14 acg +// Andy Goodrich: removed sc_signal signatures since already have sc_signal_in_if signatures. +// +// Revision 1.4 2010/11/20 17:10:57 acg +// Andy Goodrich: reset processing changes for new IEEE 1666 standard. +// +// Revision 1.3 2009/05/22 16:06:29 acg +// Andy Goodrich: process control updates. +// +// Revision 1.2 2008/05/22 17:06:26 acg +// Andy Goodrich: updated copyright notice to include 2008. +// +// Revision 1.1.1.1 2006/12/15 20:20:05 acg +// SystemC 2.3 +// +// Revision 1.6 2006/12/02 20:58:19 acg +// Andy Goodrich: updates from 2.2 for IEEE 1666 support. +// +// Revision 1.4 2006/04/11 23:13:21 acg +// Andy Goodrich: Changes for reduced reset support that only includes +// sc_cthread, but has preliminary hooks for expanding to method and thread +// processes also. +// +// Revision 1.3 2006/01/13 18:44:30 acg +// Added $Log to record CVS changes into the source. + +} // namespace sc_core + +#endif // !defined(sc_reset_h_INCLUDED) diff --git a/ext/systemc/src/sysc/kernel/sc_runnable.h b/ext/systemc/src/sysc/kernel/sc_runnable.h new file mode 100644 index 000000000..028a9b311 --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_runnable.h @@ -0,0 +1,144 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_runnable.h -- + + Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21 + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + + +#ifndef SC_RUNNABLE_H +#define SC_RUNNABLE_H + + +#include "sysc/kernel/sc_process.h" + +namespace sc_core { + +//============================================================================= +// CLASS : sc_runnable +// +// Class that manages the ready-to-run queues. +//============================================================================= + +class sc_runnable +{ + + public: + sc_runnable(); + ~sc_runnable(); + + inline void init(); + inline void toggle_methods(); + inline void toggle_threads(); + + inline void remove_method( sc_method_handle ); + inline void remove_thread( sc_thread_handle ); + + inline void execute_method_next( sc_method_handle ); + inline void execute_thread_next( sc_thread_handle ); + + inline void push_back_method( sc_method_handle ); + inline void push_back_thread( sc_thread_handle ); + inline void push_front_method( sc_method_handle ); + inline void push_front_thread( sc_thread_handle ); + + inline bool is_initialized() const; + inline bool is_empty() const; + + inline sc_method_handle pop_method(); + inline sc_thread_handle pop_thread(); + + public: // diagnostics: + void dump() const; + + private: + sc_method_handle m_methods_push_head; + sc_method_handle m_methods_push_tail; + sc_method_handle m_methods_pop; + sc_thread_handle m_threads_push_head; + sc_thread_handle m_threads_push_tail; + sc_thread_handle m_threads_pop; + + private: + // disabled + sc_runnable( const sc_runnable& ); + sc_runnable& operator = ( const sc_runnable& ); +}; + +} // namespace sc_core + +#endif + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: Andy Goodrich, 30 June 2003, Forte Design Systems + Description of Modification: Total rewrite using linked list rather than + fixed vector. + + + Name, Affiliation, Date: Bishnupriya Bhattacharya, Cadence Design Systems, + 25 August, 2003 + Description of Modification: Add tail pointers for m_methods_push and + m_threads_push to maintain the same scheduler + ordering as 2.0.1 + + *****************************************************************************/ + +// $Log: sc_runnable.h,v $ +// Revision 1.9 2011/08/26 20:46:10 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +// Revision 1.8 2011/04/08 18:26:07 acg +// Andy Goodrich: added execute_method_next() to handle method dispatch +// for asynchronous notifications that occur outside the evaluation phase. +// +// Revision 1.7 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.6 2011/02/13 21:47:38 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.5 2011/02/02 06:37:03 acg +// Andy Goodrich: removed toggle() method since it is no longer used. +// +// Revision 1.4 2011/02/01 21:09:13 acg +// Andy Goodrich: addition of toggle_methods() and toggle_threads() calls. +// +// Revision 1.3 2011/01/25 20:50:37 acg +// Andy Goodrich: changes for IEEE 1666 2011. +// +// Revision 1.2 2008/05/22 17:06:26 acg +// Andy Goodrich: updated copyright notice to include 2008. +// +// Revision 1.1.1.1 2006/12/15 20:20:05 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:44:30 acg +// Added $Log to record CVS changes into the source. + +// Taf! diff --git a/ext/systemc/src/sysc/kernel/sc_runnable_int.h b/ext/systemc/src/sysc/kernel/sc_runnable_int.h new file mode 100644 index 000000000..510e93758 --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_runnable_int.h @@ -0,0 +1,574 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/******************************************************************************* + + sc_runnable_int.h -- For inline definitions of some utility functions. + DO NOT EXPORT THIS INCLUDE FILE. Include this file + after "sc_process_int.h" so that we can get the base + class right. + + Original Author: Bishnupriya Bhattacharya , Cadence Design, 28th July, 2003 + + CHANGE LOG AT THE END OF THE FILE + ******************************************************************************/ + +#ifndef SC_RUNNABLE_INT_H +#define SC_RUNNABLE_INT_H + + +#include "sysc/kernel/sc_runnable.h" +#include "sysc/kernel/sc_method_process.h" +#include "sysc/kernel/sc_thread_process.h" + +// DEBUGGING MACROS: +// +// DEBUG_MSG(NAME,P,MSG) +// MSG = message to print +// NAME = name that must match the process for the message to print, or +// null if the message should be printed unconditionally. +// P = pointer to process message is for, or NULL in which case the +// message will not print. +#if 0 +# define DEBUG_NAME "" +# define DEBUG_MSG(NAME,P,MSG) \ + { \ + if ( P && ( (strlen(NAME)==0) || !strcmp(NAME,P->name())) ) \ + std::cout << "**** " << sc_time_stamp() << " (" \ + << sc_get_current_process_name() << "): " << MSG \ + << " - " << P->name() << std::endl; \ + } +#else +# define DEBUG_MSG(NAME,P,MSG) +#endif + +namespace sc_core { + +// The values below are used to indicate when a queue is empty. A non-zero +// non-legal pointer value is used for this so that a zero value in the +// m_execute_p field of an sc_process_b instance can be used to indicate +// that is has not been queued for run. (If we did not use a non-zero +// queue empty indicator then a sc_process_b instance that was queued +// twice in a row might end up on the queue twice if it were the first +// one that was queued!) + +#define SC_NO_METHODS ((sc_method_handle)0xdb) +#define SC_NO_THREADS ((sc_thread_handle)0xdb) + + +//------------------------------------------------------------------------------ +//"sc_runnable::dump" +// +// This method dumps the contents of this object instance. +//------------------------------------------------------------------------------ +inline void sc_runnable::dump() const +{ + // Dump the thread queues: + + std::cout << "thread pop queue: " << std::endl; + for ( sc_thread_handle p = m_threads_pop; p != SC_NO_THREADS; + p = p->next_runnable() ) + { + std::cout << " " << p << std::endl; + } + + std::cout << "thread push queue: " << std::endl; + for ( sc_thread_handle p = m_threads_push_head->next_runnable(); + p != SC_NO_THREADS; p = p->next_runnable() ) + { + std::cout << " " << p << std::endl; + } +} + +//------------------------------------------------------------------------------ +//"sc_runnable::execute_method_next" +// +// This method pushes the the supplied method to execute as the next process. +// This is done by pushing it onto the front of the m_methods_pop. +// method_h -> method process to add to the queue. +//------------------------------------------------------------------------------ +inline void sc_runnable::execute_method_next( sc_method_handle method_h ) +{ + DEBUG_MSG(DEBUG_NAME,method_h,"pushing this method to execute next"); + method_h->set_next_runnable( m_methods_pop ); + m_methods_pop = method_h; +} + +//------------------------------------------------------------------------------ +//"sc_runnable::execute_thread_next" +// +// This method pushes the the supplied thread to execute as the next process. +// This is done by pushing it onto the front of the m_threads_pop. +// thread_h -> thread process to add to the queue. +//------------------------------------------------------------------------------ +inline void sc_runnable::execute_thread_next( sc_thread_handle thread_h ) +{ + DEBUG_MSG(DEBUG_NAME,thread_h,"pushing this thread to execute next"); + thread_h->set_next_runnable( m_threads_pop ); + m_threads_pop = thread_h; +} + +//------------------------------------------------------------------------------ +//"sc_runnable::init" +// +// This method initializes this object instance. Note we allocate the queue +// heads if necessary. This is done here rather than in the constructor for +// this class to eliminate CTOR processing errors with gcc. +//------------------------------------------------------------------------------ +inline void sc_runnable::init() +{ + m_methods_pop = SC_NO_METHODS; + if ( !m_methods_push_head ) + { + m_methods_push_head = new sc_method_process("methods_push_head", true, + (SC_ENTRY_FUNC)0, 0, 0); + m_methods_push_head->dont_initialize(true); + m_methods_push_head->detach(); + } + m_methods_push_tail = m_methods_push_head; + m_methods_push_head->set_next_runnable(SC_NO_METHODS); + + m_threads_pop = SC_NO_THREADS; + if ( !m_threads_push_head ) + { + m_threads_push_head = new sc_thread_process("threads_push_head", true, + (SC_ENTRY_FUNC)0, 0, 0); + m_threads_push_head->dont_initialize(true); + m_threads_push_head->detach(); + } + m_threads_push_head->set_next_runnable(SC_NO_THREADS); + m_threads_push_tail = m_threads_push_head; +} + + +//------------------------------------------------------------------------------ +//"sc_runnable::is_empty" +// +// This method returns true if the push queue is empty, or false if not. +//------------------------------------------------------------------------------ +inline bool sc_runnable::is_empty() const +{ + return m_methods_push_head->next_runnable() == SC_NO_METHODS && + m_methods_pop == SC_NO_METHODS && + m_threads_push_head->next_runnable() == SC_NO_THREADS && + m_threads_pop == SC_NO_THREADS; +} + + +//------------------------------------------------------------------------------ +//"sc_runnable::is_initialized" +// +// This method returns true if the push queue is already initialized. +//------------------------------------------------------------------------------ +inline bool sc_runnable::is_initialized() const +{ + return m_methods_push_head && m_threads_push_head; +} + + +//------------------------------------------------------------------------------ +//"sc_runnable::push_back_method" +// +// This method pushes the supplied method process onto the back of the queue of +// runnable method processes. +// method_h -> method process to add to the queue. +//------------------------------------------------------------------------------ +inline void sc_runnable::push_back_method( sc_method_handle method_h ) +{ + // assert( method_h->next_runnable() == 0 ); // Can't queue twice. + DEBUG_MSG(DEBUG_NAME,method_h,"pushing back method"); + method_h->set_next_runnable(SC_NO_METHODS); + m_methods_push_tail->set_next_runnable(method_h); + m_methods_push_tail = method_h; +} + + +//------------------------------------------------------------------------------ +//"sc_runnable::push_back_thread" +// +// This method pushes the supplied thread process onto the back of the queue of +// runnable thread processes. +// thread_h -> thread process to add to the queue. +//------------------------------------------------------------------------------ +inline void sc_runnable::push_back_thread( sc_thread_handle thread_h ) +{ + // assert( thread_h->next_runnable() == 0 ); // Can't queue twice. + DEBUG_MSG(DEBUG_NAME,thread_h,"pushing back thread"); + thread_h->set_next_runnable(SC_NO_THREADS); + m_threads_push_tail->set_next_runnable(thread_h); + m_threads_push_tail = thread_h; +} + + +//------------------------------------------------------------------------------ +//"sc_runnable::push_front_method" +// +// This method pushes the supplied method process onto the front of the queue of +// runnable method processes. If the queue is empty the process is the tail +// also. +// method_h -> method process to add to the queue. +//------------------------------------------------------------------------------ +inline void sc_runnable::push_front_method( sc_method_handle method_h ) +{ + // assert( method_h->next_runnable() == 0 ); // Can't queue twice. + DEBUG_MSG(DEBUG_NAME,method_h,"pushing front method"); + method_h->set_next_runnable(m_methods_push_head->next_runnable()); + if ( m_methods_push_tail == m_methods_push_head ) // Empty queue. + { + m_methods_push_tail->set_next_runnable(method_h); + m_methods_push_tail = method_h; + } + else // Non-empty queue. + { + m_methods_push_head->set_next_runnable(method_h); + } +} + + +//------------------------------------------------------------------------------ +//"sc_runnable::push_front_thread" +// +// This method pushes the supplied thread process onto the front of the queue of +// runnable thread processes. If the queue is empty the process is the tail +// also. +// thread_h -> thread process to add to the queue. +//------------------------------------------------------------------------------ +inline void sc_runnable::push_front_thread( sc_thread_handle thread_h ) +{ + // assert( thread_h->next_runnable() == 0 ); // Can't queue twice. + DEBUG_MSG(DEBUG_NAME,thread_h,"pushing front thread"); + thread_h->set_next_runnable(m_threads_push_head->next_runnable()); + if ( m_threads_push_tail == m_threads_push_head ) // Empty queue. + { + m_threads_push_tail->set_next_runnable(thread_h); + m_threads_push_tail = thread_h; + } + else // Non-empty queue. + { + m_threads_push_head->set_next_runnable(thread_h); + } +} + +//------------------------------------------------------------------------------ +//"sc_runnable::pop_method" +// +// This method pops the next method process to be executed, or returns a null +// if no method processes are available for execution. +//------------------------------------------------------------------------------ +inline sc_method_handle sc_runnable::pop_method() +{ + sc_method_handle result_p; + + result_p = m_methods_pop; + if ( result_p != SC_NO_METHODS ) + { + m_methods_pop = result_p->next_runnable(); + result_p->set_next_runnable(0); + } + else + { + result_p = 0; + } + DEBUG_MSG(DEBUG_NAME,result_p,"popping method"); + return result_p; + +} + +//------------------------------------------------------------------------------ +//"sc_runnable::pop_thread" +// +// This method pops the next thread process to be executed, or returns a null +// if no thread processes are available for execution. +//------------------------------------------------------------------------------ +inline sc_thread_handle sc_runnable::pop_thread() +{ + sc_thread_handle result_p; + + result_p = m_threads_pop; + if ( result_p != SC_NO_THREADS ) + { + m_threads_pop = result_p->next_runnable(); + result_p->set_next_runnable(0); + } + else + { + result_p = 0; + } + DEBUG_MSG(DEBUG_NAME,result_p,"popping thread for execution"); + return result_p; +} + + +//------------------------------------------------------------------------------ +//"sc_runnable::remove_method" +// +// This method removes the supplied method process from the push queue if it is +// present. Note we clear the method's next pointer so that it may be queued +// again. +// remove_p -> method process to remove from the run queue. +//------------------------------------------------------------------------------ +inline void sc_runnable::remove_method( sc_method_handle remove_p ) +{ + sc_method_handle now_p; // Method now checking. + sc_method_handle prior_p; // Method prior to now_p. + + // Don't try to remove things if we have not been initialized. + + if ( !is_initialized() ) return; + + // Search the push queue: + + prior_p = m_methods_push_head; + for ( now_p = m_methods_push_head; now_p!= SC_NO_METHODS; + now_p = now_p->next_runnable() ) + { + if ( remove_p == now_p ) + { + prior_p->set_next_runnable( now_p->next_runnable() ); + if (now_p == m_methods_push_tail) { + m_methods_push_tail = prior_p; + } + now_p->set_next_runnable(0); + DEBUG_MSG(DEBUG_NAME,now_p,"removing method from push queue"); + return; + } + prior_p = now_p; + } + + // Search the pop queue: + + prior_p = NULL; + for ( now_p = m_methods_pop; now_p != SC_NO_METHODS; + now_p = now_p->next_runnable() ) + { + if ( remove_p == now_p ) + { + if ( prior_p ) + prior_p->set_next_runnable( now_p->next_runnable() ); + else + m_methods_pop = now_p->next_runnable(); + now_p->set_next_runnable(0); + DEBUG_MSG(DEBUG_NAME,now_p,"removing method from pop queue"); + return; + } + prior_p = now_p; + } +} + + +//------------------------------------------------------------------------------ +//"sc_runnable::remove_thread" +// +// This method removes the supplied thread process from the push or pop +// queue if it is present. Note we clear the thread's next pointer so that it +// may be queued again. +// remove_p -> thread process to remove from the run queue. +//------------------------------------------------------------------------------ +inline void sc_runnable::remove_thread( sc_thread_handle remove_p ) +{ + sc_thread_handle now_p; // Thread now checking. + sc_thread_handle prior_p; // Thread prior to now_p. + + // Don't try to remove things if we have not been initialized. + + if ( !is_initialized() ) return; + + // Search the push queue: + + prior_p = m_threads_push_head; + for ( now_p = m_threads_push_head; now_p != SC_NO_THREADS; + now_p = now_p->next_runnable() ) + { + if ( remove_p == now_p ) + { + prior_p->set_next_runnable( now_p->next_runnable() ); + if (now_p == m_threads_push_tail) { + m_threads_push_tail = prior_p; + } + now_p->set_next_runnable(0); + DEBUG_MSG(DEBUG_NAME,now_p,"removing thread from push queue"); + return; + } + prior_p = now_p; + } + + // Search the pop queue: + + prior_p = NULL; + for ( now_p = m_threads_pop; now_p != SC_NO_THREADS; + now_p = now_p->next_runnable() ) + { + if ( remove_p == now_p ) + { + if ( prior_p ) + prior_p->set_next_runnable( now_p->next_runnable() ); + else + m_threads_pop = now_p->next_runnable(); + now_p->set_next_runnable(0); + DEBUG_MSG(DEBUG_NAME,now_p,"removing thread from pop queue"); + return; + } + prior_p = now_p; + } +} + +//------------------------------------------------------------------------------ +//"sc_runnable::sc_runnable" +// +// This is the object instance constructor for this class. +//------------------------------------------------------------------------------ +inline sc_runnable::sc_runnable() : + m_methods_push_head(0), m_methods_push_tail(0), m_methods_pop(SC_NO_METHODS), + m_threads_push_head(0), m_threads_push_tail(0), m_threads_pop(SC_NO_THREADS) +{} + +//------------------------------------------------------------------------------ +//"sc_runnable::~sc_runnable" +// +// This is the object instance destructor for this class. +//------------------------------------------------------------------------------ +inline sc_runnable::~sc_runnable() +{ + delete m_methods_push_head; + delete m_threads_push_head; +} + + +//------------------------------------------------------------------------------ +//"sc_runnable::toggle_methods" +// +// This method moves the methods push queue to the pop queue and zeros the push +// queue. This will only be done if the pop queue is presently empty. +//------------------------------------------------------------------------------ +inline void sc_runnable::toggle_methods() +{ + if ( m_methods_pop == SC_NO_METHODS ) + { + m_methods_pop = m_methods_push_head->next_runnable(); + m_methods_push_head->set_next_runnable(SC_NO_METHODS); + m_methods_push_tail = m_methods_push_head; + } +} + + +//------------------------------------------------------------------------------ +//"sc_runnable::toggle_threads" +// +// This method moves the threads push queue to the pop queue and zeros the push +// queue. This will only be done if the pop queue is presently empty. +//------------------------------------------------------------------------------ +inline void sc_runnable::toggle_threads() +{ + if ( m_threads_pop == SC_NO_THREADS ) + { + m_threads_pop = m_threads_push_head->next_runnable(); + m_threads_push_head->set_next_runnable(SC_NO_THREADS); + m_threads_push_tail = m_threads_push_head; + } +} + +#undef SC_NO_METHODS +#undef SC_NO_THREADS +#undef DEBUG_MSG + +} // namespace sc_core + + +/******************************************************************************* + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + Andy Goodrich, Forte Design Systems, 2 September 2003 + Changed queue heads to instances to eliminate the checks for null heads. + + ******************************************************************************/ + +// $Log: sc_runnable_int.h,v $ +// Revision 1.19 2011/08/24 22:05:51 acg +// Torsten Maehne: initialization changes to remove warnings. +// +// Revision 1.18 2011/08/07 19:08:04 acg +// Andy Goodrich: moved logs to end of file so line number synching works +// better between versions. +// +// Revision 1.17 2011/04/13 02:45:11 acg +// Andy Goodrich: eliminated warning message that occurred if the DEBUG_MSG +// macro was used. +// +// Revision 1.16 2011/04/10 22:18:23 acg +// Andy Goodrich: debugging message clean up. +// +// Revision 1.15 2011/04/08 18:26:07 acg +// Andy Goodrich: added execute_method_next() to handle method dispatch +// for asynchronous notifications that occur outside the evaluation phase. +// +// Revision 1.14 2011/04/01 21:31:10 acg +// Andy Goodrich: turn off diagnostic messages by default. +// +// Revision 1.13 2011/04/01 21:30:02 acg +// Andy Goodrich: inserted conditional displays for queue manipulations. +// +// Revision 1.12 2011/03/30 00:01:34 acg +// Philip A. Hartmann: change break to return in remove_method() to short +// circuit the search the way remove_thread() works. +// +// Revision 1.11 2011/03/28 13:02:52 acg +// Andy Goodrich: Changes for disable() interactions. +// +// Revision 1.10 2011/03/06 15:58:17 acg +// Andy Goodrich: formatting changes. +// +// Revision 1.9 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.8 2011/02/13 21:47:38 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.7 2011/02/02 06:37:03 acg +// Andy Goodrich: removed toggle() method since it is no longer used. +// +// Revision 1.6 2011/02/01 21:09:13 acg +// Andy Goodrich: addition of toggle_methods() and toggle_threads() calls. +// +// Revision 1.5 2011/01/25 20:50:37 acg +// Andy Goodrich: changes for IEEE 1666 2011. +// +// Revision 1.4 2010/07/22 20:02:33 acg +// Andy Goodrich: bug fixes. +// +// Revision 1.3 2009/02/28 00:26:58 acg +// Andy Goodrich: changed boost name space to sc_boost to allow use with +// full boost library applications. +// +// Revision 1.2 2008/05/22 17:06:26 acg +// Andy Goodrich: updated copyright notice to include 2008. +// +// Revision 1.1.1.1 2006/12/15 20:20:05 acg +// SystemC 2.3 +// +// Revision 1.4 2006/04/20 17:08:17 acg +// Andy Goodrich: 3.0 style process changes. +// +// Revision 1.3 2006/01/13 18:44:30 acg +// Added $Log to record CVS changes into the source. +// + +#endif // SC_RUNNABLE_INT_H + +// Taf! diff --git a/ext/systemc/src/sysc/kernel/sc_sensitive.cpp b/ext/systemc/src/sysc/kernel/sc_sensitive.cpp new file mode 100644 index 000000000..210c2670e --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_sensitive.cpp @@ -0,0 +1,959 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_sensitive.cpp -- + + Original Author: Stan Y. Liao, Synopsys, Inc. + Martin Janssen, Synopsys, Inc. + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + + +#include "sysc/kernel/sc_event.h" +#include "sysc/kernel/sc_kernel_ids.h" +#include "sysc/kernel/sc_module.h" +#include "sysc/kernel/sc_cthread_process.h" +#include "sysc/kernel/sc_method_process.h" +#include "sysc/kernel/sc_thread_process.h" +#include "sysc/kernel/sc_process_handle.h" +#include "sysc/kernel/sc_sensitive.h" +#include "sysc/communication/sc_signal_ports.h" +#include "sysc/utils/sc_utils_ids.h" + +namespace sc_core { + +// support functions + +static +sc_method_handle +as_method_handle( sc_process_b* handle_ ) +{ + return DCAST<sc_method_handle>( handle_ ); +} + +static +sc_thread_handle +as_thread_handle( sc_process_b* handle_ ) +{ + return DCAST<sc_thread_handle>( handle_ ); +} + +static +void +warn_no_parens() +{ + static bool warn_no_parentheses=true; + if ( warn_no_parentheses ) + { + warn_no_parentheses=false; + SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, + "use of () to specify sensitivity is deprecated, use << instead" ); + } +} + +// ---------------------------------------------------------------------------- +// CLASS : sc_sensitive +// +// Static sensitivity class for events. +// ---------------------------------------------------------------------------- + +// constructor + +sc_sensitive::sc_sensitive( sc_module* module_ ) +: m_module( module_ ), + m_mode( SC_NONE_ ), + m_handle( 0 ) +{} + + +// destructor + +sc_sensitive::~sc_sensitive() +{} + + +// changing between process handles + +sc_sensitive& +sc_sensitive::operator << ( sc_process_handle handle_ ) +{ + switch ( handle_.proc_kind() ) + { + case SC_CTHREAD_PROC_: + case SC_THREAD_PROC_: + m_mode = SC_THREAD_; + break; + case SC_METHOD_PROC_: + m_mode = SC_METHOD_; + break; + default: + assert(0); + } + m_handle = (sc_process_b*)handle_; + return *this; +} + +sc_sensitive& +sc_sensitive::operator << ( const sc_event& event_ ) +{ + // check + if( sc_is_running() ) { + SC_REPORT_ERROR( SC_ID_MAKE_SENSITIVE_, "simulation running" ); + } + + // make sensitive + switch( m_mode ) { + case SC_METHOD_: + case SC_THREAD_: { + m_handle->add_static_event( event_ ); + break; + } + case SC_NONE_: + /* do nothing */ + break; + } + + return *this; +} + +void +sc_sensitive::make_static_sensitivity( + sc_process_b* handle_, const sc_event& event_) +{ + handle_->add_static_event( event_ ); +} + + +sc_sensitive& +sc_sensitive::operator << ( const sc_interface& interface_ ) +{ + // check + if( sc_is_running() ) { + SC_REPORT_ERROR( SC_ID_MAKE_SENSITIVE_, "simulation running" ); + } + + // make sensitive + switch( m_mode ) { + case SC_METHOD_: + case SC_THREAD_: { + m_handle->add_static_event( interface_.default_event() ); + break; + } + case SC_NONE_: + /* do nothing */ + break; + } + + return *this; +} + +void +sc_sensitive::make_static_sensitivity( + sc_process_b* handle_, const sc_interface& interface_) +{ + handle_->add_static_event( interface_.default_event() ); +} + +sc_sensitive& +sc_sensitive::operator << ( const sc_port_base& port_ ) +{ + // check + if( sc_is_running() ) { + SC_REPORT_ERROR( SC_ID_MAKE_SENSITIVE_, "simulation running" ); + } + + // make sensitive + switch( m_mode ) { + case SC_METHOD_: { + port_.make_sensitive( as_method_handle( m_handle ) ); + break; + } + case SC_THREAD_: { + port_.make_sensitive( as_thread_handle( m_handle ) ); + break; + } + case SC_NONE_: + /* do nothing */ + break; + } + + return *this; +} + +void +sc_sensitive::make_static_sensitivity( + sc_process_b* handle_, const sc_port_base& port_) +{ + sc_method_handle handle_m = as_method_handle( handle_ ); + if ( handle_m ) { + port_.make_sensitive( handle_m ); + return; + } + sc_thread_handle handle_t = as_thread_handle( handle_ ); + // assert(handle_t); + port_.make_sensitive( handle_t ); +} + +sc_sensitive& +sc_sensitive::operator << ( sc_event_finder& event_finder_ ) +{ + // check + if( sc_is_running() ) { + SC_REPORT_ERROR( SC_ID_MAKE_SENSITIVE_, "simulation running" ); + } + + // make sensitive + switch( m_mode ) { + case SC_METHOD_: { + event_finder_.port().make_sensitive( as_method_handle( m_handle ), + &event_finder_ ); + break; + } + case SC_THREAD_: { + event_finder_.port().make_sensitive( as_thread_handle( m_handle ), + &event_finder_ ); + break; + } + case SC_NONE_: + /* do nothing */ + break; + } + + return *this; +} + +void +sc_sensitive::make_static_sensitivity( + sc_process_b* handle_, sc_event_finder& event_finder_) +{ + if (sc_is_running()) { + handle_->add_static_event( event_finder_.find_event() ); + } else { + sc_method_handle handle_m = as_method_handle( handle_ ); + if ( handle_m ) { + event_finder_.port().make_sensitive( handle_m, &event_finder_ ); + return; + } + sc_thread_handle handle_t = as_thread_handle( handle_ ); + // assert(handle_t); + event_finder_.port().make_sensitive( handle_t, &event_finder_); + } +} + + +sc_sensitive& +sc_sensitive::operator () ( const sc_event& event_ ) +{ + warn_no_parens(); + return operator << ( event_ ); +} + +sc_sensitive& +sc_sensitive::operator () ( const sc_interface& interface_ ) +{ + warn_no_parens(); + return operator << ( interface_ ); +} + +sc_sensitive& +sc_sensitive::operator () ( const sc_port_base& port_ ) +{ + warn_no_parens(); + return operator << ( port_ ); +} + +sc_sensitive& +sc_sensitive::operator () ( sc_event_finder& event_finder_ ) +{ + warn_no_parens(); + return operator << ( event_finder_ ); +} + + +sc_sensitive& +sc_sensitive::operator () ( sc_cthread_handle handle_, + sc_event_finder& event_finder_ ) +{ + event_finder_.port().make_sensitive( handle_, &event_finder_ ); + return *this; +} + +sc_sensitive& +sc_sensitive::operator () ( sc_cthread_handle handle_, + const in_if_b_type& interface_ ) +{ + handle_->add_static_event( interface_.posedge_event() ); + return *this; +} + +sc_sensitive& +sc_sensitive::operator () ( sc_cthread_handle handle_, + const in_if_l_type& interface_ ) +{ + handle_->add_static_event( interface_.posedge_event() ); + return *this; +} + +sc_sensitive& +sc_sensitive::operator () ( sc_cthread_handle handle_, + const in_port_b_type& port_ ) +{ + port_.make_sensitive( handle_, &port_.pos() ); + return *this; +} + +sc_sensitive& +sc_sensitive::operator () ( sc_cthread_handle handle_, + const in_port_l_type& port_ ) +{ + port_.make_sensitive( handle_, &port_.pos() ); + return *this; +} + +sc_sensitive& +sc_sensitive::operator () ( sc_cthread_handle handle_, + const inout_port_b_type& port_ ) +{ + port_.make_sensitive( handle_, &port_.pos() ); + return *this; +} + +sc_sensitive& +sc_sensitive::operator () ( sc_cthread_handle handle_, + const inout_port_l_type& port_ ) +{ + port_.make_sensitive( handle_, &port_.pos() ); + return *this; +} + +void sc_sensitive::reset() +{ + m_mode = SC_NONE_; +} + + +// ---------------------------------------------------------------------------- +// CLASS : sc_sensitive_pos +// +// Static sensitivity class for positive edge events. +// ---------------------------------------------------------------------------- + +static void sc_deprecated_sensitive_pos() +{ + static bool warn_sensitive_pos=true; + if ( warn_sensitive_pos ) + { + warn_sensitive_pos=false; + SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, + "sc_sensitive_pos is deprecated use sc_sensitive << with pos() instead" ); + } +} + +// constructor + +sc_sensitive_pos::sc_sensitive_pos( sc_module* module_ ) +: m_module( module_ ), + m_mode( SC_NONE_ ), + m_handle( 0 ) +{} + + +// destructor + +sc_sensitive_pos::~sc_sensitive_pos() +{} + + +// changing between process handles + +sc_sensitive_pos& +sc_sensitive_pos::operator << ( sc_process_handle handle_ ) +{ + switch ( handle_.proc_kind() ) + { + case SC_CTHREAD_PROC_: + case SC_THREAD_PROC_: + m_mode = SC_THREAD_; + break; + case SC_METHOD_PROC_: + m_mode = SC_METHOD_; + break; + default: + assert(0); + } + m_handle = (sc_process_b*)handle_; + return *this; +} + +sc_sensitive_pos& +sc_sensitive_pos::operator << ( sc_method_handle handle_ ) +{ + m_mode = SC_METHOD_; + m_handle = handle_; + return *this; +} + +sc_sensitive_pos& +sc_sensitive_pos::operator << ( sc_thread_handle handle_ ) +{ + m_mode = SC_THREAD_; + m_handle = handle_; + return *this; +} + + +sc_sensitive_pos& +sc_sensitive_pos::operator << ( const in_if_b_type& interface_ ) +{ + sc_deprecated_sensitive_pos(); + // check + if( sc_is_running() ) { + SC_REPORT_ERROR( SC_ID_MAKE_SENSITIVE_POS_, "simulation running" ); + } + + // make sensitive + switch( m_mode ) { + case SC_METHOD_: + case SC_THREAD_: { + m_handle->add_static_event( interface_.posedge_event() ); + break; + } + case SC_NONE_: + /* do nothing */ + break; + } + + return *this; +} + +sc_sensitive_pos& +sc_sensitive_pos::operator << ( const in_if_l_type& interface_ ) +{ + sc_deprecated_sensitive_pos(); + // check + if( sc_is_running() ) { + SC_REPORT_ERROR( SC_ID_MAKE_SENSITIVE_POS_, "simulation running" ); + } + + // make sensitive + switch( m_mode ) { + case SC_METHOD_: + case SC_THREAD_: { + m_handle->add_static_event( interface_.posedge_event() ); + break; + } + case SC_NONE_: + /* do nothing */ + break; + } + + return *this; +} + +sc_sensitive_pos& +sc_sensitive_pos::operator << ( const in_port_b_type& port_ ) +{ + sc_deprecated_sensitive_pos(); + // check + if( sc_is_running() ) { + SC_REPORT_ERROR( SC_ID_MAKE_SENSITIVE_POS_, "simulation running" ); + } + + // make sensitive + switch( m_mode ) { + case SC_METHOD_: { + port_.make_sensitive( as_method_handle( m_handle ), &port_.pos() ); + break; + } + case SC_THREAD_: { + port_.make_sensitive( as_thread_handle( m_handle ), &port_.pos() ); + break; + } + case SC_NONE_: + /* do nothing */ + break; + } + + return *this; +} + +sc_sensitive_pos& +sc_sensitive_pos::operator << ( const in_port_l_type& port_ ) +{ + sc_deprecated_sensitive_pos(); + // check + if( sc_is_running() ) { + SC_REPORT_ERROR( SC_ID_MAKE_SENSITIVE_POS_, "simulation running" ); + } + + // make sensitive + switch( m_mode ) { + case SC_METHOD_: { + port_.make_sensitive( as_method_handle( m_handle ), &port_.pos() ); + break; + } + case SC_THREAD_: { + port_.make_sensitive( as_thread_handle( m_handle ), &port_.pos() ); + break; + } + case SC_NONE_: + /* do nothing */ + break; + } + + return *this; +} + +sc_sensitive_pos& +sc_sensitive_pos::operator << ( const inout_port_b_type& port_ ) +{ + sc_deprecated_sensitive_pos(); + // check + if( sc_is_running() ) { + SC_REPORT_ERROR( SC_ID_MAKE_SENSITIVE_POS_, "simulation running" ); + } + + // make sensitive + switch( m_mode ) { + case SC_METHOD_: { + port_.make_sensitive( as_method_handle( m_handle ), &port_.pos() ); + break; + } + case SC_THREAD_: { + port_.make_sensitive( as_thread_handle( m_handle ), &port_.pos() ); + break; + } + case SC_NONE_: + /* do nothing */ + break; + } + + return *this; +} + +sc_sensitive_pos& +sc_sensitive_pos::operator << ( const inout_port_l_type& port_ ) +{ + sc_deprecated_sensitive_pos(); + // check + if( sc_is_running() ) { + SC_REPORT_ERROR( SC_ID_MAKE_SENSITIVE_POS_, "simulation running" ); + } + + // make sensitive + switch( m_mode ) { + case SC_METHOD_: { + port_.make_sensitive( as_method_handle( m_handle ), &port_.pos() ); + break; + } + case SC_THREAD_: { + port_.make_sensitive( as_thread_handle( m_handle ), &port_.pos() ); + break; + } + case SC_NONE_: + /* do nothing */ + break; + } + + return *this; +} + + +sc_sensitive_pos& +sc_sensitive_pos::operator () ( const in_if_b_type& interface_ ) +{ + warn_no_parens(); + return operator << ( interface_ ); +} + +sc_sensitive_pos& +sc_sensitive_pos::operator () ( const in_if_l_type& interface_ ) +{ + warn_no_parens(); + return operator << ( interface_ ); +} + +sc_sensitive_pos& +sc_sensitive_pos::operator () ( const in_port_b_type& port_ ) +{ + warn_no_parens(); + return operator << ( port_ ); +} + +sc_sensitive_pos& +sc_sensitive_pos::operator () ( const in_port_l_type& port_ ) +{ + warn_no_parens(); + return operator << ( port_ ); +} + +sc_sensitive_pos& +sc_sensitive_pos::operator () ( const inout_port_b_type& port_ ) +{ + warn_no_parens(); + return operator << ( port_ ); +} + +sc_sensitive_pos& +sc_sensitive_pos::operator () ( const inout_port_l_type& port_ ) +{ + warn_no_parens(); + return operator << ( port_ ); +} + +void sc_sensitive_pos::reset() +{ + m_mode = SC_NONE_; +} + + +// ---------------------------------------------------------------------------- +// CLASS : sc_sensitive_neg +// +// Static sensitivity class for negative edge events. +// ---------------------------------------------------------------------------- + +static void sc_deprecated_sensitive_neg() +{ + static bool warn_sensitive_neg=true; + if ( warn_sensitive_neg ) + { + warn_sensitive_neg=false; + SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, + "sc_sensitive_neg is deprecated use sc_sensitive << with neg() instead" ); + } +} + +// constructor + +sc_sensitive_neg::sc_sensitive_neg( sc_module* module_ ) +: m_module( module_ ), + m_mode( SC_NONE_ ), + m_handle( 0 ) +{} + + +// destructor + +sc_sensitive_neg::~sc_sensitive_neg() +{} + + +// changing between process handles + +sc_sensitive_neg& +sc_sensitive_neg::operator << ( sc_process_handle handle_ ) +{ + switch ( handle_.proc_kind() ) + { + case SC_CTHREAD_PROC_: + case SC_THREAD_PROC_: + m_mode = SC_THREAD_; + break; + case SC_METHOD_PROC_: + m_mode = SC_METHOD_; + break; + default: + assert(0); + } + m_handle = (sc_process_b*)handle_; + return *this; +} + +sc_sensitive_neg& +sc_sensitive_neg::operator << ( sc_method_handle handle_ ) +{ + m_mode = SC_METHOD_; + m_handle = handle_; + return *this; +} + +sc_sensitive_neg& +sc_sensitive_neg::operator << ( sc_thread_handle handle_ ) +{ + m_mode = SC_THREAD_; + m_handle = handle_; + return *this; +} + + +sc_sensitive_neg& +sc_sensitive_neg::operator << ( const in_if_b_type& interface_ ) +{ + sc_deprecated_sensitive_neg(); + // check + if( sc_is_running() ) { + SC_REPORT_ERROR( SC_ID_MAKE_SENSITIVE_NEG_, "simulation running" ); + } + + // make sensitive + switch( m_mode ) { + case SC_METHOD_: + case SC_THREAD_: { + m_handle->add_static_event( interface_.negedge_event() ); + break; + } + case SC_NONE_: + /* do nothing */ + break; + } + + return *this; +} + +sc_sensitive_neg& +sc_sensitive_neg::operator << ( const in_if_l_type& interface_ ) +{ + sc_deprecated_sensitive_neg(); + // check + if( sc_is_running() ) { + SC_REPORT_ERROR( SC_ID_MAKE_SENSITIVE_NEG_, "simulation running" ); + } + + // make sensitive + switch( m_mode ) { + case SC_METHOD_: + case SC_THREAD_: { + m_handle->add_static_event( interface_.negedge_event() ); + break; + } + case SC_NONE_: + /* do nothing */ + break; + } + + return *this; +} + +sc_sensitive_neg& +sc_sensitive_neg::operator << ( const in_port_b_type& port_ ) +{ + sc_deprecated_sensitive_neg(); + // check + if( sc_is_running() ) { + SC_REPORT_ERROR( SC_ID_MAKE_SENSITIVE_NEG_, "simulation running" ); + } + + // make sensitive + switch( m_mode ) { + case SC_METHOD_: { + port_.make_sensitive( as_method_handle( m_handle ), &port_.neg() ); + break; + } + case SC_THREAD_: { + port_.make_sensitive( as_thread_handle( m_handle ), &port_.neg() ); + break; + } + case SC_NONE_: + /* do nothing */ + break; + } + + return *this; +} + +sc_sensitive_neg& +sc_sensitive_neg::operator << ( const in_port_l_type& port_ ) +{ + sc_deprecated_sensitive_neg(); + // check + if( sc_is_running() ) { + SC_REPORT_ERROR( SC_ID_MAKE_SENSITIVE_NEG_, "simulation running" ); + } + + // make sensitive + switch( m_mode ) { + case SC_METHOD_: { + port_.make_sensitive( as_method_handle( m_handle ), &port_.neg() ); + break; + } + case SC_THREAD_: { + port_.make_sensitive( as_thread_handle( m_handle ), &port_.neg() ); + break; + } + case SC_NONE_: + /* do nothing */ + break; + } + + return *this; +} + +sc_sensitive_neg& +sc_sensitive_neg::operator << ( const inout_port_b_type& port_ ) +{ + sc_deprecated_sensitive_neg(); + // check + if( sc_is_running() ) { + SC_REPORT_ERROR( SC_ID_MAKE_SENSITIVE_NEG_, "simulation running" ); + } + + // make sensitive + switch( m_mode ) { + case SC_METHOD_: { + port_.make_sensitive( as_method_handle( m_handle ), &port_.neg() ); + break; + } + case SC_THREAD_: { + port_.make_sensitive( as_thread_handle( m_handle ), &port_.neg() ); + break; + } + case SC_NONE_: + /* do nothing */ + break; + } + + return *this; +} + +sc_sensitive_neg& +sc_sensitive_neg::operator << ( const inout_port_l_type& port_ ) +{ + sc_deprecated_sensitive_neg(); + // check + if( sc_is_running() ) { + SC_REPORT_ERROR( SC_ID_MAKE_SENSITIVE_NEG_, "simulation running" ); + } + + // make sensitive + switch( m_mode ) { + case SC_METHOD_: { + port_.make_sensitive( as_method_handle( m_handle ), &port_.neg() ); + break; + } + case SC_THREAD_: { + port_.make_sensitive( as_thread_handle( m_handle ), &port_.neg() ); + break; + } + case SC_NONE_: + /* do nothing */ + break; + } + + return *this; +} + + +sc_sensitive_neg& +sc_sensitive_neg::operator () ( const in_if_b_type& interface_ ) +{ + warn_no_parens(); + return operator << ( interface_ ); +} + +sc_sensitive_neg& +sc_sensitive_neg::operator () ( const in_if_l_type& interface_ ) +{ + warn_no_parens(); + return operator << ( interface_ ); +} + +sc_sensitive_neg& +sc_sensitive_neg::operator () ( const in_port_b_type& port_ ) +{ + warn_no_parens(); + return operator << ( port_ ); +} + +sc_sensitive_neg& +sc_sensitive_neg::operator () ( const in_port_l_type& port_ ) +{ + warn_no_parens(); + return operator << ( port_ ); +} + +sc_sensitive_neg& +sc_sensitive_neg::operator () ( const inout_port_b_type& port_ ) +{ + warn_no_parens(); + return operator << ( port_ ); +} + +sc_sensitive_neg& +sc_sensitive_neg::operator () ( const inout_port_l_type& port_ ) +{ + warn_no_parens(); + return operator << ( port_ ); +} + +void sc_sensitive_neg::reset() +{ + m_mode = SC_NONE_; +} + +} // namespace sc_core + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: Bishnupriya Bhattacharya, Cadence Design Systems, + 25 August, 2003 + Description of Modification: add make_static_sensitivity() routines to support + dynamic method process creation with static + sensitivity + + *****************************************************************************/ + +// $Log: sc_sensitive.cpp,v $ +// Revision 1.5 2011/08/26 20:46:10 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +// Revision 1.4 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.3 2011/02/13 21:47:38 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.2 2008/05/22 17:06:26 acg +// Andy Goodrich: updated copyright notice to include 2008. +// +// Revision 1.1.1.1 2006/12/15 20:20:05 acg +// SystemC 2.3 +// +// Revision 1.8 2006/04/11 23:13:21 acg +// Andy Goodrich: Changes for reduced reset support that only includes +// sc_cthread, but has preliminary hooks for expanding to method and thread +// processes also. +// +// Revision 1.7 2006/01/27 17:31:24 acg +// Andy Goodrich: removed debugging comments from << operator code for types +// that are deprecated. +// +// Revision 1.6 2006/01/26 21:04:54 acg +// Andy Goodrich: deprecation message changes and additional messages. +// +// Revision 1.5 2006/01/25 00:31:19 acg +// Andy Goodrich: Changed over to use a standard message id of +// SC_ID_IEEE_1666_DEPRECATION for all deprecation messages. +// +// Revision 1.4 2006/01/24 20:49:05 acg +// Andy Goodrich: changes to remove the use of deprecated features within the +// simulator, and to issue warning messages when deprecated features are used. +// +// Revision 1.3 2006/01/13 18:44:30 acg +// Added $Log to record CVS changes into the source. +// + +// Taf! diff --git a/ext/systemc/src/sysc/kernel/sc_sensitive.h b/ext/systemc/src/sysc/kernel/sc_sensitive.h new file mode 100644 index 000000000..9d07bd03a --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_sensitive.h @@ -0,0 +1,306 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_sensitive.h -- Sensitivity classes. Requires "sc_process.h" + for declarations of sc_method_handle, &.c. + + Original Author: Stan Y. Liao, Synopsys, Inc. + Martin Janssen, Synopsys, Inc. + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + + +#ifndef SC_SENSITIVE_H +#define SC_SENSITIVE_H + +#include "sysc/kernel/sc_process.h" + +namespace sc_dt +{ + class sc_logic; +} + +namespace sc_core { + +class sc_process_handle; +class sc_event; +class sc_event_finder; +class sc_interface; +class sc_module; +class sc_port_base; +template <class T> class sc_in; +template <class T> class sc_inout; +template <class T> class sc_signal_in_if; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_sensitive +// +// Static sensitivity class for events. +// ---------------------------------------------------------------------------- + +class sc_sensitive +{ + friend class sc_module; + +public: + + // typedefs + typedef sc_signal_in_if<bool> in_if_b_type; + typedef sc_signal_in_if<sc_dt::sc_logic> in_if_l_type; + typedef sc_in<bool> in_port_b_type; + typedef sc_in<sc_dt::sc_logic> in_port_l_type; + typedef sc_inout<bool> inout_port_b_type; + typedef sc_inout<sc_dt::sc_logic> inout_port_l_type; + +private: + + // constructor + explicit sc_sensitive( sc_module* ); + + // destructor + ~sc_sensitive(); + +public: + + // changing between process handles + sc_sensitive& operator << ( sc_process_handle ); +#if 0 + sc_sensitive& operator << ( sc_method_handle ); + sc_sensitive& operator << ( sc_thread_handle ); +#endif // 0 + + sc_sensitive& operator () ( const sc_event& ); + sc_sensitive& operator () ( const sc_interface& ); + sc_sensitive& operator () ( const sc_port_base& ); + sc_sensitive& operator () ( sc_event_finder& ); + + sc_sensitive& operator << ( const sc_event& ); + sc_sensitive& operator << ( const sc_interface& ); + sc_sensitive& operator << ( const sc_port_base& ); + sc_sensitive& operator << ( sc_event_finder& ); + + sc_sensitive& operator () ( sc_cthread_handle, sc_event_finder& ); + sc_sensitive& operator () ( sc_cthread_handle, const in_if_b_type& ); + sc_sensitive& operator () ( sc_cthread_handle, const in_if_l_type& ); + sc_sensitive& operator () ( sc_cthread_handle, const in_port_b_type& ); + sc_sensitive& operator () ( sc_cthread_handle, const in_port_l_type& ); + sc_sensitive& operator () ( sc_cthread_handle, const inout_port_b_type& ); + sc_sensitive& operator () ( sc_cthread_handle, const inout_port_l_type& ); + + static void make_static_sensitivity( sc_process_b*, const sc_event& ); + static void make_static_sensitivity( sc_process_b*, const sc_interface& ); + static void make_static_sensitivity( sc_process_b*, const sc_port_base&); + static void make_static_sensitivity( sc_process_b*, sc_event_finder& ); + + void reset(); + +private: + + sc_module* m_module; + enum { SC_NONE_, SC_METHOD_, SC_THREAD_ } m_mode; + sc_process_b* m_handle; + +private: + + // disabled + + sc_sensitive(); + sc_sensitive( const sc_sensitive& ); + sc_sensitive& operator = ( const sc_sensitive& ); +}; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_sensitive_pos +// +// Static sensitivity class for positive edge events. +// ---------------------------------------------------------------------------- + +class sc_sensitive_pos +{ + friend class sc_module; + +public: + + // typedefs + typedef sc_signal_in_if<bool> in_if_b_type; + typedef sc_signal_in_if<sc_dt::sc_logic> in_if_l_type; + typedef sc_in<bool> in_port_b_type; + typedef sc_in<sc_dt::sc_logic> in_port_l_type; + typedef sc_inout<bool> inout_port_b_type; + typedef sc_inout<sc_dt::sc_logic> inout_port_l_type; + +private: + + // constructor + explicit sc_sensitive_pos( sc_module* ); + + // destructor + ~sc_sensitive_pos(); + +public: + + // changing between process handles + sc_sensitive_pos& operator << ( sc_process_handle ); + sc_sensitive_pos& operator << ( sc_method_handle ); + sc_sensitive_pos& operator << ( sc_thread_handle ); + + sc_sensitive_pos& operator () ( const in_if_b_type& ); + sc_sensitive_pos& operator () ( const in_if_l_type& ); + sc_sensitive_pos& operator () ( const in_port_b_type& ); + sc_sensitive_pos& operator () ( const in_port_l_type& ); + sc_sensitive_pos& operator () ( const inout_port_b_type& ); + sc_sensitive_pos& operator () ( const inout_port_l_type& ); + + sc_sensitive_pos& operator << ( const in_if_b_type& ); + sc_sensitive_pos& operator << ( const in_if_l_type& ); + sc_sensitive_pos& operator << ( const in_port_b_type& ); + sc_sensitive_pos& operator << ( const in_port_l_type& ); + sc_sensitive_pos& operator << ( const inout_port_b_type& ); + sc_sensitive_pos& operator << ( const inout_port_l_type& ); + + void reset(); + +private: + + sc_module* m_module; + enum { SC_NONE_, SC_METHOD_, SC_THREAD_ } m_mode; + sc_process_b* m_handle; + +private: + + // disabled + sc_sensitive_pos(); + sc_sensitive_pos( const sc_sensitive_pos& ); + sc_sensitive_pos& operator = ( const sc_sensitive_pos& ); +}; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_sensitive_neg +// +// Static sensitivity class for negative edge events. +// ---------------------------------------------------------------------------- + +class sc_sensitive_neg +{ + friend class sc_module; + +public: + + // typedefs + typedef sc_signal_in_if<bool> in_if_b_type; + typedef sc_signal_in_if<sc_dt::sc_logic> in_if_l_type; + typedef sc_in<bool> in_port_b_type; + typedef sc_in<sc_dt::sc_logic> in_port_l_type; + typedef sc_inout<bool> inout_port_b_type; + typedef sc_inout<sc_dt::sc_logic> inout_port_l_type; + +private: + + // constructor + explicit sc_sensitive_neg( sc_module* ); + + // destructor + ~sc_sensitive_neg(); + +public: + + // changing between process handles + sc_sensitive_neg& operator << ( sc_process_handle ); + sc_sensitive_neg& operator << ( sc_method_handle ); + sc_sensitive_neg& operator << ( sc_thread_handle ); + + sc_sensitive_neg& operator () ( const in_if_b_type& ); + sc_sensitive_neg& operator () ( const in_if_l_type& ); + sc_sensitive_neg& operator () ( const in_port_b_type& ); + sc_sensitive_neg& operator () ( const in_port_l_type& ); + sc_sensitive_neg& operator () ( const inout_port_b_type& ); + sc_sensitive_neg& operator () ( const inout_port_l_type& ); + + sc_sensitive_neg& operator << ( const in_if_b_type& ); + sc_sensitive_neg& operator << ( const in_if_l_type& ); + sc_sensitive_neg& operator << ( const in_port_b_type& ); + sc_sensitive_neg& operator << ( const in_port_l_type& ); + sc_sensitive_neg& operator << ( const inout_port_b_type& ); + sc_sensitive_neg& operator << ( const inout_port_l_type& ); + + void reset(); + +private: + + sc_module* m_module; + enum { SC_NONE_, SC_METHOD_, SC_THREAD_ } m_mode; + sc_process_b* m_handle; + +private: + + // disabled + sc_sensitive_neg(); + sc_sensitive_neg( const sc_sensitive_neg& ); + sc_sensitive_neg& operator = ( const sc_sensitive_neg& ); +}; + +} // namespace sc_core + +#endif + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: Bishnupriya Bhattacharya, Cadence Design Systems, + 25 August, 2003 + Description of Modification: Add make_static_sensitivity() methods to enable + dynamic method process creation with static + sensitivity. + + *****************************************************************************/ + +// $Log: sc_sensitive.h,v $ +// Revision 1.5 2011/08/26 20:46:10 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +// Revision 1.4 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.3 2011/02/13 21:47:38 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.2 2008/05/22 17:06:26 acg +// Andy Goodrich: updated copyright notice to include 2008. +// +// Revision 1.1.1.1 2006/12/15 20:20:05 acg +// SystemC 2.3 +// +// Revision 1.4 2006/04/11 23:13:21 acg +// Andy Goodrich: Changes for reduced reset support that only includes +// sc_cthread, but has preliminary hooks for expanding to method and thread +// processes also. +// +// Revision 1.3 2006/01/13 18:44:30 acg +// Added $Log to record CVS changes into the source. + +// Taf! diff --git a/ext/systemc/src/sysc/kernel/sc_simcontext.cpp b/ext/systemc/src/sysc/kernel/sc_simcontext.cpp new file mode 100644 index 000000000..104f7c984 --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_simcontext.cpp @@ -0,0 +1,2284 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_simcontext.cpp -- Provides a simulation context for use with multiple + simulations. + + Original Author: Stan Y. Liao, Synopsys, Inc. + Martin Janssen, Synopsys, Inc. + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + +#include <algorithm> + +#define SC_DISABLE_API_VERSION_CHECK // for in-library sc_ver.h inclusion + +#include "sysc/kernel/sc_cor_fiber.h" +#include "sysc/kernel/sc_cor_pthread.h" +#include "sysc/kernel/sc_cor_qt.h" +#include "sysc/kernel/sc_event.h" +#include "sysc/kernel/sc_kernel_ids.h" +#include "sysc/kernel/sc_module.h" +#include "sysc/kernel/sc_module_registry.h" +#include "sysc/kernel/sc_name_gen.h" +#include "sysc/kernel/sc_object_manager.h" +#include "sysc/kernel/sc_cthread_process.h" +#include "sysc/kernel/sc_method_process.h" +#include "sysc/kernel/sc_thread_process.h" +#include "sysc/kernel/sc_process_handle.h" +#include "sysc/kernel/sc_simcontext.h" +#include "sysc/kernel/sc_simcontext_int.h" +#include "sysc/kernel/sc_reset.h" +#include "sysc/kernel/sc_ver.h" +#include "sysc/kernel/sc_boost.h" +#include "sysc/kernel/sc_spawn.h" +#include "sysc/kernel/sc_phase_callback_registry.h" +#include "sysc/communication/sc_port.h" +#include "sysc/communication/sc_export.h" +#include "sysc/communication/sc_prim_channel.h" +#include "sysc/tracing/sc_trace.h" +#include "sysc/utils/sc_mempool.h" +#include "sysc/utils/sc_list.h" +#include "sysc/utils/sc_utils_ids.h" + +// DEBUGGING MACROS: +// +// DEBUG_MSG(NAME,P,MSG) +// MSG = message to print +// NAME = name that must match the process for the message to print, or +// null if the message should be printed unconditionally. +// P = pointer to process message is for, or NULL in which case the +// message will not print. +#if 0 +# define DEBUG_NAME "" +# define DEBUG_MSG(NAME,P,MSG) \ + { \ + if ( P && ( (strlen(NAME)==0) || !strcmp(NAME,P->name())) ) \ + std::cout << "**** " << sc_time_stamp() << " (" \ + << sc_get_current_process_name() << "): " << MSG \ + << " - " << P->name() << std::endl; \ + } +#else +# define DEBUG_MSG(NAME,P,MSG) +#endif + +#if SC_HAS_PHASE_CALLBACKS_ +# define SC_DO_PHASE_CALLBACK_( Kind ) \ + m_phase_cb_registry->Kind() +#else +# define SC_DO_PHASE_CALLBACK_( Kind ) \ + ((void)0) /* do nothing */ +#endif + +#if defined( SC_ENABLE_SIMULATION_PHASE_CALLBACKS_TRACING ) +// use callback based tracing +# define SC_SIMCONTEXT_TRACING_ 0 +#else +// enable tracing via explicit trace_cycle calls from simulator loop +# define SC_SIMCONTEXT_TRACING_ 1 +#endif + +namespace sc_core { + +sc_stop_mode stop_mode = SC_STOP_FINISH_DELTA; + +// ---------------------------------------------------------------------------- +// CLASS : sc_process_table +// +// Container class that keeps track of all method processes, +// (c)thread processes. +// ---------------------------------------------------------------------------- + +class sc_process_table +{ + public: + + sc_process_table(); + ~sc_process_table(); + void push_front( sc_method_handle ); + void push_front( sc_thread_handle ); + sc_method_handle method_q_head(); + sc_method_handle remove( sc_method_handle ); + sc_thread_handle thread_q_head(); + sc_thread_handle remove( sc_thread_handle ); + + + private: + + sc_method_handle m_method_q; // Queue of existing method processes. + sc_thread_handle m_thread_q; // Queue of existing thread processes. +}; + + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + +sc_process_table::sc_process_table() : m_method_q(0), m_thread_q(0) +{} + +sc_process_table::~sc_process_table() +{ + + sc_method_handle method_next_p; // Next method to delete. + sc_method_handle method_now_p; // Method now deleting. + + for( method_now_p = m_method_q; method_now_p; method_now_p = method_next_p ) + { + method_next_p = method_now_p->next_exist(); + delete method_now_p; + } + + if ( m_thread_q ) + { + ::std::cout << ::std::endl + << "WATCH OUT!! In sc_process_table destructor. " + << "Threads and cthreads are not actually getting deleted here. " + << "Some memory may leak. Look at the comments here in " + << "kernel/sc_simcontext.cpp for more details." + << ::std::endl; + } + + // don't delete threads and cthreads. If a (c)thread + // has died, then it has already been deleted. Only (c)threads created + // before simulation-start are in this table. Due to performance + // reasons, we don't look up the dying thread in the process table + // and remove it from there. simcontext::reset and ~simcontext invoke this + // destructor. At present none of these routines are ever invoked. + // We can delete threads and cthreads here if a dying thread figured out + // it was created before simulation-start and took itself off the + // process_table. + +#if 0 + sc_thread_handle thread_next_p; // Next thread to delete. + sc_thread_handle thread_now_p; // Thread now deleting. + + for( thread_now_p=m_thread_q; thread_now_p; thread_now_p=thread_next_p ) + { + thread_next_p = thread_now_p->next_exist(); + delete thread_now_p; + } +#endif // 0 +} + +inline +sc_method_handle +sc_process_table::method_q_head() +{ + return m_method_q; +} + +inline +void +sc_process_table::push_front( sc_method_handle handle_ ) +{ + handle_->set_next_exist(m_method_q); + m_method_q = handle_; +} + +inline +void +sc_process_table::push_front( sc_thread_handle handle_ ) +{ + handle_->set_next_exist(m_thread_q); + m_thread_q = handle_; +} + +sc_method_handle +sc_process_table::remove( sc_method_handle handle_ ) +{ + sc_method_handle now_p; // Entry now examining. + sc_method_handle prior_p; // Entry prior to one now examining. + + prior_p = 0; + for ( now_p = m_method_q; now_p; now_p = now_p->next_exist() ) + { + if ( now_p == handle_ ) + { + if ( prior_p ) + prior_p->set_next_exist( now_p->next_exist() ); + else + m_method_q = now_p->next_exist(); + return handle_; + } + } + return 0; +} + +sc_thread_handle +sc_process_table::remove( sc_thread_handle handle_ ) +{ + sc_thread_handle now_p; // Entry now examining. + sc_thread_handle prior_p; // Entry prior to one now examining. + + prior_p = 0; + for ( now_p = m_thread_q; now_p; now_p = now_p->next_exist() ) + { + if ( now_p == handle_ ) + { + if ( prior_p ) + prior_p->set_next_exist( now_p->next_exist() ); + else + m_thread_q = now_p->next_exist(); + return handle_; + } + } + return 0; +} + +inline +sc_thread_handle +sc_process_table::thread_q_head() +{ + return m_thread_q; +} + +int +sc_notify_time_compare( const void* p1, const void* p2 ) +{ + const sc_event_timed* et1 = static_cast<const sc_event_timed*>( p1 ); + const sc_event_timed* et2 = static_cast<const sc_event_timed*>( p2 ); + + const sc_time& t1 = et1->notify_time(); + const sc_time& t2 = et2->notify_time(); + + if( t1 < t2 ) { + return 1; + } else if( t1 > t2 ) { + return -1; + } else { + return 0; + } +} + + +// +============================================================================ +// | CLASS sc_invoke_method - class to invoke sc_method's to support +// | sc_simcontext::preempt_with(). +// +============================================================================ +SC_MODULE(sc_invoke_method) +{ + SC_CTOR(sc_invoke_method) + { + // remove from object hierarchy + detach(); + } + + virtual ~sc_invoke_method() + { + m_invokers.resize(0); + } + + // Method to call to execute a method's semantics. + + void invoke_method( sc_method_handle method_h ) + { + sc_process_handle invoker_h; // handle for invocation thread to use. + std::vector<sc_process_handle>::size_type invokers_n; // number of invocation threads available. + + m_method = method_h; + + // There is not an invocation thread to use, so allocate one. + + invokers_n = m_invokers.size(); + if ( invokers_n == 0 ) + { + sc_spawn_options options; + options.dont_initialize(); + options.set_stack_size(0x100000); + options.set_sensitivity(&m_dummy); + invoker_h = sc_spawn(sc_bind(&sc_invoke_method::invoker,this), + sc_gen_unique_name("invoker"), &options); + ((sc_process_b*)invoker_h)->detach(); + } + + // There is an invocation thread to use, use the last one on the list. + + else + { + invoker_h = m_invokers[invokers_n-1]; + m_invokers.pop_back(); + } + + // Fire off the invocation thread to invoke the method's semantics, + // When it blocks put it onto the list of invocation threads that + // are available. + + sc_get_curr_simcontext()->preempt_with( (sc_thread_handle)invoker_h ); + DEBUG_MSG( DEBUG_NAME, m_method, "back from preemption" ); + m_invokers.push_back(invoker_h); + } + + // Thread to call method from: + + void invoker() + { + sc_simcontext* csc_p = sc_get_curr_simcontext(); + sc_process_b* me = sc_get_current_process_b(); + + DEBUG_MSG( DEBUG_NAME, me, "invoker initialization" ); + for (;; ) + { + DEBUG_MSG( DEBUG_NAME, m_method, "invoker executing method" ); + csc_p->set_curr_proc( (sc_process_b*)m_method ); + csc_p->get_active_invokers().push_back((sc_thread_handle)me); + m_method->run_process(); + csc_p->set_curr_proc( me ); + csc_p->get_active_invokers().pop_back(); + DEBUG_MSG( DEBUG_NAME, m_method, "back from executing method" ); + wait(); + } + } + + sc_event m_dummy; // dummy event to wait on. + sc_method_handle m_method; // method to be invoked. + std::vector<sc_process_handle> m_invokers; // list of invoking threads. +}; + +// ---------------------------------------------------------------------------- +// CLASS : sc_simcontext +// +// The simulation context. +// ---------------------------------------------------------------------------- + +void +sc_simcontext::init() +{ + + // ALLOCATE VARIOUS MANAGERS AND REGISTRIES: + + m_object_manager = new sc_object_manager; + m_module_registry = new sc_module_registry( *this ); + m_port_registry = new sc_port_registry( *this ); + m_export_registry = new sc_export_registry( *this ); + m_prim_channel_registry = new sc_prim_channel_registry( *this ); + m_phase_cb_registry = new sc_phase_callback_registry( *this ); + m_name_gen = new sc_name_gen; + m_process_table = new sc_process_table; + m_current_writer = 0; + + + // CHECK FOR ENVIRONMENT VARIABLES THAT MODIFY SIMULATOR EXECUTION: + + const char* write_check = std::getenv("SC_SIGNAL_WRITE_CHECK"); + m_write_check = ( (write_check==0) || strcmp(write_check,"DISABLE") ) ? + true : false; + + + // FINISH INITIALIZATIONS: + + reset_curr_proc(); + m_next_proc_id = -1; + m_timed_events = new sc_ppq<sc_event_timed*>( 128, sc_notify_time_compare ); + m_something_to_trace = false; + m_runnable = new sc_runnable; + m_collectable = new sc_process_list; + m_time_params = new sc_time_params; + m_curr_time = SC_ZERO_TIME; + m_max_time = SC_ZERO_TIME; + m_change_stamp = 0; + m_delta_count = 0; + m_forced_stop = false; + m_paused = false; + m_ready_to_simulate = false; + m_elaboration_done = false; + m_execution_phase = phase_initialize; + m_error = NULL; + m_cor_pkg = 0; + m_method_invoker_p = NULL; + m_cor = 0; + m_in_simulator_control = false; + m_start_of_simulation_called = false; + m_end_of_simulation_called = false; + m_simulation_status = SC_ELABORATION; +} + +void +sc_simcontext::clean() +{ + delete m_object_manager; + delete m_module_registry; + delete m_port_registry; + delete m_export_registry; + delete m_prim_channel_registry; + delete m_phase_cb_registry; + delete m_name_gen; + delete m_process_table; + m_child_objects.resize(0); + m_delta_events.resize(0); + delete m_timed_events; + for( int i = m_trace_files.size() - 1; i >= 0; -- i ) { + delete m_trace_files[i]; + } + m_trace_files.resize(0); + delete m_runnable; + delete m_collectable; + delete m_time_params; + delete m_cor_pkg; + delete m_error; +} + + +sc_simcontext::sc_simcontext() : + m_object_manager(0), m_module_registry(0), m_port_registry(0), + m_export_registry(0), m_prim_channel_registry(0), + m_phase_cb_registry(0), m_name_gen(0), + m_process_table(0), m_curr_proc_info(), m_current_writer(0), + m_write_check(false), m_next_proc_id(-1), m_child_events(), + m_child_objects(), m_delta_events(), m_timed_events(0), m_trace_files(), + m_something_to_trace(false), m_runnable(0), m_collectable(0), + m_time_params(), m_curr_time(SC_ZERO_TIME), m_max_time(SC_ZERO_TIME), + m_change_stamp(0), m_delta_count(0), m_forced_stop(false), m_paused(false), + m_ready_to_simulate(false), m_elaboration_done(false), + m_execution_phase(phase_initialize), m_error(0), + m_in_simulator_control(false), m_end_of_simulation_called(false), + m_simulation_status(SC_ELABORATION), m_start_of_simulation_called(false), + m_cor_pkg(0), m_cor(0) +{ + init(); +} + +sc_simcontext::~sc_simcontext() +{ + clean(); +} + +// +---------------------------------------------------------------------------- +// |"sc_simcontext::active_object" +// | +// | This method returns the currently active object with respect to +// | additions to the hierarchy. It will be the top of the object hierarchy +// | stack if it is non-empty, or it will be the active process, or NULL +// | if there is no active process. +// +---------------------------------------------------------------------------- +sc_object* +sc_simcontext::active_object() +{ + sc_object* result_p; // pointer to return. + + result_p = m_object_manager->hierarchy_curr(); + if ( !result_p ) + result_p = (sc_object*)get_curr_proc_info()->process_handle; + return result_p; +} + +// +---------------------------------------------------------------------------- +// |"sc_simcontext::crunch" +// | +// | This method implements the simulator's execution of processes. It performs +// | one or more "delta" cycles. Each delta cycle consists of an evaluation, +// | an update phase, and a notification phase. During the evaluation phase any +// | processes that are ready to run are executed. After all the processes have +// | been executed the update phase is entered. During the update phase the +// | values of any signals that have changed are updated. After the updates +// | have been performed the notification phase is entered. During that phase +// | any notifications that need to occur because of of signal values changes +// | are performed. This will result in the queueing of processes for execution +// | that are sensitive to those notifications. At that point a delta cycle +// | is complete, and the process is started again unless 'once' is true. +// | +// | Arguments: +// | once = true if only one delta cycle is to be performed. +// +---------------------------------------------------------------------------- +inline void +sc_simcontext::crunch( bool once ) +{ +#ifdef DEBUG_SYSTEMC + int num_deltas = 0; // number of delta cycles +#endif + + while ( true ) + { + + // EVALUATE PHASE + + m_execution_phase = phase_evaluate; + bool empty_eval_phase = true; + while( true ) + { + + // execute method processes + + m_runnable->toggle_methods(); + sc_method_handle method_h = pop_runnable_method(); + while( method_h != 0 ) { + empty_eval_phase = false; + if ( !method_h->run_process() ) + { + goto out; + } + method_h = pop_runnable_method(); + } + + // execute (c)thread processes + + m_runnable->toggle_threads(); + sc_thread_handle thread_h = pop_runnable_thread(); + while( thread_h != 0 ) { + if ( thread_h->m_cor_p != NULL ) break; + thread_h = pop_runnable_thread(); + } + + if( thread_h != 0 ) { + empty_eval_phase = false; + m_cor_pkg->yield( thread_h->m_cor_p ); + } + if( m_error ) { + goto out; + } + + // check for call(s) to sc_stop + if( m_forced_stop ) { + if ( stop_mode == SC_STOP_IMMEDIATE ) goto out; + } + + // no more runnable processes + + if( m_runnable->is_empty() ) { + break; + } + } + + // remove finally dead zombies: + + while( ! m_collectable->empty() ) + { + sc_process_b* del_p = m_collectable->front(); + m_collectable->pop_front(); + del_p->reference_decrement(); + } + + + // UPDATE PHASE + // + // The change stamp must be updated first so that event_occurred() + // will work. + + m_execution_phase = phase_update; + if ( !empty_eval_phase ) + { +// SC_DO_PHASE_CALLBACK_(evaluation_done); + m_change_stamp++; + m_delta_count ++; + } + m_prim_channel_registry->perform_update(); + SC_DO_PHASE_CALLBACK_(update_done); + m_execution_phase = phase_notify; + +#if SC_SIMCONTEXT_TRACING_ + if( m_something_to_trace ) { + trace_cycle( /* delta cycle? */ true ); + } +#endif + + // check for call(s) to sc_stop + if( m_forced_stop ) { + break; + } + +#ifdef DEBUG_SYSTEMC + // check for possible infinite loops + if( ++ num_deltas > SC_MAX_NUM_DELTA_CYCLES ) { + ::std::cerr << "SystemC warning: " + << "the number of delta cycles exceeds the limit of " + << SC_MAX_NUM_DELTA_CYCLES + << ", defined in sc_constants.h.\n" + << "This is a possible sign of an infinite loop.\n" + << "Increase the limit if this warning is invalid.\n"; + break; + } +#endif + + // NOTIFICATION PHASE: + // + // Process delta notifications which will queue processes for + // subsequent execution. + + int size = m_delta_events.size(); + if ( size != 0 ) + { + sc_event** l_events = &m_delta_events[0]; + int i = size - 1; + do { + l_events[i]->trigger(); + } while( -- i >= 0 ); + m_delta_events.resize(0); + } + + if( m_runnable->is_empty() ) { + // no more runnable processes + break; + } + + // if sc_pause() was called we are done. + + if ( m_paused ) break; + + // IF ONLY DOING ONE CYCLE, WE ARE DONE. OTHERWISE EXECUTE NEW CALLBACKS + + if ( once ) break; + } + + // When this point is reached the processing of delta cycles is complete, + // if the completion was because of an error throw the exception specified + // by '*m_error'. +out: + this->reset_curr_proc(); + if( m_error ) throw *m_error; // re-throw propagated error +} + +inline +void +sc_simcontext::cycle( const sc_time& t) +{ + sc_time next_event_time; + + m_in_simulator_control = true; + crunch(); + SC_DO_PHASE_CALLBACK_(before_timestep); +#if SC_SIMCONTEXT_TRACING_ + if( m_something_to_trace ) { + trace_cycle( /* delta cycle? */ false ); + } +#endif + m_curr_time += t; + if ( next_time(next_event_time) && next_event_time <= m_curr_time) { + SC_REPORT_WARNING(SC_ID_CYCLE_MISSES_EVENTS_, ""); + } + m_in_simulator_control = false; + SC_DO_PHASE_CALLBACK_(simulation_paused); +} + +void +sc_simcontext::elaborate() +{ + if( m_elaboration_done || sim_status() != SC_SIM_OK ) { + return; + } + + // Instantiate the method invocation module + // (not added to public object hierarchy) + + m_method_invoker_p = + new sc_invoke_method("$$$$kernel_module$$$$_invoke_method" ); + + m_simulation_status = SC_BEFORE_END_OF_ELABORATION; + for( int cd = 0; cd != 4; /* empty */ ) + { + cd = m_port_registry->construction_done(); + cd += m_export_registry->construction_done(); + cd += m_prim_channel_registry->construction_done(); + cd += m_module_registry->construction_done(); + + // check for call(s) to sc_stop + if( m_forced_stop ) { + do_sc_stop_action(); + return; + } + + } + SC_DO_PHASE_CALLBACK_(construction_done); + + // SIGNAL THAT ELABORATION IS DONE + // + // We set the switch before the calls in case someone creates a process + // in an end_of_elaboration callback. We need the information to flag + // the process as being dynamic. + + m_elaboration_done = true; + m_simulation_status = SC_END_OF_ELABORATION; + + m_port_registry->elaboration_done(); + m_export_registry->elaboration_done(); + m_prim_channel_registry->elaboration_done(); + m_module_registry->elaboration_done(); + SC_DO_PHASE_CALLBACK_(elaboration_done); + sc_reset::reconcile_resets(); + + // check for call(s) to sc_stop + if( m_forced_stop ) { + do_sc_stop_action(); + return; + } +} + +void +sc_simcontext::prepare_to_simulate() +{ + sc_method_handle method_p; // Pointer to method process accessing. + sc_thread_handle thread_p; // Pointer to thread process accessing. + + if( m_ready_to_simulate || sim_status() != SC_SIM_OK ) { + return; + } + + // instantiate the coroutine package + m_cor_pkg = new sc_cor_pkg_t( this ); + m_cor = m_cor_pkg->get_main(); + + // NOTIFY ALL OBJECTS THAT SIMULATION IS ABOUT TO START: + + m_simulation_status = SC_START_OF_SIMULATION; + m_port_registry->start_simulation(); + m_export_registry->start_simulation(); + m_prim_channel_registry->start_simulation(); + m_module_registry->start_simulation(); + SC_DO_PHASE_CALLBACK_(start_simulation); + m_start_of_simulation_called = true; + + // CHECK FOR CALL(S) TO sc_stop + + if( m_forced_stop ) { + do_sc_stop_action(); + return; + } + + // PREPARE ALL (C)THREAD PROCESSES FOR SIMULATION: + + for ( thread_p = m_process_table->thread_q_head(); + thread_p; thread_p = thread_p->next_exist() ) + { + thread_p->prepare_for_simulation(); + } + + m_simulation_status = SC_RUNNING; + m_ready_to_simulate = true; + m_runnable->init(); + + // update phase + + m_execution_phase = phase_update; + m_prim_channel_registry->perform_update(); + m_execution_phase = phase_notify; + + int size; + + // make all method processes runnable + + for ( method_p = m_process_table->method_q_head(); + method_p; method_p = method_p->next_exist() ) + { + if ( ((method_p->m_state & sc_process_b::ps_bit_disabled) != 0) || + method_p->dont_initialize() ) + { + if ( method_p->m_static_events.size() == 0 ) + { + SC_REPORT_WARNING( SC_ID_DISABLE_WILL_ORPHAN_PROCESS_, + method_p->name() ); + } + } + else if ( (method_p->m_state & sc_process_b::ps_bit_suspended) == 0) + { + push_runnable_method_front( method_p ); + } + else + { + method_p->m_state |= sc_process_b::ps_bit_ready_to_run; + } + } + + // make thread processes runnable + // (cthread processes always have the dont_initialize flag set) + + for ( thread_p = m_process_table->thread_q_head(); + thread_p; thread_p = thread_p->next_exist() ) + { + if ( ((thread_p->m_state & sc_process_b::ps_bit_disabled) != 0) || + thread_p->dont_initialize() ) + { + if ( thread_p->m_static_events.size() == 0 ) + { + SC_REPORT_WARNING( SC_ID_DISABLE_WILL_ORPHAN_PROCESS_, + thread_p->name() ); + } + } + else if ( (thread_p->m_state & sc_process_b::ps_bit_suspended) == 0) + { + push_runnable_thread_front( thread_p ); + } + else + { + thread_p->m_state |= sc_process_b::ps_bit_ready_to_run; + } + } + + + // process delta notifications + + if( ( size = m_delta_events.size() ) != 0 ) { + sc_event** l_delta_events = &m_delta_events[0]; + int i = size - 1; + do { + l_delta_events[i]->trigger(); + } while( -- i >= 0 ); + m_delta_events.resize(0); + } + + SC_DO_PHASE_CALLBACK_(initialization_done); +} + +void +sc_simcontext::initial_crunch( bool no_crunch ) +{ + if( no_crunch || m_runnable->is_empty() ) { + return; + } + + // run the delta cycle loop + + crunch(); + if( m_error ) { + return; + } + +#if SC_SIMCONTEXT_TRACING_ + if( m_something_to_trace ) { + trace_cycle( false ); + } +#endif + + // check for call(s) to sc_stop + if( m_forced_stop ) { + do_sc_stop_action(); + } +} + +void +sc_simcontext::initialize( bool no_crunch ) +{ + m_in_simulator_control = true; + elaborate(); + + prepare_to_simulate(); + initial_crunch(no_crunch); + m_in_simulator_control = false; +} + +// +---------------------------------------------------------------------------- +// |"sc_simcontext::simulate" +// | +// | This method runs the simulation for the specified amount of time. +// | +// | Notes: +// | (1) This code always run with an SC_EXIT_ON_STARVATION starvation policy, +// | so the simulation time on return will be the minimum of the +// | simulation on entry plus the duration, and the maximum time of any +// | event present in the simulation. If the simulation policy is +// | SC_RUN_TO_TIME starvation it is implemented by the caller of this +// | method, e.g., sc_start(), by artificially setting the simulation +// | time forward after this method completes. +// | +// | Arguments: +// | duration = amount of time to simulate. +// +---------------------------------------------------------------------------- +void +sc_simcontext::simulate( const sc_time& duration ) +{ + initialize( true ); + + if (sim_status() != SC_SIM_OK) { + return; + } + + sc_time non_overflow_time = sc_max_time() - m_curr_time; + if ( duration > non_overflow_time ) + { + SC_REPORT_ERROR(SC_ID_SIMULATION_TIME_OVERFLOW_, ""); + return; + } + else if ( duration < SC_ZERO_TIME ) + { + SC_REPORT_ERROR(SC_ID_NEGATIVE_SIMULATION_TIME_,""); + } + + m_in_simulator_control = true; + m_paused = false; + + sc_time until_t = m_curr_time + duration; + sc_time t; // current simulaton time. + + // IF DURATION WAS ZERO WE ONLY CRUNCH ONCE: + // + // We duplicate the code so that we don't add the overhead of the + // check to each loop in the do below. + if ( duration == SC_ZERO_TIME ) + { + m_in_simulator_control = true; + crunch( true ); + if( m_error ) { + m_in_simulator_control = false; + return; + } +#if SC_SIMCONTEXT_TRACING_ + if( m_something_to_trace ) + trace_cycle( /* delta cycle? */ false ); +#endif + if( m_forced_stop ) { + do_sc_stop_action(); + return; + } + // return via implicit pause + goto exit_pause; + } + + // NON-ZERO DURATION: EXECUTE UP TO THAT TIME, OR UNTIL EVENT STARVATION: + + do { + + crunch(); + if( m_error ) { + m_in_simulator_control = false; + return; + } +#if SC_SIMCONTEXT_TRACING_ + if( m_something_to_trace ) { + trace_cycle( false ); + } +#endif + // check for call(s) to sc_stop() or sc_pause(). + if( m_forced_stop ) { + do_sc_stop_action(); + return; + } + if( m_paused ) goto exit_pause; // return explicit pause + + t = m_curr_time; + + do { + // See note 1 above: + + if ( !next_time(t) || (t > until_t ) ) goto exit_time; + if ( t > m_curr_time ) + { + SC_DO_PHASE_CALLBACK_(before_timestep); + m_curr_time = t; + m_change_stamp++; + } + + // PROCESS TIMED NOTIFICATIONS AT THE CURRENT TIME + + do { + sc_event_timed* et = m_timed_events->extract_top(); + sc_event* e = et->event(); + delete et; + if( e != 0 ) { + e->trigger(); + } + } while( m_timed_events->size() && + m_timed_events->top()->notify_time() == t ); + + } while( m_runnable->is_empty() ); + } while ( t < until_t ); // hold off on the delta for the until_t time. + +exit_time: // final simulation time update, if needed + if ( t > m_curr_time && t <= until_t ) + { + SC_DO_PHASE_CALLBACK_(before_timestep); + m_curr_time = t; + m_change_stamp++; + } +exit_pause: // call pause callback upon implicit or explicit pause + m_execution_phase = phase_evaluate; + m_in_simulator_control = false; + SC_DO_PHASE_CALLBACK_(simulation_paused); +} + +void +sc_simcontext::do_sc_stop_action() +{ + SC_REPORT_INFO("/OSCI/SystemC","Simulation stopped by user."); + if (m_start_of_simulation_called) { + end(); + m_in_simulator_control = false; + } + m_simulation_status = SC_STOPPED; + SC_DO_PHASE_CALLBACK_(simulation_stopped); +} + +void +sc_simcontext::mark_to_collect_process( sc_process_b* zombie ) +{ + m_collectable->push_back( zombie ); +} + + +//------------------------------------------------------------------------------ +//"sc_simcontext::stop" +// +// This method stops the simulator after some amount of further processing. +// How much processing is done depends upon the value of the global variable +// stop_mode: +// SC_STOP_IMMEDIATE - aborts the execution phase of the current delta +// cycle and performs whatever updates are pending. +// SC_STOP_FINISH_DELTA - finishes the current delta cycle - both execution +// and updates. +// If sc_stop is called outside of the purview of the simulator kernel +// (e.g., directly from sc_main), the end of simulation notifications +// are performed. From within the purview of the simulator kernel, these +// will be performed at a later time. +//------------------------------------------------------------------------------ + +void +sc_simcontext::stop() +{ + static bool stop_warning_issued = false; + if (m_forced_stop) + { + if ( !stop_warning_issued ) + { + stop_warning_issued = true; // This must be before the WARNING!!! + SC_REPORT_WARNING(SC_ID_SIMULATION_STOP_CALLED_TWICE_, ""); + } + return; + } + if ( stop_mode == SC_STOP_IMMEDIATE ) m_runnable->init(); + m_forced_stop = true; + if ( !m_in_simulator_control ) + { + do_sc_stop_action(); + } +} + +void +sc_simcontext::reset() +{ + clean(); + init(); +} + +void +sc_simcontext::end() +{ + m_simulation_status = SC_END_OF_SIMULATION; + m_ready_to_simulate = false; + m_port_registry->simulation_done(); + m_export_registry->simulation_done(); + m_prim_channel_registry->simulation_done(); + m_module_registry->simulation_done(); + SC_DO_PHASE_CALLBACK_(simulation_done); + m_end_of_simulation_called = true; +} + +void +sc_simcontext::hierarchy_push( sc_module* mod ) +{ + m_object_manager->hierarchy_push( mod ); +} + +sc_module* +sc_simcontext::hierarchy_pop() +{ + return static_cast<sc_module*>( m_object_manager->hierarchy_pop() ); +} + +sc_module* +sc_simcontext::hierarchy_curr() const +{ + return static_cast<sc_module*>( m_object_manager->hierarchy_curr() ); +} + +sc_object* +sc_simcontext::first_object() +{ + return m_object_manager->first_object(); +} + +sc_object* +sc_simcontext::next_object() +{ + return m_object_manager->next_object(); +} + +sc_object* +sc_simcontext::find_object( const char* name ) +{ + static bool warn_find_object=true; + if ( warn_find_object ) + { + warn_find_object = false; + SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, + "sc_simcontext::find_object() is deprecated,\n" \ + " use sc_find_object()" ); + } + return m_object_manager->find_object( name ); +} + +// to generate unique names for objects in an MT-Safe way + +const char* +sc_simcontext::gen_unique_name( const char* basename_, bool preserve_first ) +{ + return m_name_gen->gen_unique_name( basename_, preserve_first ); +} + + +sc_process_handle +sc_simcontext::create_cthread_process( + const char* name_p, bool free_host, SC_ENTRY_FUNC method_p, + sc_process_host* host_p, const sc_spawn_options* opt_p ) +{ + sc_thread_handle handle = + new sc_cthread_process(name_p, free_host, method_p, host_p, opt_p); + if ( m_ready_to_simulate ) + { + handle->prepare_for_simulation(); + } else { + m_process_table->push_front( handle ); + } + return sc_process_handle(handle); +} + + +sc_process_handle +sc_simcontext::create_method_process( + const char* name_p, bool free_host, SC_ENTRY_FUNC method_p, + sc_process_host* host_p, const sc_spawn_options* opt_p ) +{ + sc_method_handle handle = + new sc_method_process(name_p, free_host, method_p, host_p, opt_p); + if ( m_ready_to_simulate ) { // dynamic process + if ( !handle->dont_initialize() ) + { +#ifdef SC_HAS_PHASE_CALLBACKS_ + if( SC_UNLIKELY_( m_simulation_status + & (SC_END_OF_UPDATE|SC_BEFORE_TIMESTEP) ) ) + { + std::stringstream msg; + msg << m_simulation_status + << ":\n\t immediate method spawning of " + "`" << handle->name() << "' ignored"; + SC_REPORT_WARNING( SC_ID_PHASE_CALLBACK_FORBIDDEN_ + , msg.str().c_str() ); + } + else +#endif // SC_HAS_PHASE_CALLBACKS_ + { + push_runnable_method( handle ); + } + } + else if ( handle->m_static_events.size() == 0 ) + { + SC_REPORT_WARNING( SC_ID_DISABLE_WILL_ORPHAN_PROCESS_, + handle->name() ); + } + + } else { + m_process_table->push_front( handle ); + } + return sc_process_handle(handle); +} + + +sc_process_handle +sc_simcontext::create_thread_process( + const char* name_p, bool free_host, SC_ENTRY_FUNC method_p, + sc_process_host* host_p, const sc_spawn_options* opt_p ) +{ + sc_thread_handle handle = + new sc_thread_process(name_p, free_host, method_p, host_p, opt_p); + if ( m_ready_to_simulate ) { // dynamic process + handle->prepare_for_simulation(); + if ( !handle->dont_initialize() ) + { +#ifdef SC_HAS_PHASE_CALLBACKS_ + if( SC_UNLIKELY_( m_simulation_status + & (SC_END_OF_UPDATE|SC_BEFORE_TIMESTEP) ) ) + { + std::stringstream msg; + msg << m_simulation_status + << ":\n\t immediate thread spawning of " + "`" << handle->name() << "' ignored"; + SC_REPORT_WARNING( SC_ID_PHASE_CALLBACK_FORBIDDEN_ + , msg.str().c_str() ); + } + else +#endif // SC_HAS_PHASE_CALLBACKS_ + { + push_runnable_thread( handle ); + } + } + else if ( handle->m_static_events.size() == 0 ) + { + SC_REPORT_WARNING( SC_ID_DISABLE_WILL_ORPHAN_PROCESS_, + handle->name() ); + } + + } else { + m_process_table->push_front( handle ); + } + return sc_process_handle(handle); +} + +void +sc_simcontext::add_trace_file( sc_trace_file* tf ) +{ + m_trace_files.push_back( tf ); + m_something_to_trace = true; +} + +void +sc_simcontext::remove_trace_file( sc_trace_file* tf ) +{ + m_trace_files.erase( + std::remove( m_trace_files.begin(), m_trace_files.end(), tf ) + ); + m_something_to_trace = ( m_trace_files.size() > 0 ); +} + +sc_cor* +sc_simcontext::next_cor() +{ + if( m_error ) { + return m_cor; + } + + sc_thread_handle thread_h = pop_runnable_thread(); + while( thread_h != 0 ) { + if ( thread_h->m_cor_p != NULL ) break; + thread_h = pop_runnable_thread(); + } + + if( thread_h != 0 ) { + return thread_h->m_cor_p; + } else { + return m_cor; + } +} + +const ::std::vector<sc_object*>& +sc_simcontext::get_child_objects() const +{ + static bool warn_get_child_objects=true; + if ( warn_get_child_objects ) + { + warn_get_child_objects = false; + SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, + "sc_simcontext::get_child_objects() is deprecated,\n" \ + " use sc_get_top_level_objects()" ); + } + return m_child_objects; +} + +void +sc_simcontext::add_child_event( sc_event* event_ ) +{ + // no check if object_ is already in the set + m_child_events.push_back( event_ ); +} + +void +sc_simcontext::add_child_object( sc_object* object_ ) +{ + // no check if object_ is already in the set + m_child_objects.push_back( object_ ); +} + +void +sc_simcontext::remove_child_event( sc_event* event_ ) +{ + int size = m_child_events.size(); + for( int i = 0; i < size; ++ i ) { + if( event_ == m_child_events[i] ) { + m_child_events[i] = m_child_events[size - 1]; + m_child_events.resize(size-1); + return; + } + } + // no check if event_ is really in the set +} + +void +sc_simcontext::remove_child_object( sc_object* object_ ) +{ + int size = m_child_objects.size(); + for( int i = 0; i < size; ++ i ) { + if( object_ == m_child_objects[i] ) { + m_child_objects[i] = m_child_objects[size - 1]; + m_child_objects.resize(size-1); + return; + } + } + // no check if object_ is really in the set +} + +sc_dt::uint64 +sc_simcontext::delta_count() const +{ + static bool warn_delta_count=true; + if ( warn_delta_count ) + { + warn_delta_count = false; + SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, + "sc_simcontext::delta_count() is deprecated, use sc_delta_count()" ); + } + return m_delta_count; +} + +bool +sc_simcontext::is_running() const +{ + static bool warn_is_running=true; + if ( warn_is_running ) + { + warn_is_running = false; + SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, + "sc_simcontext::is_running() is deprecated, use sc_is_running()" ); + } + return m_ready_to_simulate; +} + +// +---------------------------------------------------------------------------- +// |"sc_simcontext::next_time" +// | +// | This method returns the time of the next event. If there are no events +// | it returns false. +// | +// | Arguments: +// | result = where to place time of the next event, if no event is +// | found this value will not be changed. +// | Result is true if an event is found, false if not. +// +---------------------------------------------------------------------------- +bool +sc_simcontext::next_time( sc_time& result ) const +{ + while( m_timed_events->size() ) { + sc_event_timed* et = m_timed_events->top(); + if( et->event() != 0 ) { + result = et->notify_time(); + return true; + } + delete m_timed_events->extract_top(); + } + return false; +} + +void +sc_simcontext::remove_delta_event( sc_event* e ) +{ + int i = e->m_delta_event_index; + int j = m_delta_events.size() - 1; + assert( i >= 0 && i <= j ); + if( i != j ) { + sc_event** l_delta_events = &m_delta_events[0]; + l_delta_events[i] = l_delta_events[j]; + l_delta_events[i]->m_delta_event_index = i; + } + m_delta_events.resize(m_delta_events.size()-1); + e->m_delta_event_index = -1; +} + +// +---------------------------------------------------------------------------- +// |"sc_simcontext::preempt_with" +// | +// | This method executes the supplied method immediately, suspending the +// | caller. After executing the supplied method the caller's execution will +// | be restored. It is used to allow a method to immediately throw an +// | exception, e.g., when the method's kill_process() method was called. +// | There are three cases to consider: +// | (1) The caller is a method, e.g., murder by method. +// | (2) The caller is a thread instance, e.g., murder by thread. +// | (3) The caller is this method instance, e.g., suicide. +// | +// | Arguments: +// | method_h -> method to be executed. +// +---------------------------------------------------------------------------- +void +sc_simcontext::preempt_with( sc_method_handle method_h ) +{ + sc_curr_proc_info caller_info; // process info for caller. + sc_method_handle active_method_h; // active method or null. + sc_thread_handle active_thread_h; // active thread or null. + + // Determine the active process and take the thread to be run off the + // run queue, if its there, since we will be explicitly causing its + // execution. + + active_method_h = DCAST<sc_method_handle>(sc_get_current_process_b()); + active_thread_h = DCAST<sc_thread_handle>(sc_get_current_process_b()); + if ( method_h->next_runnable() != NULL ) + remove_runnable_method( method_h ); + + // CALLER IS THE METHOD TO BE RUN: + // + // Should never get here, ignore it unless we are debugging. + + if ( method_h == active_method_h ) + { + DEBUG_MSG(DEBUG_NAME,method_h,"self preemption of active method"); + } + + // THE CALLER IS A METHOD: + // + // (a) Set the current process information to our method. + // (b) Invoke our method directly by-passing the run queue. + // (c) Restore the process info to the caller. + // (d) Check to see if the calling method should throw an exception + // because of activity that occurred during the preemption. + + else if ( active_method_h != NULL ) + { + caller_info = m_curr_proc_info; + DEBUG_MSG( DEBUG_NAME, method_h, + "preempting active method with method" ); + sc_get_curr_simcontext()->set_curr_proc( (sc_process_b*)method_h ); + method_h->run_process(); + sc_get_curr_simcontext()->set_curr_proc((sc_process_b*)active_method_h); + active_method_h->check_for_throws(); + } + + // CALLER IS A THREAD: + // + // (a) Use an invocation thread to execute the method. + + else if ( active_thread_h != NULL ) + { + DEBUG_MSG( DEBUG_NAME, method_h, + "preempting active thread with method" ); + m_method_invoker_p->invoke_method(method_h); + } + + // CALLER IS THE SIMULATOR: + // + // That is not allowed. + + else + { + caller_info = m_curr_proc_info; + DEBUG_MSG( DEBUG_NAME, method_h, + "preempting no active process with method" ); + sc_get_curr_simcontext()->set_curr_proc( (sc_process_b*)method_h ); + method_h->run_process(); + m_curr_proc_info = caller_info; + } +} + +//------------------------------------------------------------------------------ +//"sc_simcontext::requeue_current_process" +// +// This method requeues the current process at the beginning of the run queue +// if it is a thread. This is called by sc_process_handle::throw_it() to assure +// that a thread that is issuing a throw will execute immediately after the +// processes it notifies via the throw. +//------------------------------------------------------------------------------ +void sc_simcontext::requeue_current_process() +{ + sc_thread_handle thread_p; + thread_p = DCAST<sc_thread_handle>(get_curr_proc_info()->process_handle); + if ( thread_p ) + { + execute_thread_next( thread_p ); + } +} + +//------------------------------------------------------------------------------ +//"sc_simcontext::suspend_current_process" +// +// This method suspends the current process if it is a thread. This is called +// by sc_process_handle::throw_it() to allow the processes that have received +// a throw to execute. +//------------------------------------------------------------------------------ +void sc_simcontext::suspend_current_process() +{ + sc_thread_handle thread_p; + thread_p = DCAST<sc_thread_handle>(get_curr_proc_info()->process_handle); + if ( thread_p ) + { + thread_p->suspend_me(); + } +} + +void +sc_simcontext::trace_cycle( bool delta_cycle ) +{ + int size; + if( ( size = m_trace_files.size() ) != 0 ) { + sc_trace_file** l_trace_files = &m_trace_files[0]; + int i = size - 1; + do { + l_trace_files[i]->cycle( delta_cycle ); + } while( -- i >= 0 ); + } +} + +// ---------------------------------------------------------------------------- + +#if 1 +#ifdef PURIFY + static sc_simcontext sc_default_global_context; + sc_simcontext* sc_curr_simcontext = &sc_default_global_context; +#else + sc_simcontext* sc_curr_simcontext = 0; + sc_simcontext* sc_default_global_context = 0; +#endif +#else +// Not MT-safe! +static sc_simcontext* sc_curr_simcontext = 0; + + +sc_simcontext* +sc_get_curr_simcontext() +{ + if( sc_curr_simcontext == 0 ) { +#ifdef PURIFY + static sc_simcontext sc_default_global_context; + sc_curr_simcontext = &sc_default_global_context; +#else + static sc_simcontext* sc_default_global_context = new sc_simcontext; + sc_curr_simcontext = sc_default_global_context; +#endif + } + return sc_curr_simcontext; +} +#endif // 0 + +// Generates unique names within each module. + +const char* +sc_gen_unique_name( const char* basename_, bool preserve_first ) +{ + sc_simcontext* simc = sc_get_curr_simcontext(); + sc_module* curr_module = simc->hierarchy_curr(); + if( curr_module != 0 ) { + return curr_module->gen_unique_name( basename_, preserve_first ); + } else { + sc_process_b* curr_proc_p = sc_get_current_process_b(); + if ( curr_proc_p ) + { + return curr_proc_p->gen_unique_name( basename_, preserve_first ); + } + else + { + return simc->gen_unique_name( basename_, preserve_first ); + } + } +} + +// Get a handle for the current process +// +// Note that this method should not be called if the current process is +// in the act of being deleted, it will mess up the reference count management +// of sc_process_b instance the handle represents. Instead, use the a +// pointer to the raw sc_process_b instance, which may be acquired via +// sc_get_current_process_b(). + +sc_process_handle +sc_get_current_process_handle() +{ + return ( sc_is_running() ) ? + sc_process_handle(sc_get_current_process_b()) : + sc_get_last_created_process_handle(); +} + +// THE FOLLOWING FUNCTION IS DEPRECATED IN 2.1 +sc_process_b* +sc_get_curr_process_handle() +{ + static bool warn=true; + if ( warn ) + { + warn = false; + SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, + "sc_get_curr_process_handle deprecated use sc_get_current_process_handle" + ); + } + + return sc_get_curr_simcontext()->get_curr_proc_info()->process_handle; +} + +// Return indication if there are more processes to execute in this delta phase + +bool +sc_simcontext::pending_activity_at_current_time() const +{ + return ( m_delta_events.size() != 0) || + ( m_runnable->is_initialized() && !m_runnable->is_empty() ) || + m_prim_channel_registry->pending_updates(); +} + +// Return time of next activity. + +sc_time sc_time_to_pending_activity( const sc_simcontext* simc_p ) +{ + // If there is an activity pending at the current time + // return a delta of zero. + + sc_time result=SC_ZERO_TIME; // time of pending activity. + + if ( simc_p->pending_activity_at_current_time() ) + { + return result; + } + + // Any activity will take place in the future pick up the next event's time. + + else + { + result = simc_p->max_time(); + simc_p->next_time(result); + result -= sc_time_stamp(); + } + return result; +} + +// Set the random seed for controlled randomization -- not yet implemented + +void +sc_set_random_seed( unsigned int ) +{ + SC_REPORT_WARNING( SC_ID_NOT_IMPLEMENTED_, + "void sc_set_random_seed( unsigned int )" ); +} + + +// +---------------------------------------------------------------------------- +// |"sc_start" +// | +// | This function starts, or restarts, the execution of the simulator. +// | +// | Arguments: +// | duration = the amount of time the simulator should execute. +// | p = event starvation policy. +// +---------------------------------------------------------------------------- +void +sc_start( const sc_time& duration, sc_starvation_policy p ) +{ + sc_simcontext* context_p; // current simulation context. + sc_time entry_time; // simulation time upon entry. + sc_time exit_time; // simulation time to set upon exit. + sc_dt::uint64 starting_delta; // delta count upon entry. + int status; // current simulation status. + + // Set up based on the arguments passed to us: + + context_p = sc_get_curr_simcontext(); + starting_delta = sc_delta_count(); + entry_time = context_p->m_curr_time; + if ( p == SC_RUN_TO_TIME ) + exit_time = context_p->m_curr_time + duration; + + // called with duration = SC_ZERO_TIME for the first time + static bool init_delta_or_pending_updates = + ( starting_delta == 0 && exit_time == SC_ZERO_TIME ); + + // If the simulation status is bad issue the appropriate message: + + status = context_p->sim_status(); + if( status != SC_SIM_OK ) + { + if ( status == SC_SIM_USER_STOP ) + SC_REPORT_ERROR(SC_ID_SIMULATION_START_AFTER_STOP_, ""); + if ( status == SC_SIM_ERROR ) + SC_REPORT_ERROR(SC_ID_SIMULATION_START_AFTER_ERROR_, ""); + return; + } + + if ( context_p->m_prim_channel_registry->pending_updates() ) + init_delta_or_pending_updates = true; + + // If the simulation status is good perform the simulation: + + context_p->simulate( duration ); + + // Re-check the status: + + status = context_p->sim_status(); + + // Update the current time to the exit time if that is the starvation + // policy: + + if ( p == SC_RUN_TO_TIME && !context_p->m_paused && status == SC_SIM_OK ) + { + context_p->m_curr_time = exit_time; + } + + // If there was no activity and the simulation clock did not move warn + // the user, except if we're in a first sc_start(SC_ZERO_TIME) for + // initialisation (only) or there have been pending updates: + + if ( !init_delta_or_pending_updates && + starting_delta == sc_delta_count() && + context_p->m_curr_time == entry_time && + status == SC_SIM_OK ) + { + SC_REPORT_WARNING(SC_ID_NO_SC_START_ACTIVITY_, ""); + } + + // reset init/update flag for subsequent calls + init_delta_or_pending_updates = false; +} + +void +sc_start() +{ + sc_start( sc_max_time() - sc_time_stamp(), + SC_EXIT_ON_STARVATION ); +} + +// for backward compatibility with 1.0 +#if 0 +void +sc_start( double duration ) // in default time units +{ + static bool warn_sc_start=true; + if ( warn_sc_start ) + { + warn_sc_start = false; + SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, + "sc_start(double) deprecated, use sc_start(sc_time) or sc_start()"); + } + + if( duration == -1 ) // simulate forever + { + sc_start( + sc_time(~sc_dt::UINT64_ZERO, false) - sc_time_stamp() ); + } + else + { + sc_start( sc_time( duration, true ) ); + } +} +#endif // + +void +sc_stop() +{ + sc_get_curr_simcontext()->stop(); +} + + +// The following function is deprecated in favor of sc_start(SC_ZERO_TIME): + +void +sc_initialize() +{ + static bool warning_initialize = true; + + if ( warning_initialize ) + { + warning_initialize = false; + SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, + "sc_initialize() is deprecated: use sc_start(SC_ZERO_TIME)" ); + } + sc_get_curr_simcontext()->initialize(); +} + +// The following function has been deprecated in favor of sc_start(duration): + +void +sc_cycle( const sc_time& duration ) +{ + static bool warning_cycle = true; + + if ( warning_cycle ) + { + warning_cycle = false; + SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, + "sc_cycle is deprecated: use sc_start(sc_time)" ); + } + sc_get_curr_simcontext()->cycle( duration ); +} + +sc_event* sc_find_event( const char* name ) +{ + return sc_get_curr_simcontext()->get_object_manager()->find_event( name ); +} + +sc_object* sc_find_object( const char* name ) +{ + return sc_get_curr_simcontext()->get_object_manager()->find_object( name ); +} + + +const sc_time& +sc_max_time() +{ + return sc_get_curr_simcontext()->max_time(); +} + +const sc_time& +sc_time_stamp() +{ + return sc_get_curr_simcontext()->time_stamp(); +} + +double +sc_simulation_time() +{ + static bool warn_simulation_time=true; + if ( warn_simulation_time ) + { + warn_simulation_time=false; + SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, + "sc_simulation_time() is deprecated use sc_time_stamp()" ); + } + return sc_get_curr_simcontext()->time_stamp().to_default_time_units(); +} + +void +sc_defunct_process_function( sc_module* ) +{ + // This function is pointed to by defunct sc_thread_process'es and + // sc_cthread_process'es. In a correctly constructed world, this + // function should never be called; hence the assert. + assert( false ); +} + +//------------------------------------------------------------------------------ +//"sc_set_stop_mode" +// +// This function sets the mode of operation when sc_stop() is called. +// mode = SC_STOP_IMMEDIATE or SC_STOP_FINISH_DELTA. +//------------------------------------------------------------------------------ +void sc_set_stop_mode(sc_stop_mode mode) +{ + if ( sc_is_running() ) + { + SC_REPORT_ERROR(SC_ID_STOP_MODE_AFTER_START_,""); + } + else + { + switch( mode ) + { + case SC_STOP_IMMEDIATE: + case SC_STOP_FINISH_DELTA: + stop_mode = mode; + break; + default: + break; + } + } +} + +sc_stop_mode +sc_get_stop_mode() +{ + return stop_mode; +} + +bool sc_is_unwinding() +{ + return sc_get_current_process_handle().is_unwinding(); +} + +// The IEEE 1666 Standard for 2011 designates that the treatment of +// certain process control interactions as being "implementation dependent". +// These interactions are: +// (1) What happens when a resume() call is performed on a disabled, +// suspended process. +// (2) What happens when sync_reset_on() or sync_reset_off() is called +// on a suspended process. +// (3) What happens when the value specified in a reset_signal_is() +// call changes value while a process is suspended. +// +// By default this Proof of Concept implementation reports an error +// for these interactions. However, the implementation also provides +// a non-error treatment. The non-error treatment for the interactions is: +// (1) A resume() call performed on a disabled, suspended process will +// mark the process as no longer suspended, and if it is capable +// of execution (not waiting on any events) it will be placed on +// the queue of runnable processes. See the state diagram below. +// (2) A call to sync_reset_on() or sync_reset_off() will set or clear +// the synchronous reset flag. Whether the process is in reset or +// not will be determined when the process actually executes by +// looking at the flag's value at that time. +// (3) If a suspended process has a reset_signal_is() specification +// the value of the reset variable at the time of its next execution +// will determine whether it is in reset or not. +// +// TO GET THE NON-ERROR BEHAVIOR SET THE VARIABLE BELOW TO TRUE. +// +// This can be done in this source before you build the library, or you +// can use an assignment as the first statement in your sc_main() function: +// sc_core::sc_allow_process_control_corners = true; + +bool sc_allow_process_control_corners = false; + +// The state transition diagram for the interaction of disable and suspend +// when sc_allow_process_control_corners is true is shown below: +// +// ...................................................................... +// . ENABLED . DISABLED . +// . . . +// . +----------+ disable +----------+ . +// . +------------>| |-------.-------->| | . +// . | | runnable | . | runnable | . +// . | +-------| |<------.---------| |------+ . +// . | | +----------+ enable +----------+ | . +// . | | | ^ . | ^ | . +// . | | suspend | | resume . suspend | | resume | . +// . | | V | . V | | . +// . | | +----------+ disable +----------+ | . +// . | | | suspend |-------.-------->| suspend | | . +// . t | r | | | . | | | r . +// . r | u | | ready |<------.---------| ready | | u . +// . i | n | +----------+ enable +----------+ | n . +// . g | / | ^ . | / . +// . g | w | trigger| . | w . +// . e | a | | . | a . +// . r | i | +----------+ disable +----------+ | i . +// . | t | | suspend |-------.-------->| suspend | | t . +// . | | | | . | | | . +// . | | | waiting |<------.---------| waiting | | . +// . | | +----------+ enable +----------+ | . +// . | | | ^ . | ^ | . +// . | | suspend | | resume . suspend | | resume | . +// . | | V | . V | | . +// . | | +----------+ disable +----------+ | . +// . | +------>| |-------.-------->| | | . +// . | | waiting | . | waiting | | . +// . +-------------| |<------.---------| |<-----+ . +// . +----------+ enable +----------+ . +// . . . +// ...................................................................... + +// ---------------------------------------------------------------------------- + +static std::ostream& +print_status_expression( std::ostream& os, sc_status s ); + +// utility helper to print a simulation status +std::ostream& operator << ( std::ostream& os, sc_status s ) +{ + // print primitive values + switch(s) + { +# define PRINT_STATUS( Status ) \ + case Status: { os << #Status; } break + + PRINT_STATUS( SC_UNITIALIZED ); + PRINT_STATUS( SC_ELABORATION ); + PRINT_STATUS( SC_BEFORE_END_OF_ELABORATION ); + PRINT_STATUS( SC_END_OF_ELABORATION ); + PRINT_STATUS( SC_START_OF_SIMULATION ); + + PRINT_STATUS( SC_RUNNING ); + PRINT_STATUS( SC_PAUSED ); + PRINT_STATUS( SC_STOPPED ); + PRINT_STATUS( SC_END_OF_SIMULATION ); + + PRINT_STATUS( SC_END_OF_INITIALIZATION ); +// PRINT_STATUS( SC_END_OF_EVALUATION ); + PRINT_STATUS( SC_END_OF_UPDATE ); + PRINT_STATUS( SC_BEFORE_TIMESTEP ); + + PRINT_STATUS( SC_STATUS_ANY ); + +# undef PRINT_STATUS + default: + + if( s & SC_STATUS_ANY ) // combination of status bits + print_status_expression( os, s ); + else // invalid number, print hex value + os << "0x" << std::hex << +s; + } + + return os; +} + +// pretty-print a combination of sc_status bits (i.e. a callback mask) +static std::ostream& +print_status_expression( std::ostream& os, sc_status s ) +{ + std::vector<sc_status> bits; + unsigned is_set = SC_ELABORATION; + + // collect bits + while( is_set <= SC_STATUS_LAST ) + { + if( s & is_set ) + bits.push_back( (sc_status)is_set ); + is_set <<= 1; + } + if( s & ~SC_STATUS_ANY ) // remaining bits + bits.push_back( (sc_status)( s & ~SC_STATUS_ANY ) ); + + // print expression + std::vector<sc_status>::size_type i=0, n=bits.size(); + if ( n>1 ) + os << "("; + for( ; i<n-1; ++i ) + os << bits[i] << "|"; + os << bits[i]; + if ( n>1 ) + os << ")"; + return os; +} + +} // namespace sc_core + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: Ali Dasdan, Synopsys, Inc. + Description of Modification: - Added sc_stop() detection into initial_crunch + and crunch. This makes it possible to exit out + of a combinational loop using sc_stop(). + + Name, Affiliation, Date: Andy Goodrich, Forte Design Systems 20 May 2003 + Description of Modification: - sc_stop mode + - phase callbacks + + Name, Affiliation, Date: Bishnupriya Bhattacharya, Cadence Design Systems, + 25 August 2003 + Description of Modification: - support for dynamic process + - support for sc export registry + - new member methods elaborate(), + prepare_to_simulate(), and initial_crunch() + that are invoked by initialize() in that order + - implement sc_get_last_created_process_handle() for use + before simulation starts + - remove "set_curr_proc(handle)" from + register_method_process and + register_thread_process - led to bugs + + Name, Affiliation, Date: Andy Goodrich, Forte Design Systems 04 Sep 2003 + Description of Modification: - changed process existence structures to + linked lists to eliminate exponential + execution problem with using sc_pvector. + *****************************************************************************/ +// $Log: sc_simcontext.cpp,v $ +// Revision 1.37 2011/08/29 18:04:32 acg +// Philipp A. Hartmann: miscellaneous clean ups. +// +// Revision 1.36 2011/08/26 20:46:10 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +// Revision 1.35 2011/08/24 22:05:51 acg +// Torsten Maehne: initialization changes to remove warnings. +// +// Revision 1.34 2011/08/04 17:15:28 acg +// Andy Goodrich: added documentation to crunch() routine. +// +// Revision 1.32 2011/07/24 11:16:36 acg +// Philipp A. Hartmann: fix reference counting on deferred deletions of +// processes. +// +// Revision 1.31 2011/07/01 18:49:07 acg +// Andy Goodrich: moved pln() from sc_simcontext.cpp to sc_ver.cpp. +// +// Revision 1.30 2011/05/09 04:07:49 acg +// Philipp A. Hartmann: +// (1) Restore hierarchy in all phase callbacks. +// (2) Ensure calls to before_end_of_elaboration. +// +// Revision 1.29 2011/04/08 22:39:09 acg +// Andy Goodrich: moved method invocation code to sc_method.h so that the +// details are hidden from sc_simcontext. +// +// Revision 1.28 2011/04/05 20:50:57 acg +// Andy Goodrich: +// (1) changes to make sure that event(), posedge() and negedge() only +// return true if the clock has not moved. +// (2) fixes for method self-resumes. +// (3) added SC_PRERELEASE_VERSION +// (4) removed kernel events from the object hierarchy, added +// sc_hierarchy_name_exists(). +// +// Revision 1.27 2011/04/05 06:14:15 acg +// Andy Goodrich: fix typo. +// +// Revision 1.26 2011/04/05 06:03:32 acg +// Philipp A. Hartmann: added code to set ready to run bit for a suspended +// process that does not have dont_initialize specified at simulation +// start up. +// +// Revision 1.25 2011/04/01 21:31:55 acg +// Andy Goodrich: make sure processes suspended before the start of execution +// don't get scheduled for initial execution. +// +// Revision 1.24 2011/03/28 13:02:52 acg +// Andy Goodrich: Changes for disable() interactions. +// +// Revision 1.23 2011/03/12 21:07:51 acg +// Andy Goodrich: changes to kernel generated event support. +// +// Revision 1.22 2011/03/07 17:38:43 acg +// Andy Goodrich: tightening up of checks for undefined interaction between +// synchronous reset and suspend. +// +// Revision 1.21 2011/03/06 19:57:11 acg +// Andy Goodrich: refinements for the illegal suspend - synchronous reset +// interaction. +// +// Revision 1.20 2011/03/06 15:58:50 acg +// Andy Goodrich: added escape to turn off process control corner case +// checks. +// +// Revision 1.19 2011/03/05 04:45:16 acg +// Andy Goodrich: moved active process calculation to the sc_simcontext class. +// +// Revision 1.18 2011/03/05 01:39:21 acg +// Andy Goodrich: changes for named events. +// +// Revision 1.17 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.16 2011/02/17 19:53:28 acg +// Andy Goodrich: eliminated use of ready_to_run() as part of process control +// simplification. +// +// Revision 1.15 2011/02/13 21:47:38 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.14 2011/02/11 13:25:24 acg +// Andy Goodrich: Philipp A. Hartmann's changes: +// (1) Removal of SC_CTHREAD method overloads. +// (2) New exception processing code. +// +// Revision 1.13 2011/02/08 08:42:50 acg +// Andy Goodrich: fix ordering of check for stopped versus paused. +// +// Revision 1.12 2011/02/07 19:17:20 acg +// Andy Goodrich: changes for IEEE 1666 compatibility. +// +// Revision 1.11 2011/02/02 07:18:11 acg +// Andy Goodrich: removed toggle() calls for the new crunch() toggle usage. +// +// Revision 1.10 2011/02/01 23:01:53 acg +// Andy Goodrich: removed dead code. +// +// Revision 1.9 2011/02/01 21:11:59 acg +// Andy Goodrich: +// (1) Use of new toggle_methods() and toggle_threads() run queue methods +// to make sure the thread run queue does not execute when allow preempt_me() +// is called from an SC_METHOD. +// (2) Use of execute_thread_next() to allow thread execution in the current +// delta cycle() rather than push_runnable_thread_front which executed +// in the following cycle. +// +// Revision 1.8 2011/01/25 20:50:37 acg +// Andy Goodrich: changes for IEEE 1666 2011. +// +// Revision 1.7 2011/01/19 23:21:50 acg +// Andy Goodrich: changes for IEEE 1666 2011 +// +// Revision 1.6 2011/01/18 20:10:45 acg +// Andy Goodrich: changes for IEEE1666_2011 semantics. +// +// Revision 1.5 2010/11/20 17:10:57 acg +// Andy Goodrich: reset processing changes for new IEEE 1666 standard. +// +// Revision 1.4 2010/07/22 20:02:33 acg +// Andy Goodrich: bug fixes. +// +// Revision 1.3 2008/05/22 17:06:26 acg +// Andy Goodrich: updated copyright notice to include 2008. +// +// Revision 1.2 2007/09/20 20:32:35 acg +// Andy Goodrich: changes to the semantics of throw_it() to match the +// specification. A call to throw_it() will immediately suspend the calling +// thread until all the throwees have executed. At that point the calling +// thread will be restarted before the execution of any other threads. +// +// Revision 1.1.1.1 2006/12/15 20:20:05 acg +// SystemC 2.3 +// +// Revision 1.21 2006/08/29 23:37:13 acg +// Andy Goodrich: Added check for negative time. +// +// Revision 1.20 2006/05/26 20:33:16 acg +// Andy Goodrich: changes required by additional platform compilers (i.e., +// Microsoft VC++, Sun Forte, HP aCC). +// +// Revision 1.19 2006/05/08 17:59:52 acg +// Andy Goodrich: added a check before m_curr_time is set to make sure it +// is not set to a time before its current value. This will treat +// sc_event.notify( ) calls with negative times as calls with a zero time. +// +// Revision 1.18 2006/04/20 17:08:17 acg +// Andy Goodrich: 3.0 style process changes. +// +// Revision 1.17 2006/04/11 23:13:21 acg +// Andy Goodrich: Changes for reduced reset support that only includes +// sc_cthread, but has preliminary hooks for expanding to method and thread +// processes also. +// +// Revision 1.16 2006/03/21 00:00:34 acg +// Andy Goodrich: changed name of sc_get_current_process_base() to be +// sc_get_current_process_b() since its returning an sc_process_b instance. +// +// Revision 1.15 2006/03/13 20:26:50 acg +// Andy Goodrich: Addition of forward class declarations, e.g., +// sc_reset, to keep gcc 4.x happy. +// +// Revision 1.14 2006/02/02 23:42:41 acg +// Andy Goodrich: implemented a much better fix to the sc_event_finder +// proliferation problem. This new version allocates only a single event +// finder for each port for each type of event, e.g., pos(), neg(), and +// value_change(). The event finder persists as long as the port does, +// which is what the LRM dictates. Because only a single instance is +// allocated for each event type per port there is not a potential +// explosion of storage as was true in the 2.0.1/2.1 versions. +// +// Revision 1.13 2006/02/02 21:29:10 acg +// Andy Goodrich: removed the call to sc_event_finder::free_instances() that +// was in end_of_elaboration(), leaving only the call in clean(). This is +// because the LRM states that sc_event_finder instances are persistent as +// long as the sc_module hierarchy is valid. +// +// Revision 1.12 2006/02/02 21:09:50 acg +// Andy Goodrich: added call to sc_event_finder::free_instances in the clean() +// method. +// +// Revision 1.11 2006/02/02 20:43:14 acg +// Andy Goodrich: Added an existence linked list to sc_event_finder so that +// the dynamically allocated instances can be freed after port binding +// completes. This replaces the individual deletions in ~sc_bind_ef, as these +// caused an exception if an sc_event_finder instance was used more than +// once, due to a double freeing of the instance. +// +// Revision 1.10 2006/01/31 21:43:26 acg +// Andy Goodrich: added comments in constructor to highlight environmental +// overrides section. +// +// Revision 1.9 2006/01/26 21:04:54 acg +// Andy Goodrich: deprecation message changes and additional messages. +// +// Revision 1.8 2006/01/25 00:31:19 acg +// Andy Goodrich: Changed over to use a standard message id of +// SC_ID_IEEE_1666_DEPRECATION for all deprecation messages. +// +// Revision 1.7 2006/01/24 20:49:05 acg +// Andy Goodrich: changes to remove the use of deprecated features within the +// simulator, and to issue warning messages when deprecated features are used. +// +// Revision 1.6 2006/01/19 00:29:52 acg +// Andy Goodrich: Yet another implementation for signal write checking. This +// one uses an environment variable SC_SIGNAL_WRITE_CHECK, that when set to +// DISABLE will disable write checking on signals. +// +// Revision 1.5 2006/01/13 18:44:30 acg +// Added $Log to record CVS changes into the source. +// +// Revision 1.4 2006/01/03 23:18:44 acg +// Changed copyright to include 2006. +// +// Revision 1.3 2005/12/20 22:11:10 acg +// Fixed $Log lines. +// +// Revision 1.2 2005/12/20 22:02:30 acg +// Changed where delta cycles are incremented to match IEEE 1666. Added the +// event_occurred() method to hide how delta cycle comparisions are done within +// sc_simcontext. Changed the boolean update_phase to an enum that shows all +// the phases. +// Taf! diff --git a/ext/systemc/src/sysc/kernel/sc_simcontext.h b/ext/systemc/src/sysc/kernel/sc_simcontext.h new file mode 100644 index 000000000..997a3f49c --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_simcontext.h @@ -0,0 +1,903 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_simcontext.h -- Definition of the simulation context class. + + Original Author: Stan Y. Liao, Synopsys, Inc. + Martin Janssen, Synopsys, Inc. + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + +#ifndef SC_SIMCONTEXT_H +#define SC_SIMCONTEXT_H + +#include "sysc/kernel/sc_cmnhdr.h" +#include "sysc/kernel/sc_process.h" +#include "sysc/kernel/sc_status.h" +#include "sysc/kernel/sc_time.h" +#include "sysc/utils/sc_hash.h" +#include "sysc/utils/sc_pq.h" + +namespace sc_core { + +// forward declarations + +class sc_cor; +class sc_cor_pkg; +class sc_event; +class sc_event_timed; +class sc_export_registry; +class sc_module; +class sc_module_name; +class sc_module_registry; +class sc_name_gen; +class sc_object; +class sc_object_manager; +class sc_phase_callback_registry; +class sc_process_handle; +class sc_port_registry; +class sc_prim_channel_registry; +class sc_process_table; +class sc_signal_bool_deval; +class sc_trace_file; +class sc_runnable; +class sc_process_host; +class sc_method_process; +class sc_cthread_process; +class sc_thread_process; + +template< typename > class sc_plist; +typedef sc_plist< sc_process_b* > sc_process_list; + +struct sc_curr_proc_info +{ + sc_process_b* process_handle; + sc_curr_proc_kind kind; + sc_curr_proc_info() : process_handle( 0 ), kind( SC_NO_PROC_ ) {} +}; + +typedef const sc_curr_proc_info* sc_curr_proc_handle; + +enum sc_stop_mode { // sc_stop modes: + SC_STOP_FINISH_DELTA, + SC_STOP_IMMEDIATE +}; +extern void sc_set_stop_mode( sc_stop_mode mode ); +extern sc_stop_mode sc_get_stop_mode(); + +enum sc_starvation_policy +{ + SC_EXIT_ON_STARVATION, + SC_RUN_TO_TIME +}; +extern void sc_start(); +extern void sc_start( const sc_time& duration, + sc_starvation_policy p=SC_RUN_TO_TIME ); +inline void sc_start( int duration, sc_time_unit unit, + sc_starvation_policy p=SC_RUN_TO_TIME ) +{ + sc_start( sc_time((double)duration,unit), p ); +} + +inline void sc_start( double duration, sc_time_unit unit, + sc_starvation_policy p=SC_RUN_TO_TIME ) +{ + sc_start( sc_time(duration,unit), p ); +} + +extern void sc_stop(); + +// friend function declarations + +sc_dt::uint64 sc_delta_count(); +const std::vector<sc_event*>& sc_get_top_level_events( + const sc_simcontext* simc_p); +const std::vector<sc_object*>& sc_get_top_level_objects( + const sc_simcontext* simc_p); +bool sc_is_running( const sc_simcontext* simc_p ); +void sc_pause(); +bool sc_end_of_simulation_invoked(); +void sc_start( const sc_time&, sc_starvation_policy ); +bool sc_start_of_simulation_invoked(); +void sc_set_time_resolution( double, sc_time_unit ); +sc_time sc_get_time_resolution(); +void sc_set_default_time_unit( double, sc_time_unit ); +sc_time sc_get_default_time_unit(); +bool sc_pending_activity_at_current_time( const sc_simcontext* ); +bool sc_pending_activity_at_future_time( const sc_simcontext* ); +sc_time sc_time_to_pending_activity( const sc_simcontext* ); + +struct sc_invoke_method; + +// ---------------------------------------------------------------------------- +// CLASS : sc_simcontext +// +// The simulation context. +// ---------------------------------------------------------------------------- + +class sc_simcontext +{ + friend struct sc_invoke_method; + friend class sc_event; + friend class sc_module; + friend class sc_object; + friend class sc_time; + friend class sc_clock; + friend class sc_method_process; + friend class sc_phase_callback_registry; + friend class sc_process_b; + friend class sc_process_handle; + friend class sc_prim_channel; + friend class sc_cthread_process; + friend class sc_thread_process; + friend sc_dt::uint64 sc_delta_count(); + friend const std::vector<sc_event*>& sc_get_top_level_events( + const sc_simcontext* simc_p); + friend const std::vector<sc_object*>& sc_get_top_level_objects( + const sc_simcontext* simc_p); + friend bool sc_is_running( const sc_simcontext* simc_p ); + friend void sc_pause(); + friend bool sc_end_of_simulation_invoked(); + friend void sc_start( const sc_time&, sc_starvation_policy ); + friend bool sc_start_of_simulation_invoked(); + friend void sc_thread_cor_fn(void*); + friend sc_time sc_time_to_pending_activity( const sc_simcontext* ); + friend bool sc_pending_activity_at_current_time( const sc_simcontext* ); + friend bool sc_pending_activity_at_future_time( const sc_simcontext* ); + + + void init(); + void clean(); + +public: + + sc_simcontext(); + ~sc_simcontext(); + + void initialize( bool = false ); + void cycle( const sc_time& ); + void simulate( const sc_time& duration ); + void stop(); + void end(); + void reset(); + + int sim_status() const; + bool elaboration_done() const; + + std::vector<sc_thread_handle>& get_active_invokers(); + + sc_object_manager* get_object_manager(); + + inline sc_status get_status() const; + + sc_object* active_object(); + + void hierarchy_push( sc_module* ); + sc_module* hierarchy_pop(); + sc_module* hierarchy_curr() const; + sc_object* first_object(); + sc_object* next_object(); + sc_object* find_object( const char* name ); + + sc_module_registry* get_module_registry(); + sc_port_registry* get_port_registry(); + sc_export_registry* get_export_registry(); + sc_prim_channel_registry* get_prim_channel_registry(); + + // to generate unique names for objects in an MT-Safe way + const char* gen_unique_name( const char* basename_, + bool preserve_first = false + ); + + // process creation + sc_process_handle create_cthread_process( + const char* name_p, bool free_host, SC_ENTRY_FUNC method_p, + sc_process_host* host_p, const sc_spawn_options* opt_p ); + + sc_process_handle create_method_process( + const char* name_p, bool free_host, SC_ENTRY_FUNC method_p, + sc_process_host* host_p, const sc_spawn_options* opt_p ); + + sc_process_handle create_thread_process( + const char* name_p, bool free_host, SC_ENTRY_FUNC method_p, + sc_process_host* host_p, const sc_spawn_options* opt_p ); + + sc_curr_proc_handle get_curr_proc_info(); + sc_object* get_current_writer() const; + bool write_check() const; + void set_curr_proc( sc_process_b* ); + void reset_curr_proc(); + + int next_proc_id(); + + void add_trace_file( sc_trace_file* ); + void remove_trace_file( sc_trace_file* ); + + friend void sc_set_time_resolution( double, sc_time_unit ); + friend sc_time sc_get_time_resolution(); + friend void sc_set_default_time_unit( double, sc_time_unit ); + friend sc_time sc_get_default_time_unit(); + + const sc_time& max_time() const; + const sc_time& time_stamp() const; + + sc_dt::uint64 change_stamp() const; + sc_dt::uint64 delta_count() const; + bool event_occurred( sc_dt::uint64 last_change_count ) const; + bool evaluation_phase() const; + bool is_running() const; + bool update_phase() const; + bool notify_phase() const; + bool get_error(); + void set_error( sc_report* ); + + sc_cor_pkg* cor_pkg() + { return m_cor_pkg; } + sc_cor* next_cor(); + + const ::std::vector<sc_object*>& get_child_objects() const; + + void elaborate(); + void prepare_to_simulate(); + inline void initial_crunch( bool no_crunch ); + bool next_time( sc_time& t ) const; + bool pending_activity_at_current_time() const; + +private: + + void add_child_event( sc_event* ); + void add_child_object( sc_object* ); + void remove_child_event( sc_event* ); + void remove_child_object( sc_object* ); + + void crunch( bool once=false ); + + int add_delta_event( sc_event* ); + void remove_delta_event( sc_event* ); + void add_timed_event( sc_event_timed* ); + + void trace_cycle( bool delta_cycle ); + + const ::std::vector<sc_event*>& get_child_events_internal() const; + const ::std::vector<sc_object*>& get_child_objects_internal() const; + + void execute_method_next( sc_method_handle ); + void execute_thread_next( sc_thread_handle ); + + sc_method_handle pop_runnable_method(); + sc_thread_handle pop_runnable_thread(); + + void preempt_with( sc_method_handle ); + inline void preempt_with( sc_thread_handle ); + + void push_runnable_method( sc_method_handle ); + void push_runnable_thread( sc_thread_handle ); + + void push_runnable_method_front( sc_method_handle ); + void push_runnable_thread_front( sc_thread_handle ); + + void remove_runnable_method( sc_method_handle ); + void remove_runnable_thread( sc_thread_handle ); + + void requeue_current_process(); + void suspend_current_process(); + + void do_sc_stop_action(); + void mark_to_collect_process( sc_process_b* zombie_p ); + +private: + + enum execution_phases { + phase_initialize = 0, + phase_evaluate, + phase_update, + phase_notify + }; + sc_object_manager* m_object_manager; + + sc_module_registry* m_module_registry; + sc_port_registry* m_port_registry; + sc_export_registry* m_export_registry; + sc_prim_channel_registry* m_prim_channel_registry; + sc_phase_callback_registry* m_phase_cb_registry; + + sc_name_gen* m_name_gen; + + sc_process_table* m_process_table; + sc_curr_proc_info m_curr_proc_info; + sc_object* m_current_writer; + bool m_write_check; + int m_next_proc_id; + + std::vector<sc_thread_handle> m_active_invokers; + + std::vector<sc_event*> m_child_events; + std::vector<sc_object*> m_child_objects; + + std::vector<sc_event*> m_delta_events; + sc_ppq<sc_event_timed*>* m_timed_events; + + std::vector<sc_trace_file*> m_trace_files; + bool m_something_to_trace; + + sc_runnable* m_runnable; + sc_process_list* m_collectable; + + sc_time_params* m_time_params; + sc_time m_curr_time; + mutable sc_time m_max_time; + + sc_invoke_method* m_method_invoker_p; + sc_dt::uint64 m_change_stamp; // "time" change occurred. + sc_dt::uint64 m_delta_count; + bool m_forced_stop; + bool m_paused; + bool m_ready_to_simulate; + bool m_elaboration_done; + execution_phases m_execution_phase; + sc_report* m_error; + bool m_in_simulator_control; + bool m_end_of_simulation_called; + sc_status m_simulation_status; + bool m_start_of_simulation_called; + + sc_cor_pkg* m_cor_pkg; // the simcontext's coroutine package + sc_cor* m_cor; // the simcontext's coroutine + +private: + + // disabled + sc_simcontext( const sc_simcontext& ); + sc_simcontext& operator = ( const sc_simcontext& ); +}; + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + +// Not MT safe. + +#if 1 +extern sc_simcontext* sc_curr_simcontext; +extern sc_simcontext* sc_default_global_context; + +inline sc_simcontext* +sc_get_curr_simcontext() +{ + if( sc_curr_simcontext == 0 ) { + sc_default_global_context = new sc_simcontext; + sc_curr_simcontext = sc_default_global_context; + } + return sc_curr_simcontext; +} +#else + extern sc_simcontext* sc_get_curr_simcontext(); +#endif // 0 +inline sc_status sc_get_status() +{ + return sc_get_curr_simcontext()->get_status(); +} + + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + +inline +bool +sc_simcontext::elaboration_done() const +{ + return m_elaboration_done; +} + + +inline sc_status sc_simcontext::get_status() const +{ + return m_simulation_status != SC_RUNNING ? + m_simulation_status : + (m_in_simulator_control ? SC_RUNNING : SC_PAUSED); +} + +inline +int +sc_simcontext::sim_status() const +{ + if( m_error ) { + return SC_SIM_ERROR; + } + if( m_forced_stop ) { + return SC_SIM_USER_STOP; + } + return SC_SIM_OK; +} + + +inline +sc_object_manager* +sc_simcontext::get_object_manager() +{ + return m_object_manager; +} + +inline +sc_module_registry* +sc_simcontext::get_module_registry() +{ + return m_module_registry; +} + +inline +sc_port_registry* +sc_simcontext::get_port_registry() +{ + return m_port_registry; +} + +inline +sc_export_registry* +sc_simcontext::get_export_registry() +{ + return m_export_registry; +} + +inline +sc_prim_channel_registry* +sc_simcontext::get_prim_channel_registry() +{ + return m_prim_channel_registry; +} + + +inline +sc_curr_proc_handle +sc_simcontext::get_curr_proc_info() +{ + return &m_curr_proc_info; +} + + +inline +int +sc_simcontext::next_proc_id() +{ + return ( ++ m_next_proc_id ); +} + + +inline +const sc_time& +sc_simcontext::max_time() const +{ + if ( m_max_time == SC_ZERO_TIME ) + { + m_max_time = sc_time::from_value( ~sc_dt::UINT64_ZERO ); + } + return m_max_time; +} + +inline +sc_dt::uint64 +sc_simcontext::change_stamp() const +{ + return m_change_stamp; +} + +inline +const sc_time& +sc_simcontext::time_stamp() const +{ + return m_curr_time; +} + + +inline +bool +sc_simcontext::event_occurred(sc_dt::uint64 last_change_stamp) const +{ + return m_change_stamp == last_change_stamp; +} + +inline +bool +sc_simcontext::evaluation_phase() const +{ + return (m_execution_phase == phase_evaluate) && + m_ready_to_simulate; +} + +inline +bool +sc_simcontext::update_phase() const +{ + return m_execution_phase == phase_update; +} + +inline +bool +sc_simcontext::notify_phase() const +{ + return m_execution_phase == phase_notify; +} + +inline +void +sc_simcontext::set_error( sc_report* err ) +{ + delete m_error; + m_error = err; +} + + +inline +bool +sc_simcontext::get_error() +{ + return m_error != NULL; +} + +inline +int +sc_simcontext::add_delta_event( sc_event* e ) +{ + m_delta_events.push_back( e ); + return ( m_delta_events.size() - 1 ); +} + +inline +void +sc_simcontext::add_timed_event( sc_event_timed* et ) +{ + m_timed_events->insert( et ); +} + +inline sc_object* +sc_simcontext::get_current_writer() const +{ + return m_current_writer; +} + +inline bool +sc_simcontext::write_check() const +{ + return m_write_check; +} + +// ---------------------------------------------------------------------------- + +class sc_process_handle; +sc_process_handle sc_get_current_process_handle(); + +// Get the current object hierarchy context +// +// Returns a pointer the the sc_object (module or process) that +// would become the parent object of a newly created element +// of the SystemC object hierarchy, or NULL. +// +inline sc_object* +sc_get_current_object() +{ + return sc_get_curr_simcontext()->active_object(); +} + +inline +sc_process_b* +sc_get_current_process_b() +{ + return sc_get_curr_simcontext()->get_curr_proc_info()->process_handle; +} + +// THE FOLLOWING FUNCTION IS DEPRECATED IN 2.1 +extern sc_process_b* sc_get_curr_process_handle(); + +inline +sc_curr_proc_kind +sc_get_curr_process_kind() +{ + return sc_get_curr_simcontext()->get_curr_proc_info()->kind; +} + + +inline int sc_get_simulator_status() +{ + return sc_get_curr_simcontext()->sim_status(); +} + + +// Generates unique names within each module. +extern +const char* +sc_gen_unique_name( const char* basename_, bool preserve_first = false ); + + +// Set the random seed for controlled randomization -- not yet implemented +extern +void +sc_set_random_seed( unsigned int seed_ ); + + +extern void sc_initialize(); + +extern const sc_time& sc_max_time(); // Get maximum time value. +extern const sc_time& sc_time_stamp(); // Current simulation time. +extern double sc_simulation_time(); // Current time in default time units. + +inline +const std::vector<sc_event*>& sc_get_top_level_events( + const sc_simcontext* simc_p = sc_get_curr_simcontext() ) +{ + return simc_p->m_child_events; +} + +inline +const std::vector<sc_object*>& sc_get_top_level_objects( + const sc_simcontext* simc_p = sc_get_curr_simcontext() ) +{ + return simc_p->m_child_objects; +} + +extern sc_event* sc_find_event( const char* name ); + +extern sc_object* sc_find_object( const char* name ); + +inline +sc_dt::uint64 sc_delta_count() +{ + return sc_get_curr_simcontext()->m_delta_count; +} + +inline +bool sc_is_running( const sc_simcontext* simc_p = sc_get_curr_simcontext() ) +{ + return simc_p->m_ready_to_simulate; +} + +bool sc_is_unwinding(); + +inline void sc_pause() +{ + sc_get_curr_simcontext()->m_paused = true; +} + +// Return indication if there are more processes to execute in this delta phase + +inline bool sc_pending_activity_at_current_time + ( const sc_simcontext* simc_p = sc_get_curr_simcontext() ) +{ + return simc_p->pending_activity_at_current_time(); +} + +// Return indication if there are timed notifications in the future + +inline bool sc_pending_activity_at_future_time + ( const sc_simcontext* simc_p = sc_get_curr_simcontext() ) +{ + sc_time ignored; + return simc_p->next_time( ignored ); +} + +// Return indication if there are processes to run, +// or notifications in the future + +inline bool sc_pending_activity + ( const sc_simcontext* simc_p = sc_get_curr_simcontext() ) +{ + return sc_pending_activity_at_current_time( simc_p ) + || sc_pending_activity_at_future_time( simc_p ); +} + +sc_time +sc_time_to_pending_activity + ( const sc_simcontext* simc_p = sc_get_curr_simcontext() ); + + +inline +bool +sc_end_of_simulation_invoked() +{ + return sc_get_curr_simcontext()->m_end_of_simulation_called; +} + +inline bool sc_hierarchical_name_exists( const char* name ) +{ + return sc_find_object(name) || sc_find_event(name); +} + +inline +bool +sc_start_of_simulation_invoked() +{ + return sc_get_curr_simcontext()->m_start_of_simulation_called; +} + +// The following variable controls whether process control corners should +// be considered errors or not. See sc_simcontext.cpp for details on what +// happens if this value is set to true. + +extern bool sc_allow_process_control_corners; + +} // namespace sc_core + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: Andy Goodrich, Forte Design Systems 20 May 2003 + Description of Modification: - phase callbacks + - sc_stop mode + + Name, Affiliation, Date: Bishnupriya Bhattacharya, Cadence Design Systems, + 25 August, 2003 + Description of Modification: - support for dynamic process + - support for sc export registry + - new member methods elaborate(), + prepare_to_simulate(), and initial_crunch() + that are invoked by initialize() in that order + - add sc_get_last_created_process_handle() for + use before simulation starts + + Name, Affiliation, Date: Bishnupriya Bhattacharya, Cadence Design Systems, + 3 March, 2004 + Description of Modification: add sc_get_curr_process_kind() + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ +// $Log: sc_simcontext.h,v $ +// Revision 1.26 2011/09/05 21:20:22 acg +// Andy Goodrich: result of automake invocation. +// +// Revision 1.25 2011/09/01 15:28:10 acg +// Andy Goodrich: the aftermath of automake. +// +// Revision 1.24 2011/08/29 18:04:32 acg +// Philipp A. Hartmann: miscellaneous clean ups. +// +// Revision 1.23 2011/08/26 20:46:10 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +// Revision 1.22 2011/08/24 22:05:51 acg +// Torsten Maehne: initialization changes to remove warnings. +// +// Revision 1.21 2011/05/09 04:07:49 acg +// Philipp A. Hartmann: +// (1) Restore hierarchy in all phase callbacks. +// (2) Ensure calls to before_end_of_elaboration. +// +// Revision 1.20 2011/04/08 18:26:07 acg +// Andy Goodrich: added execute_method_next() to handle method dispatch +// for asynchronous notifications that occur outside the evaluation phase. +// +// Revision 1.19 2011/04/05 20:50:57 acg +// Andy Goodrich: +// (1) changes to make sure that event(), posedge() and negedge() only +// return true if the clock has not moved. +// (2) fixes for method self-resumes. +// (3) added SC_PRERELEASE_VERSION +// (4) removed kernel events from the object hierarchy, added +// sc_hierarchical_name_exists(). +// +// Revision 1.18 2011/03/20 13:43:23 acg +// Andy Goodrich: added async_signal_is() plus suspend() as a corner case. +// +// Revision 1.17 2011/03/07 18:25:19 acg +// Andy Goodrich: tightening of check for resume on a disabled process to +// only produce an error if it is ready to run. +// +// Revision 1.16 2011/03/06 15:58:50 acg +// Andy Goodrich: added escape to turn off process control corner case +// checks. +// +// Revision 1.15 2011/03/05 04:45:16 acg +// Andy Goodrich: moved active process calculation to the sc_simcontext class. +// +// Revision 1.14 2011/03/05 01:39:21 acg +// Andy Goodrich: changes for named events. +// +// Revision 1.13 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.12 2011/02/13 21:47:38 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.11 2011/02/13 21:34:35 acg +// Andy Goodrich: added SC_UNITIALIZED enum value to process status so +// its possible to detect throws before initialization. +// +// Revision 1.10 2011/02/11 13:25:24 acg +// Andy Goodrich: Philipp A. Hartmann's changes: +// (1) Removal of SC_CTHREAD method overloads. +// (2) New exception processing code. +// +// Revision 1.9 2011/02/01 21:18:56 acg +// Andy Goodrich: addition of new preempt_with() method used to immediately +// throw exceptions from threads. +// +// Revision 1.8 2011/01/25 20:50:37 acg +// Andy Goodrich: changes for IEEE 1666 2011. +// +// Revision 1.7 2011/01/19 23:21:50 acg +// Andy Goodrich: changes for IEEE 1666 2011 +// +// Revision 1.6 2011/01/18 20:10:45 acg +// Andy Goodrich: changes for IEEE1666_2011 semantics. +// +// Revision 1.5 2010/07/22 20:02:33 acg +// Andy Goodrich: bug fixes. +// +// Revision 1.4 2009/05/22 16:06:29 acg +// Andy Goodrich: process control updates. +// +// Revision 1.3 2008/05/22 17:06:26 acg +// Andy Goodrich: updated copyright notice to include 2008. +// +// Revision 1.2 2007/09/20 20:32:35 acg +// Andy Goodrich: changes to the semantics of throw_it() to match the +// specification. A call to throw_it() will immediately suspend the calling +// thread until all the throwees have executed. At that point the calling +// thread will be restarted before the execution of any other threads. +// +// Revision 1.1.1.1 2006/12/15 20:20:05 acg +// SystemC 2.3 +// +// Revision 1.13 2006/05/08 18:00:06 acg +// Andy Goodrich: added David Long's forward declarations for friend +// functions, methods, and operators to keep the Microsoft compiler happy. +// +// Revision 1.11 2006/04/11 23:13:21 acg +// Andy Goodrich: Changes for reduced reset support that only includes +// sc_cthread, but has preliminary hooks for expanding to method and thread +// processes also. +// +// Revision 1.10 2006/03/21 00:00:34 acg +// Andy Goodrich: changed name of sc_get_current_process_base() to be +// sc_get_current_process_b() since its returning an sc_process_b instance. +// +// Revision 1.9 2006/01/26 21:04:54 acg +// Andy Goodrich: deprecation message changes and additional messages. +// +// Revision 1.8 2006/01/24 20:49:05 acg +// Andy Goodrich: changes to remove the use of deprecated features within the +// simulator, and to issue warning messages when deprecated features are used. +// +// Revision 1.7 2006/01/19 00:29:52 acg +// Andy Goodrich: Yet another implementation for signal write checking. This +// one uses an environment variable SC_SIGNAL_WRITE_CHECK, that when set to +// DISABLE will disable write checking on signals. +// +// Revision 1.6 2006/01/18 21:42:37 acg +// Andy Goodrich: Changes for check writer support. +// +// Revision 1.5 2006/01/13 18:44:30 acg +// Added $Log to record CVS changes into the source. +// +// Revision 1.4 2006/01/03 23:18:44 acg +// Changed copyright to include 2006. +// +// Revision 1.3 2005/12/20 22:11:10 acg +// Fixed $Log lines. +// +// Revision 1.2 2005/12/20 22:02:30 acg +// Changed where delta cycles are incremented to match IEEE 1666. Added the +// event_occurred() method to hide how delta cycle comparisions are done within +// sc_simcontext. Changed the boolean update_phase to an enum that shows all +// the phases. + +#endif diff --git a/ext/systemc/src/sysc/kernel/sc_simcontext_int.h b/ext/systemc/src/sysc/kernel/sc_simcontext_int.h new file mode 100644 index 000000000..039237f4a --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_simcontext_int.h @@ -0,0 +1,365 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_simcontext_int.h -- For inline definitions of some utility functions. + DO NOT EXPORT THIS INCLUDE FILE. Include this file + after "sc_process_int.h" so that we can get the base + class right. + + Original Author: Stan Y. Liao, Synopsys, Inc. + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + +#ifndef SC_SIMCONTEXT_INT_H +#define SC_SIMCONTEXT_INT_H + +#include "sysc/kernel/sc_simcontext.h" +#include "sysc/kernel/sc_runnable.h" +#include "sysc/kernel/sc_runnable_int.h" + +// DEBUGGING MACROS: +// +// DEBUG_MSG(NAME,P,MSG) +// MSG = message to print +// NAME = name that must match the process for the message to print, or +// null if the message should be printed unconditionally. +// P = pointer to process message is for, or NULL in which case the +// message will not print. +#if 0 +# define DEBUG_NAME "" +# define DEBUG_MSG(NAME,P,MSG) \ + { \ + if ( P && ( (strlen(NAME)==0) || !strcmp(NAME,P->name())) ) \ + std::cout << "**** " << sc_time_stamp() << " (" \ + << sc_get_current_process_name() << "): " << MSG \ + << " - " << P->name() << std::endl; \ + } +#else +# define DEBUG_MSG(NAME,P,MSG) +#endif + + +namespace sc_core { + +inline +const char* +sc_get_current_process_name() +{ + sc_process_b* active_p; // active process to get name of. + const char* result; // name of active process. + + active_p = sc_get_curr_simcontext()->get_curr_proc_info()->process_handle; + if ( active_p ) + result = active_p->name(); + else + result = "** NONE **"; + return result; +} + +// We use m_current_writer rather than m_curr_proc_info.process_handle to +// return the active process for sc_signal<T>::check_write since that lets +// us turn it off a library compile time, and only incur the overhead at +// the time of process switches rather than having to interrogate an +// additional switch every time a signal is written. + +inline +void +sc_simcontext::set_curr_proc( sc_process_b* process_h ) +{ + m_curr_proc_info.process_handle = process_h; + m_curr_proc_info.kind = process_h->proc_kind(); + m_current_writer = m_write_check ? process_h : (sc_object*)0; +} + +inline +void +sc_simcontext::reset_curr_proc() +{ + m_curr_proc_info.process_handle = 0; + m_curr_proc_info.kind = SC_NO_PROC_; + m_current_writer = 0; + sc_process_b::m_last_created_process_p = 0; +} + +inline +void +sc_simcontext::execute_method_next( sc_method_handle method_h ) +{ + m_runnable->execute_method_next( method_h ); +} + +inline +void +sc_simcontext::execute_thread_next( sc_thread_handle thread_h ) +{ + m_runnable->execute_thread_next( thread_h ); +} + +// +---------------------------------------------------------------------------- +// |"sc_simcontext::preempt_with" +// | +// | This method executes the supplied thread immediately, suspending the +// | caller. After executing the supplied thread the caller's execution will +// | be restored. It is used to allow a thread to immediately throw an +// | exception, e.g., when the thread's kill_process() method was called. +// | There are three cases to consider: +// | (1) The caller is a method, e.g., murder by method. +// | (2) The caller is another thread instance, e.g., murder by thread. +// | (3) The caller is this thread instance, e.g., suicide. +// | +// | Arguments: +// | thread_h -> thread to be executed. +// +---------------------------------------------------------------------------- +inline +void +sc_simcontext::preempt_with( sc_thread_handle thread_h ) +{ + sc_thread_handle active_p; // active thread or null. + sc_curr_proc_info caller_info; // process info for caller. + + // Determine the active process and take the thread to be run off the + // run queue, if its there, since we will be explicitly causing its + // execution. + + active_p = DCAST<sc_thread_handle>(sc_get_current_process_b()); + if ( thread_h->next_runnable() != NULL ) + remove_runnable_thread( thread_h ); + + // THE CALLER IS A METHOD: + // + // (a) Set the current process information to our thread. + // (b) If the method was called by an invoker thread push that thread + // onto the front of the run queue, this will cause the method + // to be resumed after this thread waits. + // (c) Invoke our thread directly by-passing the run queue. + // (d) Restore the process info to the caller. + // (e) Check to see if the calling method should throw an exception + // because of activity that occurred during the preemption. + + if ( active_p == NULL ) + { + std::vector<sc_thread_handle>* invokers_p; // active invokers stack. + sc_thread_handle invoke_thread_p; // latest invocation thread. + sc_method_handle method_p; // active method. + + method_p = DCAST<sc_method_handle>(sc_get_current_process_b()); + invokers_p = &get_active_invokers(); + caller_info = m_curr_proc_info; + if ( invokers_p->size() != 0 ) + { + invoke_thread_p = invokers_p->back(); + DEBUG_MSG( DEBUG_NAME, invoke_thread_p, + "queueing invocation thread to execute next" ); + execute_thread_next(invoke_thread_p); + } + DEBUG_MSG( DEBUG_NAME, thread_h, "preempting method with thread" ); + set_curr_proc( (sc_process_b*)thread_h ); + m_cor_pkg->yield( thread_h->m_cor_p ); + m_curr_proc_info = caller_info; + DEBUG_MSG(DEBUG_NAME, thread_h, "back from preempting method w/thread"); + method_p->check_for_throws(); + } + + // CALLER IS A THREAD, BUT NOT THE THREAD TO BE RUN: + // + // (a) Push the calling thread onto the front of the runnable queue + // so it be the first thread to be run after this thread. + // (b) Push the thread to be run onto the front of the runnable queue so + // it will execute when we suspend the calling thread. + // (c) Suspend the active thread. + + else if ( active_p != thread_h ) + { + DEBUG_MSG( DEBUG_NAME, thread_h, + "preempting active thread with thread" ); + execute_thread_next( active_p ); + execute_thread_next( thread_h ); + active_p->suspend_me(); + } + + // CALLER IS THE THREAD TO BE RUN: + // + // (a) Push the thread to be run onto the front of the runnable queue so + // it will execute when we suspend the calling thread. + // (b) Suspend the active thread. + + else + { + DEBUG_MSG(DEBUG_NAME,thread_h,"self preemption of active thread"); + execute_thread_next( thread_h ); + active_p->suspend_me(); + } +} + + +inline +void +sc_simcontext::push_runnable_method( sc_method_handle method_h ) +{ + m_runnable->push_back_method( method_h ); +} + +inline +void +sc_simcontext::push_runnable_method_front( sc_method_handle method_h ) +{ + m_runnable->push_front_method( method_h ); +} + +inline +void +sc_simcontext::push_runnable_thread( sc_thread_handle thread_h ) +{ + m_runnable->push_back_thread( thread_h ); +} + +inline +void +sc_simcontext::push_runnable_thread_front( sc_thread_handle thread_h ) +{ + m_runnable->push_front_thread( thread_h ); +} + + +inline +sc_method_handle +sc_simcontext::pop_runnable_method() +{ + sc_method_handle method_h = m_runnable->pop_method(); + if( method_h == 0 ) { + reset_curr_proc(); + return 0; + } + set_curr_proc( (sc_process_b*)method_h ); + return method_h; +} + +inline +sc_thread_handle +sc_simcontext::pop_runnable_thread() +{ + sc_thread_handle thread_h = m_runnable->pop_thread(); + if( thread_h == 0 ) { + reset_curr_proc(); + return 0; + } + set_curr_proc( (sc_process_b*)thread_h ); + return thread_h; +} + +inline +void +sc_simcontext::remove_runnable_method( sc_method_handle method_h ) +{ + m_runnable->remove_method( method_h ); +} + +inline +void +sc_simcontext::remove_runnable_thread( sc_thread_handle thread_h ) +{ + m_runnable->remove_thread( thread_h ); +} + +inline +std::vector<sc_thread_handle>& +sc_simcontext::get_active_invokers() +{ + return m_active_invokers; +} + +// ---------------------------------------------------------------------------- + +extern void sc_defunct_process_function( sc_module* ); + + +} // namespace sc_core + +#undef DEBUG_MSG +#undef DEBUG_NAME + +// $Log: sc_simcontext_int.h,v $ +// Revision 1.14 2011/08/29 18:04:32 acg +// Philipp A. Hartmann: miscellaneous clean ups. +// +// Revision 1.13 2011/08/26 20:46:11 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +// Revision 1.12 2011/07/29 22:45:06 acg +// Andy Goodrich: added invocation of sc_method_process::check_for_throws() +// to the preempt_with() code to handle case where the preempting process +// causes a throw on the invoking method process. +// +// Revision 1.11 2011/04/13 02:45:11 acg +// Andy Goodrich: eliminated warning message that occurred if the DEBUG_MSG +// macro was used. +// +// Revision 1.10 2011/04/11 22:05:48 acg +// Andy Goodrich: use the DEBUG_NAME macro in DEBUG_MSG invocations. +// +// Revision 1.9 2011/04/10 22:12:32 acg +// Andy Goodrich: adding debugging macros. +// +// Revision 1.8 2011/04/08 18:26:07 acg +// Andy Goodrich: added execute_method_next() to handle method dispatch +// for asynchronous notifications that occur outside the evaluation phase. +// +// Revision 1.7 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.6 2011/02/13 21:47:38 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.5 2011/02/08 08:17:50 acg +// Andy Goodrich: fixed bug in preempt_with() where I was resetting the +// process context rather than saving and restoring it. +// +// Revision 1.4 2011/02/01 21:12:56 acg +// Andy Goodrich: addition of preempt_with() method to allow immediate +// execution of threads for throws. +// +// Revision 1.3 2011/01/25 20:50:37 acg +// Andy Goodrich: changes for IEEE 1666 2011. +// +// Revision 1.2 2008/05/22 17:06:26 acg +// Andy Goodrich: updated copyright notice to include 2008. +// +// Revision 1.1.1.1 2006/12/15 20:20:05 acg +// SystemC 2.3 +// +// Revision 1.6 2006/05/26 20:33:16 acg +// Andy Goodrich: changes required by additional platform compilers (i.e., +// Microsoft VC++, Sun Forte, HP aCC). +// +// Revision 1.5 2006/01/19 00:29:52 acg +// Andy Goodrich: Yet another implementation for signal write checking. This +// one uses an environment variable SC_SIGNAL_WRITE_CHECK, that when set to +// DISABLE will disable write checking on signals. +// +// Revision 1.4 2006/01/18 21:42:37 acg +// Andy Goodrich: Changes for check writer support. +// +// Revision 1.3 2006/01/13 18:44:30 acg +// Added $Log to record CVS changes into the source. + +#endif diff --git a/ext/systemc/src/sysc/kernel/sc_spawn.h b/ext/systemc/src/sysc/kernel/sc_spawn.h new file mode 100644 index 000000000..e54886929 --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_spawn.h @@ -0,0 +1,337 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_spawn.h -- Process spawning support. + + Original Authors: Andy Goodrich, Forte Design Systems, 17 June 2003 + Stuart Swan, Cadence, + Bishnupriya Bhattacharya, Cadence Design Systems, + 25 August, 2003 + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + + +#if !defined(sc_spawn_h_INCLUDED) +#define sc_spawn_h_INCLUDED + +#include "sysc/kernel/sc_process_handle.h" +#include "sysc/kernel/sc_spawn_options.h" + +namespace sc_core { + +class sc_event; +class sc_port_base; +class sc_interface; +class sc_event_finder; +class sc_process_b; + +//============================================================================= +// CLASS sc_spawn_object<T> +// +// This templated helper class allows an object to provide the execution +// semantics for a process via its () operator. An instance of the supplied +// execution object will be kept to provide the semantics when the process is +// scheduled for execution. The () operator does not return a value. An example +// of an object that might be used for this helper function would be void +// SC_BOOST bound function or method. +// +// This class is derived from sc_process_host and overloads +// sc_process_host::semantics to provide the actual semantic content. +// +// sc_spawn_object(T object, const char* name, const sc_spawn_options* opt_p) +// This is the object instance constructor for this class. It makes a +// copy of the supplied object. The tp_call constructor is called +// with an indication that this object instance should be reclaimed when +// execution completes. +// object = object whose () operator will be called to provide +// the process semantics. +// name_p = optional name for object instance, or zero. +// opt_p -> spawn options or zero. +// +// virtual void semantics() +// This virtual method provides the execution semantics for its process. +// It performs a () operation on m_object. +//============================================================================= +template<typename T> +class sc_spawn_object : public sc_process_host { + public: + sc_spawn_object( T object) : m_object(object) + { + } + + virtual void semantics() + { + m_object(); + } + + protected: + T m_object; +}; + + +//------------------------------------------------------------------------------ +//"sc_spawn - semantic object with no return value" +// +// This inline function spawns a process for execution. The execution semantics +// for the process being spawned will be provided by the supplied object +// instance via its () operator. (E.g., a SC_BOOST bound function) +// After creating the process it is registered with the simulator. +// object = object instance providing the execution semantics via its +// () operator. +// name_p = optional name for object instance, or zero. +// opt_p -> optional spawn options for process, or zero for the default. +//------------------------------------------------------------------------------ +template <typename T> +inline sc_process_handle sc_spawn( + T object, + const char* name_p = 0, + const sc_spawn_options* opt_p = 0) +{ + sc_simcontext* context_p; + sc_spawn_object<T>* spawn_p; + + context_p = sc_get_curr_simcontext(); + spawn_p = new sc_spawn_object<T>(object); + if ( !opt_p || !opt_p->is_method() ) + { + sc_process_handle thread_handle = context_p->create_thread_process( + name_p, true, + SC_MAKE_FUNC_PTR(sc_spawn_object<T>,semantics), + spawn_p, opt_p + ); + return thread_handle; + } + else + { + sc_process_handle method_handle = context_p->create_method_process( + name_p, true, + SC_MAKE_FUNC_PTR(sc_spawn_object<T>,semantics), + spawn_p, opt_p + ); + return method_handle; + } +} + +//============================================================================= +// CLASS sc_spawn_object_v<T> for all compilers except HP aCC +// or +// CLASS sc_spawn_object_v<T, R> for HP aCC which tries to match this +// one template argument class when the sc_spawn() declared above is +// invoked with 3 arguments or 2 arguments, and generates compiler errors. +// +// This templated helper class allows an object to provide the execution +// semantics for a process via its () operator. An instance of the supplied +// object will be kept to provide the semantics when the process is scheduled +// for execution. The () operator returns a value, which will be stored at the +// location specified by the supplied pointer. An example of an object that +// might be used for this helper function would be valued SC_BOOST bound +// function or method. +// +// sc_spawn_object_v( typename F::result_type* r_p, T f, const char* name_p, +// const sc_spawn_options* opt_p ) +// r_p -> where to place the result of the function invocation. +// f = information to be executed. +// name_p = optional name for object instance, or zero. +// opt_p -> optional spawn options for process, or zero for the default +// This is the object instance constructor for this class. It makes a +// copy of the supplied object. The tp_call constructor is called +// with an indication that this object instance should be reclaimed when +// execution completes. +// result_p -> where to place the value of the () operator. +// object = object whose () operator will be called to provide +// the process semantics. +// +// virtual void semantics() +// This virtual method provides the execution semantics for its process. +// It performs a () operation on m_object, placing the result at m_result_p. +//============================================================================= + +//------------------------------------------------------------------------------ +//"sc_spawn_object_v - semantic object with return value" +// +// This inline function spawns a process for execution. The execution semantics +// for the process being spawned will be provided by the supplied object +// instance via its () operator. (E.g., a SC_BOOST bound function) That +// operator returns a value, which will be placed in the supplied return +// location. +// After creating the process it is registered with the simulator. +// object = object instance providing the execution semantics via its () +// operator. +// r_p -> where to place the value of the () operator. +// name_p = optional name for object instance, or zero. +// opt_p -> optional spawn options for process, or zero for the default. +//------------------------------------------------------------------------------ + +#if !defined (__HP_aCC) + +template<typename T> +class sc_spawn_object_v : public sc_process_host { + public: + sc_spawn_object_v( typename T::result_type* r_p, T object ) : + m_object(object), m_result_p(r_p) + { + } + + virtual void semantics() + { + *m_result_p = m_object(); + } + + protected: + T m_object; + typename T::result_type* m_result_p; +}; + +template <typename T> +inline sc_process_handle sc_spawn( + typename T::result_type* r_p, + T object, + const char* name_p = 0, + const sc_spawn_options* opt_p = 0) +{ + sc_simcontext* context_p; + sc_spawn_object_v<T>* spawn_p; + + context_p = sc_get_curr_simcontext(); + + spawn_p = new sc_spawn_object_v<T>(r_p, object); + if ( !opt_p || !opt_p->is_method() ) + { + sc_process_handle thread_handle = context_p->create_thread_process( + name_p, true, + SC_MAKE_FUNC_PTR(sc_spawn_object_v<T>,semantics), + spawn_p, opt_p + ); + return thread_handle; + } + else + { + sc_process_handle method_handle = context_p->create_method_process( + name_p, true, + SC_MAKE_FUNC_PTR(sc_spawn_object_v<T>,semantics), + spawn_p, opt_p + ); + return method_handle; + } +} + +#else +// for HP aCC +template<typename T, typename R> +class sc_spawn_object_v : public sc_process_host { + public: + sc_spawn_object_v( R* r_p, T object) : + m_object(object), m_result_p(r_p) + { + } + + virtual void semantics() + { + *m_result_p = m_object(); + } + + protected: + T m_object; + R* m_result_p; +}; + +template <typename T, typename R> +inline sc_process_handle sc_spawn( + R* r_p, + T object, + const char* name_p = 0, + const sc_spawn_options* opt_p = 0) +{ + sc_simcontext* context_p; + sc_spawn_object_v<T,R>* spawn_p; + + context_p = sc_get_curr_simcontext(); + + spawn_p = new sc_spawn_object_v<T,R>(r_p, object); + if ( !opt_p || !opt_p->is_method() ) + { + sc_process_handle thread_handle = context_p->create_thread_process( + name_p, true, + static_cast<sc_core::SC_ENTRY_FUNC>( + &sc_spawn_object_v<T,R>::semantics), + spawn_p, opt_p + ); + return thread_handle; + } + else + { + sc_process_handle method_handle = context_p->create_method_process( + name_p, true, + static_cast<sc_core::SC_ENTRY_FUNC>( + &sc_spawn_object_v<T,R>::semantics), + spawn_p, opt_p + ); + return method_handle; + } +} + +#endif // HP + +} // namespace sc_core + +// $Log: sc_spawn.h,v $ +// Revision 1.7 2011/08/26 20:46:11 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +// Revision 1.6 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.5 2011/02/13 21:47:38 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.4 2011/02/01 21:14:02 acg +// Andy Goodrich: formatting. +// +// Revision 1.3 2009/07/28 01:10:53 acg +// Andy Goodrich: updates for 2.3 release candidate. +// +// Revision 1.2 2008/05/22 17:06:26 acg +// Andy Goodrich: updated copyright notice to include 2008. +// +// Revision 1.1.1.1 2006/12/15 20:20:05 acg +// SystemC 2.3 +// +// Revision 1.6 2006/05/26 20:33:16 acg +// Andy Goodrich: changes required by additional platform compilers (i.e., +// Microsoft VC++, Sun Forte, HP aCC). +// +// Revision 1.5 2006/05/08 18:01:44 acg +// Andy Goodrich: changed the HP-specific implementations of sc_spawn() to +// use a static_cast to create their entry functions rather than the +// SC_MAKE_FUNC_PTR macro. The HP preprocessor does not parse template +// arguments that contain a comma properly. +// +// Revision 1.4 2006/04/11 23:13:21 acg +// Andy Goodrich: Changes for reduced reset support that only includes +// sc_cthread, but has preliminary hooks for expanding to method and thread +// processes also. +// +// Revision 1.3 2006/01/13 18:44:30 acg +// Added $Log to record CVS changes into the source. + +#endif // !defined(sc_spawn_h_INCLUDED) diff --git a/ext/systemc/src/sysc/kernel/sc_spawn_options.cpp b/ext/systemc/src/sysc/kernel/sc_spawn_options.cpp new file mode 100644 index 000000000..c577f1d87 --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_spawn_options.cpp @@ -0,0 +1,124 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_spawn_options.cpp -- Process spawning options implementation. + + Original Authors: Andy Goodrich, Forte Design Systems, 17 June 2003 + Stuart Swan, Cadence, + Bishnupriya Bhattacharya, Cadence Design Systems, + 25 August, 2003 + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + +#include "sysc/kernel/sc_spawn_options.h" +#include "sysc/kernel/sc_reset.h" + +namespace sc_core { + +// +====================================================================== +// | CLASS sc_spawn_reset_base - Class to do a generic access to an +// | sc_spawn_rest object instance +// +====================================================================== +class sc_spawn_reset_base +{ + public: + sc_spawn_reset_base( bool async, bool level ) + : m_async( async ), m_level(level) + {} + virtual ~sc_spawn_reset_base() {} + virtual void specify_reset() = 0; + + protected: + bool m_async; // = true if async reset. + bool m_level; // level indicating reset. +}; + +// +====================================================================== +// | CLASS sc_spawn_reset<SOURCE> +// | - Reset specification for sc_spawn_options. +// +====================================================================== +template<typename SOURCE> +class sc_spawn_reset : public sc_spawn_reset_base +{ + public: + sc_spawn_reset( bool async, const SOURCE& source, bool level ) + : sc_spawn_reset_base(async, level), m_source(source) + {} + virtual ~sc_spawn_reset() {} + virtual void specify_reset() + { + sc_reset::reset_signal_is( m_async, m_source, m_level ); + } + + protected: + const SOURCE& m_source; // source of reset signal. +}; + +// +====================================================================== +// | CLASS sc_spawn_options (implementation) +// | +// +====================================================================== + +sc_spawn_options::~sc_spawn_options() +{ + std::vector<sc_spawn_reset_base*>::size_type resets_n = m_resets.size(); + for ( std::vector<sc_spawn_reset_base*>::size_type reset_i = 0; reset_i < resets_n; reset_i++ ) + delete m_resets[reset_i]; +} + +#define SC_DEFINE_RESET_SIGNALS( Port ) \ + /* asynchronous reset */ \ + void \ + sc_spawn_options:: \ + async_reset_signal_is ( const Port & port, bool level ) \ + { \ + m_resets.push_back( \ + new sc_spawn_reset< Port >(true, port, level) ); \ + } \ + /* sync reset */ \ + void \ + sc_spawn_options:: \ + reset_signal_is ( const Port & port, bool level ) \ + { \ + m_resets.push_back( \ + new sc_spawn_reset< Port >(false, port, level) ); \ + } + +SC_DEFINE_RESET_SIGNALS( sc_in<bool> ) +SC_DEFINE_RESET_SIGNALS( sc_inout<bool> ) +SC_DEFINE_RESET_SIGNALS( sc_out<bool> ) +SC_DEFINE_RESET_SIGNALS( sc_signal_in_if<bool> ) + +#undef SC_DEFINE_RESET_SIGNALS + +void +sc_spawn_options::specify_resets() const +{ + std::vector<sc_spawn_reset_base*>::size_type resets_n; // number of reset specifications to process. + resets_n = m_resets.size(); + for ( std::vector<sc_spawn_reset_base*>::size_type reset_i = 0; reset_i < resets_n; reset_i++ ) + m_resets[reset_i]->specify_reset(); +} + +} // namespace sc_core + +// Taf! diff --git a/ext/systemc/src/sysc/kernel/sc_spawn_options.h b/ext/systemc/src/sysc/kernel/sc_spawn_options.h new file mode 100644 index 000000000..4c3f64baa --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_spawn_options.h @@ -0,0 +1,161 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_spawn_options.h -- Process spawning options specification. + + Original Authors: Andy Goodrich, Forte Design Systems, 17 June 2003 + Stuart Swan, Cadence, + Bishnupriya Bhattacharya, Cadence Design Systems, + 25 August, 2003 + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + +#if !defined(sc_spawn_options_h_INCLUDED) +#define sc_spawn_options_h_INCLUDED + +#include <vector> +#include "sysc/communication/sc_export.h" +#include "sysc/communication/sc_signal_ports.h" + +namespace sc_core { + +class sc_event; +class sc_port_base; +class sc_interface; +class sc_event_finder; +class sc_process_b; +class sc_spawn_reset_base; + +//============================================================================= +// CLASS sc_spawn_options +// +//============================================================================= +class sc_spawn_options { + friend class sc_cthread_process; + friend class sc_method_process; + friend class sc_process_b; + friend class sc_thread_process; + public: + sc_spawn_options() : + m_dont_initialize(false), m_resets(), m_sensitive_events(), + m_sensitive_event_finders(), m_sensitive_interfaces(), + m_sensitive_port_bases(), m_spawn_method(false), m_stack_size(0) + { } + + ~sc_spawn_options(); + + void async_reset_signal_is( const sc_in<bool>&, bool level ); + void async_reset_signal_is( const sc_inout<bool>&, bool level ); + void async_reset_signal_is( const sc_out<bool>&, bool level ); + void async_reset_signal_is( const sc_signal_in_if<bool>&, bool level ); + + void reset_signal_is( const sc_in<bool>&, bool level ); + void reset_signal_is( const sc_inout<bool>&, bool level ); + void reset_signal_is( const sc_out<bool>&, bool level ); + void reset_signal_is( const sc_signal_in_if<bool>&, bool level ); + + void dont_initialize() { m_dont_initialize = true; } + + bool is_method() const { return m_spawn_method; } + + void set_stack_size(int stack_size) { m_stack_size = stack_size; } + + void set_sensitivity(const sc_event* event) + { m_sensitive_events.push_back(event); } + + void set_sensitivity(sc_port_base* port_base) + { m_sensitive_port_bases.push_back(port_base); } + + void set_sensitivity(sc_interface* interface_p) + { m_sensitive_interfaces.push_back(interface_p); } + + void set_sensitivity(sc_export_base* export_base) + { m_sensitive_interfaces.push_back(export_base->get_interface()); } + + void set_sensitivity(sc_event_finder* event_finder) + { m_sensitive_event_finders.push_back(event_finder); } + + void spawn_method() { m_spawn_method = true; } + + protected: + void specify_resets() const; + + private: + sc_spawn_options( const sc_spawn_options& ); + const sc_spawn_options& operator = ( const sc_spawn_options& ); + + protected: + bool m_dont_initialize; + std::vector<sc_spawn_reset_base*> m_resets; + std::vector<const sc_event*> m_sensitive_events; + std::vector<sc_event_finder*> m_sensitive_event_finders; + std::vector<sc_interface*> m_sensitive_interfaces; + std::vector<sc_port_base*> m_sensitive_port_bases; + bool m_spawn_method; // Method not thread. + int m_stack_size; // Thread stack size. +}; + +} // namespace sc_core + +// $Log: sc_spawn_options.h,v $ +// Revision 1.11 2011/08/26 20:46:11 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +// Revision 1.10 2011/08/24 22:05:51 acg +// Torsten Maehne: initialization changes to remove warnings. +// +// Revision 1.9 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.8 2011/02/13 21:47:38 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.7 2011/02/07 19:17:20 acg +// Andy Goodrich: changes for IEEE 1666 compatibility. +// +// Revision 1.6 2010/12/07 20:09:15 acg +// Andy Goodrich: replaced sc_signal signatures with sc_signal_in_if signatures for reset methods. +// +// Revision 1.5 2010/11/20 17:10:57 acg +// Andy Goodrich: reset processing changes for new IEEE 1666 standard. +// +// Revision 1.4 2009/05/22 16:06:29 acg +// Andy Goodrich: process control updates. +// +// Revision 1.3 2009/02/28 00:26:58 acg +// Andy Goodrich: changed boost name space to sc_boost to allow use with +// full boost library applications. +// +// Revision 1.2 2008/05/22 17:06:26 acg +// Andy Goodrich: updated copyright notice to include 2008. +// +// Revision 1.1.1.1 2006/12/15 20:20:05 acg +// SystemC 2.3 +// +// Revision 1.4 2006/04/20 17:08:17 acg +// Andy Goodrich: 3.0 style process changes. +// +// Revision 1.3 2006/01/13 18:44:30 acg +// Added $Log to record CVS changes into the source. + +#endif // !defined(sc_spawn_options_h_INCLUDED) diff --git a/ext/systemc/src/sysc/kernel/sc_status.h b/ext/systemc/src/sysc/kernel/sc_status.h new file mode 100644 index 000000000..1d3b016db --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_status.h @@ -0,0 +1,83 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_status.h -- Definition of the simulation phases + + Original Author: Philipp A. Hartmann, OFFIS, 2013-02-15 + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + +#ifndef SC_STATUS_H_INCLUDED_ +#define SC_STATUS_H_INCLUDED_ + +#include <iosfwd> + +namespace sc_core { + +// simulation status codes + +const int SC_SIM_OK = 0; +const int SC_SIM_ERROR = 1; +const int SC_SIM_USER_STOP = 2; + +enum sc_status +{ // sc_get_status values: + SC_UNITIALIZED=0x00, // initialize() not called yet + + SC_ELABORATION = 0x01, // during module hierarchy construction + SC_BEFORE_END_OF_ELABORATION = 0x02, // during before_end_of_elaboration() + SC_END_OF_ELABORATION = 0x04, // during end_of_elaboration() + SC_START_OF_SIMULATION = 0x08, // during start_of_simulation() + + SC_RUNNING = 0x10, // initialization, evaluation or update + SC_PAUSED = 0x20, // when scheduler stopped by sc_pause() + SC_STOPPED = 0x40, // when scheduler stopped by sc_stop() + SC_END_OF_SIMULATION = 0x80, // during end_of_simulation() + + // detailed simulation phases (for dynamic callbacks) + SC_END_OF_INITIALIZATION = 0x100, // after initialization +// SC_END_OF_EVALUATION = 0x200, // between eval and update + SC_END_OF_UPDATE = 0x400, // after update/notify phase + SC_BEFORE_TIMESTEP = 0x800, // before next time step + + SC_STATUS_LAST = SC_BEFORE_TIMESTEP, + SC_STATUS_ANY = 0xdff +}; + +// pretty-printing of sc_status values +std::ostream& operator << ( std::ostream&, sc_status ); + +} // namespace sc_core + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + +#endif /* SC_STATUS_H_INCLUDED_ */ +// Taf! + diff --git a/ext/systemc/src/sysc/kernel/sc_thread_process.cpp b/ext/systemc/src/sysc/kernel/sc_thread_process.cpp new file mode 100644 index 000000000..140096c95 --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_thread_process.cpp @@ -0,0 +1,1127 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_thread_process.cpp -- Thread process implementation + + Original Author: Andy Goodrich, Forte Design Systems, 4 August 2005 + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + +#include "sysc/kernel/sc_cmnhdr.h" +#include "sysc/kernel/sc_constants.h" +#include "sysc/kernel/sc_thread_process.h" +#include "sysc/kernel/sc_process_handle.h" +#include "sysc/kernel/sc_simcontext_int.h" +#include "sysc/kernel/sc_module.h" +#include "sysc/utils/sc_machine.h" + +// DEBUGGING MACROS: +// +// DEBUG_MSG(NAME,P,MSG) +// MSG = message to print +// NAME = name that must match the process for the message to print, or +// null if the message should be printed unconditionally. +// P = pointer to process message is for, or NULL in which case the +// message will not print. +#if 0 +# define DEBUG_NAME "" +# define DEBUG_MSG(NAME,P,MSG) \ + { \ + if ( P && ( (strlen(NAME)==0) || !strcmp(NAME,P->name())) ) \ + std::cout << "**** " << sc_time_stamp() << " (" \ + << sc_get_current_process_name() << "): " << MSG \ + << " - " << P->name() << std::endl; \ + } +#else +# define DEBUG_MSG(NAME,P,MSG) +#endif + + +//------------------------------------------------------------------------------ +// user-defined default stack-size +//------------------------------------------------------------------------------ +#if defined(SC_OVERRIDE_DEFAULT_STACK_SIZE) +# define SC_DEFAULT_STACK_SIZE_ SC_OVERRIDE_DEFAULT_STACK_SIZE + +//------------------------------------------------------------------------------ +// architecture-specific default stack sizes +//------------------------------------------------------------------------------ +#elif !defined(SC_USE_PTHREADS) && (defined(__CYGWIN32__) || defined(__CYGWIN32)) +# define SC_DEFAULT_STACK_SIZE_ 0x50000 + +#elif defined(SC_LONG_64) || defined(__x86_64__) || defined(__LP64__) || \ + defined(_M_X64) || defined(_M_AMD64) +# define SC_DEFAULT_STACK_SIZE_ 0x40000 + +#else +# define SC_DEFAULT_STACK_SIZE_ 0x20000 + +#endif // SC_DEFAULT_STACK_SIZE_ + + +//------------------------------------------------------------------------------ +// force 16-byte alignment on coroutine entry functions, needed for +// QuickThreads (32-bit, see also fixes in qt/md/{i386,iX86_64}.[hs]), +// and MinGW32 / Cygwin32 compilers on Windows platforms +#if defined(__GNUC__) && !defined(__ICC) && !defined(__x86_64__) && \ + (__GNUC__ > 4 || __GNUC__ == 4 && __GNUC_MINOR__ > 1 ) +# define SC_ALIGNED_STACK_ \ + __attribute__((force_align_arg_pointer)) +#else +# define SC_ALIGNED_STACK_ /* empty */ +#endif + + +namespace sc_core { + +const int SC_DEFAULT_STACK_SIZE = SC_DEFAULT_STACK_SIZE_; +#undef SC_DEFAULT_STACK_SIZE_ +#undef SC_OVERRIDE_DEFAULT_STACK_SIZE + +//------------------------------------------------------------------------------ +//"sc_thread_cor_fn" +// +// This function invokes the coroutine for the supplied object instance. +//------------------------------------------------------------------------------ +SC_ALIGNED_STACK_ +void sc_thread_cor_fn( void* arg ) +{ + sc_simcontext* simc_p = sc_get_curr_simcontext(); + sc_thread_handle thread_h = RCAST<sc_thread_handle>( arg ); + + // PROCESS THE THREAD AND PROCESS ANY EXCEPTIONS THAT ARE THROWN: + + while( true ) { + + try { + thread_h->semantics(); + } + catch( sc_user ) { + continue; + } + catch( sc_halt ) { + ::std::cout << "Terminating process " + << thread_h->name() << ::std::endl; + } + catch( const sc_unwind_exception& ex ) { + ex.clear(); + if ( ex.is_reset() ) continue; + } + catch( ... ) { + sc_report* err_p = sc_handle_exception(); + thread_h->simcontext()->set_error( err_p ); + } + break; + } + + sc_process_b* active_p = sc_get_current_process_b(); + + // REMOVE ALL TRACES OF OUR THREAD FROM THE SIMULATORS DATA STRUCTURES: + + thread_h->disconnect_process(); + + // IF WE AREN'T ACTIVE MAKE SURE WE WON'T EXECUTE: + + if ( thread_h->next_runnable() != 0 ) + { + simc_p->remove_runnable_thread(thread_h); + } + + // IF WE ARE THE ACTIVE PROCESS ABORT OUR EXECUTION: + + + if ( active_p == (sc_process_b*)thread_h ) + { + + sc_core::sc_cor* x = simc_p->next_cor(); + simc_p->cor_pkg()->abort( x ); + } + +} + + +//------------------------------------------------------------------------------ +//"sc_thread_process::disable_process" +// +// This virtual method suspends this process and its children if requested to. +// descendants = indicator of whether this process' children should also +// be suspended +//------------------------------------------------------------------------------ +void sc_thread_process::disable_process( + sc_descendant_inclusion_info descendants ) +{ + + // IF NEEDED PROPOGATE THE DISABLE REQUEST THROUGH OUR DESCENDANTS: + + if ( descendants == SC_INCLUDE_DESCENDANTS ) + { + const std::vector<sc_object*>& children = get_child_objects(); + int child_n = children.size(); + + for ( int child_i = 0; child_i < child_n; child_i++ ) + { + sc_process_b* child_p = DCAST<sc_process_b*>(children[child_i]); + if ( child_p ) child_p->disable_process(descendants); + } + } + + // DON'T ALLOW CORNER CASE BY DEFAULT: + + if ( !sc_allow_process_control_corners ) + { + switch( m_trigger_type ) + { + case AND_LIST_TIMEOUT: + case EVENT_TIMEOUT: + case OR_LIST_TIMEOUT: + case TIMEOUT: + report_error(SC_ID_PROCESS_CONTROL_CORNER_CASE_, + "attempt to disable a thread with timeout wait"); + break; + default: + break; + } + } + + // DISABLE OUR OBJECT INSTANCE: + + m_state = m_state | ps_bit_disabled; + + // IF THIS CALL IS BEFORE THE SIMULATION DON'T RUN THE THREAD: + + if ( !sc_is_running() ) + { + m_state = m_state | ps_bit_ready_to_run; + simcontext()->remove_runnable_thread(this); + } +} + +//------------------------------------------------------------------------------ +//"sc_thread_process::enable_process" +// +// This method resumes the execution of this process, and if requested, its +// descendants. If the process was suspended and has a resumption pending it +// will be dispatched in the next delta cycle. Otherwise the state will be +// adjusted to indicate it is no longer suspended, but no immediate execution +// will occur. +//------------------------------------------------------------------------------ +void sc_thread_process::enable_process( + sc_descendant_inclusion_info descendants ) +{ + + // IF NEEDED PROPOGATE THE ENABLE REQUEST THROUGH OUR DESCENDANTS: + + if ( descendants == SC_INCLUDE_DESCENDANTS ) + { + const std::vector<sc_object*>& children = get_child_objects(); + int child_n = children.size(); + + for ( int child_i = 0; child_i < child_n; child_i++ ) + { + sc_process_b* child_p = DCAST<sc_process_b*>(children[child_i]); + if ( child_p ) child_p->enable_process(descendants); + } + } + + // ENABLE THIS OBJECT INSTANCE: + // + // If it was disabled and ready to run then put it on the run queue. + + m_state = m_state & ~ps_bit_disabled; + if ( m_state == ps_bit_ready_to_run && sc_allow_process_control_corners ) + { + m_state = ps_normal; + if ( next_runnable() == 0 ) + simcontext()->push_runnable_thread(this); + } +} + + +//------------------------------------------------------------------------------ +//"sc_thread_process::kill_process" +// +// This method removes this object instance from use. It calls the +// sc_process_b::kill_process() method to perform low level clean up. Then +// it aborts this process if it is the active process. +//------------------------------------------------------------------------------ +void sc_thread_process::kill_process(sc_descendant_inclusion_info descendants ) +{ + + // IF THE SIMULATION HAS NOT BEEN INITIALIZED YET THAT IS AN ERROR: + + if ( !sc_is_running() ) + { + report_error( SC_ID_KILL_PROCESS_WHILE_UNITIALIZED_ ); + } + + // IF NEEDED PROPOGATE THE KILL REQUEST THROUGH OUR DESCENDANTS: + + if ( descendants == SC_INCLUDE_DESCENDANTS ) + { + const std::vector<sc_object*> children = get_child_objects(); + int child_n = children.size(); + + for ( int child_i = 0; child_i < child_n; child_i++ ) + { + sc_process_b* child_p = DCAST<sc_process_b*>(children[child_i]); + if ( child_p ) child_p->kill_process(descendants); + } + } + + // IF THE PROCESS IS CURRENTLY UNWINDING OR IS ALREADY A ZOMBIE + // IGNORE THE KILL: + + if ( m_unwinding ) + { + SC_REPORT_WARNING( SC_ID_PROCESS_ALREADY_UNWINDING_, name() ); + return; + } + + if ( m_state & ps_bit_zombie ) + return; + + // SET UP TO KILL THE PROCESS IF SIMULATION HAS STARTED: + // + // If the thread does not have a stack don't try the throw! + + if ( sc_is_running() && m_has_stack ) + { + m_throw_status = THROW_KILL; + m_wait_cycle_n = 0; + simcontext()->preempt_with(this); + } + + // IF THE SIMULATION HAS NOT STARTED REMOVE TRACES OF OUR PROCESS FROM + // EVENT QUEUES, ETC.: + + else + { + disconnect_process(); + } +} + +//------------------------------------------------------------------------------ +//"sc_thread_process::prepare_for_simulation" +// +// This method prepares this object instance for simulation. It calls the +// coroutine package to create the actual thread. +//------------------------------------------------------------------------------ +void sc_thread_process::prepare_for_simulation() +{ + m_cor_p = simcontext()->cor_pkg()->create( m_stack_size, + sc_thread_cor_fn, this ); + m_cor_p->stack_protect( true ); +} + + +//------------------------------------------------------------------------------ +//"sc_thread_process::resume_process" +// +// This method resumes the execution of this process, and if requested, its +// descendants. If the process was suspended and has a resumption pending it +// will be dispatched in the next delta cycle. Otherwise the state will be +// adjusted to indicate it is no longer suspended, but no immediate execution +// will occur. +//------------------------------------------------------------------------------ +void sc_thread_process::resume_process( + sc_descendant_inclusion_info descendants ) +{ + + // IF NEEDED PROPOGATE THE RESUME REQUEST THROUGH OUR DESCENDANTS: + + if ( descendants == SC_INCLUDE_DESCENDANTS ) + { + const std::vector<sc_object*>& children = get_child_objects(); + int child_n = children.size(); + + for ( int child_i = 0; child_i < child_n; child_i++ ) + { + sc_process_b* child_p = DCAST<sc_process_b*>(children[child_i]); + if ( child_p ) child_p->resume_process(descendants); + } + } + + // BY DEFAULT THE CORNER CASE IS AN ERROR: + + if ( !sc_allow_process_control_corners && (m_state & ps_bit_disabled) && + (m_state & ps_bit_suspended) ) + { + m_state = m_state & ~ps_bit_suspended; + report_error(SC_ID_PROCESS_CONTROL_CORNER_CASE_, + "call to resume() on a disabled suspended thread"); + } + + // CLEAR THE SUSPENDED BIT: + + m_state = m_state & ~ps_bit_suspended; + + // RESUME OBJECT INSTANCE IF IT IS READY TO RUN: + + if ( m_state & ps_bit_ready_to_run ) + { + m_state = m_state & ~ps_bit_ready_to_run; + if ( next_runnable() == 0 ) + simcontext()->push_runnable_thread(this); + remove_dynamic_events(); // order important. + } +} + +//------------------------------------------------------------------------------ +//"sc_thread_process::sc_thread_process" +// +// This is the object instance constructor for this class. +//------------------------------------------------------------------------------ +sc_thread_process::sc_thread_process( const char* name_p, bool free_host, + SC_ENTRY_FUNC method_p, sc_process_host* host_p, + const sc_spawn_options* opt_p +): + sc_process_b( + name_p ? name_p : sc_gen_unique_name("thread_p"), + true, free_host, method_p, host_p, opt_p), + m_cor_p(0), m_monitor_q(), m_stack_size(SC_DEFAULT_STACK_SIZE), + m_wait_cycle_n(0) +{ + + // CHECK IF THIS IS AN sc_module-BASED PROCESS AND SIMULATION HAS STARTED: + + if ( DCAST<sc_module*>(host_p) != 0 && sc_is_running() ) + { + report_error( SC_ID_MODULE_THREAD_AFTER_START_ ); + } + + // INITIALIZE VALUES: + // + // If there are spawn options use them. + + m_process_kind = SC_THREAD_PROC_; + + if (opt_p) { + m_dont_init = opt_p->m_dont_initialize; + if ( opt_p->m_stack_size ) m_stack_size = opt_p->m_stack_size; + + // traverse event sensitivity list + for (unsigned int i = 0; i < opt_p->m_sensitive_events.size(); i++) { + sc_sensitive::make_static_sensitivity( + this, *opt_p->m_sensitive_events[i]); + } + + // traverse port base sensitivity list + for ( unsigned int i = 0; i < opt_p->m_sensitive_port_bases.size(); i++) + { + sc_sensitive::make_static_sensitivity( + this, *opt_p->m_sensitive_port_bases[i]); + } + + // traverse interface sensitivity list + for ( unsigned int i = 0; i < opt_p->m_sensitive_interfaces.size(); i++) + { + sc_sensitive::make_static_sensitivity( + this, *opt_p->m_sensitive_interfaces[i]); + } + + // traverse event finder sensitivity list + for ( unsigned int i = 0; i < opt_p->m_sensitive_event_finders.size(); + i++) + { + sc_sensitive::make_static_sensitivity( + this, *opt_p->m_sensitive_event_finders[i]); + } + + // process any reset signal specification: + + opt_p->specify_resets(); + + } + + else + { + m_dont_init = false; + } + +} + +//------------------------------------------------------------------------------ +//"sc_thread_process::~sc_thread_process" +// +// This is the object instance constructor for this class. +//------------------------------------------------------------------------------ +sc_thread_process::~sc_thread_process() +{ + + // DESTROY THE COROUTINE FOR THIS THREAD: + + if( m_cor_p != 0 ) { + m_cor_p->stack_protect( false ); + delete m_cor_p; + m_cor_p = 0; + } +} + + +//------------------------------------------------------------------------------ +//"sc_thread_process::signal_monitors" +// +// This methods signals the list of monitors for this object instance. +//------------------------------------------------------------------------------ +void sc_thread_process::signal_monitors(int type) +{ + int mon_n; // # of monitors present. + + mon_n = m_monitor_q.size(); + for ( int mon_i = 0; mon_i < mon_n; mon_i++ ) + m_monitor_q[mon_i]->signal(this, type); +} + + +//------------------------------------------------------------------------------ +//"sc_thread_process::suspend_process" +// +// This virtual method suspends this process and its children if requested to. +// descendants = indicator of whether this process' children should also +// be suspended +//------------------------------------------------------------------------------ +void sc_thread_process::suspend_process( + sc_descendant_inclusion_info descendants ) +{ + + // IF NEEDED PROPOGATE THE SUSPEND REQUEST THROUGH OUR DESCENDANTS: + + if ( descendants == SC_INCLUDE_DESCENDANTS ) + { + const std::vector<sc_object*>& children = get_child_objects(); + int child_n = children.size(); + + for ( int child_i = 0; child_i < child_n; child_i++ ) + { + sc_process_b* child_p = DCAST<sc_process_b*>(children[child_i]); + if ( child_p ) child_p->suspend_process(descendants); + } + } + + // CORNER CASE CHECKS, THE FOLLOWING ARE ERRORS: + // (a) if this thread has a reset_signal_is specification + // (b) if this thread is in synchronous reset + + if ( !sc_allow_process_control_corners && m_has_reset_signal ) + { + report_error(SC_ID_PROCESS_CONTROL_CORNER_CASE_, + "attempt to suspend a thread that has a reset signal"); + } + else if ( !sc_allow_process_control_corners && m_sticky_reset ) + { + report_error(SC_ID_PROCESS_CONTROL_CORNER_CASE_, + "attempt to suspend a thread in synchronous reset"); + } + + // SUSPEND OUR OBJECT INSTANCE: + // + // (1) If we are on the runnable queue then set suspended and ready_to_run, + // and remove ourselves from the run queue. + // (2) If this is a self-suspension then a resume should cause immediate + // scheduling of the process, and we need to call suspend_me() here. + + m_state = m_state | ps_bit_suspended; + if ( next_runnable() != 0 ) + { + m_state = m_state | ps_bit_ready_to_run; + simcontext()->remove_runnable_thread( this ); + } + if ( sc_get_current_process_b() == DCAST<sc_process_b*>(this) ) + { + m_state = m_state | ps_bit_ready_to_run; + suspend_me(); + } +} + +//------------------------------------------------------------------------------ +//"sc_thread_process::throw_reset" +// +// This virtual method is invoked when an reset is to be thrown. The +// method will cancel any dynamic waits. If the reset is asynchronous it will +// queue this object instance to be executed. +//------------------------------------------------------------------------------ +void sc_thread_process::throw_reset( bool async ) +{ + // IF THE PROCESS IS CURRENTLY UNWINDING OR IS ALREADY A ZOMBIE + // IGNORE THE RESET: + + if ( m_unwinding ) + { + SC_REPORT_WARNING( SC_ID_PROCESS_ALREADY_UNWINDING_, name() ); + return; + } + + if ( m_state & ps_bit_zombie ) + return; + + + // Set the throw type and clear any pending dynamic events: + + m_throw_status = async ? THROW_ASYNC_RESET : THROW_SYNC_RESET; + m_wait_cycle_n = 0; + + // If this is an asynchronous reset: + // + // (a) Cancel any dynamic events + // (b) Set the thread up for execution: + // (i) If we are in the execution phase do it now. + // (ii) If we are not queue it to execute next when we hit + // the execution phase. + + if ( async ) + { + m_state = m_state & ~ps_bit_ready_to_run; + remove_dynamic_events(); + if ( simcontext()->evaluation_phase() ) + { + simcontext()->preempt_with( this ); + } + else + { + if ( is_runnable() ) + simcontext()->remove_runnable_thread(this); + simcontext()->execute_thread_next(this); + } + } +} + + +//------------------------------------------------------------------------------ +//"sc_thread_process::throw_user" +// +// This virtual method is invoked when a user exception is to be thrown. +// If requested it will also throw the exception to the children of this +// object instance. The order of dispatch for the processes that are +// thrown the exception is from youngest child to oldest child and then +// this process instance. This means that this instance will be pushed onto +// the front of the simulator's runnable queue and then the children will +// be processed recursively. +// helper_p = helper object to use to throw the exception. +// descendants = indicator of whether this process' children should also +// be suspended +//------------------------------------------------------------------------------ +void sc_thread_process::throw_user( const sc_throw_it_helper& helper, + sc_descendant_inclusion_info descendants ) +{ + + // IF THE SIMULATION IS NOT ACTAULLY RUNNING THIS IS AN ERROR: + + if ( sc_get_status() != SC_RUNNING ) + { + report_error( SC_ID_THROW_IT_WHILE_NOT_RUNNING_ ); + } + + // IF NEEDED PROPOGATE THE THROW REQUEST THROUGH OUR DESCENDANTS: + + if ( descendants == SC_INCLUDE_DESCENDANTS ) + { + const std::vector<sc_object*> children = get_child_objects(); + int child_n = children.size(); + + for ( int child_i = 0; child_i < child_n; child_i++ ) + { + sc_process_b* child_p = DCAST<sc_process_b*>(children[child_i]); + if ( child_p ) + { + DEBUG_MSG(DEBUG_NAME,child_p,"about to throw user on"); + child_p->throw_user(helper, descendants); + } + } + } + + // IF THE PROCESS IS CURRENTLY UNWINDING IGNORE THE THROW: + + if ( m_unwinding ) + { + SC_REPORT_WARNING( SC_ID_PROCESS_ALREADY_UNWINDING_, name() ); + return; + } + + // SET UP THE THROW REQUEST FOR THIS OBJECT INSTANCE AND QUEUE IT FOR + // EXECUTION: + + if( m_has_stack ) + { + remove_dynamic_events(); + DEBUG_MSG(DEBUG_NAME,this,"throwing user exception to"); + m_throw_status = THROW_USER; + if ( m_throw_helper_p != 0 ) delete m_throw_helper_p; + m_throw_helper_p = helper.clone(); + simcontext()->preempt_with( this ); + } + else + { + SC_REPORT_WARNING( SC_ID_THROW_IT_IGNORED_, name() ); + } +} + + +//------------------------------------------------------------------------------ +//"sc_thread_process::trigger_dynamic" +// +// This method sets up a dynamic trigger on an event. +// +// Notes: +// (1) This method is identical to sc_method_process::trigger_dynamic(), +// but they cannot be combined as sc_process_b::trigger_dynamic() +// because the signatures things like sc_event::remove_dynamic() +// have different overloads for sc_thread_process* and sc_method_process*. +// So if you change code here you'll also need to change it in +// sc_method_process.cpp. +// +// Result is true if this process should be removed from the event's list, +// false if not. +//------------------------------------------------------------------------------ +bool sc_thread_process::trigger_dynamic( sc_event* e ) +{ + // No time outs yet, and keep gcc happy. + + m_timed_out = false; + + // Escape cases: + // (a) If this thread issued the notify() don't schedule it for + // execution, but leave the sensitivity in place. + // (b) If this thread is already runnable can't trigger an event. + + // not possible for thread processes! +#if 0 // ! defined( SC_ENABLE_IMMEDIATE_SELF_NOTIFICATIONS ) + if ( sc_get_current_process_b() == (sc_process_b*)this ) + { + report_immediate_self_notification(); + return false; + } +#endif // SC_ENABLE_IMMEDIATE_SELF_NOTIFICATIONS + + if( is_runnable() ) + return true; + + // If a process is disabled then we ignore any events, leaving them enabled: + // + // But if this is a time out event we need to remove both it and the + // event that was being waited for. + + if ( m_state & ps_bit_disabled ) + { + if ( e == m_timeout_event_p ) + { + remove_dynamic_events( true ); + return true; + } + else + { + return false; + } + } + + + // Process based on the event type and current process state: + // + // Every case needs to set 'rc' and continue on to the end of + // this method to allow suspend processing to work correctly. + + switch( m_trigger_type ) + { + case EVENT: + m_event_p = 0; + m_trigger_type = STATIC; + break; + + case AND_LIST: + -- m_event_count; + if ( m_event_count == 0 ) + { + m_event_list_p->auto_delete(); + m_event_list_p = 0; + m_trigger_type = STATIC; + } + else + { + return true; + } + break; + + case OR_LIST: + m_event_list_p->remove_dynamic( this, e ); + m_event_list_p->auto_delete(); + m_event_list_p = 0; + m_trigger_type = STATIC; + break; + + case TIMEOUT: + m_trigger_type = STATIC; + break; + + case EVENT_TIMEOUT: + if ( e == m_timeout_event_p ) + { + m_timed_out = true; + m_event_p->remove_dynamic( this ); + m_event_p = 0; + m_trigger_type = STATIC; + } + else + { + m_timeout_event_p->cancel(); + m_timeout_event_p->reset(); + m_event_p = 0; + m_trigger_type = STATIC; + } + break; + + case OR_LIST_TIMEOUT: + if ( e == m_timeout_event_p ) + { + m_timed_out = true; + m_event_list_p->remove_dynamic( this, e ); + m_event_list_p->auto_delete(); + m_event_list_p = 0; + m_trigger_type = STATIC; + } + + else + { + m_timeout_event_p->cancel(); + m_timeout_event_p->reset(); + m_event_list_p->remove_dynamic( this, e ); + m_event_list_p->auto_delete(); + m_event_list_p = 0; + m_trigger_type = STATIC; + } + break; + + case AND_LIST_TIMEOUT: + if ( e == m_timeout_event_p ) + { + m_timed_out = true; + m_event_list_p->remove_dynamic( this, e ); + m_event_list_p->auto_delete(); + m_event_list_p = 0; + m_trigger_type = STATIC; + } + + else + { + -- m_event_count; + if ( m_event_count == 0 ) + { + m_timeout_event_p->cancel(); + m_timeout_event_p->reset(); + // no need to remove_dynamic + m_event_list_p->auto_delete(); + m_event_list_p = 0; + m_trigger_type = STATIC; + } + else + { + return true; + } + } + break; + + case STATIC: { + // we should never get here, but throw_it() can make it happen. + SC_REPORT_WARNING(SC_ID_NOT_EXPECTING_DYNAMIC_EVENT_NOTIFY_, name()); + return true; + } + } + + // If we get here then the thread is has satisfied its wait criteria, if + // its suspended mark its state as ready to run. If its not suspended then + // push it onto the runnable queue. + + if ( (m_state & ps_bit_suspended) ) + { + m_state = m_state | ps_bit_ready_to_run; + } + else + { + simcontext()->push_runnable_thread(this); + } + + return true; +} + + +//------------------------------------------------------------------------------ +//"sc_set_stack_size" +// +//------------------------------------------------------------------------------ +void +sc_set_stack_size( sc_thread_handle thread_h, std::size_t size ) +{ + thread_h->set_stack_size( size ); +} + +#undef DEBUG_MSG +#undef DEBUG_NAME + +} // namespace sc_core + + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + +// $Log: sc_thread_process.cpp,v $ +// Revision 1.57 2011/08/24 22:05:51 acg +// Torsten Maehne: initialization changes to remove warnings. +// +// Revision 1.56 2011/08/07 19:08:04 acg +// Andy Goodrich: moved logs to end of file so line number synching works +// better between versions. +// +// Revision 1.55 2011/08/04 17:16:22 acg +// Philipp A. Hartmann: fix handling of child objects in kill routine, need +// to use a copy rather than a reference. +// +// Revision 1.53 2011/07/29 22:45:38 acg +// Philipp A. Hartmann: changes to handle case where a process control +// invocation on a child process causes the list of child processes to change. +// +// Revision 1.52 2011/07/24 11:27:04 acg +// Andy Goodrich: moved the check for unwinding processes until after the +// descendants have been processed in throw_user and kill. +// +// Revision 1.51 2011/07/24 11:20:03 acg +// Philipp A. Hartmann: process control error message improvements: +// (1) Downgrade error to warning for re-kills of processes. +// (2) Add process name to process messages. +// (3) drop some superfluous colons in messages. +// +// Revision 1.50 2011/05/09 04:07:49 acg +// Philipp A. Hartmann: +// (1) Restore hierarchy in all phase callbacks. +// (2) Ensure calls to before_end_of_elaboration. +// +// Revision 1.49 2011/05/05 17:45:27 acg +// Philip A. Hartmann: changes in WIN64 support. +// Andy Goodrich: additional DEBUG_MSG instances to trace process handling. +// +// Revision 1.48 2011/04/19 15:04:27 acg +// Philipp A. Hartmann: clean up SC_ID messages. +// +// Revision 1.47 2011/04/19 02:39:09 acg +// Philipp A. Hartmann: added checks for additional throws during stack unwinds. +// +// Revision 1.46 2011/04/14 22:33:43 acg +// Andy Goodrich: added missing checks for a process being a zombie. +// +// Revision 1.45 2011/04/13 02:45:11 acg +// Andy Goodrich: eliminated warning message that occurred if the DEBUG_MSG +// macro was used. +// +// Revision 1.44 2011/04/11 22:04:33 acg +// Andy Goodrich: use the DEBUG_NAME macro for DEBUG_MSG messages. +// +// Revision 1.43 2011/04/10 22:12:32 acg +// Andy Goodrich: adding debugging macros. +// +// Revision 1.42 2011/04/08 22:40:26 acg +// Andy Goodrich: moved the reset event notification code out of throw_reset() +// and into suspend_me. +// +// Revision 1.41 2011/04/08 18:24:07 acg +// Andy Goodrich: fix asynchronous reset dispatch and when the reset_event() +// is fired. +// +// Revision 1.40 2011/04/05 20:50:57 acg +// Andy Goodrich: +// (1) changes to make sure that event(), posedge() and negedge() only +// return true if the clock has not moved. +// (2) fixes for method self-resumes. +// (3) added SC_PRERELEASE_VERSION +// (4) removed kernel events from the object hierarchy, added +// sc_hierarchy_name_exists(). +// +// Revision 1.39 2011/04/01 22:30:39 acg +// Andy Goodrich: change hard assertion to warning for trigger_dynamic() +// getting called when there is only STATIC sensitivity. This can result +// because of sc_process_handle::throw_it(). +// +// Revision 1.38 2011/03/23 16:17:52 acg +// Andy Goodrich: don't emit an error message for a resume on a disabled +// process that is not suspended. +// +// Revision 1.37 2011/03/20 13:43:23 acg +// Andy Goodrich: added async_signal_is() plus suspend() as a corner case. +// +// Revision 1.36 2011/03/08 20:49:31 acg +// Andy Goodrich: implement coarse checking for synchronous reset - suspend +// interaction. +// +// Revision 1.35 2011/03/08 20:32:28 acg +// Andy Goodrich: implemented "coarse" checking for undefined process +// control interactions. +// +// Revision 1.34 2011/03/07 18:25:19 acg +// Andy Goodrich: tightening of check for resume on a disabled process to +// only produce an error if it is ready to run. +// +// Revision 1.33 2011/03/07 17:38:44 acg +// Andy Goodrich: tightening up of checks for undefined interaction between +// synchronous reset and suspend. +// +// Revision 1.32 2011/03/06 23:30:13 acg +// Andy Goodrich: refining suspend - sync reset corner case checking so that +// the following are error situations: +// (1) Calling suspend on a process with a reset_signal_is() specification +// or sync_reset_on() is active. +// (2) Calling sync_reset_on() on a suspended process. +// +// Revision 1.31 2011/03/06 19:57:11 acg +// Andy Goodrich: refinements for the illegal suspend - synchronous reset +// interaction. +// +// Revision 1.30 2011/03/06 16:47:09 acg +// Andy Goodrich: changes for testing sync_reset - suspend corner cases. +// +// Revision 1.29 2011/03/06 15:59:23 acg +// Andy Goodrich: added process control corner case checks. +// +// Revision 1.28 2011/03/05 19:44:20 acg +// Andy Goodrich: changes for object and event naming and structures. +// +// Revision 1.27 2011/02/19 08:30:53 acg +// Andy Goodrich: Moved process queueing into trigger_static from +// sc_event::notify. +// +// Revision 1.26 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.25 2011/02/17 19:54:33 acg +// Andy Goodrich: +// (1) Changed signature of trigger_dynamic() back to bool, and moved +// run queue processing into trigger_dynamic. +// (2) Simplified process control usage. +// +// Revision 1.24 2011/02/16 22:37:31 acg +// Andy Goodrich: clean up to remove need for ps_disable_pending. +// +// Revision 1.23 2011/02/14 17:51:40 acg +// Andy Goodrich: proper pushing an poppping of the module hierarchy for +// start_of_simulation() and end_of_simulation. +// +// Revision 1.22 2011/02/13 23:09:58 acg +// Andy Goodrich: only remove dynamic events for asynchronous resets. +// +// Revision 1.21 2011/02/13 21:47:38 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.20 2011/02/13 21:37:13 acg +// Andy Goodrich: removed temporary diagnostic. Also there is +// remove_dynamic_events() call in reset code. +// +// Revision 1.19 2011/02/13 21:35:09 acg +// Andy Goodrich: added error messages for throws before the simulator is +// initialized. +// +// Revision 1.18 2011/02/11 13:25:24 acg +// Andy Goodrich: Philipp A. Hartmann's changes: +// (1) Removal of SC_CTHREAD method overloads. +// (2) New exception processing code. +// +// Revision 1.17 2011/02/08 08:18:16 acg +// Andy Goodrich: removed obsolete code. +// +// Revision 1.16 2011/02/07 19:17:20 acg +// Andy Goodrich: changes for IEEE 1666 compatibility. +// +// Revision 1.15 2011/02/04 15:27:36 acg +// Andy Goodrich: changes for suspend-resume semantics. +// +// Revision 1.14 2011/02/01 23:01:53 acg +// Andy Goodrich: removed dead code. +// +// Revision 1.13 2011/02/01 21:16:36 acg +// Andy Goodrich: +// (1) New version of trigger_dynamic() to implement new return codes and +// proper processing of events with new dynamic process rules. +// (2) Recoding of kill_process(), throw_user() and reset support to +// consolidate preemptive thread execution in sc_simcontext::preempt_with(). +// +// Revision 1.12 2011/01/25 20:50:37 acg +// Andy Goodrich: changes for IEEE 1666 2011. +// +// Revision 1.11 2011/01/20 16:52:20 acg +// Andy Goodrich: changes for IEEE 1666 2011. +// +// Revision 1.10 2011/01/19 23:21:50 acg +// Andy Goodrich: changes for IEEE 1666 2011 +// +// Revision 1.9 2011/01/18 20:10:45 acg +// Andy Goodrich: changes for IEEE1666_2011 semantics. +// +// Revision 1.8 2011/01/06 18:02:16 acg +// Andy Goodrich: added check for disabled thread to trigger_dynamic(). +// +// Revision 1.7 2010/11/20 17:10:57 acg +// Andy Goodrich: reset processing changes for new IEEE 1666 standard. +// +// Revision 1.6 2010/07/22 20:02:33 acg +// Andy Goodrich: bug fixes. +// +// Revision 1.5 2009/07/28 01:10:53 acg +// Andy Goodrich: updates for 2.3 release candidate. +// +// Revision 1.4 2009/05/22 16:06:29 acg +// Andy Goodrich: process control updates. +// +// Revision 1.3 2008/05/22 17:06:06 acg +// Andy Goodrich: formatting and comments. +// +// Revision 1.2 2007/09/20 20:32:35 acg +// Andy Goodrich: changes to the semantics of throw_it() to match the +// specification. A call to throw_it() will immediately suspend the calling +// thread until all the throwees have executed. At that point the calling +// thread will be restarted before the execution of any other threads. +// +// Revision 1.1.1.1 2006/12/15 20:20:05 acg +// SystemC 2.3 +// +// Revision 1.8 2006/04/20 17:08:17 acg +// Andy Goodrich: 3.0 style process changes. +// +// Revision 1.7 2006/04/11 23:13:21 acg +// Andy Goodrich: Changes for reduced reset support that only includes +// sc_cthread, but has preliminary hooks for expanding to method and thread +// processes also. +// +// Revision 1.6 2006/03/21 00:00:34 acg +// Andy Goodrich: changed name of sc_get_current_process_base() to be +// sc_get_current_process_b() since its returning an sc_process_b instance. +// +// Revision 1.5 2006/01/26 21:04:55 acg +// Andy Goodrich: deprecation message changes and additional messages. +// +// Revision 1.4 2006/01/24 20:49:05 acg +// Andy Goodrich: changes to remove the use of deprecated features within the +// simulator, and to issue warning messages when deprecated features are used. +// +// Revision 1.3 2006/01/13 18:44:30 acg +// Added $Log to record CVS changes into the source. +// diff --git a/ext/systemc/src/sysc/kernel/sc_thread_process.h b/ext/systemc/src/sysc/kernel/sc_thread_process.h new file mode 100644 index 000000000..5e834506a --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_thread_process.h @@ -0,0 +1,635 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_thread_process.h -- Thread process declarations + + Original Author: Andy Goodrich, Forte Design Systems, 4 August 2005 + + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + + +#if !defined(sc_thread_process_h_INCLUDED) +#define sc_thread_process_h_INCLUDED + +#include "sysc/kernel/sc_spawn_options.h" +#include "sysc/kernel/sc_process.h" +#include "sysc/kernel/sc_cor.h" +#include "sysc/kernel/sc_event.h" +#include "sysc/kernel/sc_except.h" +#include "sysc/kernel/sc_reset.h" + +// DEBUGGING MACROS: +// +// DEBUG_MSG(NAME,P,MSG) +// MSG = message to print +// NAME = name that must match the process for the message to print, or +// null if the message should be printed unconditionally. +// P = pointer to process message is for, or NULL in which case the +// message will not print. +#if 0 +# define DEBUG_NAME "" +# define DEBUG_MSG(NAME,P,MSG) \ + { \ + if ( P && ( (strlen(NAME)==0) || !strcmp(NAME,P->name())) ) \ + std::cout << "**** " << sc_time_stamp() << " (" \ + << sc_get_current_process_name() << "): " << MSG \ + << " - " << P->name() << std::endl; \ + } +#else +# define DEBUG_MSG(NAME,P,MSG) +#endif + + +namespace sc_core { + +// forward references: +class sc_event_and_list; +class sc_event_or_list; +class sc_reset; +void sc_thread_cor_fn( void* ); +void sc_set_stack_size( sc_thread_handle, std::size_t ); +class sc_event; +class sc_join; +class sc_module; +class sc_process_handle; +class sc_process_table; +class sc_simcontext; +class sc_runnable; + +sc_cor* get_cor_pointer( sc_process_b* process_p ); +void sc_set_stack_size( sc_thread_handle thread_h, std::size_t size ); +void wait( sc_simcontext* ); +void wait( const sc_event&, sc_simcontext* ); +void wait( const sc_event_or_list&, sc_simcontext* ); +void wait( const sc_event_and_list&, sc_simcontext* ); +void wait( const sc_time&, sc_simcontext* ); +void wait( const sc_time&, const sc_event&, sc_simcontext* ); +void wait( const sc_time&, const sc_event_or_list&, sc_simcontext* ); +void wait( const sc_time&, const sc_event_and_list&, sc_simcontext* ); + +//============================================================================== +// sc_thread_process - +// +//============================================================================== +class sc_thread_process : public sc_process_b { + friend void sc_thread_cor_fn( void* ); + friend void sc_set_stack_size( sc_thread_handle, std::size_t ); + friend class sc_event; + friend class sc_join; + friend class sc_module; + friend class sc_process_b; + friend class sc_process_handle; + friend class sc_process_table; + friend class sc_simcontext; + friend class sc_runnable; + friend sc_cor* get_cor_pointer( sc_process_b* process_p ); + + friend void wait( sc_simcontext* ); + friend void wait( const sc_event&, sc_simcontext* ); + friend void wait( const sc_event_or_list&, sc_simcontext* ); + friend void wait( const sc_event_and_list&, sc_simcontext* ); + friend void wait( const sc_time&, sc_simcontext* ); + friend void wait( const sc_time&, const sc_event&, sc_simcontext* ); + friend void wait( const sc_time&, const sc_event_or_list&, sc_simcontext* ); + friend void wait( const sc_time&, const sc_event_and_list&, sc_simcontext*); + public: + sc_thread_process( const char* name_p, bool free_host, + SC_ENTRY_FUNC method_p, sc_process_host* host_p, + const sc_spawn_options* opt_p ); + + virtual const char* kind() const + { return "sc_thread_process"; } + + protected: + // may not be deleted manually (called from sc_process_b) + virtual ~sc_thread_process(); + + virtual void disable_process( + sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS ); + virtual void enable_process( + sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS ); + virtual void kill_process( + sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS ); + sc_thread_handle next_exist(); + sc_thread_handle next_runnable(); + virtual void prepare_for_simulation(); + virtual void resume_process( + sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS ); + void set_next_exist( sc_thread_handle next_p ); + void set_next_runnable( sc_thread_handle next_p ); + + void set_stack_size( std::size_t size ); + inline void suspend_me(); + virtual void suspend_process( + sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS ); + virtual void throw_reset( bool async ); + virtual void throw_user( const sc_throw_it_helper& helper, + sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS ); + + bool trigger_dynamic( sc_event* ); + inline void trigger_static(); + + void wait( const sc_event& ); + void wait( const sc_event_or_list& ); + void wait( const sc_event_and_list& ); + void wait( const sc_time& ); + void wait( const sc_time&, const sc_event& ); + void wait( const sc_time&, const sc_event_or_list& ); + void wait( const sc_time&, const sc_event_and_list& ); + void wait_cycles( int n=1 ); + + protected: + void add_monitor( sc_process_monitor* monitor_p ); + void remove_monitor( sc_process_monitor* monitor_p); + void signal_monitors( int type = 0 ); + + protected: + sc_cor* m_cor_p; // Thread's coroutine. + std::vector<sc_process_monitor*> m_monitor_q; // Thread monitors. + std::size_t m_stack_size; // Thread stack size. + int m_wait_cycle_n; // # of waits to be done. + + private: // disabled + sc_thread_process( const sc_thread_process& ); + const sc_thread_process& operator = ( const sc_thread_process& ); + +}; + +//------------------------------------------------------------------------------ +//"sc_thread_process::set_stack_size" +// +//------------------------------------------------------------------------------ +inline void sc_thread_process::set_stack_size( std::size_t size ) +{ + assert( size ); + m_stack_size = size; +} + +//------------------------------------------------------------------------------ +//"sc_thread_process::suspend_me" +// +// This method suspends this object instance in favor of the next runnable +// process. Upon awakening we check to see if an exception should be thrown. +// There are two types of exceptions that can be thrown, synchronous reset +// and asynchronous reset. At a future time there may be more asynchronous +// exceptions. If an asynchronous reset is seen and there is not static reset +// specified, or the static reset is not active then clear the throw +// type for the next time this method is called. +// +// Notes: +// (1) For an explanation of how the reset mechanism works see the top of +// the file sc_reset.cpp. +// (2) The m_sticky_reset field is used to handle synchronous resets that +// are enabled via the sc_process_handle::sync_reset_on() method. These +// resets are not generated by a signal, but rather are modal by +// method call: sync_reset_on() - sync_reset_off(). +//------------------------------------------------------------------------------ +inline void sc_thread_process::suspend_me() +{ + // remember, if we're currently unwinding + + bool unwinding_preempted = m_unwinding; + + sc_simcontext* simc_p = simcontext(); + sc_cor* cor_p = simc_p->next_cor(); + + // do not switch, if we're about to execute next (e.g. suicide) + + if( m_cor_p != cor_p ) + { + DEBUG_MSG( DEBUG_NAME , this, "suspending thread"); + simc_p->cor_pkg()->yield( cor_p ); + DEBUG_MSG( DEBUG_NAME , this, "resuming thread"); + } + + // IF THERE IS A THROW TO BE DONE FOR THIS PROCESS DO IT NOW: + // + // (1) Optimize THROW_NONE for speed as it is the normal case. + // (2) If this thread is already unwinding then suspend_me() was + // called from the catch clause to throw an exception on another + // process, so just go back to the catch clause. + + if ( m_throw_status == THROW_NONE ) return; + + if ( m_unwinding ) return; + + switch( m_throw_status ) + { + case THROW_ASYNC_RESET: + case THROW_SYNC_RESET: + DEBUG_MSG( DEBUG_NAME , this, "throwing reset for"); + if ( m_reset_event_p ) m_reset_event_p->notify(); + throw sc_unwind_exception( this, true ); + + case THROW_USER: + DEBUG_MSG( DEBUG_NAME, this, "invoking throw_it for"); + m_throw_status = m_active_areset_n ? THROW_ASYNC_RESET : + (m_active_reset_n ? THROW_SYNC_RESET : + THROW_NONE); + m_throw_helper_p->throw_it(); + break; + + case THROW_KILL: + DEBUG_MSG( DEBUG_NAME, this, "throwing kill for"); + throw sc_unwind_exception( this, false ); + + default: // THROWING_NOW + sc_assert( unwinding_preempted ); + DEBUG_MSG( DEBUG_NAME, this, "restarting thread"); + break; + } +} + + +//------------------------------------------------------------------------------ +//"sc_thread_process::wait" +// +//------------------------------------------------------------------------------ +inline +void +sc_thread_process::wait( const sc_event& e ) +{ + if( m_unwinding ) + SC_REPORT_ERROR( SC_ID_WAIT_DURING_UNWINDING_, name() ); + + m_event_p = &e; // for cleanup. + e.add_dynamic( this ); + m_trigger_type = EVENT; + suspend_me(); +} + +inline +void +sc_thread_process::wait( const sc_event_or_list& el ) +{ + if( m_unwinding ) + SC_REPORT_ERROR( SC_ID_WAIT_DURING_UNWINDING_, name() ); + + el.add_dynamic( this ); + m_event_list_p = ⪙ + m_trigger_type = OR_LIST; + suspend_me(); +} + +inline +void +sc_thread_process::wait( const sc_event_and_list& el ) +{ + if( m_unwinding ) + SC_REPORT_ERROR( SC_ID_WAIT_DURING_UNWINDING_, name() ); + + el.add_dynamic( this ); + m_event_list_p = ⪙ + m_event_count = el.size(); + m_trigger_type = AND_LIST; + suspend_me(); +} + +inline +void +sc_thread_process::wait( const sc_time& t ) +{ + if( m_unwinding ) + SC_REPORT_ERROR( SC_ID_WAIT_DURING_UNWINDING_, name() ); + + m_timeout_event_p->notify_internal( t ); + m_timeout_event_p->add_dynamic( this ); + m_trigger_type = TIMEOUT; + suspend_me(); +} + +inline +void +sc_thread_process::wait( const sc_time& t, const sc_event& e ) +{ + if( m_unwinding ) + SC_REPORT_ERROR( SC_ID_WAIT_DURING_UNWINDING_, name() ); + + m_timeout_event_p->notify_internal( t ); + m_timeout_event_p->add_dynamic( this ); + e.add_dynamic( this ); + m_event_p = &e; + m_trigger_type = EVENT_TIMEOUT; + suspend_me(); +} + +inline +void +sc_thread_process::wait( const sc_time& t, const sc_event_or_list& el ) +{ + if( m_unwinding ) + SC_REPORT_ERROR( SC_ID_WAIT_DURING_UNWINDING_, name() ); + + m_timeout_event_p->notify_internal( t ); + m_timeout_event_p->add_dynamic( this ); + el.add_dynamic( this ); + m_event_list_p = ⪙ + m_trigger_type = OR_LIST_TIMEOUT; + suspend_me(); +} + +inline +void +sc_thread_process::wait( const sc_time& t, const sc_event_and_list& el ) +{ + if( m_unwinding ) + SC_REPORT_ERROR( SC_ID_WAIT_DURING_UNWINDING_, name() ); + + m_timeout_event_p->notify_internal( t ); + m_timeout_event_p->add_dynamic( this ); + el.add_dynamic( this ); + m_event_list_p = ⪙ + m_event_count = el.size(); + m_trigger_type = AND_LIST_TIMEOUT; + suspend_me(); +} + +//------------------------------------------------------------------------------ +//"sc_thread_process::wait_cycles" +// +// This method suspends this object instance for the specified number of cycles. +// A cycle is defined as the event the thread is set up to staticly wait on. +// The field m_wait_cycle_n is set to one less than the number of cycles to +// be waited for, since the value is tested before being decremented in +// the simulation kernel. +//------------------------------------------------------------------------------ +inline +void +sc_thread_process::wait_cycles( int n ) +{ + if( m_unwinding ) + SC_REPORT_ERROR( SC_ID_WAIT_DURING_UNWINDING_, name() ); + + m_wait_cycle_n = n-1; + suspend_me(); +} + +//------------------------------------------------------------------------------ +//"sc_thread_process::miscellaneous support" +// +//------------------------------------------------------------------------------ +inline +void sc_thread_process::add_monitor(sc_process_monitor* monitor_p) +{ + m_monitor_q.push_back(monitor_p); +} + + +inline +void sc_thread_process::remove_monitor(sc_process_monitor* monitor_p) +{ + int mon_n = m_monitor_q.size(); + + for ( int mon_i = 0; mon_i < mon_n; mon_i++ ) + { + if ( m_monitor_q[mon_i] == monitor_p ) + { + m_monitor_q[mon_i] = m_monitor_q[mon_n-1]; + m_monitor_q.resize(mon_n-1); + } + } +} + +inline +void sc_thread_process::set_next_exist(sc_thread_handle next_p) +{ + m_exist_p = next_p; +} + +inline +sc_thread_handle sc_thread_process::next_exist() +{ + return (sc_thread_handle)m_exist_p; +} + +inline +void sc_thread_process::set_next_runnable(sc_thread_handle next_p) +{ + m_runnable_p = next_p; +} + +inline +sc_thread_handle sc_thread_process::next_runnable() +{ + return (sc_thread_handle)m_runnable_p; +} + +inline sc_cor* get_cor_pointer( sc_process_b* process_p ) +{ + sc_thread_handle thread_p = DCAST<sc_thread_handle>(process_p); + return thread_p->m_cor_p; +} + +//------------------------------------------------------------------------------ +//"sc_thread_process::trigger_static" +// +// This inline method adds the current thread to the queue of runnable +// processes, if required. This is the case if the following criteria +// are met: +// (1) The process is in a runnable state. +// (2) The process is not already on the run queue. +// (3) The process is expecting a static trigger, +// dynamic event waits take priority. +// (4) The process' static wait count is zero. +// +// If the triggering process is the same process, the trigger is +// ignored as well, unless SC_ENABLE_IMMEDIATE_SELF_NOTIFICATIONS +// is defined. +//------------------------------------------------------------------------------ +inline +void +sc_thread_process::trigger_static() +{ + // No need to try queueing this thread if one of the following is true: + // (a) its disabled + // (b) its already queued for execution + // (c) its waiting on a dynamic event + // (d) its wait count is not satisfied + + if ( (m_state & ps_bit_disabled) || is_runnable() || + m_trigger_type != STATIC ) + return; + +#if ! defined( SC_ENABLE_IMMEDIATE_SELF_NOTIFICATIONS ) + if( SC_UNLIKELY_( sc_get_current_process_b() == this ) ) + { + report_immediate_self_notification(); + return; + } +#endif // SC_ENABLE_IMMEDIATE_SELF_NOTIFICATIONS + + if ( m_wait_cycle_n > 0 ) + { + --m_wait_cycle_n; + return; + } + + // If we get here then the thread is has satisfied its wait criteria, if + // its suspended mark its state as ready to run. If its not suspended then + // push it onto the runnable queue. + + if ( m_state & ps_bit_suspended ) + { + m_state = m_state | ps_bit_ready_to_run; + } + else + { + simcontext()->push_runnable_thread(this); + } +} + +#undef DEBUG_MSG +#undef DEBUG_NAME + +} // namespace sc_core + +// $Log: sc_thread_process.h,v $ +// Revision 1.30 2011/08/26 20:46:11 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +// Revision 1.29 2011/08/24 23:36:12 acg +// Andy Goodrich: removed break statements that can never be reached and +// which causes warnings in the Greenhills C++ compiler. +// +// Revision 1.28 2011/04/14 22:34:27 acg +// Andy Goodrich: removed dead code. +// +// Revision 1.27 2011/04/13 05:02:18 acg +// Andy Goodrich: added missing check to the wake up code in suspend_me() +// so that we just return if the call to suspend_me() was issued from a +// stack unwinding. +// +// Revision 1.26 2011/04/13 02:44:26 acg +// Andy Goodrich: added m_unwinding flag in place of THROW_NOW because the +// throw status will be set back to THROW_*_RESET if reset is active and +// the check for an unwind being complete was expecting THROW_NONE as the +// clearing of THROW_NOW. +// +// Revision 1.25 2011/04/11 22:05:14 acg +// Andy Goodrich: use the DEBUG_NAME macro in DEBUG_MSG invocations. +// +// Revision 1.24 2011/04/10 22:12:32 acg +// Andy Goodrich: adding debugging macros. +// +// Revision 1.23 2011/04/08 22:41:28 acg +// Andy Goodrich: added comment pointing to the description of the reset +// mechanism in sc_reset.cpp. +// +// Revision 1.22 2011/04/08 18:27:33 acg +// Andy Goodrich: added check to make sure we don't schedule a running process +// because of it issues a notify() it is sensitive to. +// +// Revision 1.21 2011/04/05 06:22:38 acg +// Andy Goodrich: expanded comment for trigger_static() initial vetting. +// +// Revision 1.20 2011/04/01 21:24:57 acg +// Andy Goodrich: removed unused code. +// +// Revision 1.19 2011/02/19 08:30:53 acg +// Andy Goodrich: Moved process queueing into trigger_static from +// sc_event::notify. +// +// Revision 1.18 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.17 2011/02/17 19:55:58 acg +// Andy Goodrich: +// (1) Changed signature of trigger_dynamic() back to a bool. +// (2) Simplified process control usage. +// (3) Changed trigger_static() to recognize process controls and to +// do the down-count on wait(N), allowing the elimination of +// ready_to_run(). +// +// Revision 1.16 2011/02/16 22:37:31 acg +// Andy Goodrich: clean up to remove need for ps_disable_pending. +// +// Revision 1.15 2011/02/13 21:47:38 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.14 2011/02/13 21:35:54 acg +// Andy Goodrich: added error for performing a wait() during unwinding. +// +// Revision 1.13 2011/02/11 13:25:24 acg +// Andy Goodrich: Philipp A. Hartmann's changes: +// (1) Removal of SC_CTHREAD method overloads. +// (2) New exception processing code. +// +// Revision 1.12 2011/02/01 23:01:53 acg +// Andy Goodrich: removed dead code. +// +// Revision 1.11 2011/02/01 21:18:01 acg +// Andy Goodrich: +// (1) Changes in throw processing for new process control rules. +// (2) Support of new process_state enum values. +// +// Revision 1.10 2011/01/25 20:50:37 acg +// Andy Goodrich: changes for IEEE 1666 2011. +// +// Revision 1.9 2011/01/19 23:21:50 acg +// Andy Goodrich: changes for IEEE 1666 2011 +// +// Revision 1.8 2011/01/18 20:10:45 acg +// Andy Goodrich: changes for IEEE1666_2011 semantics. +// +// Revision 1.7 2011/01/06 17:59:58 acg +// Andy Goodrich: removed debugging output. +// +// Revision 1.6 2010/07/22 20:02:33 acg +// Andy Goodrich: bug fixes. +// +// Revision 1.5 2009/07/28 01:10:53 acg +// Andy Goodrich: updates for 2.3 release candidate. +// +// Revision 1.4 2009/05/22 16:06:29 acg +// Andy Goodrich: process control updates. +// +// Revision 1.3 2009/03/12 22:59:58 acg +// Andy Goodrich: updates for 2.4 stuff. +// +// Revision 1.2 2008/05/22 17:06:06 acg +// Andy Goodrich: formatting and comments. +// +// Revision 1.1.1.1 2006/12/15 20:20:05 acg +// SystemC 2.3 +// +// Revision 1.7 2006/05/08 17:57:13 acg +// Andy Goodrich: Added David Long's forward declarations for friend functions +// to keep the Microsoft C++ compiler happy. +// +// Revision 1.6 2006/04/20 17:08:17 acg +// Andy Goodrich: 3.0 style process changes. +// +// Revision 1.5 2006/04/11 23:13:21 acg +// Andy Goodrich: Changes for reduced reset support that only includes +// sc_cthread, but has preliminary hooks for expanding to method and thread +// processes also. +// +// Revision 1.4 2006/01/24 20:49:05 acg +// Andy Goodrich: changes to remove the use of deprecated features within the +// simulator, and to issue warning messages when deprecated features are used. +// +// Revision 1.3 2006/01/13 18:44:30 acg +// Added $Log to record CVS changes into the source. + +#endif // !defined(sc_thread_process_h_INCLUDED) diff --git a/ext/systemc/src/sysc/kernel/sc_time.cpp b/ext/systemc/src/sysc/kernel/sc_time.cpp new file mode 100644 index 000000000..e3fdd5865 --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_time.cpp @@ -0,0 +1,465 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_time.cpp -- + + Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21 + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + + +#include <math.h> +#include <stdio.h> + +#include "sysc/kernel/sc_kernel_ids.h" +#include "sysc/kernel/sc_simcontext.h" +#include "sysc/kernel/sc_time.h" +#include "sysc/utils/sc_utils_ids.h" + +#if !defined(PRIu64) +# if defined(_MSC_VER) || defined(__MINGW32__) +# define PRIu64 "I64u" +# else +# define PRIu64 "llu" +# endif +#endif // PRIu64 + +#ifdef SC_ENABLE_EARLY_MAXTIME_CREATION +# define SC_MAXTIME_ALLOWED_ 1 +#else +# define SC_MAXTIME_ALLOWED_ 0 +#endif + +namespace sc_core { + +static +double time_values[] = { + 1, // fs + 1e3, // ps + 1e6, // ns + 1e9, // us + 1e12, // ms + 1e15 // s +}; + +static +const char* time_units[] = { + "fs", + "ps", + "ns", + "us", + "ms", + "s" +}; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_time +// +// The time class. +// ---------------------------------------------------------------------------- + +// constructors + +sc_time::sc_time( double v, sc_time_unit tu ) +: m_value( 0 ) +{ + if( v != 0 ) { + sc_time_params* time_params = sc_get_curr_simcontext()->m_time_params; + double scale_fac = time_values[tu] / time_params->time_resolution; + // linux bug workaround; don't change next two lines + volatile double tmp = v * scale_fac + 0.5; + m_value = SCAST<sc_dt::int64>( tmp ); + time_params->time_resolution_fixed = true; + } +} + +sc_time::sc_time( double v, sc_time_unit tu, sc_simcontext* simc ) +: m_value( 0 ) +{ + if( v != 0 ) { + sc_time_params* time_params = simc->m_time_params; + double scale_fac = time_values[tu] / time_params->time_resolution; + // linux bug workaround; don't change next two lines + volatile double tmp = v * scale_fac + 0.5; + m_value = SCAST<sc_dt::int64>( tmp ); + time_params->time_resolution_fixed = true; + } +} + +sc_time::sc_time( double v, bool scale ) +: m_value( 0 ) +{ + static bool warn_constructor=true; + if ( warn_constructor ) { + warn_constructor=false; + SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, + "deprecated constructor: sc_time(double,bool)"); + } + + if( v != 0 ) { + sc_time_params* time_params = sc_get_curr_simcontext()->m_time_params; + if( scale ) { + double scale_fac = sc_dt::uint64_to_double( + time_params->default_time_unit ); + // linux bug workaround; don't change next two lines + volatile double tmp = v * scale_fac + 0.5; + m_value = SCAST<sc_dt::int64>( tmp ); + } else { + // linux bug workaround; don't change next two lines + volatile double tmp = v + 0.5; + m_value = SCAST<sc_dt::int64>( tmp ); + } + time_params->time_resolution_fixed = true; + } +} + +sc_time::sc_time( value_type v, bool scale ) +: m_value( 0 ) +{ + static bool warn_constructor=true; + if ( warn_constructor ) { + warn_constructor=false; + SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, + "deprecated constructor: sc_time(uint64,bool)"); + } + + if( v != 0 ) { + sc_time_params* time_params = sc_get_curr_simcontext()->m_time_params; + if( scale ) { + double scale_fac = sc_dt::uint64_to_double( + time_params->default_time_unit ); + // linux bug workaround; don't change next two lines + volatile double tmp = sc_dt::uint64_to_double( v ) * + scale_fac + 0.5; + m_value = SCAST<sc_dt::int64>( tmp ); + } else { + m_value = v; + } + time_params->time_resolution_fixed = true; + } +} + +sc_time +sc_time::from_value( value_type v ) +{ + sc_time t; + if( v != 0 && !(SC_MAXTIME_ALLOWED_ && v == ~sc_dt::UINT64_ZERO) ) { + sc_time_params* time_params = sc_get_curr_simcontext()->m_time_params; + time_params->time_resolution_fixed = true; + } + t.m_value = v; + return t; +} + + +// conversion functions + +double +sc_time::to_default_time_units() const +{ + sc_time_params* time_params = sc_get_curr_simcontext()->m_time_params; +# if SC_MAXTIME_ALLOWED_ + if( m_value == 0 ) + return 0.0; + time_params->time_resolution_fixed = true; +# endif // SC_MAXTIME_ALLOWED_ + return ( sc_dt::uint64_to_double( m_value ) / + sc_dt::uint64_to_double( time_params->default_time_unit ) ); +} + +double +sc_time::to_seconds() const +{ + sc_time_params* time_params = sc_get_curr_simcontext()->m_time_params; +# if SC_MAXTIME_ALLOWED_ + if( m_value == 0 ) + return 0.0; + time_params->time_resolution_fixed = true; +# endif // SC_MAXTIME_ALLOWED_ + return ( sc_dt::uint64_to_double( m_value ) * + time_params->time_resolution * 1e-15 ); +} + +const std::string +sc_time::to_string() const +{ + value_type val = m_value; + if( val == 0 ) { + return std::string( "0 s" ); + } + sc_time_params* time_params = sc_get_curr_simcontext()->m_time_params; +# if SC_MAXTIME_ALLOWED_ + time_params->time_resolution_fixed = true; +# endif // SC_MAXTIME_ALLOWED_ + value_type tr = SCAST<sc_dt::int64>( time_params->time_resolution ); + int n = 0; + while( ( tr % 10 ) == 0 ) { + tr /= 10; + n ++; + } + assert( tr == 1 ); + while( ( val % 10 ) == 0 ) { + val /= 10; + n ++; + } + char buf[BUFSIZ]; + std::sprintf( buf, "%" PRIu64, val ); + std::string result( buf ); + if( n >= 15 ) { + for( int i = n - 15; i > 0; -- i ) { + result += "0"; + } + result += " s"; + } else { + for( int i = n % 3; i > 0; -- i ) { + result += "0"; + } + result += " "; + result += time_units[n / 3]; + } + return result; +} + + +// print function + +void +sc_time::print( ::std::ostream& os ) const +{ + os << to_string(); +} + + +// ---------------------------------------------------------------------------- +// STRUCT : sc_time_params +// +// Struct that holds the time resolution and default time unit. +// ---------------------------------------------------------------------------- + +sc_time_params::sc_time_params() +: time_resolution( 1000 ), // default 1 ps + time_resolution_specified( false ), + time_resolution_fixed( false ), + default_time_unit( 1000 ), // default 1 ns + default_time_unit_specified( false ) +{} + +sc_time_params::~sc_time_params() +{} + + +// ---------------------------------------------------------------------------- + +// functions for accessing the time resolution and default time unit + +void +sc_set_time_resolution( double v, sc_time_unit tu ) +{ + // first perform the necessary checks + + // must be positive + if( v < 0.0 ) { + SC_REPORT_ERROR( SC_ID_SET_TIME_RESOLUTION_, "value not positive" ); + } + + // must be a power of ten + double dummy; +#if defined( __HP_aCC ) || defined(__ppc__) + // aCC seems to have a bug in modf() + if( modf( log10( v < 1.0 ? 1.0/v : v ), &dummy ) != 0.0 ) { +#else + if( modf( log10( v ), &dummy ) != 0.0 ) { +#endif + SC_REPORT_ERROR( SC_ID_SET_TIME_RESOLUTION_, + "value not a power of ten" ); + } + + sc_simcontext* simc = sc_get_curr_simcontext(); + + // can only be specified during elaboration + if( sc_is_running() ) { + SC_REPORT_ERROR( SC_ID_SET_TIME_RESOLUTION_, "simulation running" ); + } + + sc_time_params* time_params = simc->m_time_params; + + // can be specified only once + if( time_params->time_resolution_specified ) { + SC_REPORT_ERROR( SC_ID_SET_TIME_RESOLUTION_, "already specified" ); + } + + // can only be specified before any sc_time is constructed + if( time_params->time_resolution_fixed ) { + SC_REPORT_ERROR( SC_ID_SET_TIME_RESOLUTION_, + "sc_time object(s) constructed" ); + } + + // must be larger than or equal to 1 fs + volatile double resolution = v * time_values[tu]; + if( resolution < 1.0 ) { + SC_REPORT_ERROR( SC_ID_SET_TIME_RESOLUTION_, + "value smaller than 1 fs" ); + } + + // recalculate the default time unit + volatile double time_unit = sc_dt::uint64_to_double( + time_params->default_time_unit ) * + ( time_params->time_resolution / resolution ); + if( time_unit < 1.0 ) { + SC_REPORT_WARNING( SC_ID_DEFAULT_TIME_UNIT_CHANGED_, 0 ); + time_params->default_time_unit = 1; + } else { + time_params->default_time_unit = SCAST<sc_dt::int64>( time_unit ); + } + + time_params->time_resolution = resolution; + time_params->time_resolution_specified = true; +} + +sc_time +sc_get_time_resolution() +{ + return sc_time::from_value( sc_dt::UINT64_ONE ); +} + + +void +sc_set_default_time_unit( double v, sc_time_unit tu ) +{ + static bool warn_default_time_unit=true; + if ( warn_default_time_unit ) + { + warn_default_time_unit=false; + SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, + "deprecated function: sc_set_default_time_unit"); + } + + // first perform the necessary checks + + // must be positive + if( v < 0.0 ) { + SC_REPORT_ERROR( SC_ID_SET_DEFAULT_TIME_UNIT_, "value not positive" ); + } + + // must be a power of ten + double dummy; + if( modf( log10( v ), &dummy ) != 0.0 ) { + SC_REPORT_ERROR( SC_ID_SET_DEFAULT_TIME_UNIT_, + "value not a power of ten" ); + } + + sc_simcontext* simc = sc_get_curr_simcontext(); + + // can only be specified during elaboration + if( sc_is_running() ) { + SC_REPORT_ERROR( SC_ID_SET_DEFAULT_TIME_UNIT_, "simulation running" ); + } + + sc_time_params* time_params = simc->m_time_params; + + // can only be specified before any sc_time is constructed + if( time_params->time_resolution_fixed ) { + SC_REPORT_ERROR( SC_ID_SET_DEFAULT_TIME_UNIT_, + "sc_time object(s) constructed" ); + } + + // can be specified only once + if( time_params->default_time_unit_specified ) { + SC_REPORT_ERROR( SC_ID_SET_DEFAULT_TIME_UNIT_, "already specified" ); + } + + // must be larger than or equal to the time resolution + volatile double time_unit = ( v * time_values[tu] ) / + time_params->time_resolution; + if( time_unit < 1.0 ) { + SC_REPORT_ERROR( SC_ID_SET_DEFAULT_TIME_UNIT_, + "value smaller than time resolution" ); + } + + time_params->default_time_unit = SCAST<sc_dt::int64>( time_unit ); + time_params->default_time_unit_specified = true; +} + +sc_time +sc_get_default_time_unit() +{ + static bool warn_get_default_time_unit = true; + if ( warn_get_default_time_unit ) + { + warn_get_default_time_unit=false; + SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, + "deprecated function: sc_get_default_time_unit"); + } + return sc_time::from_value( + sc_get_curr_simcontext()->m_time_params->default_time_unit + ); +} + + +// ---------------------------------------------------------------------------- + +const sc_time SC_ZERO_TIME; + +#undef SC_MAXTIME_ALLOWED_ + +} // namespace sc_core + +// $Log: sc_time.cpp,v $ +// Revision 1.7 2011/08/26 20:46:11 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +// Revision 1.6 2011/07/24 16:08:36 acg +// Philipp A. Hartmann: fix C99 format specifiers for Solaris. +// +// Revision 1.5 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.4 2011/02/13 21:47:38 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.3 2011/01/19 23:21:50 acg +// Andy Goodrich: changes for IEEE 1666 2011 +// +// Revision 1.2 2008/05/22 17:06:27 acg +// Andy Goodrich: updated copyright notice to include 2008. +// +// Revision 1.1.1.1 2006/12/15 20:20:05 acg +// SystemC 2.3 +// +// Revision 1.6 2006/01/26 21:04:55 acg +// Andy Goodrich: deprecation message changes and additional messages. +// +// Revision 1.5 2006/01/25 00:31:19 acg +// Andy Goodrich: Changed over to use a standard message id of +// SC_ID_IEEE_1666_DEPRECATION for all deprecation messages. +// +// Revision 1.4 2006/01/24 20:49:05 acg +// Andy Goodrich: changes to remove the use of deprecated features within the +// simulator, and to issue warning messages when deprecated features are used. +// +// Revision 1.3 2006/01/13 18:44:30 acg +// Added $Log to record CVS changes into the source. +// + +// Taf! diff --git a/ext/systemc/src/sysc/kernel/sc_time.h b/ext/systemc/src/sysc/kernel/sc_time.h new file mode 100644 index 000000000..af222dd0f --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_time.h @@ -0,0 +1,414 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_time.h -- The time class. + + Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21 + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + + +#ifndef SC_TIME_H +#define SC_TIME_H + + +#include "sysc/datatypes/int/sc_nbdefs.h" +#include "sysc/datatypes/fx/scfx_ieee.h" +#include "sysc/utils/sc_iostream.h" + +namespace sc_core { + +class sc_simcontext; + +// friend operator declarations + + const sc_time operator + ( const sc_time&, const sc_time& ); + const sc_time operator - ( const sc_time&, const sc_time& ); + const sc_time operator * ( const sc_time&, double ); + const sc_time operator * ( double, const sc_time& ); + const sc_time operator / ( const sc_time&, double ); + double operator / ( const sc_time&, const sc_time& ); + + +// ---------------------------------------------------------------------------- +// ENUM : sc_time_unit +// +// Enumeration of time units. +// ---------------------------------------------------------------------------- + +enum sc_time_unit +{ + SC_FS = 0, + SC_PS, + SC_NS, + SC_US, + SC_MS, + SC_SEC +}; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_time +// +// The time class. +// ---------------------------------------------------------------------------- + +class sc_time +{ +public: + + typedef sc_dt::uint64 value_type; + + // constructors + + sc_time(); + sc_time( double, sc_time_unit ); + sc_time( double, sc_time_unit, sc_simcontext* ); + sc_time( const sc_time& ); + + static sc_time from_value( value_type ); + + // deprecated, use from_value(v) + sc_time( double, bool scale ); + sc_time( value_type, bool scale ); + + // assignment operator + + sc_time& operator = ( const sc_time& ); + + + // conversion functions + + value_type value() const; // relative to the time resolution + double to_double() const; // relative to the time resolution + double to_default_time_units() const; + double to_seconds() const; + const std::string to_string() const; + + + // relational operators + + bool operator == ( const sc_time& ) const; + bool operator != ( const sc_time& ) const; + bool operator < ( const sc_time& ) const; + bool operator <= ( const sc_time& ) const; + bool operator > ( const sc_time& ) const; + bool operator >= ( const sc_time& ) const; + + + // arithmetic operators + + sc_time& operator += ( const sc_time& ); + sc_time& operator -= ( const sc_time& ); + + friend const sc_time operator + ( const sc_time&, const sc_time& ); + friend const sc_time operator - ( const sc_time&, const sc_time& ); + + sc_time& operator *= ( double ); + sc_time& operator /= ( double ); + sc_time& operator %= ( const sc_time& ); + + friend const sc_time operator * ( const sc_time&, double ); + friend const sc_time operator * ( double, const sc_time& ); + friend const sc_time operator / ( const sc_time&, double ); + friend double operator / ( const sc_time&, const sc_time& ); + friend const sc_time operator % ( const sc_time&, const sc_time& ); + + + // print function + + void print( ::std::ostream& os = std::cout ) const; + +private: + + value_type m_value; +}; + + +// print operator + +inline ::std::ostream& operator << ( ::std::ostream&, const sc_time& ); + + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + +// constructors + +inline +sc_time::sc_time() +: m_value( 0 ) +{} + +inline +sc_time::sc_time( const sc_time& t ) +: m_value( t.m_value ) +{} + + +// assignment operator + +inline +sc_time& +sc_time::operator = ( const sc_time& t ) +{ + m_value = t.m_value; + return *this; +} + + +// conversion functions + +inline +sc_time::value_type +sc_time::value() const // relative to the time resolution +{ + return m_value; +} + + +inline +double +sc_time::to_double() const // relative to the time resolution +{ + return sc_dt::uint64_to_double( m_value ); +} + + +// relational operators + +inline +bool +sc_time::operator == ( const sc_time& t ) const +{ + return ( m_value == t.m_value ); +} + +inline +bool +sc_time::operator != ( const sc_time& t ) const +{ + return ( m_value != t.m_value ); +} + +inline +bool +sc_time::operator < ( const sc_time& t ) const +{ + return ( m_value < t.m_value ); +} + +inline +bool +sc_time::operator <= ( const sc_time& t ) const +{ + return ( m_value <= t.m_value ); +} + +inline +bool +sc_time::operator > ( const sc_time& t ) const +{ + return ( m_value > t.m_value ); +} + +inline +bool +sc_time::operator >= ( const sc_time& t ) const +{ + return ( m_value >= t.m_value ); +} + + +// arithmetic operators + +inline +sc_time& +sc_time::operator += ( const sc_time& t ) +{ + m_value += t.m_value; + return *this; +} + +inline +sc_time& +sc_time::operator -= ( const sc_time& t ) +{ + m_value -= t.m_value; + return *this; +} + + +inline +const sc_time +operator + ( const sc_time& t1, const sc_time& t2 ) +{ + return sc_time( t1 ) += t2; +} + +inline +const sc_time +operator - ( const sc_time& t1, const sc_time& t2 ) +{ + return sc_time( t1 ) -= t2; +} + + +inline +sc_time& +sc_time::operator *= ( double d ) +{ + // linux bug workaround; don't change next two lines + volatile double tmp = sc_dt::uint64_to_double( m_value ) * d + 0.5; + m_value = SCAST<sc_dt::int64>( tmp ); + return *this; +} + +inline +sc_time& +sc_time::operator /= ( double d ) +{ + // linux bug workaround; don't change next two lines + volatile double tmp = sc_dt::uint64_to_double( m_value ) / d + 0.5; + m_value = SCAST<sc_dt::int64>( tmp ); + return *this; +} + +inline +sc_time& +sc_time::operator %= ( const sc_time& t ) +{ + m_value %= t.m_value; + return *this; +} + +inline +const sc_time +operator * ( const sc_time& t, double d ) +{ + sc_time tmp( t ); + return tmp *= d; +} + +inline +const sc_time +operator * ( double d, const sc_time& t ) +{ + sc_time tmp( t ); + return tmp *= d; +} + +inline +const sc_time +operator / ( const sc_time& t, double d ) +{ + sc_time tmp( t ); + return tmp /= d; +} + +inline +double +operator / ( const sc_time& t1, const sc_time& t2 ) +{ + return ( t1.to_double() / t2.to_double() ); +} + +inline +const sc_time +operator % ( const sc_time& t1, const sc_time& t2 ) +{ + sc_time tmp(t1); + return tmp %= t2; +} + +// print operator + +inline +::std::ostream& +operator << ( ::std::ostream& os, const sc_time& t ) +{ + t.print( os ); + return os; +} + + +// ---------------------------------------------------------------------------- +// STRUCT : sc_time_params +// +// Struct that holds the time resolution and default time unit. +// ---------------------------------------------------------------------------- + +struct sc_time_params +{ + double time_resolution; // in femto seconds + bool time_resolution_specified; + bool time_resolution_fixed; + + sc_time::value_type default_time_unit; // in time resolution + bool default_time_unit_specified; + + sc_time_params(); + ~sc_time_params(); +}; + + +// ---------------------------------------------------------------------------- + +extern const sc_time SC_ZERO_TIME; + + +// functions for accessing the time resolution and default time unit + +extern void sc_set_time_resolution( double, sc_time_unit ); +extern sc_time sc_get_time_resolution(); + +extern void sc_set_default_time_unit( double, sc_time_unit ); +extern sc_time sc_get_default_time_unit(); + +} // namespace sc_core + +#endif + +// $Log: sc_time.h,v $ +// Revision 1.5 2011/08/26 20:46:11 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +// Revision 1.4 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.3 2011/02/13 21:47:38 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.2 2008/05/22 17:06:27 acg +// Andy Goodrich: updated copyright notice to include 2008. +// +// Revision 1.1.1.1 2006/12/15 20:20:05 acg +// SystemC 2.3 +// +// Revision 1.4 2006/05/08 18:02:06 acg +// Andy Goodrich: added David Long's forward declarations for friend +// functions, methods, and operators to keep the Microsoft compiler happy. +// +// Revision 1.3 2006/01/13 18:44:30 acg +// Added $Log to record CVS changes into the source. + +// Taf! diff --git a/ext/systemc/src/sysc/kernel/sc_ver.cpp b/ext/systemc/src/sysc/kernel/sc_ver.cpp new file mode 100644 index 000000000..9883cd3bc --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_ver.cpp @@ -0,0 +1,228 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_ver.cpp -- copyright information. + + Original Author: Stan Y. Liao, Synopsys, Inc. + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + +#include <cstddef> +#include <cstdlib> + +#define SC_DISABLE_API_VERSION_CHECK // for in-library sc_ver.h inclusion + +#include "sysc/kernel/sc_ver.h" +#include "sysc/kernel/sc_kernel_ids.h" +#include "sysc/utils/sc_iostream.h" +#include "sysc/utils/sc_report.h" + +using std::getenv; +using std::strcmp; +using std::cerr; +using std::endl; + +namespace sc_core { + + +static +const char systemc_version[] = + "SystemC " SC_VERSION " --- " __DATE__ " " __TIME__; + +const unsigned int sc_version_major = SC_VERSION_MAJOR; +const unsigned int sc_version_minor = SC_VERSION_MINOR; +const unsigned int sc_version_patch = SC_VERSION_PATCH; +const bool sc_is_prerelease = SC_IS_PRERELEASE; + +const std::string sc_version_originator = SC_VERSION_ORIGINATOR; +const std::string sc_version_release_date = SC_VERSION_RELEASE_DATE; +const std::string sc_version_prerelease = SC_VERSION_PRERELEASE; +const std::string sc_version_string = SC_VERSION; +const std::string sc_copyright_string = SC_COPYRIGHT; + +const char* +sc_copyright() +{ + return SC_COPYRIGHT; +} + + +const char* +sc_release() +{ + return SC_VERSION; +} + + +const char* +sc_version() +{ + return systemc_version; +} + + +#if !defined(SC_DISABLE_COPYRIGHT_MESSAGE) +# define SC_DISABLE_COPYRIGHT_MESSAGE 0 +#endif + +// ---------------------------------------------------------------------------- + +void +pln() +{ + static bool lnp = SC_DISABLE_COPYRIGHT_MESSAGE; + if ( lnp || getenv("SYSTEMC_DISABLE_COPYRIGHT_MESSAGE") != 0 ) + lnp = true; + if ( const char * lnp_env = getenv("SC_COPYRIGHT_MESSAGE") ) { + lnp = !strcmp( lnp_env, "DISABLE" ); + } + if( ! lnp ) { + + static const char indent[] = " "; + std::string line; + std::stringstream copyright; + + // temporary stream to print copyright line-wise with indentation + copyright << sc_copyright(); + + cerr << endl; + cerr << indent << sc_version() << endl; + while( getline( copyright, line ) ) + cerr << indent << line << endl; + + // regressions check point + + if( getenv( "SYSTEMC_REGRESSION" ) != 0 ) { + cerr << "SystemC Simulation" << endl; + } + + lnp = true; + } +} + +#define SC_API_PERFORM_CHECK_( Type, Name, Symbol ) \ + do { \ + static bool SC_CONCAT_UNDERSCORE_( Name, config_seen ) = false; \ + static Type SC_CONCAT_UNDERSCORE_( Name, config ); \ + if( ! SC_CONCAT_UNDERSCORE_( Name, config_seen ) ) { \ + SC_CONCAT_UNDERSCORE_( Name, config_seen ) = true; \ + SC_CONCAT_UNDERSCORE_( Name, config ) = Name; \ + } else if( SC_CONCAT_UNDERSCORE_( Name, config ) != Name ) { \ + SC_REPORT_FATAL( SC_ID_INCONSISTENT_API_CONFIG_, Symbol ); \ + } \ + } while( false ) + +// THIS CONSTRUCTOR ROOTS OUT OLD OBJECTS AT LINK TIME +// +// Each source file which includes sc_ver.h for this SystemC version +// will have a static instance of the class sc_api_version_XXX defined +// in it. That object instanciation will cause the constructor below +// to be invoked. If the version of the SystemC being linked against +// does not contain the constructor below a linkage error will occur. +// +// Some preprocessor switches need to be consistent between the application +// and the library (e.g. if sizes of classes are affected or other parts of +// the ABI are affected). (Some of) these are checked here at link-time as +// well, by setting template parameters to sc_api_version_XXX, while only +// one variant is defined here. +// +// Some preprocessor switches need to be consistent between different +// translation units of an application. Those can't be easily checked +// during link-time. Instead, perform a check during run-time by +// passing the value to the constructor of the api_version_check object. + +// const int DEBUG_SYSTEMC_CHECK_ = 1; +const int SC_DISABLE_VIRTUAL_BIND_CHECK_ = 1; + +template<> +SC_API_VERSION_STRING +< +// & DEBUG_SYSTEMC_CHECK_, + & SC_DISABLE_VIRTUAL_BIND_CHECK_ +> +::SC_API_VERSION_STRING +( + sc_writer_policy default_writer_policy +) +{ + SC_API_PERFORM_CHECK_( sc_writer_policy + , default_writer_policy + , "SC_DEFAULT_WRITER_POLICY" ); +} + +} // namespace sc_core + +// $Log: sc_ver.cpp,v $ +// Revision 1.14 2011/08/26 21:56:55 acg +// Torsten Maehne: use usings rather than absolute namespace addressing. +// +// Revision 1.13 2011/08/26 20:46:11 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +// Revision 1.12 2011/07/25 10:20:34 acg +// Andy Goodrich: check in aftermath of call to automake. +// +// Revision 1.11 2011/07/02 12:55:19 acg +// Andy Goodrich: automake refresh. +// +// Revision 1.10 2011/07/01 18:49:07 acg +// Andy Goodrich: moved pln() from sc_simcontext.cpp to sc_ver.cpp. +// +// Revision 1.9 2011/07/01 18:33:08 acg +// Andy Goodrich: changes for IEEE 1666, removal of macros and use of them. +// +// Revision 1.8 2011/04/08 18:27:53 acg +// Andy Goodrich: respin of the PoC. +// +// Revision 1.7 2011/04/05 20:50:57 acg +// Andy Goodrich: +// (1) changes to make sure that event(), posedge() and negedge() only +// return true if the clock has not moved. +// (2) fixes for method self-resumes. +// (3) added SC_PRERELEASE_VERSION +// (4) removed kernel events from the object hierarchy, added +// sc_hierarchy_name_exists(). +// +// Revision 1.6 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.5 2011/02/13 21:47:38 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.4 2011/01/18 20:10:45 acg +// Andy Goodrich: changes for IEEE1666_2011 semantics. +// +// Revision 1.3 2010/11/20 17:10:57 acg +// Andy Goodrich: reset processing changes for new IEEE 1666 standard. +// +// Revision 1.2 2008/05/22 17:06:27 acg +// Andy Goodrich: updated copyright notice to include 2008. +// +// Revision 1.1.1.1 2006/12/15 20:20:05 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:44:30 acg +// Added $Log to record CVS changes into the source. +// + +// Taf! diff --git a/ext/systemc/src/sysc/kernel/sc_ver.h b/ext/systemc/src/sysc/kernel/sc_ver.h new file mode 100644 index 000000000..34112f9f8 --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_ver.h @@ -0,0 +1,186 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_ver.h -- Version and copyright information. + + Original Author: Stan Y. Liao, Synopsys, Inc. + + NO AUTOMATIC CHANGE LOG IS GENERATED, EXPLICIT CHANGE LOG AT END OF FILE + *****************************************************************************/ + + +#ifndef SC_VER_H +#define SC_VER_H + +#include "sysc/kernel/sc_macros.h" // SC_CONCAT_UNDERSCORE_ + // SC_STRINGIFY_HELPER_ +#include "sysc/communication/sc_writer_policy.h" // SC_DEFAULT_WRITER_POLICY + +#include <string> + +namespace sc_core { + +extern const char* sc_copyright(); +extern const char* sc_release(); +extern const char* sc_version(); + +extern const unsigned int sc_version_major; +extern const unsigned int sc_version_minor; +extern const unsigned int sc_version_patch; + +extern const std::string sc_version_originator; +extern const std::string sc_version_release_date; +extern const std::string sc_version_prerelease; +extern const bool sc_is_prerelease; +extern const std::string sc_version_string; +extern const std::string sc_copyright_string; + +#define SYSTEMC_2_3_1 + +#define SYSTEMC_VERSION 20140417 +#define SC_VERSION_ORIGINATOR "Accellera" +#define SC_VERSION_MAJOR 2 +#define SC_VERSION_MINOR 3 +#define SC_VERSION_PATCH 1 +#define SC_IS_PRERELEASE 0 + +/// compliancy with IEEE 1666-2011 (see 8.6.5) +#define IEEE_1666_SYSTEMC 201101L + +#define SC_COPYRIGHT \ + "Copyright (c) 1996-2014 by all Contributors,\n" \ + "ALL RIGHTS RESERVED\n" + + +#define SC_VERSION_RELEASE_DATE \ + SC_STRINGIFY_HELPER_( SYSTEMC_VERSION ) + +#if ( SC_IS_PRERELEASE == 1 ) +# define SC_VERSION_PRERELEASE "pub_rev" +# define SC_VERSION \ + SC_STRINGIFY_HELPER_( SC_VERSION_MAJOR.SC_VERSION_MINOR.SC_VERSION_PATCH ) \ + "_" SC_VERSION_PRERELEASE "_" SC_VERSION_RELEASE_DATE \ + "-" SC_VERSION_ORIGINATOR +#else +# define SC_VERSION_PRERELEASE "" // nothing +# define SC_VERSION \ + SC_STRINGIFY_HELPER_( SC_VERSION_MAJOR.SC_VERSION_MINOR.SC_VERSION_PATCH ) \ + "-" SC_VERSION_ORIGINATOR +#endif + +// THIS CLASS AND STATIC INSTANCE BELOW DETECTS BAD REV OBJECTS AT LINK TIME +// +// Each source file which includes this file for the current SystemC version +// will have a static instance of the class sc_api_version_XXX defined +// in it. That object instance will cause the constructor below +// to be invoked. If the version of the SystemC being linked against +// does not contain the constructor below a linkage error will occur. + +#define SC_API_VERSION_STRING \ + SC_CONCAT_UNDERSCORE_( sc_api_version, \ + SC_CONCAT_UNDERSCORE_( SC_VERSION_MAJOR, \ + SC_CONCAT_UNDERSCORE_( SC_VERSION_MINOR, \ + SC_VERSION_PATCH ) ) ) + +// explicitly avoid macro expansion +#define SC_API_DEFINED_( Symbol ) \ + Symbol ## _DEFINED_ +#define SC_API_UNDEFINED_( Symbol ) \ + Symbol ## _UNDEFINED_ + +// Some preprocessor switches need to be consistent between the application +// and the library (e.g. if sizes of classes are affected or other parts of +// the ABI are affected). (Some of) these are checked here at link-time as +// well, by setting template parameters to sc_api_version_XXX, while only +// one variant is defined in sc_ver.cpp. + +#if 0 // don't enforce check of DEBUG_SYSTEMC for now +// DEBUG_SYSTEMC +#if defined( DEBUG_SYSTEMC ) +# define DEBUG_SYSTEMC_CHECK_ \ + SC_CONFIG_DEFINED_(DEBUG_SYSTEMC) +#else +# define DEBUG_SYSTEMC_CHECK_ \ + SC_CONFIG_UNDEFINED_(DEBUG_SYSTEMC) +#endif +extern const int DEBUG_SYSTEMC_CHECK_; +#endif + +// SC_DISABLE_VIRTUAL_BIND +#if defined( SC_DISABLE_VIRTUAL_BIND ) +# define SC_DISABLE_VIRTUAL_BIND_CHECK_ \ + SC_API_DEFINED_(SC_DISABLE_VIRTUAL_BIND) +#else +# define SC_DISABLE_VIRTUAL_BIND_CHECK_ \ + SC_API_UNDEFINED_(SC_DISABLE_VIRTUAL_BIND) +#endif +extern const int SC_DISABLE_VIRTUAL_BIND_CHECK_; + +// Some preprocessor switches need to be consistent between different +// translation units of an application. Those can't be easily checked +// during link-time. Instead, perform a check during run-time by +// passing the value to the constructor of the api_version_check object. + +// Note: Template and constructor parameters are not passed as default +// values to avoid ODR violations in the check itself. + +template // use pointers for more verbose error messages +< +// const int * DebugSystemC, + const int * DisableVirtualBind +> +struct SC_API_VERSION_STRING +{ + SC_API_VERSION_STRING + ( + // SC_DEFAULT_WRITER_POLICY + sc_writer_policy default_writer_policy + ); +}; + +#if !defined( SC_DISABLE_API_VERSION_CHECK ) // disabled in sc_ver.cpp +static +SC_API_VERSION_STRING +< +// & DEBUG_SYSTEMC_CHECK_, + & SC_DISABLE_VIRTUAL_BIND_CHECK_ +> +api_version_check +( + SC_DEFAULT_WRITER_POLICY +); +#endif // SC_DISABLE_API_VERSION_CHECK + +//#undef SC_API_DEFINED_ +//#undef SC_API_UNDEFINED_ + +} // namespace sc_core + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ +#endif diff --git a/ext/systemc/src/sysc/kernel/sc_wait.cpp b/ext/systemc/src/sysc/kernel/sc_wait.cpp new file mode 100644 index 000000000..9c9f2bdfb --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_wait.cpp @@ -0,0 +1,446 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_wait.cpp -- Wait() and related functions. + + Original Author: Stan Y. Liao, Synopsys, Inc. + Martin Janssen, Synopsys, Inc. + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + + +#include "sysc/kernel/sc_except.h" +#include "sysc/kernel/sc_kernel_ids.h" +#include "sysc/kernel/sc_cthread_process.h" +#include "sysc/kernel/sc_thread_process.h" +#include "sysc/kernel/sc_simcontext_int.h" +#include "sysc/kernel/sc_wait.h" +#include "sysc/utils/sc_utils_ids.h" + +namespace sc_core { + +// static sensitivity for SC_THREADs and SC_CTHREADs + +void warn_cthread_wait() +{ + static bool warn_wait = true; + if ( warn_wait ) + { + warn_wait = false; + SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, + "all waits except wait() and wait(N)\n" \ + " are deprecated for SC_CTHREAD, " \ + "use an SC_THREAD instead"); + } +} + +void +wait( sc_simcontext* simc ) +{ + sc_curr_proc_handle cpi = simc->get_curr_proc_info(); + switch( cpi->kind ) { + case SC_THREAD_PROC_: + case SC_CTHREAD_PROC_: { + RCAST<sc_cthread_handle>( cpi->process_handle )->wait_cycles(); + break; + } + default: + SC_REPORT_ERROR( SC_ID_WAIT_NOT_ALLOWED_, "\n " + "in SC_METHODs use next_trigger() instead" ); + break; + } +} + +// dynamic sensitivity for SC_THREADs and SC_CTHREADs + +void +wait( const sc_event& e, sc_simcontext* simc ) +{ + sc_curr_proc_handle cpi = simc->get_curr_proc_info(); + switch( cpi->kind ) { + case SC_THREAD_PROC_: { + RCAST<sc_thread_handle>( cpi->process_handle )->wait( e ); + break; + } + case SC_CTHREAD_PROC_: { + warn_cthread_wait(); + sc_cthread_handle cthread_h = + RCAST<sc_cthread_handle>( cpi->process_handle ); + cthread_h->wait( e ); + cthread_h->wait_cycles(); + break; + } + default: + SC_REPORT_ERROR( SC_ID_WAIT_NOT_ALLOWED_, "\n " + "in SC_METHODs use next_trigger() instead" ); + break; + } +} + +void +wait( const sc_event_or_list& el, sc_simcontext* simc ) +{ + sc_curr_proc_handle cpi = simc->get_curr_proc_info(); + switch( cpi->kind ) { + case SC_THREAD_PROC_: { + RCAST<sc_thread_handle>( cpi->process_handle )->wait( el ); + break; + } + case SC_CTHREAD_PROC_: { + warn_cthread_wait(); + SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, + "wait(event_list) is deprecated for SC_CTHREAD, use SC_THREAD"); + sc_cthread_handle cthread_h = + RCAST<sc_cthread_handle>( cpi->process_handle ); + cthread_h->wait( el ); + cthread_h->wait_cycles(); + break; + } + default: + SC_REPORT_ERROR( SC_ID_WAIT_NOT_ALLOWED_, "\n " + "in SC_METHODs use next_trigger() instead" ); + break; + } +} + +void +wait( const sc_event_and_list& el, sc_simcontext* simc ) +{ + sc_curr_proc_handle cpi = simc->get_curr_proc_info(); + switch( cpi->kind ) { + case SC_THREAD_PROC_: { + RCAST<sc_thread_handle>( cpi->process_handle )->wait( el ); + break; + } + case SC_CTHREAD_PROC_: { + warn_cthread_wait(); + sc_cthread_handle cthread_h = + RCAST<sc_cthread_handle>( cpi->process_handle ); + cthread_h->wait( el ); + cthread_h->wait_cycles(); + break; + } + default: + SC_REPORT_ERROR( SC_ID_WAIT_NOT_ALLOWED_, "\n " + "in SC_METHODs use next_trigger() instead" ); + break; + } +} + +void +wait( const sc_time& t, sc_simcontext* simc ) +{ + sc_curr_proc_handle cpi = simc->get_curr_proc_info(); + switch( cpi->kind ) { + case SC_THREAD_PROC_: { + RCAST<sc_thread_handle>( cpi->process_handle )->wait( t ); + break; + } + case SC_CTHREAD_PROC_: { + warn_cthread_wait(); + sc_cthread_handle cthread_h = + RCAST<sc_cthread_handle>( cpi->process_handle ); + cthread_h->wait( t ); + cthread_h->wait_cycles(); + break; + } + default: + SC_REPORT_ERROR( SC_ID_WAIT_NOT_ALLOWED_, "\n " + "in SC_METHODs use next_trigger() instead" ); + break; + } +} + +void +wait( const sc_time& t, const sc_event& e, sc_simcontext* simc ) +{ + sc_curr_proc_handle cpi = simc->get_curr_proc_info(); + switch( cpi->kind ) { + case SC_THREAD_PROC_: { + RCAST<sc_thread_handle>( cpi->process_handle )->wait( t, e ); + break; + } + case SC_CTHREAD_PROC_: { + warn_cthread_wait(); + sc_cthread_handle cthread_h = + RCAST<sc_cthread_handle>( cpi->process_handle ); + cthread_h->wait( t, e ); + cthread_h->wait_cycles(); + break; + } + default: + SC_REPORT_ERROR( SC_ID_WAIT_NOT_ALLOWED_, "\n " + "in SC_METHODs use next_trigger() instead" ); + break; + } +} + +void +wait( const sc_time& t, const sc_event_or_list& el, sc_simcontext* simc ) +{ + sc_curr_proc_handle cpi = simc->get_curr_proc_info(); + switch( cpi->kind ) { + case SC_THREAD_PROC_: { + RCAST<sc_thread_handle>( cpi->process_handle )->wait( t, el ); + break; + } + case SC_CTHREAD_PROC_: { + warn_cthread_wait(); + sc_cthread_handle cthread_h = + RCAST<sc_cthread_handle>( cpi->process_handle ); + cthread_h->wait( t, el ); + cthread_h->wait_cycles(); + break; + } + default: + SC_REPORT_ERROR( SC_ID_WAIT_NOT_ALLOWED_, "\n " + "in SC_METHODs use next_trigger() instead" ); + break; + } +} + +void +wait( const sc_time& t, const sc_event_and_list& el, sc_simcontext* simc ) +{ + sc_curr_proc_handle cpi = simc->get_curr_proc_info(); + switch( cpi->kind ) { + case SC_THREAD_PROC_: { + RCAST<sc_thread_handle>( cpi->process_handle )->wait( t, el ); + break; + } + case SC_CTHREAD_PROC_: { + warn_cthread_wait(); + sc_cthread_handle cthread_h = + RCAST<sc_cthread_handle>( cpi->process_handle ); + cthread_h->wait( t, el ); + cthread_h->wait_cycles(); + break; + } + default: + SC_REPORT_ERROR( SC_ID_WAIT_NOT_ALLOWED_, "\n " + "in SC_METHODs use next_trigger() instead" ); + break; + } +} + + +// static sensitivity for SC_METHODs + +void +next_trigger( sc_simcontext* simc ) +{ + sc_curr_proc_handle cpi = simc->get_curr_proc_info(); + if( cpi->kind == SC_METHOD_PROC_ ) { + RCAST<sc_method_handle>( cpi->process_handle )->clear_trigger(); + } else { + SC_REPORT_ERROR( SC_ID_NEXT_TRIGGER_NOT_ALLOWED_, "\n " + "in SC_THREADs and SC_CTHREADs use wait() instead" ); + } +} + + +// dynamic sensitivity for SC_METHODs + +void +next_trigger( const sc_event& e, sc_simcontext* simc ) +{ + sc_curr_proc_handle cpi = simc->get_curr_proc_info(); + if( cpi->kind == SC_METHOD_PROC_ ) { + RCAST<sc_method_handle>( cpi->process_handle )->next_trigger( e ); + } else { + SC_REPORT_ERROR( SC_ID_NEXT_TRIGGER_NOT_ALLOWED_, "\n " + "in SC_THREADs and SC_CTHREADs use wait() instead" ); + } +} + +void +next_trigger( const sc_event_or_list& el, sc_simcontext* simc ) +{ + sc_curr_proc_handle cpi = simc->get_curr_proc_info(); + if( cpi->kind == SC_METHOD_PROC_ ) { + RCAST<sc_method_handle>( cpi->process_handle )->next_trigger( el ); + } else { + SC_REPORT_ERROR( SC_ID_NEXT_TRIGGER_NOT_ALLOWED_, "\n " + "in SC_THREADs and SC_CTHREADs use wait() instead" ); + } +} + +void +next_trigger( const sc_event_and_list& el, sc_simcontext* simc ) +{ + sc_curr_proc_handle cpi = simc->get_curr_proc_info(); + if( cpi->kind == SC_METHOD_PROC_ ) { + RCAST<sc_method_handle>( cpi->process_handle )->next_trigger( el ); + } else { + SC_REPORT_ERROR( SC_ID_NEXT_TRIGGER_NOT_ALLOWED_, "\n " + "in SC_THREADs and SC_CTHREADs use wait() instead" ); + } +} + +void +next_trigger( const sc_time& t, sc_simcontext* simc ) +{ + sc_curr_proc_handle cpi = simc->get_curr_proc_info(); + if( cpi->kind == SC_METHOD_PROC_ ) { + RCAST<sc_method_handle>( cpi->process_handle )->next_trigger( t ); + } else { + SC_REPORT_ERROR( SC_ID_NEXT_TRIGGER_NOT_ALLOWED_, "\n " + "in SC_THREADs and SC_CTHREADs use wait() instead" ); + } +} + +void +next_trigger( const sc_time& t, const sc_event& e, sc_simcontext* simc ) +{ + sc_curr_proc_handle cpi = simc->get_curr_proc_info(); + if( cpi->kind == SC_METHOD_PROC_ ) { + RCAST<sc_method_handle>( cpi->process_handle )->next_trigger( t, e ); + } else { + SC_REPORT_ERROR( SC_ID_NEXT_TRIGGER_NOT_ALLOWED_, "\n " + "in SC_THREADs and SC_CTHREADs use wait() instead" ); + } +} + +void +next_trigger( const sc_time& t, const sc_event_or_list& el, sc_simcontext* simc) +{ + sc_curr_proc_handle cpi = simc->get_curr_proc_info(); + if( cpi->kind == SC_METHOD_PROC_ ) { + RCAST<sc_method_handle>( cpi->process_handle )->next_trigger( t, el ); + } else { + SC_REPORT_ERROR( SC_ID_NEXT_TRIGGER_NOT_ALLOWED_, "\n " + "in SC_THREADs and SC_CTHREADs use wait() instead" ); + } +} + +void +next_trigger(const sc_time& t, const sc_event_and_list& el, sc_simcontext* simc) +{ + sc_curr_proc_handle cpi = simc->get_curr_proc_info(); + if( cpi->kind == SC_METHOD_PROC_ ) { + RCAST<sc_method_handle>( cpi->process_handle )->next_trigger( t, el ); + } else { + SC_REPORT_ERROR( SC_ID_NEXT_TRIGGER_NOT_ALLOWED_, "\n " + "in SC_THREADs and SC_CTHREADs use wait() instead" ); + } +} + + +// for SC_METHODs and SC_THREADs and SC_CTHREADs + +bool +timed_out( sc_simcontext* simc ) +{ + static bool warn_timed_out=true; + if ( warn_timed_out ) + { + warn_timed_out = false; + SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, + "timed_out() function is deprecated" ); + } + + sc_curr_proc_handle cpi = simc->get_curr_proc_info(); + return cpi->process_handle->timed_out(); +} + + + +// misc. + +void +sc_set_location( const char* file, int lineno, sc_simcontext* simc ) +{ + sc_curr_proc_handle cpi = simc->get_curr_proc_info(); + sc_process_b* handle = cpi->process_handle; + handle->file = file; + handle->lineno = lineno; +} + +} // namespace sc_core + +/* +$Log: sc_wait.cpp,v $ +Revision 1.6 2011/08/26 20:46:11 acg + Andy Goodrich: moved the modification log to the end of the file to + eliminate source line number skew when check-ins are done. + +Revision 1.5 2011/02/18 20:27:14 acg + Andy Goodrich: Updated Copyrights. + +Revision 1.4 2011/02/13 21:47:38 acg + Andy Goodrich: update copyright notice. + +Revision 1.3 2011/01/18 20:10:45 acg + Andy Goodrich: changes for IEEE1666_2011 semantics. + +Revision 1.2 2008/05/22 17:06:27 acg + Andy Goodrich: updated copyright notice to include 2008. + +Revision 1.1.1.1 2006/12/15 20:20:05 acg +SystemC 2.3 + +Revision 1.7 2006/02/02 20:20:39 acg + Andy Goodrich: warnings for SC_THREAD waits. + +Revision 1.6 2006/02/01 01:36:54 acg + Andy Goodrich: addition of deprecation comments for SC_CTHREAD waits other + than wait() and wait(N). + +Revision 1.5 2006/01/31 22:17:40 acg + Andy Goodrich: added deprecation warnings for SC_CTHREAD waits other than + wait() and wait(N). + +Revision 1.4 2006/01/25 00:31:20 acg + Andy Goodrich: Changed over to use a standard message id of + SC_ID_IEEE_1666_DEPRECATION for all deprecation messages. + +Revision 1.3 2006/01/24 20:49:05 acg +Andy Goodrich: changes to remove the use of deprecated features within the +simulator, and to issue warning messages when deprecated features are used. + +Revision 1.2 2006/01/03 23:18:45 acg +Changed copyright to include 2006. + +Revision 1.1.1.1 2005/12/19 23:16:44 acg +First check in of SystemC 2.1 into its own archive. + +Revision 1.10 2005/09/02 19:03:30 acg +Changes for dynamic processes. Removal of lambda support. + +Revision 1.9 2005/07/30 03:45:05 acg +Changes from 2.1, including changes for sc_process_handle. + +Revision 1.8 2005/04/04 00:16:07 acg +Changes for directory name change to sys from systemc. +Changes for sc_string going to std::string. +Changes for sc_pvector going to std::vector. +Changes for reference pools for bit and part selections. +Changes for const sc_concatref support. + +Revision 1.5 2004/09/27 20:49:10 acg +Andy Goodrich, Forte Design Systems, Inc. + - Added a $Log comment so that CVS checkin comments appear in the + checkout source. + +*/ + +// Taf! diff --git a/ext/systemc/src/sysc/kernel/sc_wait.h b/ext/systemc/src/sysc/kernel/sc_wait.h new file mode 100644 index 000000000..f598cf4bb --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_wait.h @@ -0,0 +1,277 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_wait.h -- Wait() and related functions. + + Original Author: Stan Y. Liao, Synopsys, Inc. + Martin Janssen, Synopsys, Inc. + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + +#ifndef SC_WAIT_H +#define SC_WAIT_H + + +#include "sysc/kernel/sc_simcontext.h" + +namespace sc_core { + +class sc_event; +class sc_event_and_list; +class sc_event_or_list; +class sc_simcontext; + +extern sc_simcontext* sc_get_curr_simcontext(); + +// static sensitivity for SC_THREADs and SC_CTHREADs + +extern +void +wait( sc_simcontext* = sc_get_curr_simcontext() ); + + +// dynamic sensitivity for SC_THREADs and SC_CTHREADs + +extern +void +wait( const sc_event&, + sc_simcontext* = sc_get_curr_simcontext() ); + +extern +void +wait( const sc_event_or_list&, + sc_simcontext* = sc_get_curr_simcontext() ); + +extern +void +wait( const sc_event_and_list&, + sc_simcontext* = sc_get_curr_simcontext() ); + +extern +void +wait( const sc_time&, + sc_simcontext* = sc_get_curr_simcontext() ); + +inline +void +wait( double v, sc_time_unit tu, + sc_simcontext* simc = sc_get_curr_simcontext() ) +{ + wait( sc_time( v, tu, simc ), simc ); +} + +extern +void +wait( const sc_time&, + const sc_event&, + sc_simcontext* = sc_get_curr_simcontext() ); + +inline +void +wait( double v, sc_time_unit tu, + const sc_event& e, + sc_simcontext* simc = sc_get_curr_simcontext() ) +{ + wait( sc_time( v, tu, simc ), e, simc ); +} + +extern +void +wait( const sc_time&, + const sc_event_or_list&, + sc_simcontext* = sc_get_curr_simcontext() ); + +inline +void +wait( double v, sc_time_unit tu, + const sc_event_or_list& el, + sc_simcontext* simc = sc_get_curr_simcontext() ) +{ + wait( sc_time( v, tu, simc ), el, simc ); +} + +extern +void +wait( const sc_time&, + const sc_event_and_list&, + sc_simcontext* = sc_get_curr_simcontext() ); + +inline +void +wait( double v, sc_time_unit tu, + const sc_event_and_list& el, + sc_simcontext* simc = sc_get_curr_simcontext() ) +{ + wait( sc_time( v, tu, simc ), el, simc ); +} + + +// static sensitivity for SC_METHODs + +extern +void +next_trigger( sc_simcontext* = sc_get_curr_simcontext() ); + + +// dynamic sensitivity for SC_METHODs + +extern +void +next_trigger( const sc_event&, + sc_simcontext* = sc_get_curr_simcontext() ); + +extern +void +next_trigger( const sc_event_or_list&, + sc_simcontext* = sc_get_curr_simcontext() ); + +extern +void +next_trigger( const sc_event_and_list&, + sc_simcontext* = sc_get_curr_simcontext() ); + +extern +void +next_trigger( const sc_time&, + sc_simcontext* = sc_get_curr_simcontext() ); + +inline +void +next_trigger( double v, sc_time_unit tu, + sc_simcontext* simc = sc_get_curr_simcontext() ) +{ + next_trigger( sc_time( v, tu, simc ), simc ); +} + +extern +void +next_trigger( const sc_time&, + const sc_event&, + sc_simcontext* = sc_get_curr_simcontext() ); + +inline +void +next_trigger( double v, sc_time_unit tu, + const sc_event& e, + sc_simcontext* simc = sc_get_curr_simcontext() ) +{ + next_trigger( sc_time( v, tu, simc ), e, simc ); +} + +extern +void +next_trigger( const sc_time&, + const sc_event_or_list&, + sc_simcontext* = sc_get_curr_simcontext() ); + +inline +void +next_trigger( double v, sc_time_unit tu, + const sc_event_or_list& el, + sc_simcontext* simc = sc_get_curr_simcontext() ) +{ + next_trigger( sc_time( v, tu, simc ), el, simc ); +} + +extern +void +next_trigger( const sc_time&, + const sc_event_and_list&, + sc_simcontext* = sc_get_curr_simcontext() ); + +inline +void +next_trigger( double v, sc_time_unit tu, + const sc_event_and_list& el, + sc_simcontext* simc = sc_get_curr_simcontext() ) +{ + next_trigger( sc_time( v, tu, simc ), el, simc ); +} + + +// for SC_METHODs and SC_THREADs and SC_CTHREADs + +extern +bool +timed_out( sc_simcontext* = sc_get_curr_simcontext() ); + +// misc. + +extern +void +sc_set_location( const char*, + int, + sc_simcontext* = sc_get_curr_simcontext() ); + +} // namespace sc_core + +/* +$Log: sc_wait.h,v $ +Revision 1.6 2011/08/26 20:46:11 acg + Andy Goodrich: moved the modification log to the end of the file to + eliminate source line number skew when check-ins are done. + +Revision 1.5 2011/02/18 20:27:14 acg + Andy Goodrich: Updated Copyrights. + +Revision 1.4 2011/02/13 21:47:38 acg + Andy Goodrich: update copyright notice. + +Revision 1.3 2011/01/18 20:10:45 acg + Andy Goodrich: changes for IEEE1666_2011 semantics. + +Revision 1.2 2008/05/22 17:06:27 acg + Andy Goodrich: updated copyright notice to include 2008. + +Revision 1.1.1.1 2006/12/15 20:20:05 acg +SystemC 2.3 + +Revision 1.2 2006/01/03 23:18:45 acg +Changed copyright to include 2006. + +Revision 1.1.1.1 2005/12/19 23:16:44 acg +First check in of SystemC 2.1 into its own archive. + +Revision 1.10 2005/07/30 03:45:05 acg +Changes from 2.1, including changes for sc_process_handle. + +Revision 1.9 2005/04/04 00:16:08 acg +Changes for directory name change to sys from systemc. +Changes for sc_string going to std::string. +Changes for sc_pvector going to std::vector. +Changes for reference pools for bit and part selections. +Changes for const sc_concatref support. + +Revision 1.6 2004/10/13 18:13:22 acg +sc_ver.h - updated version number. sc_wait.h remove inclusion of +sysc/kernel/sc_event.h because it is not necessary. + +Revision 1.5 2004/09/27 20:49:10 acg +Andy Goodrich, Forte Design Systems, Inc. + - Added a $Log comment so that CVS checkin comments appear in the + checkout source. + +*/ + +#endif + +// Taf! diff --git a/ext/systemc/src/sysc/kernel/sc_wait_cthread.cpp b/ext/systemc/src/sysc/kernel/sc_wait_cthread.cpp new file mode 100644 index 000000000..4dee96ed7 --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_wait_cthread.cpp @@ -0,0 +1,169 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_wait_cthread.cpp -- Wait() and related functions for SC_CTHREADs. + + Original Author: Stan Y. Liao, Synopsys, Inc. + Martin Janssen, Synopsys, Inc. + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + + + +#include "sysc/kernel/sc_kernel_ids.h" +#include "sysc/kernel/sc_cthread_process.h" +#include "sysc/kernel/sc_simcontext_int.h" +#include "sysc/kernel/sc_wait_cthread.h" +#include "sysc/communication/sc_port.h" +#include "sysc/kernel/sc_wait.h" +namespace sc_core +{ + +// for SC_CTHREADs + +void +halt( sc_simcontext* simc ) +{ + sc_curr_proc_handle cpi = simc->get_curr_proc_info(); + switch( cpi->kind ) { + case SC_CTHREAD_PROC_: { + RCAST<sc_cthread_handle>( cpi->process_handle )->wait_halt(); + break; + } + default: + SC_REPORT_ERROR( SC_ID_HALT_NOT_ALLOWED_, 0 ); + break; + } +} + + +void +wait( int n, sc_simcontext* simc ) +{ + sc_curr_proc_handle cpi = simc->get_curr_proc_info(); + if( n <= 0 ) { + char msg[BUFSIZ]; + std::sprintf( msg, "n = %d", n ); + SC_REPORT_ERROR( SC_ID_WAIT_N_INVALID_, msg ); + } + switch( cpi->kind ) { + case SC_THREAD_PROC_: + case SC_CTHREAD_PROC_: + RCAST<sc_cthread_handle>( cpi->process_handle )->wait_cycles( n ); + break; + default: + SC_REPORT_ERROR( SC_ID_WAIT_NOT_ALLOWED_, "\n " + "in SC_METHODs use next_trigger() instead" ); + break; + } +} + + +void +at_posedge( const sc_signal_in_if<bool>& s, sc_simcontext* simc ) +{ + if( s.read() == true ) + do { wait(simc); } while ( s.read() == true ); + do { wait(simc); } while ( s.read() == false ); +} + +void +at_posedge( const sc_signal_in_if<sc_dt::sc_logic>& s, sc_simcontext* simc ) +{ + if( s.read() == '1' ) + do { wait(simc); } while ( s.read() == '1' ); + do { wait(simc); } while ( s.read() == '0' ); +} + +void +at_negedge( const sc_signal_in_if<bool>& s, sc_simcontext* simc ) +{ + if( s.read() == false ) + do { wait(simc); } while ( s.read() == false ); + do { wait(simc); } while ( s.read() == true ); +} + +void +at_negedge( const sc_signal_in_if<sc_dt::sc_logic>& s, sc_simcontext* simc ) +{ + if( s.read() == '0' ) + do { wait(simc); } while ( s.read() == '0' ); + do { wait(simc); } while ( s.read() == '1' ); +} + + +} // namespace sc_core + +/* +$Log: sc_wait_cthread.cpp,v $ +Revision 1.6 2011/08/26 20:46:11 acg + Andy Goodrich: moved the modification log to the end of the file to + eliminate source line number skew when check-ins are done. + +Revision 1.5 2011/02/18 20:27:14 acg + Andy Goodrich: Updated Copyrights. + +Revision 1.4 2011/02/13 21:47:38 acg + Andy Goodrich: update copyright notice. + +Revision 1.3 2009/10/14 19:07:42 acg + Andy Goodrich: added an error message for wait(n) being called from an + SC_METHOD. + +Revision 1.2 2008/05/22 17:06:27 acg + Andy Goodrich: updated copyright notice to include 2008. + +Revision 1.1.1.1 2006/12/15 20:20:05 acg +SystemC 2.3 + +Revision 1.3 2006/03/13 20:26:51 acg + Andy Goodrich: Addition of forward class declarations, e.g., + sc_reset, to keep gcc 4.x happy. + +Revision 1.2 2006/01/03 23:18:45 acg +Changed copyright to include 2006. + +Revision 1.1.1.1 2005/12/19 23:16:44 acg +First check in of SystemC 2.1 into its own archive. + +Revision 1.10 2005/09/15 23:02:18 acg +Added std:: prefix to appropriate methods and types to get around +issues with the Edison Front End. + +Revision 1.9 2005/09/02 19:03:30 acg +Changes for dynamic processes. Removal of lambda support. + +Revision 1.8 2005/04/04 00:16:08 acg +Changes for directory name change to sys from systemc. +Changes for sc_string going to std::string. +Changes for sc_pvector going to std::vector. +Changes for reference pools for bit and part selections. +Changes for const sc_concatref support. + +Revision 1.5 2004/09/27 20:49:10 acg +Andy Goodrich, Forte Design Systems, Inc. + - Added a $Log comment so that CVS checkin comments appear in the + checkout source. + +*/ + +// Taf! diff --git a/ext/systemc/src/sysc/kernel/sc_wait_cthread.h b/ext/systemc/src/sysc/kernel/sc_wait_cthread.h new file mode 100644 index 000000000..a04bfecc1 --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_wait_cthread.h @@ -0,0 +1,126 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_wait_cthread.h -- Wait() and related functions for SC_CTHREADs. + + Original Author: Stan Y. Liao, Synopsys, Inc. + Martin Janssen, Synopsys, Inc. + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + + +#ifndef SC_WAIT_CTHREAD_H +#define SC_WAIT_CTHREAD_H + + +#include "sysc/kernel/sc_simcontext.h" +#include "sysc/datatypes/bit/sc_logic.h" +#include "sysc/communication/sc_signal_ifs.h" + + +namespace sc_core +{ + +// for SC_CTHREADs + +extern +void +halt( sc_simcontext* = sc_get_curr_simcontext() ); + + +extern +void +wait( int, + sc_simcontext* = sc_get_curr_simcontext() ); + + +extern +void +at_posedge( const sc_signal_in_if<bool>&, + sc_simcontext* = sc_get_curr_simcontext() ); + +extern +void +at_posedge( const sc_signal_in_if<sc_dt::sc_logic>&, + sc_simcontext* = sc_get_curr_simcontext() ); + +extern +void +at_negedge( const sc_signal_in_if<bool>&, + sc_simcontext* = sc_get_curr_simcontext() ); + +extern +void +at_negedge( const sc_signal_in_if<sc_dt::sc_logic>&, + sc_simcontext* = sc_get_curr_simcontext() ); + + +} // namespace sc_core + +/* +$Log: sc_wait_cthread.h,v $ +Revision 1.6 2011/08/26 20:46:11 acg + Andy Goodrich: moved the modification log to the end of the file to + eliminate source line number skew when check-ins are done. + +Revision 1.5 2011/08/24 22:05:51 acg + Torsten Maehne: initialization changes to remove warnings. + +Revision 1.4 2011/02/18 20:27:14 acg + Andy Goodrich: Updated Copyrights. + +Revision 1.3 2011/02/13 21:47:38 acg + Andy Goodrich: update copyright notice. + +Revision 1.2 2008/05/22 17:06:27 acg + Andy Goodrich: updated copyright notice to include 2008. + +Revision 1.1.1.1 2006/12/15 20:20:05 acg +SystemC 2.3 + +Revision 1.2 2006/01/03 23:18:45 acg +Changed copyright to include 2006. + +Revision 1.1.1.1 2005/12/19 23:16:44 acg +First check in of SystemC 2.1 into its own archive. + +Revision 1.10 2005/09/02 19:03:30 acg +Changes for dynamic processes. Removal of lambda support. + +Revision 1.9 2005/04/04 00:16:08 acg +Changes for directory name change to sys from systemc. +Changes for sc_string going to std::string. +Changes for sc_pvector going to std::vector. +Changes for reference pools for bit and part selections. +Changes for const sc_concatref support. + +Revision 1.6 2005/01/10 17:52:20 acg +Addition of namespace specifications. + +Revision 1.5 2004/09/27 20:49:10 acg +Andy Goodrich, Forte Design Systems, Inc. + - Added a $Log comment so that CVS checkin comments appear in the + checkout source. + +*/ + +#endif diff --git a/ext/systemc/src/sysc/qt/CHANGES b/ext/systemc/src/sysc/qt/CHANGES new file mode 100644 index 000000000..1b74921ee --- /dev/null +++ b/ext/systemc/src/sysc/qt/CHANGES @@ -0,0 +1,15 @@ +QuickThreads 002: Changes since QuickThreads 001. + + - Now can be used by C++ programs. + - Now *really* works with stacks that grow up. + - Supports AXP OSF 2.x cc's varargs. + - Supports HP Precision (HP-PA) on workstations and Convex. + - Supports assemblers for Intel iX86 ith only '//'-style comments. + - Supports Silicon Graphics Irix 5.x with dynamic linking. + - Supports System V and Solaris 2.x with no `_' on compiler-generated + identifiers; *some* platforms only. + +Note: not all "./config" arguments are compatible with QT 001. + + +QuickThreads 001: Base version. diff --git a/ext/systemc/src/sysc/qt/INSTALL b/ext/systemc/src/sysc/qt/INSTALL new file mode 100644 index 000000000..5b20f5d5e --- /dev/null +++ b/ext/systemc/src/sysc/qt/INSTALL @@ -0,0 +1,81 @@ +Installation of the `QuickThreads' threads-building toolkit. + +* Notice + +QuickThreads -- Threads-building toolkit. +Copyright (c) 1993 by David Keppel + +Permission to use, copy, modify and distribute this software and +its documentation for any purpose and without fee is hereby +granted, provided that the above copyright notice and this notice +appear in all copies. This software is provided as a +proof-of-concept and for demonstration purposes; there is no +representation about the suitability of this software for any +purpose. + + +* Configuration + +Configure with + + ./config *machtype* + +where "*machtype*" is one of the supported target machines. As of +October 1994, the supported machines (targets) are: + + axp -- All Digital Equipment Corporation AXP (DEC Alpha) + processors, compile with GNU CC + axp-osf1 -- AXP running OSF 1.x + axp-osf2 -- AXP running OSF 2.x + hppa -- HP's PA-RISC 1.1 processor + hppa-cnx-spp -- Convex SPP (PA-RISC 1.1 processor) + iX86 -- 80386, 80486, and 80586-compatible processors + See notes below for OS/2. + iX86-ss -- 'iX86 for assemblers that use slash-slash ('//') + comments. + ksr1 -- All KSR processors + m88k -- All members of the Motorola 88000 family + mips -- MIPS R2000 and R3000 processors + mips-irix5 -- Irix 5.xx (use `mips' for Irix 4.xx) + sparc-os1 -- V8-compliant SPARC processors using compilers + that prefix labels (e.g. "foo" appears as "_foo") + Includes Solaris 1 (SunOS 4.X). + sparc-os2 -- V8-compliant SPARC processors using compilers + that do not prefix labels. Includes Solaris 2. + vax -- All VAX processors + +In addition, the target `clean' will deconfigure QuickThreads. + +Note that a given machine target may not work on all instances of that +machine because e.g., the assembler syntax varies from machine to +machine. + +Note also that additions to a processor family may require a new +target. So, for example, the `vax' target might not work for all +future VAX processors if, say, new VAX processors are introduced and +they use separate floating-point registers. + +For OS/2, change `ranlib' to `ar -s', `configure' to `configure.cmd' +(or was that `config' to `config.cmd'?), and replace the soft links +(`ln -s') with plain copies. + + +* Build + +To build the QuickThreads library, first configure (see above) then +type `make libqt.a' in the top-level directory. + +To build the demonstration threads package, SimpleThreads, type +`make libstp.a' in the top-level directory. + +To build an executable ``stress-test'' and measurement program, type +`make run' in the top-level directory. Run `time/raw' to run the +stress tests. + + +* Installation + +Build the QuickThreads library (see above) and then copy `libqt.a' to +the installation library directory (e.g., /usr/local/lib) and `qt.h' +and `qtmd.h' to the installation include directory (e.g., +/usr/local/include). diff --git a/ext/systemc/src/sysc/qt/README b/ext/systemc/src/sysc/qt/README new file mode 100644 index 000000000..b014b91bf --- /dev/null +++ b/ext/systemc/src/sysc/qt/README @@ -0,0 +1,89 @@ +This is a source code distribution for QuickThreads. QuickThreads is a +toolkit for building threads packages; it is described in detail in the +University of Washington CS&E Technical report #93-05-06, available via +anonymous ftp from `ftp.cs.washington.edu' (128.95.1.4, as of Oct. '94) +in `tr/1993/05/UW-CSE-93-05-06.PS.Z'. + +This distribution shows basic ideas in QuickThreads and elaborates with +example implementations for a gaggle of machines. As of October those +machines included: + + 80386 faimly + 88000 faimily + DEC AXP (Alpha) family + HP-PA family + KSR + MIPS family + SPARC V8 family + VAX family + +Configuration, build, and installation are described in INSTALL. + +Be aware: that there is no varargs code for the KSR. + +The HP-PA port was designed to work with both HP workstations +and Convex SPP computers. It was generously provided by Uwe Reder +<uereder@cip.informatik.uni-erlangen.de>. It is part of the ELiTE +(Erlangen Lightweight Thread Environment) project directed by +Frank Bellosa <bellosa@informatik.uni-erlangen.de> at the Operating +Systems Department of the University of Erlangen (Germany). + +Other contributors include: Weihaw Chuang, Richard O'Keefe, +Laurent Perron, John Polstra, Shinji Suzuki, Assar Westerlund, +thanks also to Peter Buhr and Dirk Grunwald. + + +Here is a brief summary: + +QuickThreads is a toolkit for building threads packages. It is my hope +that you'll find it easier to use QuickThreads normally than to take it +and modify the raw cswap code to fit your application. The idea behind +QuickThreads is that it should make it easy for you to write & retarget +threads packages. If you want the routine `t_create' to create threads +and `t_block' to suspend threads, you write them using the QuickThreads +`primitive' operations `QT_SP', `QT_INIT', and `QT_BLOCK', that perform +machine-dependent initialization and blocking, plus code you supply for +performing the portable operatons. For example, you might write: + + t_create (func, arg) + { + stk = malloc (STKSIZE); + stackbase = QT_SP (stk, STKSIZE); + sp = QT_INIT (stakcbase, func, arg); + qput (runq, sp); + } + +Threads block by doing something like: + + t_block() + { + sp_next = qget (runq); + QT_BLOCK (helper, runq, sp_next); + // wake up again here + } + + // called by QT_BLOCK after the old thread has blocked, + // puts the old thread on the queue `onq'. + helper (sp_old, onq) + { + qput (onq, sp_old); + } + +(Of course) it's actually a bit more complex than that, but the general +idea is that you write portable code to allocate stacks and enqueue and +dequeue threads. Than, to get your threads package up and running on a +different machine, you just reconfigure QuickThreads and recompile, and +that's it. + +The QuickThreads `distribution' includes a sample threads package (look +at stp.{c,h}) that is written in terms of QuickThreads operations. The +TR mentioned above explains the simple threads package in detail. + + + +If you do use QuickThreads, I'd like to hear both about what worked for +you and what didn't work, problems you had, insights gleaned, etc. + +Let me know what you think. + +David Keppel <pardo@cs.washington.edu> diff --git a/ext/systemc/src/sysc/qt/README.MISC b/ext/systemc/src/sysc/qt/README.MISC new file mode 100644 index 000000000..d10e487cf --- /dev/null +++ b/ext/systemc/src/sysc/qt/README.MISC @@ -0,0 +1,56 @@ +Here's some machine-specific informatin for various systems: + +m88k on g88.sim + + .g88init: + echo (gdb) target sim\n + target sim + echo (gdb) ecatch all\n + ecatch all + echo (gdb) break exit\n + break exit + % vi Makefile // set CC and AS + % setenv MEERKAT /projects/cer/meerkat + % set path=($MEERKAT/bin $path) + % make run + % g88.sim run + (g88) run run N // where `N' is the test number + + +m88k on meerkats, cross compile as above (make run) + + Run w/ g88: + %g88 run + (g88) source /homes/rivers/robertb/.gdbinit + (g88) me + which does + (g88) set $firstchars=6 + (g88) set $resetonattach=1 + (g88) attach /dev/pp0 + then download + (g88) dl + and run with + (g88) continue + + Really the way to run it is: + (g88) source + (g88) me + (g88) win + (g88) dead 1 + (g88) dead 2 + (g88) dead 3 + (g88) dl + (g88) cont + + To rerun + (g88) init + (g88) dl + + To run simulated meerkat: + (g88) att sim + <<then use normal commands>> + + On 4.5 g88: + (g88) target sim memsize + instead of attatch + (g88) ecatch all # catch exception before becomes error diff --git a/ext/systemc/src/sysc/qt/README.PORT b/ext/systemc/src/sysc/qt/README.PORT new file mode 100644 index 000000000..d56300923 --- /dev/null +++ b/ext/systemc/src/sysc/qt/README.PORT @@ -0,0 +1,112 @@ +Date: Tue, 11 Jan 94 13:23:11 -0800 +From: "pardo@cs.washington.edu" <pardo@meitner.cs.washington.edu> + +>[What's needed to get `qt' on an i860-based machine?] + +Almost certainly "some assembly required" (pun accepted). + +To write a cswap port, you need to understand the context switching +model. Turn to figure 2 in the QT TR. Here's about what the assembly +code looks like to implement that: + + qt_cswap: + adjust stack pointer + save callee-save registers on to old's stack + argument register <- old sp + sp <- new sp + (*helper)(args...) + restore callee-save registers from new's stack + unadjust stack pointer + return + +Once more in slow motion: + + - `old' thread calls context switch routine (new, a0, a1, h) + - cswap routine saves registers that have useful values + - cswap routine switches to new stack + - cswap routine calls helper function (*h)(old, a0, a1) + - when helper returns, cswap routine restores registers + that were saved the last time `new' was suspended + - cswap routine returns to whatever `new' routine called the + context switch routine + +There's a few tricks here. First, how do you start a thread running +for the very first time? Answer is: fake some stuff on the stack +so it *looks* like it was called from the middle of some routine. +When the new thread is restarted, it is treated like any other +thread. It just so happens that it's never really run before, but +you can't tell that because the saved state makes it look like like +it's been run. The return pc is set to point at a little stub of +assembly code that loads up registers with the right values and +then calls `only'. + +Second, I advise you to forget about varargs routines (at least +until you get single-arg routines up and running). + +Third, on most machines `qt_abort' is the same as `qt_cswap' except +that it need not save any callee-save registers. + +Fourth, `qt_cswap' needs to save and restore any floating-point +registers that are callee-save (see your processor handbook). On +some machines, *no* floating-point registers are callee-save, so +`qt_cswap' is exactly the same as the integer-only cswap routine. + +I suggest staring at the MIPS code for a few minutes. It's "mostly" +generic RISC code, so it gets a lot of the flavor across without +getting too bogged down in little nitty details. + + + +Now for a bit more detail: The stack is laid out to hold callee-save +registers. On many machines, I implemented fp cswap as save fp +regs, call integer cswap, and when integer cswap returns (when the +thread wakes up again), restore fp regs. + +For thread startup, I figure out some callee-save registers that +I use to hold parameters to the startup routine (`only'). When +the thread is being started it doesn't have any saved registers +that need to be restored, but I go ahead and let the integer context +switch routine restore some registers then "return" to the stub +code. The stub code then copies the "callee save" registers to +argument registers and calls the startup routine. That keeps the +stub code pretty darn simple. + +For each machine I need to know the machine's procedure calling +convention before I write a port. I figure out how many callee-save +registers are there and allocate enough stack space for those +registers. I also figure out how parameters are passed, since I +will need to call the helper function. On most RISC machines, I +just need to put the old sp in the 0'th arg register and then call +indirect through the 3rd arg register; the 1st and 2nd arg registers +are already set up correctly. Likewise, I don't touch the return +value register between the helper's return and the context switch +routine's return. + +I have a bunch of macros set up to do the stack initialization. +The easiest way to debug this stuff is to go ahead and write a C +routine to do stack initialization. Once you're happy with it you +can turn it in to a macro. + +In general there's a lot of ugly macros, but most of them do simple +things like return constants, etc. Any time you're looking at it +and it looks confusing you just need to remember "this is actually +simple code, the only tricky thing is calling the helper between +the stack switch and the new thread's register restore." + + +You will almost certainly need to write the assembly code fragment +that starts a thread. You might be able to do a lot of the context +switch code with `setjmp' and `longjmp', if they *happen* to have +the "right" implementation. But getting all the details right (the +helper can return a value to the new thread's cswap routine caller) +is probaby trickier than writing code that does the minimum and +thus doesn't have any extra instructions (or generality) to cause +problems. + +I don't know of any ports besides those included with the source +code distribution. If you send me a port I will hapily add it to +the distribution. + +Let me know as you have questions and/or comments. + + ;-D on ( Now *that*'s a switch... ) Pardo diff --git a/ext/systemc/src/sysc/qt/b.h b/ext/systemc/src/sysc/qt/b.h new file mode 100644 index 000000000..49e587c77 --- /dev/null +++ b/ext/systemc/src/sysc/qt/b.h @@ -0,0 +1,11 @@ +#ifndef B_H +#define B_H "$Header: /Users/acg/CVSROOT/systemc-2.3/src/sysc/qt/b.h,v 1.1.1.1 2006/12/15 20:20:06 acg Exp $" + +#include "copyright.h" + +extern void b_call_reg (int n); +extern void b_call_imm (int n); +extern void b_add (int n); +extern void b_load (int n); + +#endif /* ndef B_H */ diff --git a/ext/systemc/src/sysc/qt/config b/ext/systemc/src/sysc/qt/config new file mode 100755 index 000000000..35d54647f --- /dev/null +++ b/ext/systemc/src/sysc/qt/config @@ -0,0 +1,392 @@ +#! /bin/sh + +# set -x + +: ${LN_S:="ln -s"} + +# rm -f Makefile Makefile.md README.md qtmd.h qtmdb.s qtmdc.c qtmds.s configuration +rm -f qtmdc.c qtmds.s configuration + +case $1 in + axp*) + : "DEC AXP" + case $1 in + axp-osf1*) + : "Compile using /bin/cc under OSF 1.x." +# ${LN_S} md/axp.1.Makefile Makefile.md + ;; + axp-osf2*) + : "Compile using /bin/cc under OSF 2.x." +# ${LN_S} md/axp.1.Makefile Makefile.md + ;; + *) + : "Compile using GNU CC." +# ${LN_S} md/axp.Makefile Makefile.md + ;; + esac + +# ${LN_S} md/axp.h qtmd.h + ${LN_S} md/axp.c qtmdc.c + ${LN_S} md/axp.s qtmds.s +# ${LN_S} md/axp_b.s qtmdb.s +# ${LN_S} md/axp.README README.md + iter_init=1000000000 + iter_runone=10000000 + iter_blockint=10000000 + iter_blockfloat=10000000 + iter_vainit0=10000000 + iter_vainit2=10000000 + iter_vainit4=10000000 + iter_vainit8=10000000 + iter_vastart0=10000000 + iter_vastart2=10000000 + iter_vastart4=10000000 + iter_vastart8=10000000 + iter_bench_call_reg=10000000 + iter_bench_call_imm=10000000 + iter_bench_add=100000000 + iter_bench_load=100000000 + ;; + + hppa*) + : "HP's PA-RISC 1.1 processors." + + case $1 in + hppa-cnx-spp*) + : "Convex SPP (PA-RISC 1.1 processors)." +# ${LN_S} md/hppa-cnx.Makefile Makefile.md + ;; + *) +# ${LN_S} md/hppa.Makefile Makefile.md + ;; + esac + +# ${LN_S} md/hppa.h qtmd.h +# ${LN_S} md/null.c qtmdc.c + ${LN_S} md/hppa.s qtmds.s +# ${LN_S} md/hppa_b.s qtmdb.s + iter_init=10000000 + iter_runone=1000000 + iter_blockint=1000000 + iter_blockfloat=1000000 + iter_vainit0=1000000 + iter_vainit2=1000000 + iter_vainit4=1000000 + iter_vainit8=1000000 + iter_vastart0=1000000 + iter_vastart2=1000000 + iter_vastart4=1000000 + iter_vastart8=1000000 + iter_bench_call_reg=10000000 + iter_bench_call_imm=10000000 + iter_bench_add=100000000 + iter_bench_load=100000000 + ;; + + x86_64*) + case $1 in + iX86-ss*) + : "Assembler comments '//'" + sed 's/\/\*/\/\//' < md/i386_64.s > qtmds.s + ;; + + *) + ${LN_S} md/iX86_64.s qtmds.s + ;; + esac + : "Intel X386 64-bit and compatibles" +# ${LN_S} md/null.c qtmdc.c + iter_init=10000000 + iter_runone=1000000 + iter_blockint=1000000 + iter_blockfloat=1000000 + iter_vainit0=1000000 + iter_vainit2=1000000 + iter_vainit4=1000000 + iter_vainit8=1000000 + iter_vastart0=1000000 + iter_vastart2=1000000 + iter_vastart4=1000000 + iter_vastart8=1000000 + iter_bench_call_reg=1000000 + iter_bench_call_imm=1000000 + iter_bench_add=100000000 + iter_bench_load=10000000 + ;; + + iX86*) + case $1 in + iX86-ss*) + : "Assembler comments '//'" + sed 's/\/\*/\/\//' < md/i386.s > qtmds.s +# sed 's/\/\*/\/\//' < md/i386_b.s > qtmdb.s + ;; + + *) + ${LN_S} md/i386.s qtmds.s +# ${LN_S} md/i386_b.s qtmdb.s + ;; + esac + : "Intel 80386 and compatibles (not '286...)" +# ${LN_S} md/default.Makefile Makefile.md +# ${LN_S} md/i386.h qtmd.h +# ${LN_S} md/null.c qtmdc.c +# ${LN_S} md/i386.README README.md + iter_init=10000000 + iter_runone=1000000 + iter_blockint=1000000 + iter_blockfloat=1000000 + iter_vainit0=1000000 + iter_vainit2=1000000 + iter_vainit4=1000000 + iter_vainit8=1000000 + iter_vastart0=1000000 + iter_vastart2=1000000 + iter_vastart4=1000000 + iter_vastart8=1000000 + iter_bench_call_reg=1000000 + iter_bench_call_imm=1000000 + iter_bench_add=100000000 + iter_bench_load=10000000 + ;; + + + m68k) + : "Motorola 68000 family -- incomplete!" +# ${LN_S} md/default.Makefile Makefile.md +# ${LN_S} md/m68k.h qtmd.h +# ${LN_S} md/null.c qtmdc.c + ${LN_S} md/m68k.s qtmds.s +# ${LN_S} md/m68k_b.s qtmdb.s +# ${LN_S} md/null.README README.md + ;; + + m88k) + : "Motorola 88000 family" +# ${LN_S} md/m88k.Makefile Makefile.md +# ${LN_S} md/m88k.h qtmd.h + ${LN_S} md/m88k.c qtmdc.c + ${LN_S} md/m88k.s qtmds.s +# ${LN_S} md/m88k_b.s qtmdb.s +# ${LN_S} md/null.README README.md + iter_init=1000000 + iter_runone=100000 + iter_blockint=100000 + iter_blockfloat=100000 + iter_vainit0=100000 + iter_vainit2=100000 + iter_vainit4=100000 + iter_vainit8=100000 + iter_vastart0=100000 + iter_vastart2=100000 + iter_vastart4=100000 + iter_vastart8=100000 + iter_bench_call_reg=100000000 + iter_bench_call_imm=100000000 + iter_bench_add=1000000000 + iter_bench_load=100000000 + ;; + + mips*) + : "MIPS R2000 and R3000." + + case $1 in + mips-irix5*) + : "Silicon Graphics Irix with dynamic linking" + : "Use mips for irix4." + ${LN_S} md/mips-irix5.s qtmds.s + ;; + *) + ${LN_S} md/mips.s qtmds.s + ;; + esac + +# ${LN_S} md/default.Makefile Makefile.md +# ${LN_S} md/mips.h qtmd.h +# ${LN_S} md/null.c qtmdc.c +# ${LN_S} md/mips_b.s qtmdb.s +# ${LN_S} md/null.README README.md + iter_init=10000000 + iter_runone=10000000 + iter_blockint=10000000 + iter_blockfloat=10000000 + iter_vainit0=1000000 + iter_vainit2=1000000 + iter_vainit4=1000000 + iter_vainit8=1000000 + iter_vastart0=1000000 + iter_vastart2=1000000 + iter_vastart4=1000000 + iter_vastart8=1000000 + iter_bench_call_reg=100000000 + iter_bench_call_imm=100000000 + iter_bench_add=1000000000 + iter_bench_load=100000000 + ;; + + sparc*) + : "SPARC processors" + case $1 in + sparc-os2*) + sed 's/_qt_/qt_/' md/sparc.s > qtmds.s +# sed 's/_b_/b_/' md/sparc_b.s > qtmdb.s +# ${LN_S} md/solaris.README README.md + ;; + *) + ${LN_S} md/sparc.s qtmds.s +# ${LN_S} md/sparc_b.s qtmdb.s +# ${LN_S} md/null.README README.md + ;; + esac + + ${LN_S} md/default.Makefile Makefile.md +# ${LN_S} md/sparc.h qtmd.h +# ${LN_S} md/null.c qtmdc.c + iter_init=10000000 + iter_runone=1000000 + iter_blockint=1000000 + iter_blockfloat=1000000 + iter_vainit0=1000000 + iter_vainit2=1000000 + iter_vainit4=1000000 + iter_vainit8=1000000 + iter_vastart0=1000000 + iter_vastart2=1000000 + iter_vastart4=1000000 + iter_vastart8=1000000 + iter_bench_call_reg=10000000 + iter_bench_call_imm=10000000 + iter_bench_add=100000000 + iter_bench_load=100000000 + ;; + + vax*) + : "DEC VAX processors." +# ${LN_S} md/default.Makefile Makefile.md +# ${LN_S} md/vax.h qtmd.h +# ${LN_S} md/null.c qtmdc.c + ${LN_S} md/vax.s qtmds.s +# ${LN_S} md/vax_b.s qtmdb.s +# ${LN_S} md/null.README README.md + iter_init=1000000 + iter_runone=100000 + iter_blockint=100000 + iter_blockfloat=100000 + iter_vainit0=100000 + iter_vainit2=100000 + iter_vainit4=100000 + iter_vainit8=100000 + iter_vastart0=100000 + iter_vastart2=100000 + iter_vastart4=100000 + iter_vastart8=100000 + iter_bench_call_reg=10000000 + iter_bench_call_imm=10000000 + iter_bench_add=10000000 + iter_bench_load=1000000 + ;; + + ksr1) + : "Kendall Square Research model KSR-1." + : "Varargs is not currently supported." +# ${LN_S} md/ksr1.Makefile Makefile.md +# ${LN_S} md/ksr1.h qtmd.h +# ${LN_S} md/null.c qtmdc.c + ${LN_S} md/ksr1.s qtmds.s +# ${LN_S} md/ksr1_b.s qtmdb.s +# ${LN_S} md/null.README README.md + iter_init=1000000 + iter_runone=100000 + iter_blockint=100000 + iter_blockfloat=100000 + iter_vainit0=100000 + iter_vainit2=100000 + iter_vainit4=100000 + iter_vainit8=100000 + iter_vastart0=100000 + iter_vastart2=100000 + iter_vastart4=100000 + iter_vastart8=100000 + iter_bench_call_reg=10000000 + iter_bench_call_imm=10000000 + iter_bench_add=10000000 + iter_bench_load=1000000 + ;; + + powerpc*) + : "PowerPC IBM/Motorola processors." + + case $1 in + powerpc-apple-macosx*) + : "PowerPC using Mach Application Binary Interface" + : "NOTICE: Darwin assembler syntax is used:" + : " (i.e. registers are named rx not %rx)" + ${LN_S} md/default.Makefile Makefile.md +# ${LN_S} md/powerpc_mach.h qtmd.h + ${LN_S} md/powerpc_mach.s qtmds.s + ;; + powerpc-linux*) + : "PowerPC using System V Application Binary Interface" + : " (e.g. LinuxPPC)" + : "Use powerpc-darwin for MacOS X and other systems based on Mac +h ABI" +# ${LN_S} md/powerpc_sys5.h qtmd.h + ${LN_S} md/powerpc_sys5.s qtmds.s + ;; + *) + echo "Unknown configuration" + echo "See md/powerpc.README for documentation" + echo "Use powerpc-darwin for MacOS X and other systems based on +Mach ABI" + echo "Use powerpc-linux for Linux and other systems based on Sys +tem V ABI" + exit 1 + ;; + + esac + + ${LN_S} md/powerpc.c qtmdc.c + ${LN_S} md/powerpc.README README.md + ;; + + + pthreads*) + : Posix thread support rather than Quick threads. +# ${LN_S} md/hppa.h qtmd.h +# ${LN_S} md/null.c qtmdc.c +# ${LN_S} md/null.s qtmds.s +# ${LN_S} md/hppa_b.s qtmdb.s +# cp md/pthreads.Makefile Makefile + exit 0 + ;; + + clean) + : Deconfigure + exit 0 + ;; + + *) + echo "Unknown configuration" + exit 1 + ;; +esac + +# cat Makefile.md Makefile.base > Makefile + +echo set config_machine=$1 >> configuration +echo set config_init=$iter_init >> configuration +echo set config_runone=$iter_runone >> configuration +echo set config_blockint=$iter_blockint >> configuration +echo set config_blockfloat=$iter_blockfloat >> configuration +echo set config_vainit0=$iter_vainit0 >> configuration +echo set config_vainit2=$iter_vainit2 >> configuration +echo set config_vainit4=$iter_vainit4 >> configuration +echo set config_vainit8=$iter_vainit8 >> configuration +echo set config_vastart0=$iter_vastart0 >> configuration +echo set config_vastart2=$iter_vastart2 >> configuration +echo set config_vastart4=$iter_vastart4 >> configuration +echo set config_vastart8=$iter_vastart8 >> configuration +echo set config_bcall_reg=$iter_bench_call_reg >> configuration +echo set config_bcall_imm=$iter_bench_call_imm >> configuration +echo set config_b_add=$iter_bench_add >> configuration +echo set config_b_load=$iter_bench_load >> configuration diff --git a/ext/systemc/src/sysc/qt/copyright.h b/ext/systemc/src/sysc/qt/copyright.h new file mode 100644 index 000000000..8a2361f9e --- /dev/null +++ b/ext/systemc/src/sysc/qt/copyright.h @@ -0,0 +1,12 @@ +/* + * QuickThreads -- Threads-building toolkit. + * Copyright (c) 1993 by David Keppel + * + * Permission to use, copy, modify and distribute this software and + * its documentation for any purpose and without fee is hereby + * granted, provided that the above copyright notice and this notice + * appear in all copies. This software is provided as a + * proof-of-concept and for demonstration purposes; there is no + * representation about the suitability of this software for any + * purpose. + */ diff --git a/ext/systemc/src/sysc/qt/md/axp.1.Makefile b/ext/systemc/src/sysc/qt/md/axp.1.Makefile new file mode 100644 index 000000000..86ccd8f42 --- /dev/null +++ b/ext/systemc/src/sysc/qt/md/axp.1.Makefile @@ -0,0 +1,5 @@ + +# +# Compiling for the DEC AXP (alpha) with GNU CC or version 1.x of OSF. +# +CC = cc -std1 -D__AXP__ -D__OSF1__ diff --git a/ext/systemc/src/sysc/qt/md/axp.2.Makefile b/ext/systemc/src/sysc/qt/md/axp.2.Makefile new file mode 100644 index 000000000..268636fc9 --- /dev/null +++ b/ext/systemc/src/sysc/qt/md/axp.2.Makefile @@ -0,0 +1,5 @@ + +# +# Compiling for the DEC AXP (alpha) with GNU CC or version 2.x of OSF. +# +CC = cc -std1 -D__AXP__ -D__OSF2__ diff --git a/ext/systemc/src/sysc/qt/md/axp.Makefile b/ext/systemc/src/sysc/qt/md/axp.Makefile new file mode 100644 index 000000000..4e6d74da4 --- /dev/null +++ b/ext/systemc/src/sysc/qt/md/axp.Makefile @@ -0,0 +1,5 @@ + +# +# GNU CC +# +CC = gcc -D__AXP__ diff --git a/ext/systemc/src/sysc/qt/md/axp.README b/ext/systemc/src/sysc/qt/md/axp.README new file mode 100644 index 000000000..b6a705c07 --- /dev/null +++ b/ext/systemc/src/sysc/qt/md/axp.README @@ -0,0 +1,10 @@ +The handling of varargs is platform-dependent. Assar Westerlund +stared at the problem for a while and deduces the following table: + +vers / compiler cc gcc +---------------------------------------------------------------------- +1.3 a0, offset __base, __offset +2.0 _a0, _offset __base, __offset + +The current code should handle both cc and gcc versions, provided +you configure for the correct compiler. diff --git a/ext/systemc/src/sysc/qt/md/axp.c b/ext/systemc/src/sysc/qt/md/axp.c new file mode 100644 index 000000000..268612993 --- /dev/null +++ b/ext/systemc/src/sysc/qt/md/axp.c @@ -0,0 +1,133 @@ +/* + * QuickThreads -- Threads-building toolkit. + * Copyright (c) 1993 by David Keppel + * + * Permission to use, copy, modify and distribute this software and + * its documentation for any purpose and without fee is hereby + * granted, provided that the above copyright notice and this notice + * appear in all copies. This software is provided as a + * proof-of-concept and for demonstration purposes; there is no + * representation about the suitability of this software for any + * purpose. + */ + +#include <stdarg.h> +#include "qt.h" + + +/* Varargs is harder on the AXP. Parameters are saved on the stack as + something like (stack grows down to low memory; low at bottom of + picture): + + | : + | arg6 + +--- + | iarg5 + | : + | iarg3 <-- va_list._a0 + va_list._offset + | : + | iarg0 <-- va_list._a0 + +--- + | farg5 + | : + | farg0 + +--- + + When some of the arguments have known type, there is no need to + save all of them in the struct. So, for example, if the routine is + called + + zork (int a0, float a1, int a2, ...) + { + va_list ap; + va_start (ap, a2); + qt_vargs (... &ap ...); + } + + then offset is set to 3 * 8 (8 === sizeof machine word) = 24. + + What this means for us is that the user's routine needs to be + called with an arg list where some of the words in the `any type' + parameter list have to be split and moved up in to the int/fp + region. + + Ways in which this can fail: + - The user might not know the size of the pushed arguments anyway. + - Structures have funny promotion rules. + - Probably lots of other things. + + All in all, we never promised varargs would work reliably. */ + + + +#define QUICKTHREADS_VADJ(sp) (((char *)sp) - QUICKTHREADS_VSTKBASE) + +#define QUICKTHREADS_VARGS_MD0(sp, vabytes) \ + ((qt_t *)(((char *)(sp)) - 6*2*8 - QUICKTHREADS_STKROUNDUP(vabytes))) + +extern void qt_vstart(void); +#define QUICKTHREADS_VARGS_MD1(sp) (QUICKTHREADS_SPUT (sp, QUICKTHREADS_R26, qt_vstart)) + + +/* Different machines use different implementations for varargs. + Unfortunately, the code below ``looks in to'' the varargs + structure, `va_list', and thus depends on the conventions. + The following #defines try to deal with it but don't catch + everything. */ + +#ifdef __GNUC__ +#define _a0 __base +#define _offset __offset +#else +#ifdef __OSF1__ +#define _a0 a0 +#define _offset offset +#endif +#endif /* def __GNUC__ */ + + + struct qt_t * +qt_vargs (struct qt_t *qsp, int nbytes, struct va_list *vargs, + void *pt, qt_function_t *startup, + qt_function_t *vuserf, qt_function_t *cleanup) +{ + va_list ap; + int i; + int max; /* Maximum *words* of args to copy. */ + int tmove; /* *Words* of args moved typed->typed. */ + qt_word_t *sp; + + ap = *(va_list *)vargs; + qsp = QUICKTHREADS_VARGS_MD0 (qsp, nbytes); + sp = (qt_word_t *)qsp; + + tmove = 6 - ap._offset/sizeof(qt_word_t); + + /* Copy from one typed area to the other. */ + for (i=0; i<tmove; ++i) { + /* Integer args: */ + sp[i+6] = ((qt_word_t *)(ap._a0 + ap._offset))[i]; + /* Fp args: */ + sp[i] = ((qt_word_t *)(ap._a0 + ap._offset))[i-6]; + } + + max = nbytes/sizeof(qt_word_t); + + /* Copy from the untyped area to the typed area. Split each arg. + in to integer and floating-point save areas. */ + for (; i<6 && i<max; ++i) { + sp[i] = sp[i+6] = ((qt_word_t *)(ap._a0 + ap._offset))[i]; + } + + /* Copy from the untyped area to the other untyped area. */ + for (; i<max; ++i) { + sp[i+6] = ((qt_word_t *)(ap._a0 + ap._offset))[i]; + } + + QUICKTHREADS_VARGS_MD1 (QUICKTHREADS_VADJ(sp)); + QUICKTHREADS_SPUT (QUICKTHREADS_VADJ(sp), QUICKTHREADS_VARGT_INDEX, pt); + QUICKTHREADS_SPUT (QUICKTHREADS_VADJ(sp), QUICKTHREADS_VSTARTUP_INDEX, startup); + QUICKTHREADS_SPUT (QUICKTHREADS_VADJ(sp), QUICKTHREADS_VUSERF_INDEX, vuserf); + QUICKTHREADS_SPUT (QUICKTHREADS_VADJ(sp), QUICKTHREADS_VCLEANUP_INDEX, cleanup); + return ((qt_t *)QUICKTHREADS_VADJ(sp)); +} diff --git a/ext/systemc/src/sysc/qt/md/axp.h b/ext/systemc/src/sysc/qt/md/axp.h new file mode 100644 index 000000000..3aac9ff1d --- /dev/null +++ b/ext/systemc/src/sysc/qt/md/axp.h @@ -0,0 +1,160 @@ +/* + * QuickThreads -- Threads-building toolkit. + * Copyright (c) 1993 by David Keppel + * + * Permission to use, copy, modify and distribute this software and + * its documentation for any purpose and without fee is hereby + * granted, provided that the above copyright notice and this notice + * appear in all copies. This software is provided as a + * proof-of-concept and for demonstration purposes; there is no + * representation about the suitability of this software for any + * purpose. + */ + +#ifndef QUICKTHREADS_AXP_H +#define QUICKTHREADS_AXP_H + +#define QUICKTHREADS_GROW_DOWN + +typedef unsigned long qt_word_t; + + +/* Stack layout on the Alpha: + + Integer: + + Caller-save: r0..r8, r22..r25, r27..r29 + argument/caller-save: r16..r21 + callee-save: r9..r15 + return pc *callee-save*: r26 + stack pointer: r30 + zero: r31 + + Floating-point: + + Caller-save: f0..f1, f10..f15 + argument/caller-save: f16..f21, f22..f30 + callee-save: f2..f9 + zero: f31 + + Non-varargs: + + +--- + | padding + | f9 + | f8 + | f7 + | f6 + | f5 + | f4 + | f3 + | f2 + | r26 + +--- + | padding + | r29 + | r15 + | r14 + | r13 + | r12 on startup === `only' + | r11 on startup === `userf' + | r10 on startup === `qt' + | r9 on startup === `qu' + | r26 on startup === qt_start <--- qt.sp + +--- + + Conventions for varargs startup: + + | : + | arg6 + | iarg5 + | : + | iarg0 + | farg5 + | : + | farg0 + +--- + | padding + | r29 + | r15 + | r14 + | r13 + | r12 on startup === `startup' + | r11 on startup === `vuserf' + | r10 on startup === `cleanup' + | r9 on startup === `qt' + | r26 on startup === qt_vstart <--- qt.sp + +--- + + Note: this is a pretty cheap/sleazy way to get things going, + but ``there must be a better way.'' For instance, some varargs + parameters could be loaded in to integer registers, or the return + address could be stored on top of the stack. */ + + +/* Stack must be 16-byte aligned. */ +#define QUICKTHREADS_STKALIGN (16) + +/* How much space is allocated to hold all the crud for + initialization: 7 registers times 8 bytes/register. */ + +#define QUICKTHREADS_STKBASE (10 * 8) +#define QUICKTHREADS_VSTKBASE QUICKTHREADS_STKBASE + + +/* Offsets of various registers. */ +#define QUICKTHREADS_R26 0 +#define QUICKTHREADS_R9 1 +#define QUICKTHREADS_R10 2 +#define QUICKTHREADS_R11 3 +#define QUICKTHREADS_R12 4 + + +/* When a never-before-run thread is restored, the return pc points + to a fragment of code that starts the thread running. For + non-vargs functions, it just calls the client's `only' function. + For varargs functions, it calls the startup, user, and cleanup + functions. + + The varargs startup routine always reads 12 8-byte arguments from + the stack. If fewer argumets were pushed, the startup routine + would read off the top of the stack. To prevent errors we always + allocate enough space. When there are fewer args, the preallocated + words are simply wasted. */ + +extern void qt_start(void); +#define QUICKTHREADS_ARGS_MD(sp) (QUICKTHREADS_SPUT (sp, QUICKTHREADS_R26, qt_start)) + + +/* The AXP uses a struct for `va_list', so pass a pointer to the + struct. This may break some uses of `QUICKTHREADS_VARGS', but then we never + claimed it was totally portable. */ + +typedef void (qt_function_t)(void); + +struct qt_t; +struct va_list; +extern struct qt_t *qt_vargs (struct qt_t *sp, int nbytes, + struct va_list *vargs, void *pt, + qt_function_t *startup, + qt_function_t *vuserf, + qt_function_t *cleanup); + +#define QUICKTHREADS_VARGS(sp, nbytes, vargs, pt, startup, vuserf, cleanup) \ + (qt_vargs (sp, nbytes, (struct va_list *)(&(vargs)), pt, \ + (qt_function_t *) startup, (qt_function_t *)vuserf, \ + (qt_function_t *)cleanup)); + + +/* The *index* (positive offset) of where to put each value. */ +#define QUICKTHREADS_ONLY_INDEX (QUICKTHREADS_R12) +#define QUICKTHREADS_USER_INDEX (QUICKTHREADS_R11) +#define QUICKTHREADS_ARGT_INDEX (QUICKTHREADS_R10) +#define QUICKTHREADS_ARGU_INDEX (QUICKTHREADS_R9) + +#define QUICKTHREADS_VCLEANUP_INDEX (QUICKTHREADS_R10) +#define QUICKTHREADS_VUSERF_INDEX (QUICKTHREADS_R11) +#define QUICKTHREADS_VSTARTUP_INDEX (QUICKTHREADS_R12) +#define QUICKTHREADS_VARGT_INDEX (QUICKTHREADS_R9) + +#endif /* ndef QUICKTHREADS_AXP_H */ diff --git a/ext/systemc/src/sysc/qt/md/axp.s b/ext/systemc/src/sysc/qt/md/axp.s new file mode 100644 index 000000000..a84aab2cc --- /dev/null +++ b/ext/systemc/src/sysc/qt/md/axp.s @@ -0,0 +1,160 @@ +/* + * QuickThreads -- Threads-building toolkit. + * Copyright (c) 1993 by David Keppel + * + * Permission to use, copy, modify and distribute this software and + * its documentation for any purpose and without fee is hereby + * granted, provided that the above copyright notice and this notice + * appear in all copies. This software is provided as a + * proof-of-concept and for demonstration purposes; there is no + * representation about the suitability of this software for any + * purpose. + */ + +/* axp.s -- assembly support. */ + + .text + .align 4 + .file 2 "axp.s" + + .globl qt_block + .globl qt_blocki + .globl qt_abort + .globl qt_start + .globl qt_vstart + + /* + ** $16: ptr to function to call once curr is suspended + ** and control is on r19's stack. + ** $17: 1'th arg to (*$16)(...). + ** $18: 2'th arg to (*$16)(...). + ** $19: sp of thread to resume. + ** + ** The helper routine returns a value that is passed on as the + ** return value from the blocking routine. Since we don't + ** touch r0 between the helper's return and the end of + ** function, we get this behavior for free. + */ + + .ent qt_blocki +qt_blocki: + subq $30,80, $30 /* Allocate save area. */ + stq $26, 0($30) /* Save registers. */ + stq $9, 8($30) + stq $10,16($30) + stq $11,24($30) + stq $12,32($30) + stq $13,40($30) + stq $14,48($30) + stq $15,56($30) + stq $29,64($30) + .end qt_blocki + .ent qt_abort +qt_abort: + addq $16,$31, $27 /* Put argument function in PV. */ + addq $30,$31, $16 /* Save stack ptr in outgoing arg. */ + addq $19,$31, $30 /* Set new stack pointer. */ + jsr $26,($27),0 /* Call helper function. */ + + ldq $26, 0($30) /* Restore registers. */ + ldq $9, 8($30) + ldq $10,16($30) + ldq $11,24($30) + ldq $12,32($30) + ldq $13,40($30) + ldq $14,48($30) + ldq $15,56($30) + ldq $29,64($30) + + addq $30,80, $30 /* Deallocate save area. */ + ret $31,($26),1 /* Return, predict===RET. */ + .end qt_abort + + + /* + ** Non-varargs thread startup. + */ + .ent qt_start +qt_start: + addq $9,$31, $16 /* Load up `qu'. */ + addq $10,$31, $17 /* ... user function's `pt'. */ + addq $11,$31, $18 /* ... user function's `userf'. */ + addq $12,$31, $27 /* ... set procedure value to `only'. */ + jsr $26,($27),0 /* Call `only'. */ + + jsr $26,qt_error /* `only' erroniously returned. */ + .end qt_start + + + .ent qt_vstart: +qt_vstart: + /* Call startup function. */ + addq $9,$31, $16 /* Arg0 to `startup'. */ + addq $12,$31, $27 /* Set procedure value. */ + jsr $26,($27),0 /* Call `startup'. */ + + /* Call user function. */ + ldt $f16, 0($30) /* Load fp arg regs. */ + ldt $f17, 8($30) + ldt $f18,16($30) + ldt $f19,24($30) + ldt $f20,32($30) + ldt $f21,40($30) + ldq $16,48($30) /* And integer arg regs. */ + ldq $17,56($30) + ldq $18,64($30) + ldq $19,72($30) + ldq $20,80($30) + ldq $21,88($30) + addq $30,96 $30 /* Pop 6*2*8 saved arg regs. */ + addq $11,$31, $27 /* Set procedure value. */ + jsr $26,($27),0 /* Call `vuserf'. */ + + /* Call cleanup. */ + addq $9,$31, $16 /* Arg0 to `cleanup'. */ + addq $0,$31, $17 /* Users's return value is arg1. */ + addq $10,$31, $27 /* Set procedure value. */ + jsr $26,($27),0 /* Call `cleanup'. */ + + jsr $26,qt_error /* Cleanup erroniously returned. */ + .end qt_start + + + /* + ** Save calle-save floating-point regs $f2..$f9. + ** Also save return pc from whomever called us. + ** + ** Return value from `qt_block' is the same as the return from + ** `qt_blocki'. We get that for free since we don't touch $0 + ** between the return from `qt_blocki' and the return from + ** `qt_block'. + */ + .ent qt_block +qt_block: + subq $30,80, $30 /* Allocate a save space. */ + stq $26, 0($30) /* Save registers. */ + stt $f2, 8($30) + stt $f3,16($30) + stt $f4,24($30) + stt $f5,32($30) + stt $f6,40($30) + stt $f7,48($30) + stt $f8,56($30) + stt $f9,64($30) + + jsr $26,qt_blocki /* Call helper. */ + /* .. who will also restore $gp. */ + + ldq $26, 0($30) /* restore registers. */ + ldt $f2, 8($30) + ldt $f3,16($30) + ldt $f4,24($30) + ldt $f5,32($30) + ldt $f6,40($30) + ldt $f7,48($30) + ldt $f8,56($30) + ldt $f9,64($30) + + addq $30,80, $30 /* Deallcate save space. */ + ret $31,($26),1 /* Return, predict===RET. */ + .end qt_block diff --git a/ext/systemc/src/sysc/qt/md/axp_b.s b/ext/systemc/src/sysc/qt/md/axp_b.s new file mode 100644 index 000000000..60be726ff --- /dev/null +++ b/ext/systemc/src/sysc/qt/md/axp_b.s @@ -0,0 +1,111 @@ +/* + * QuickThreads -- Threads-building toolkit. + * Copyright (c) 1993 by David Keppel + * + * Permission to use, copy, modify and distribute this software and + * its documentation for any purpose and without fee is hereby + * granted, provided that the above copyright notice and this notice + * appear in all copies. This software is provided as a + * proof-of-concept and for demonstration purposes; there is no + * representation about the suitability of this software for any + * purpose. + */ + + .text + .globl b_call_reg + .globl b_call_imm + .globl b_add + .globl b_load + + .ent b_null +b_null: + ret $31,($18),1 + .end b_null + + .ent b_call_reg +b_call_reg: + lda $27,b_null +$L0: + jsr $18,($27) + jsr $18,($27) + jsr $18,($27) + jsr $18,($27) + jsr $18,($27) + + jsr $18,($27) + jsr $18,($27) + jsr $18,($27) + jsr $18,($27) + jsr $18,($27) + + subq $16,1,$16 + bgt $16,$L0 + + ret $31,($26),1 + .end + + + .ent b_call_imm +b_call_imm: +$L1: + jsr $18,b_null + jsr $18,b_null + jsr $18,b_null + jsr $18,b_null + jsr $18,b_null + + jsr $18,b_null + jsr $18,b_null + jsr $18,b_null + jsr $18,b_null + jsr $18,b_null + + subq $16,1,$16 + bgt $16,$L1 + + ret $31,($26),1 + .end + + + .ent b_add +b_add: +$L2: + addq $31,$31,$31 + addq $31,$31,$31 + addq $31,$31,$31 + addq $31,$31,$31 + addq $31,$31,$31 + + addq $31,$31,$31 + addq $31,$31,$31 + addq $31,$31,$31 + addq $31,$31,$31 + addq $31,$31,$31 + + subq $16,1,$16 + bgt $16,$L2 + + ret $31,($26),1 + .end + + + .ent b_load +b_load: +$L3: + ldq $31,0($30) + ldq $31,8($30) + ldq $31,16($30) + ldq $31,24($30) + ldq $31,32($30) + + ldq $31,0($30) + ldq $31,8($30) + ldq $31,16($30) + ldq $31,24($30) + ldq $31,32($30) + + subq $16,1,$16 + bgt $16,$L3 + + ret $31,($26),1 + .end diff --git a/ext/systemc/src/sysc/qt/md/default.Makefile b/ext/systemc/src/sysc/qt/md/default.Makefile new file mode 100644 index 000000000..2f3ded151 --- /dev/null +++ b/ext/systemc/src/sysc/qt/md/default.Makefile @@ -0,0 +1,8 @@ + +# +# `Normal' configuration. +# +CC = gcc -ansi -Wall -pedantic + +.o.s: + as -o $@ $< diff --git a/ext/systemc/src/sysc/qt/md/hppa-cnx.Makefile b/ext/systemc/src/sysc/qt/md/hppa-cnx.Makefile new file mode 100644 index 000000000..bff257d9f --- /dev/null +++ b/ext/systemc/src/sysc/qt/md/hppa-cnx.Makefile @@ -0,0 +1,9 @@ +# This file (cnx_spp.Makefile) is part of the port of QuickThreads for +# PA-RISC 1.1 architecture on a Convex SPP. This file is a machine dependent +# makefile for QuickThreads. It was written in 1994 by Uwe Reder +# (`uereder@cip.informatik.uni-erlangen.de') for the Operating Systems +# Department (IMMD4) at the University of Erlangen/Nuernberg Germany. + +# `Normal' configuration. + +CC = /usr/convex/bin/cc diff --git a/ext/systemc/src/sysc/qt/md/hppa.Makefile b/ext/systemc/src/sysc/qt/md/hppa.Makefile new file mode 100644 index 000000000..bf770ae3b --- /dev/null +++ b/ext/systemc/src/sysc/qt/md/hppa.Makefile @@ -0,0 +1,12 @@ +# This file (pa-risc.Makefile) is part of the port of QuickThreads for +# PA-RISC 1.1 architecture. This file is a machine dependent makefile +# for QuickThreads. It was written in 1994 by Uwe Reder +# (`uereder@cip.informatik.uni-erlangen.de') for the Operating Systems +# Department (IMMD4) at the University of Erlangen/Nuernberg Germany. + +# `Normal' configuration. + +CC = cc -Aa + +.s.o: + /usr/ccs/bin/as -o $@ $< diff --git a/ext/systemc/src/sysc/qt/md/hppa.h b/ext/systemc/src/sysc/qt/md/hppa.h new file mode 100644 index 000000000..fdb9cef93 --- /dev/null +++ b/ext/systemc/src/sysc/qt/md/hppa.h @@ -0,0 +1,196 @@ +/* + * QuickThreads -- Threads-building toolkit. + * Copyright (c) 1993 by David Keppel + * + * Permission to use, copy, modify and distribute this software and + * its documentation for any purpose and without fee is hereby + * granted, provided that the above copyright notice and this notice + * appear in all copies. This software is provided as a + * proof-of-concept and for demonstration purposes; there is no + * representation about the suitability of this software for any + * purpose. + */ + +/* + * This file (pa-risc.h) is part of the port of QuickThreads for the + * PA-RISC 1.1 architecture. This file is a machine dependent header + * file. It was written in 1994 by Uwe Reder + * (`uereder@cip.informatik.uni-erlangen.de') for the Operating Systems + * Department (IMMD4) at the University of Erlangen/Nuernberg Germany. + */ + + +#ifndef QUICKTHREADS_PA_RISC_H +#define QUICKTHREADS_PA_RISC_H + +#if 0 +#include <qt.h> +#endif + +/* size of an integer-register (32 bit) */ +typedef unsigned long qt_word_t; + +/* PA-RISC's stack grows up */ +#define QUICKTHREADS_GROW_UP + +/* Stack layout on PA-RISC according to PA-RISC Procedure Calling Conventions: + + Callee-save registers are: gr3-gr18, fr12-fr21. + Also save gr2, return pointer. + + +--- + | fr12 Each floating register is a double word (8 bytes). + | fr13 Floating registers are only saved if `qt_block' is + | fr14 called, in which case it saves the floating-point + | fr15 registers then calls `qt_blocki' to save the integer + | fr16 registers. + | fr17 + | fr18 + | fr19 + | fr20 + | fr21 + | <arg word 3> fixed arguments (must be allocated; may remain unused) + | <arg word 2> + | <arg word 1> + | <arg word 0> + | <LPT> frame marker + | <LPT'> + | <RP'> + | <Current RP> + | <Static Link> + | <Clean Up> + | <RP''> + | <Previous SP> + +--- + | gr3 word each (4 bytes) + | gr4 + | gr5 + | gr6 + | gr7 + | gr8 + | gr9 + | gr10 + | gr11 + | gr12 + | gr13 + | gr14 + | gr15 + | gr16 + | gr17 + | gr18 + | <16 bytes filled in (sp has to be 64-bytes aligned)> + | <arg word 3> fixed arguments (must be allocated; may remain unused) + | <arg word 2> + | <arg word 1> + | <arg word 0> + | <LPT> frame marker + | <LPT'> + | <RP'> + | <Current RP> + | <Static Link> + | <Clean Up> + | <RP''> + | <Previous SP> + +--- <--- sp +*/ + +/* When a never-before-run thread is restored, the return pc points + to a fragment of code that starts the thread running. For + non-vargs functions, it just calls the client's `only' function. + For varargs functions, it calls the startup, user, and cleanup + functions. */ + +/* Note: Procedue Labels on PA-RISC + + <--2--><-------28---------><1-><1-> + ----------------------------------- + | SID | Adress Part | L | X | + ----------------------------------- + + On HP-UX the L field is used to flag wheather the procedure + label (plabel) is a pointer to an LT entry or to the entry point + of the procedure (PA-RISC Procedure Calling Conventions Reference + Manual, 5.3.2 Procedure Labels and Dynamic Calls). */ + +#define QUICKTHREADS_PA_RISC_READ_PLABEL(plabel) \ + ( (((int)plabel) & 2) ? \ + ( (*((int *)(((int)plabel) & 0xfffffffc)))) : ((int)plabel) ) + +/* Stack must be 64 bytes aligned. */ +#define QUICKTHREADS_STKALIGN (64) + +/* Internal helper for putting stuff on stack (negative index!). */ +#define QUICKTHREADS_SPUT(top, at, val) \ + (((qt_word_t *)(top))[-(at)] = (qt_word_t)(val)) + +/* Offsets of various registers which are modified on the stack. + rp (return-pointer) has to be stored in the frame-marker-area + of the "older" stack-segment. */ + +#define QUICKTHREADS_crp (12+4+16+5) +#define QUICKTHREADS_15 (12+4+4) +#define QUICKTHREADS_16 (12+4+3) +#define QUICKTHREADS_17 (12+4+2) +#define QUICKTHREADS_18 (12+4+1) + + +/** This stuff is for NON-VARARGS. **/ + +/* Stack looks like this (2 stack frames): + + <--- 64-bytes aligned --><------- 64-bytes aligned ------------> + | || | + <--16--><------48-------><----16*4-----><--16-><------48-------> + || | || | | || + ||filler|arg|frame-marker||register-save|filler|arg|frame-marker|| + ------------------------------------------------------------------ + */ + +#define QUICKTHREADS_STKBASE (16+48+(16*sizeof(qt_word_t))+16+48) + +/* The index, relative to sp, of where to put each value. */ +#define QUICKTHREADS_ONLY_INDEX (QUICKTHREADS_15) +#define QUICKTHREADS_USER_INDEX (QUICKTHREADS_16) +#define QUICKTHREADS_ARGT_INDEX (QUICKTHREADS_17) +#define QUICKTHREADS_ARGU_INDEX (QUICKTHREADS_18) + +extern void qt_start(void); +#define QUICKTHREADS_ARGS_MD(sp) \ + (QUICKTHREADS_SPUT (sp, QUICKTHREADS_crp, QUICKTHREADS_PA_RISC_READ_PLABEL(qt_start))) + + +/** This is for VARARGS. **/ + +#define QUICKTHREADS_VARGS_DEFAULT + +/* Stack looks like this (2 stack frames): + + <------ 64-bytes aligned -------><--------- 64-bytes aligned ----------> + | || | + <---?--><--?---><16><----32-----><----16*4-----><-16--><16><----32-----> + || | | | || | | | || + ||filler|varargs|arg|frame-marker||register-save|filler|arg|frame-marker|| + -------------------------------------------------------------------------- + */ + +/* Sp is moved to the end of the first stack frame. */ +#define QUICKTHREADS_VARGS_MD0(sp, vasize) \ + ((qt_t *)(((char *)sp) + QUICKTHREADS_STKROUNDUP(vasize + 4*4 + 32))) + +/* To reach the arguments from the end of the first stack frame use 32 + as a negative adjustment. */ +#define QUICKTHREADS_VARGS_ADJUST(sp) ((qt_t *)(((char *)sp) - 32)) + +/* Offset to reach the end of the second stack frame. */ +#define QUICKTHREADS_VSTKBASE ((16*sizeof(qt_word_t)) + 16 + 4*4 + 32) + +extern void qt_vstart(void); +#define QUICKTHREADS_VARGS_MD1(sp) \ + (QUICKTHREADS_SPUT (sp, QUICKTHREADS_crp, QUICKTHREADS_PA_RISC_READ_PLABEL(qt_vstart))) + +#define QUICKTHREADS_VARGT_INDEX (QUICKTHREADS_15) +#define QUICKTHREADS_VSTARTUP_INDEX (QUICKTHREADS_16) +#define QUICKTHREADS_VUSERF_INDEX (QUICKTHREADS_17) +#define QUICKTHREADS_VCLEANUP_INDEX (QUICKTHREADS_18) + +#endif /* ndef QUICKTHREADS_PA_RISC_H */ diff --git a/ext/systemc/src/sysc/qt/md/hppa.s b/ext/systemc/src/sysc/qt/md/hppa.s new file mode 100644 index 000000000..84d8e875b --- /dev/null +++ b/ext/systemc/src/sysc/qt/md/hppa.s @@ -0,0 +1,237 @@ +; pa-risc.s -- assembly support. + +; QuickThreads -- Threads-building toolkit. +; Copyright (c) 1993 by David Keppel +; +; Permission to use, copy, modify and distribute this software and +; its documentation for any purpose and without fee is hereby +; granted, provided that the above copyright notice and this notice +; appear in all copies. This software is provided as a +; proof-of-concept and for demonstration purposes; there is no +; representation about the suitability of this software for any +; purpose. + +; This file (pa-risc.s) is part of the port of QuickThreads for +; PA-RISC 1.1 architecture. This file implements context switches +; and thread startup. It was written in 1994 by Uwe Reder +; (`uereder@cip.informatik.uni-erlangen.de') for the Operating +; Systems Department (IMMD4) at the University of Erlangen/Nuernberg +; Germany. + + +; Callee saves general registers gr3..gr18, +; floating-point registers fr12..fr21. + + .CODE + + .IMPORT $$dyncall, MILLICODE + .IMPORT qt_error, CODE + + .EXPORT qt_blocki, ENTRY + .EXPORT qt_block, ENTRY + .EXPORT qt_abort, ENTRY + .EXPORT qt_start, ENTRY + .EXPORT qt_vstart, ENTRY + + +; arg0: ptr to function (helper) to call once curr is suspended +; and control is on arg3's stack. +; arg1: 1'th arg to *arg0. +; arg2: 2'th arg to *arg0. +; arg3: sp of new thread. + +qt_blocki + .PROC + .CALLINFO CALLER, FRAME=0, SAVE_RP, ENTRY_GR=18 + .ENTRY + + stw %rp,-20(%sp) ; save rp to old frame-marker + + stwm %r3,128(%sp) ; save callee-saves general registers + stw %r4,-124(%sp) + stw %r5,-120(%sp) + stw %r6,-116(%sp) + stw %r7,-112(%sp) + stw %r8,-108(%sp) + stw %r9,-104(%sp) + stw %r10,-100(%sp) + stw %r11,-96(%sp) + stw %r12,-92(%sp) + stw %r13,-88(%sp) + stw %r14,-84(%sp) + stw %r15,-80(%sp) + stw %r16,-76(%sp) + stw %r17,-72(%sp) + stw %r18,-68(%sp) + +qt_abort + copy %arg0,%r22 ; helper to be called by $$dyncall + copy %sp,%arg0 ; pass current sp as arg0 to helper + copy %arg3,%sp ; set new sp + + .CALL + bl $$dyncall,%mrp ; call helper + copy %mrp,%rp + + ldw -68(%sp),%r18 ; restore general registers + ldw -72(%sp),%r17 + ldw -76(%sp),%r16 + ldw -80(%sp),%r15 + ldw -84(%sp),%r14 + ldw -88(%sp),%r13 + ldw -92(%sp),%r12 + ldw -96(%sp),%r11 + ldw -100(%sp),%r10 + ldw -104(%sp),%r9 + ldw -108(%sp),%r8 + ldw -112(%sp),%r7 + ldw -116(%sp),%r6 + ldw -120(%sp),%r5 + ldw -124(%sp),%r4 + + ldw -148(%sp),%rp ; restore return-pointer + + bv %r0(%rp) ; return to caller + ldwm -128(%sp),%r3 + + .EXIT + .PROCEND + + +qt_block + .PROC + .CALLINFO CALLER, FRAME=0, SAVE_RP, ENTRY_FR=21 + .ENTRY + + stw %rp,-20(%sp) ; save rp to old frame-marker + + fstds,ma %fr12,8(%sp) ; save callee-saves float registers + fstds,ma %fr13,8(%sp) + fstds,ma %fr14,8(%sp) + fstds,ma %fr15,8(%sp) + fstds,ma %fr16,8(%sp) + fstds,ma %fr17,8(%sp) + fstds,ma %fr18,8(%sp) + fstds,ma %fr19,8(%sp) + fstds,ma %fr20,8(%sp) + fstds,ma %fr21,8(%sp) + + .CALL + bl qt_blocki,%rp + ldo 48(%sp),%sp + + ldo -48(%sp),%sp + + fldds,mb -8(%sp),%fr21 ; restore callee-saves float registers + fldds,mb -8(%sp),%fr20 + fldds,mb -8(%sp),%fr19 + fldds,mb -8(%sp),%fr18 + fldds,mb -8(%sp),%fr17 + fldds,mb -8(%sp),%fr16 + fldds,mb -8(%sp),%fr15 + fldds,mb -8(%sp),%fr14 + fldds,mb -8(%sp),%fr13 + + ldw -28(%sp),%rp ; restore return-pointer + + bv %r0(%rp) ; return to caller. + fldds,mb -8(%sp),%fr12 + + .EXIT + .PROCEND + + +qt_start + .PROC + .CALLINFO CALLER, FRAME=0 + .ENTRY + + copy %r18,%arg0 ; set user arg `pu'. + copy %r17,%arg1 ; ... user function pt. + copy %r16,%arg2 ; ... user function userf. + ; %r22 is a caller-saves register + copy %r15,%r22 ; function to be called by $$dyncall + + .CALL ; in=%r22 + bl $$dyncall,%mrp ; call `only'. + copy %mrp,%rp + + bl,n qt_error,%r0 ; `only' erroniously returned. + + .EXIT + .PROCEND + + +; Varargs +; +; First, call `startup' with the `pt' argument. +; +; Next, call the user's function with all arguments. +; We don't know whether arguments are integers, 32-bit floating-points or +; even 64-bit floating-points, so we reload all the registers, possibly +; with garbage arguments. The thread creator provided non-garbage for +; the arguments that the callee actually uses, so the callee never gets +; garbage. +; +; -48 -44 -40 -36 -32 +; | arg3 | arg2 | arg1 | arg0 | +; ----------------------------- +; integers: arg3 arg2 arg1 arg0 +; 32-bit fps: farg3 farg2 farg1 farg0 +; 64-bit fps: <---farg3--> <---farg1--> +; +; Finally, call `cleanup' with the `pt' argument and with the return value +; from the user's function. It is an error for `cleanup' to return. + +qt_vstart + .PROC + .CALLINFO CALLER, FRAME=0 + .ENTRY + + ; Because the startup function may damage the fixed arguments + ; on the stack (PA-RISC Procedure Calling Conventions Reference + ; Manual, 2.4 Fixed Arguments Area), we allocate a seperate + ; stack frame for it. + ldo 64(%sp),%sp + + ; call: void startup(void *pt) + + copy %r15,%arg0 ; `pt' is arg0 to `startup'. + copy %r16,%r22 + .CALL + bl $$dyncall,%mrp ; Call `startup'. + copy %mrp,%rp + + ldo -64(%sp),%sp + + ; call: void *qt_vuserf_t(...) + + ldw -36(%sp),%arg0 ; Load args to integer registers. + ldw -40(%sp),%arg1 + ldw -44(%sp),%arg2 + ldw -48(%sp),%arg3 + ; Index of fld[w|d]s only ranges from -16 to 15, so we + ; take r22 to be our new base register. + ldo -32(%sp),%r22 + fldws -4(%r22),%farg0 ; Load args to floating-point registers. + fldds -8(%r22),%farg1 + fldws -12(%r22),%farg2 + fldds -16(%r22),%farg3 + copy %r17,%r22 + .CALL + bl $$dyncall,%mrp ; Call `userf'. + copy %mrp,%rp + + ; call: void cleanup(void *pt, void *vuserf_return) + + copy %r15,%arg0 ; `pt' is arg0 to `cleanup'. + copy %ret0,%arg1 ; Return-value is arg1 to `cleanup'. + copy %r18,%r22 + .CALL + bl $$dyncall,%mrp ; Call `cleanup'. + copy %mrp,%rp + + bl,n qt_error,%r0 + + .EXIT + .PROCEND diff --git a/ext/systemc/src/sysc/qt/md/hppa_b.s b/ext/systemc/src/sysc/qt/md/hppa_b.s new file mode 100644 index 000000000..1b1e8264e --- /dev/null +++ b/ext/systemc/src/sysc/qt/md/hppa_b.s @@ -0,0 +1,203 @@ +; QuickThreads -- Threads-building toolkit. +; Copyright (c) 1993 by David Keppel + +; Permission to use, copy, modify and distribute this software and +; its documentation for any purpose and without fee is hereby +; granted, provided that the above copyright notice and this notice +; appear in all copies. This software is provided as a +; proof-of-concept and for demonstration purposes; there is no +; representation about the suitability of this software for any +; purpose. + +; This file (pa-risc_b.s) is part of the port of QuickThreads for +; PA-RISC 1.1 architecture. It contains assembly-level support for +; raw processor performance measurement. It was written in 1994 by +; Uwe Reder (`uereder@cip.informatik.uni-erlangen.de') +; for the Operating Systems Department (IMMD4) at the +; University of Erlangen/Nuernberg Germany. + + +; Note that the number of instructions in the measurement-loops, differ +; from implementation to implementation. I took eight instructions in a loop +; for every test (execute eight instructions and loop to the start). + + .CODE + + .IMPORT $global$,DATA + .IMPORT $$dyncall,MILLICODE + .EXPORT b_call_reg + .EXPORT b_call_imm + .EXPORT b_add + .EXPORT b_load + +; Just do nothing, only return to caller. This procedure is called by +; `b_call_reg' and `b_call_imm'. + +b_null + .PROC + .CALLINFO NO_CALLS, FRAME=0 + .ENTRY + + bv,n %r0(%rp) ; just return + + .EXIT + .PROCEND + +; Call the procedure `b_null' with function pointer in a register. + +b_call_reg + .PROC + .CALLINFO CALLER, FRAME=0 + .ENTRY + + stwm %r3,64(%sp) ; store r3 (may be used by caller) + stw %rp,-20(%sp) ; save return-pointer to frame-marker + + addil LR'to_call-$global$,%r27 + ldw RR'to_call-$global$(%r1),%r3 + +_loop0 + copy %r3,%r22 ; copy the procedure label to r22, ... + .CALL ; ...this is the input to $$dyncall + bl $$dyncall,%mrp ; call $$dyncall (millicode function) + copy %mrp,%rp ; remember the return-pointer + + copy %r3,%r22 + .CALL + bl $$dyncall,%mrp + copy %mrp,%rp + + copy %r3,%r22 + .CALL + bl $$dyncall,%mrp + copy %mrp,%rp + + copy %r3,%r22 + .CALL + bl $$dyncall,%mrp + copy %mrp,%rp + + copy %r3,%r22 + .CALL + bl $$dyncall,%mrp + copy %mrp,%rp + + copy %r3,%r22 + .CALL + bl $$dyncall,%mrp + copy %mrp,%rp + + copy %r3,%r22 + .CALL + bl $$dyncall,%mrp + copy %mrp,%rp + + copy %r3,%r22 + .CALL + bl $$dyncall,%mrp + copy %mrp,%rp + + addibf,<= -8,%arg0,_loop0 ; decrement counter by 8 and loop + nop + + ldw -20(%sp),%rp ; restore return-pointer + bv %r0(%rp) ; return to caller + ldwm -64(%sp),%r3 ; resore r3 and remove stack frame + + .EXIT + .PROCEND + +; Call the procedure `b_null' immediate. + +b_call_imm + .PROC + .CALLINFO CALLER, FRAME=0, SAVE_RP + .ENTRY + + ldo 64(%sp),%sp ; caller needs a stack-frame + stw %rp,-20(%sp) ; save return-pointer to frame-marker + +_loop1 + bl b_null,%rp ; call `b_null' immediate (8 times) + nop + bl b_null,%rp + nop + bl b_null,%rp + nop + bl b_null,%rp + nop + bl b_null,%rp + nop + bl b_null,%rp + nop + bl b_null,%rp + nop + bl b_null,%rp + nop + + addibf,<= -8,%arg0,_loop1 ; decrement counter by 8 and loop + nop + + ldw -20(%sp),%rp ; restore return-pointer + bv %r0(%rp) ; return to caller + ldo -64(%sp),%sp ; remove stack-frame + + .EXIT + .PROCEND + +; Copy register-to-register. +; On PA-RISC this is implemented with an `or'. +; The `or' is hidden by a pseudo-operation called `copy'. + +b_add + .PROC + .CALLINFO NO_CALLS, FRAME=0 + .ENTRY + +_loop2 + copy %r19,%r20 ; copy register-to-register + copy %r20,%r21 ; use caller-saves registers + copy %r21,%r22 + copy %r22,%r21 + copy %r21,%r20 + copy %r20,%r19 + copy %r19,%r20 + copy %r20,%r21 + + addibf,<= -8,%arg0,_loop2 ; decrement counter by 8 and loop + nop + + bv,n %r0(%rp) + + .EXIT + .PROCEND + +; Load memory to a register. + +b_load + .PROC + .CALLINFO NO_CALLS, FRAME=0 + .ENTRY + +_loop3 + ldw -4(%sp),%r22 ; load data from frame-marker + ldw -8(%sp),%r22 ; use a caller-saves register + ldw -12(%sp),%r22 + ldw -16(%sp),%r22 + ldw -20(%sp),%r22 + ldw -24(%sp),%r22 + ldw -28(%sp),%r22 + ldw -32(%sp),%r22 + + addibf,<= -8,%arg0,_loop3 ; decrement counter by 8 and loop + nop + + bv,n %r0(%rp) + + .EXIT + .PROCEND + + + .ALIGN 8 +to_call + .WORD b_null diff --git a/ext/systemc/src/sysc/qt/md/i386.README b/ext/systemc/src/sysc/qt/md/i386.README new file mode 100644 index 000000000..8ffb92198 --- /dev/null +++ b/ext/systemc/src/sysc/qt/md/i386.README @@ -0,0 +1,7 @@ +Note that some machines want labels to have leading underscores, +while others (e.g. System V) do not. Thus, several labels appear +duplicated except for the leading underscore, e.g. + + _qt_cswap: + qt_cswap: + diff --git a/ext/systemc/src/sysc/qt/md/i386.h b/ext/systemc/src/sysc/qt/md/i386.h new file mode 100644 index 000000000..04513857e --- /dev/null +++ b/ext/systemc/src/sysc/qt/md/i386.h @@ -0,0 +1,132 @@ +/* + * QuickThreads -- Threads-building toolkit. + * Copyright (c) 1993 by David Keppel + * + * Permission to use, copy, modify and distribute this software and + * its documentation for any purpose and without fee is hereby + * granted, provided that the above copyright notice and this notice + * appear in all copies. This software is provided as a + * proof-of-concept and for demonstration purposes; there is no + * representation about the suitability of this software for any + * purpose. + */ + +#ifndef QUICKTHREADS_386_H +#define QUICKTHREADS_386_H + +typedef unsigned long qt_word_t; + +/* Thread's initial stack layout on the i386: + + non-varargs: + + +--- + | arg[2] === `userf' on startup + | arg[1] === `pt' on startup + | arg[0] === `pu' on startup + +--- + | ret pc === qt_error + +--- + | ret pc === `only' on startup + +--- + | %ebp + | %esi + | %edi + | %ebx <--- qt_t.sp + +--- + + When a non-varargs thread is started, it ``returns'' directly to + the client's `only' function. + + varargs: + + +--- + | arg[n-1] + | .. + | arg[0] + +--- + | ret pc === `qt_vstart' + +--- + | %ebp === `startup' + | %esi === `cleanup' + | %edi === `pt' + | %ebx === `vuserf' <--- qt_t.sp + +--- + + When a varargs thread is started, it ``returns'' to the `qt_vstart' + startup code. The startup code calls the appropriate functions. */ + + +/* What to do to start a varargs thread running. */ +extern void qt_vstart (void); + + +/* Hold 4 saved regs plus two return pcs (qt_error, qt_start) plus + three args. */ +#define QUICKTHREADS_STKBASE (13 * 4) + +/* Hold 4 saved regs plus one return pc (qt_vstart). */ +#define QUICKTHREADS_VSTKBASE (5 * 4) + + +/* Stack must be 16-byte aligned at function call instr. (SSE data support) */ +#define QUICKTHREADS_STKALIGN (16) + + +/* Where to place various arguments. */ +#define QUICKTHREADS_ONLY_INDEX (QUICKTHREADS_PC) +#define QUICKTHREADS_USER_INDEX (QUICKTHREADS_ARG2) +#define QUICKTHREADS_ARGT_INDEX (QUICKTHREADS_ARG1) +#define QUICKTHREADS_ARGU_INDEX (QUICKTHREADS_ARG0) + +#define QUICKTHREADS_VSTARTUP_INDEX (QUICKTHREADS_EBP) +#define QUICKTHREADS_VUSERF_INDEX (QUICKTHREADS_EBX) +#define QUICKTHREADS_VCLEANUP_INDEX (QUICKTHREADS_ESI) +#define QUICKTHREADS_VARGT_INDEX (QUICKTHREADS_EDI) + + +#define QUICKTHREADS_EBX 0 +#define QUICKTHREADS_EDI 1 +#define QUICKTHREADS_ESI 2 +#define QUICKTHREADS_EBP 3 +#define QUICKTHREADS_POP0 4 +#define QUICKTHREADS_POP1 5 +#define QUICKTHREADS_POP2 6 +#define QUICKTHREADS_PC 7 +/* The following are defined only for non-varargs. */ +#define QUICKTHREADS_POPE 8 +#define QUICKTHREADS_ARG0 9 +#define QUICKTHREADS_ARG1 10 +#define QUICKTHREADS_ARG2 11 +#define QUICKTHREADS_RPC 12 + + +/* Stack grows down. The top of the stack is the first thing to + pop off (preincrement, postdecrement). */ +#define QUICKTHREADS_GROW_DOWN + +extern void qt_error (void); + +/* For correct 16-byte stack alignment (auto-relocatable functions) */ +extern void qt_tramp (void); +extern void qt_align (void); + +/* Push on the error return address and the alignment/trampoline functions. */ +#define QUICKTHREADS_ARGS_MD(sto) \ + (QUICKTHREADS_SPUT (sto, QUICKTHREADS_POP0, qt_align), \ + QUICKTHREADS_SPUT (sto, QUICKTHREADS_POP1, qt_align), \ + QUICKTHREADS_SPUT (sto, QUICKTHREADS_POP2, qt_align), \ + QUICKTHREADS_SPUT (sto, QUICKTHREADS_POPE, qt_tramp), \ + QUICKTHREADS_SPUT (sto, QUICKTHREADS_RPC, qt_error)) + + +/* When varargs are pushed, allocate space for all the args. */ +#define QUICKTHREADS_VARGS_MD0(sto, nbytes) \ + ((qt_t *)(((char *)(sto)) - QUICKTHREADS_STKROUNDUP(nbytes))) + +#define QUICKTHREADS_VARGS_MD1(sto) \ + (QUICKTHREADS_SPUT (sto, QUICKTHREADS_PC, qt_vstart)) + +#define QUICKTHREADS_VARGS_DEFAULT + +#endif /* QUICKTHREADS_386_H */ diff --git a/ext/systemc/src/sysc/qt/md/i386.s b/ext/systemc/src/sysc/qt/md/i386.s new file mode 100644 index 000000000..b5806cd27 --- /dev/null +++ b/ext/systemc/src/sysc/qt/md/i386.s @@ -0,0 +1,119 @@ +/* i386.s -- assembly support. */ + +/* +// QuickThreads -- Threads-building toolkit. +// Copyright (c) 1993 by David Keppel +// +// Permission to use, copy, modify and distribute this software and +// its documentation for any purpose and without fee is hereby +// granted, provided that the above copyright notice and this notice +// appear in all copies. This software is provided as a +// proof-of-concept and for demonstration purposes; there is no +// representation about the suitability of this software for any +// purpose. */ + +/* NOTE: double-labeled `_name' and `name' for System V compatability. */ +/* NOTE: Mixed C/C++-style comments used. Sorry! */ + +/* Callee-save: %esi, %edi, %ebx, %ebp +// Caller-save: %eax, %ecx +// Can't tell: %edx (seems to work w/o saving it.) +// +// Assignment: +// +// See ``i386.h'' for the somewhat unconventional stack layout. */ + + + .text + .align 2 + + .globl _qt_abort + .globl qt_abort + .globl _qt_block + .globl qt_block + .globl _qt_blocki + .globl qt_blocki + .globl _qt_align + .globl qt_align + +/* These all have the type signature +// +// void *blocking (helper, arg0, arg1, new) +// +// On procedure entry, the helper is at 4(sp), args at 8(sp) and +// 12(sp) and the new thread's sp at 16(sp). It *appears* that the +// calling convention for the 8X86 requires the caller to save all +// floating-point registers, this makes our life easy. */ + +/* Halt the currently-running thread. Save it's callee-save regs on +// to the stack, 32 bytes. Switch to the new stack (next == 16+32(sp)) +// and call the user function (f == 4+32(sp) with arguments: old sp +// arg1 (8+32(sp)) and arg2 (12+32(sp)). When the user function is +// done, restore the new thread's state and return. +// +// `qt_abort' is (currently) an alias for `qt_block' because most of +// the work is shared. We could save the insns up to `qt_common' by +// replicating, but w/o replicating we need an inital subtract (to +// offset the stack as if it had been a qt_block) and then a jump +// to qt_common. For the cost of a jump, we might as well just do +// all the work. +// +// The helper function (4(sp)) can return a void* that is returned +// by the call to `qt_blockk{,i}'. Since we don't touch %eax in +// between, we get that ``for free''. */ + +_qt_abort: +qt_abort: +_qt_block: +qt_block: +_qt_blocki: +qt_blocki: + pushl %ebp /* Save callee-save, sp-=4. */ + pushl %esi /* Save callee-save, sp-=4. */ + pushl %edi /* Save callee-save, sp-=4. */ + pushl %ebx /* Save callee-save, sp-=4. */ + movl %esp, %eax /* Remember old stack pointer. */ + +qt_common: + movl 32(%esp), %esp /* Move to new thread. */ + pushl 28(%eax) /* Push arg 2. */ + pushl 24(%eax) /* Push arg 1. */ + pushl %eax /* Push arg 0. */ + movl 20(%eax), %ebx /* Get function to call. */ + call *%ebx /* Call f. */ + addl $12, %esp /* Pop args. */ + + popl %ebx /* Restore callee-save, sp+=4. */ + popl %edi /* Restore callee-save, sp+=4. */ + popl %esi /* Restore callee-save, sp+=4. */ + popl %ebp /* Restore callee-save, sp+=4. */ +_qt_align: +qt_align: + ret /* Resume the stopped function. */ + + .globl _qt_tramp + .globl qt_tramp +_qt_tramp: +qt_tramp: + movl 12(%esp), %eax /* Load 'qt_error' address */ + sub $4, %esp /* Align stack pointer to 16-byte boundary */ + jmp *%eax /* call 'qt_error' */ + hlt /* 'qt_error' never returns */ + +/* Start a varargs thread. */ + + .globl _qt_vstart + .globl qt_vstart +_qt_vstart: +qt_vstart: + pushl %edi /* Push `pt' arg to `startup'. */ + call *%ebp /* Call `startup'. */ + popl %eax /* Clean up the stack. */ + + call *%ebx /* Call the user's function. */ + + pushl %eax /* Push return from user's. */ + pushl %edi /* Push `pt' arg to `cleanup'. */ + call *%esi /* Call `cleanup'. */ + + hlt /* `cleanup' never returns. */ diff --git a/ext/systemc/src/sysc/qt/md/i386_b.s b/ext/systemc/src/sysc/qt/md/i386_b.s new file mode 100644 index 000000000..32129a5d1 --- /dev/null +++ b/ext/systemc/src/sysc/qt/md/i386_b.s @@ -0,0 +1,30 @@ +/* +// QuickThreads -- Threads-building toolkit. +// Copyright (c) 1993 by David Keppel +// +// Permission to use, copy, modify and distribute this software and +// its documentation for any purpose and without fee is hereby +// granted, provided that the above copyright notice and this notice +// appear in all copies. This software is provided as a +// proof-of-concept and for demonstration purposes; there is no +// representation about the suitability of this software for any +// purpose. */ + + .globl _b_call_reg + .globl b_call_reg + .globl _b_call_imm + .globl b_call_imm + .globl _b_add + .globl b_add + .globl _b_load + .globl b_load + +_b_call_reg: +b_call_reg: +_b_call_imm: +b_call_imm: +_b_add: +b_add: +_b_load: +b_load: + hlt diff --git a/ext/systemc/src/sysc/qt/md/iX86_64.h b/ext/systemc/src/sysc/qt/md/iX86_64.h new file mode 100644 index 000000000..97bfe39b4 --- /dev/null +++ b/ext/systemc/src/sysc/qt/md/iX86_64.h @@ -0,0 +1,140 @@ +/* + * QuickThreads -- Threads-building toolkit. + * Copyright (c) 1993 by David Keppel + * + * Permission to use, copy, modify and distribute this software and + * its documentation for any purpose and without fee is hereby + * granted, provided that the above copyright notice and this notice + * appear in all copies. This software is provided as a + * proof-of-concept and for demonstration purposes; there is no + * representation about the suitability of this software for any + * purpose. + */ + +#ifndef QUICKTHREADS_X86_64_H +#define QUICKTHREADS_X86_64_H + +typedef unsigned long qt_word_t; + +/* Thread's initial stack layout on the iX86_64: + + non-varargs: + + +--- + | arg[2] === `userf' on startup + | arg[1] === `pt' on startup + | arg[0] === `pu' on startup + +--- + | ret pc === qt_error + +--- + | ret pc === `only' on startup + +--- + | %ebp + | %esi + | %edi + | %ebx <--- qt_t.sp + +--- + + When a non-varargs thread is started, it ``returns'' directly to + the client's `only' function. + + varargs: + + +--- + | arg[n-1] + | .. + | arg[0] + +--- + | ret pc === `qt_vstart' + +--- + | %ebp === `startup' + | %esi === `cleanup' + | %edi === `pt' + | %ebx === `vuserf' <--- qt_t.sp + +--- + + When a varargs thread is started, it ``returns'' to the `qt_vstart' + startup code. The startup code calls the appropriate functions. */ + + +/* What to do to start a varargs thread running. */ +extern void qt_vstart (void); + + +/* Hold four return pcs (qt_error, qt_start and twice qt_align) + plus ten args and two qt_word_t's for correct alignment. */ +#define QUICKTHREADS_STKBASE (16 * sizeof(long)) + +/* Hold 4 saved regs plus one return pc (qt_vstart). */ +#define QUICKTHREADS_VSTKBASE (5 * sizeof(long)) + + +/* Stack must be 16-byte aligned at function call instr. (SSE data support) */ +#define QUICKTHREADS_STKALIGN (16) + + +/* Where to place various arguments. */ +#define QUICKTHREADS_ONLY_INDEX (QUICKTHREADS_PC) +#define QUICKTHREADS_USER_INDEX (QUICKTHREADS_ARG2) +#define QUICKTHREADS_ARGT_INDEX (QUICKTHREADS_ARG1) +#define QUICKTHREADS_ARGU_INDEX (QUICKTHREADS_ARG0) + +#define QUICKTHREADS_VSTARTUP_INDEX (QUICKTHREADS_EBP) +#define QUICKTHREADS_VUSERF_INDEX (QUICKTHREADS_EBX) +#define QUICKTHREADS_VCLEANUP_INDEX (QUICKTHREADS_ESI) +#define QUICKTHREADS_VARGT_INDEX (QUICKTHREADS_EDI) + + +/* Stack layout offsets relative to stack at initial stack setup. */ + +/* Stack alignment 15 */ +#define QUICKTHREADS_RPC 14 +#define QUICKTHREADS_POP0 13 +#define QUICKTHREADS_PC 12 +#define QUICKTHREADS_POP1 11 +#define QUICKTHREADS_RBP 10 +/* Stack alignment 9 */ +#define QUICKTHREADS_R12 8 +#define QUICKTHREADS_R13 7 +#define QUICKTHREADS_R14 6 +#define QUICKTHREADS_R15 5 +#define QUICKTHREADS_RBX 4 +#define QUICKTHREADS_RCX 3 +#define QUICKTHREADS_RDX 2 +#define QUICKTHREADS_RDI 1 +#define QUICKTHREADS_RSI 0 + + +/* Arguments to save stack function. */ + +#define QUICKTHREADS_ARG0 QUICKTHREADS_RDI +#define QUICKTHREADS_ARG1 QUICKTHREADS_RSI +#define QUICKTHREADS_ARG2 QUICKTHREADS_RDX + + +/* Stack grows down. The top of the stack is the first thing to + pop off (preincrement, postdecrement). */ +#define QUICKTHREADS_GROW_DOWN + +extern void qt_error (void); +extern void qt_align (void); /* For correct stack alignment */ + +/* Push on the error return address, force Frame Pointer to 0 and + push stack alignment trampoline function. */ +#define QUICKTHREADS_ARGS_MD(sto) \ + (QUICKTHREADS_SPUT (sto, QUICKTHREADS_RBP, 0), \ + QUICKTHREADS_SPUT (sto, QUICKTHREADS_POP0, qt_align), \ + QUICKTHREADS_SPUT (sto, QUICKTHREADS_POP1, qt_align), \ + QUICKTHREADS_SPUT (sto, QUICKTHREADS_RPC, qt_error)) + + +/* When varargs are pushed, allocate space for all the args. */ +#define QUICKTHREADS_VARGS_MD0(sto, nbytes) \ + ((qt_t *)(((char *)(sto)) - QUICKTHREADS_STKROUNDUP(nbytes))) + +#define QUICKTHREADS_VARGS_MD1(sto) \ + (QUICKTHREADS_SPUT (sto, QUICKTHREADS_PC, qt_vstart)) + +#define QUICKTHREADS_VARGS_DEFAULT + +#endif /* QUICKTHREADS_X86_64_H */ diff --git a/ext/systemc/src/sysc/qt/md/iX86_64.s b/ext/systemc/src/sysc/qt/md/iX86_64.s new file mode 100644 index 000000000..a8bcfcd96 --- /dev/null +++ b/ext/systemc/src/sysc/qt/md/iX86_64.s @@ -0,0 +1,74 @@ +/* iX386_64.s -- assembly support. */ + +/* +// QuickThreads -- Threads-building toolkit. +// Copyright (c) 1993 by David Keppel +// +// Permission to use, copy, modify and distribute this software and +// its documentation for any purpose and without fee is hereby +// granted, provided that the above copyright notice and this notice +// appear in all copies. This software is provided as a +// proof-of-concept and for demonstration purposes; there is no +// representation about the suitability of this software for any +// purpose. */ + +/* 64-bit Intel Architecture Support +// written by Andy Goodrich, Forte Design Systms, Inc. */ + +/* NOTE: double-labeled `_name' and `name' for System V compatability. */ +/* NOTE: Mixed C/C++-style comments used. Sorry! */ + + .text + .align 2 + + .globl _qt_abort + .globl qt_abort + .globl _qt_block + .globl qt_block + .globl _qt_blocki + .globl qt_blocki + .globl _qt_align + .globl qt_align + +_qt_abort: +qt_abort: +_qt_block: +qt_block: +_qt_blocki: +qt_blocki: + /* 11 (return address.) */ + pushq %rbp /* 10 (push stack frame top.) */ + movq %rsp, %rbp /* set new stack frame top. */ + /* save registers. */ + subq $8, %rsp /* 9 (Stack alignment) */ + pushq %r12 /* 8 ... */ + pushq %r13 /* 7 ... */ + pushq %r14 /* 6 ... */ + pushq %r15 /* 5 ... */ + pushq %rbx /* 4 ... */ + pushq %rcx /* 3 ... (new stack address) */ + pushq %rdx /* 2 ... (arg) */ + pushq %rdi /* 1 ... (address of save function.) */ + pushq %rsi /* 0 ... (cor) */ + + movq %rdi, %rax /* get address of save function. */ + movq %rsp, %rdi /* set current stack as save argument. */ + movq %rcx, %rsp /* swap stacks. */ + movq %rcx, %rbp /* adjust stack frame pointer. */ + addq $10*8, %rbp /* ... */ + call *%rax /* call function to save stack pointer. */ + + /* restore registers. */ + popq %rsi /* ... */ + popq %rdi /* ... */ + popq %rdx /* ... */ + popq %rcx /* ... */ + popq %rbx /* ... */ + popq %r15 /* restore registers from new stack. */ + popq %r14 /* ... */ + popq %r13 /* ... */ + popq %r12 /* ... */ + leave /* unwind stack. */ +_qt_align: +qt_align: + ret /* return. */ diff --git a/ext/systemc/src/sysc/qt/md/ksr1.Makefile b/ext/systemc/src/sysc/qt/md/ksr1.Makefile new file mode 100644 index 000000000..aa195839a --- /dev/null +++ b/ext/systemc/src/sysc/qt/md/ksr1.Makefile @@ -0,0 +1,6 @@ + +# +# KSR1 configuration. +# +CC = cc -ansi + diff --git a/ext/systemc/src/sysc/qt/md/ksr1.h b/ext/systemc/src/sysc/qt/md/ksr1.h new file mode 100644 index 000000000..b3877505d --- /dev/null +++ b/ext/systemc/src/sysc/qt/md/ksr1.h @@ -0,0 +1,164 @@ +/* + * QuickThreads -- Threads-building toolkit. + * Copyright (c) 1993 by David Keppel + * + * Permission to use, copy, modify and distribute this software and + * its documentation for any purpose and without fee is hereby + * granted, provided that the above copyright notice and this notice + * appear in all copies. This software is provided as a + * proof-of-concept and for demonstration purposes; there is no + * representation about the suitability of this software for any + * purpose. + */ + +#ifndef QUICKTHREADS_KSR1_H +#define QUICKTHREADS_KSR1_H + +/* + Stack layout: + + Registers are saved in strictly low to high order, FPU regs first + (only if qt_block is called), CEU regs second, IPU regs next, with no + padding between the groups. + + Callee-save: f16..f63; c15..c30; i12..i30. + Args passed in i2..i5. + + Note: c31 is a private data pointer. It is not changed on thread + swaps with the assumption that it represents per-processor rather + than per-thread state. + + Note: i31 is an instruction count register that is updated by the + context switch routines. Like c31, it is not changed on context + switches. + + This is what we want on startup: + + + +------ <-- BOS: Bottom of stack (grows down) + | 80 (128 - 48) bytes of padding to a 128-byte boundary + +--- + | only + | userf + | t + | u + | qt_start$TXT + | (empty) <-- qt.sp + +------ <-- (BOS - 128) + + This is why we want this on startup: + + A thread begins running when the restore procedure switches thread stacks + and pops a return address off of the top of the new stack (see below + for the reason why we explicitly store qt_start$TXT). The + block procedure pushes two jump addresses on a thread's stack before + it switches stacks. The first is the return address for the block + procedure, and the second is a restore address. The return address + is used to jump back to the thread that has been switched to; the + restore address is a jump within the block code to restore the registers. + Normally, this is just a jump to the next address. However, on thread + startup, this is a jump to qt_start$TXT. (The block procedure stores + the restore address at an offset of 8 bytes from the top of the stack, + which is also the offset at which qt_start$TXT is stored on the stacks + of new threads. Hence, when the block procedure switches to a new + thread stack, it will initially jump to qt_start$TXT; thereafter, + it jumps to the restore code.) + + qt_start$TXT, after it has read the initial data on the new thread's + stack and placed it in registers, pops the initial stack frame + and gives the thread the entire stack to use for execution. + + The KSR runtime system has an unusual treatment of pointers to + functions. From C, taking the `name' of a function yields a + pointer to a _constant block_ and *not* the address of the + function. The zero'th entry in the constant block is a pointer to + the function. + + We have to be careful: the restore procedure expects a return + address on the top of the stack (pointed to by qt.sp). This is not + a problem when restoring a thread that has run before, since the + block routine would have stored the return address on top of the + stack. However, when ``faking up'' a thread start (bootstrapping a + thread stack frame), the top of the stack needs to contain a + pointer to the code that will start the thread running. + + The pointer to the startup code is *not* `qt_start'. It is the + word *pointed to* by `qt_start'. Thus, we dereference `qt_start', + see QUICKTHREADS_ARGS_MD below. + + On varargs startup (still unimplemented): + + | padding to 128 byte boundary + | varargs <-- padded to a 128-byte-boundary + +--- + | caller's frame, 16 bytes + | 80 bytes of padding (frame padded to a 128-byte boundary) + +--- + | cleanup + | vuserf + | startup + | t + +--- + | qt_start <-- qt.sp + +--- + + Of a suspended thread: + + +--- + | caller's frame, 16 bytes + | fpu registers 47 regs * 8 bytes/reg 376 bytes + | ceu registers 16 regs * 8 bytes/reg 128 bytes + | ipu registers 19 regs * 8 bytes/reg 152 bytes + | : + | 80 bytes of padding + | : + | qt_restore <-- qt.sp + +--- + + */ + + +#define QUICKTHREADS_STKALIGN 128 +#define QUICKTHREADS_GROW_DOWN +typedef unsigned long qt_word_t; + +#define QUICKTHREADS_STKBASE QUICKTHREADS_STKALIGN +#define QUICKTHREADS_VSTKBASE QUICKTHREADS_STKBASE + +extern void qt_start(void); +/* + * See the discussion above for what indexing into a procedure ptr + * does for us (it's lovely, though, isn't it?). + * + * This assumes that the address of a procedure's code is the + * first word in a procedure's constant block. That's how the manual + * says it will be arranged. + */ +#define QUICKTHREADS_ARGS_MD(sp) (QUICKTHREADS_SPUT (sp, 1, ((qt_word_t *)qt_start)[0])) + +/* + * The *index* (positive offset) of where to put each value. + * See the picture of the stack above that explains the offsets. + */ +#define QUICKTHREADS_ONLY_INDEX (5) +#define QUICKTHREADS_USER_INDEX (4) +#define QUICKTHREADS_ARGT_INDEX (3) +#define QUICKTHREADS_ARGU_INDEX (2) + +#define QUICKTHREADS_VARGS_DEFAULT +#define QUICKTHREADS_VARGS(sp, nb, vargs, pt, startup, vuserf, cleanup) \ + (qt_vargs (sp, nbytes, &vargs, pt, startup, vuserf, cleanup)) + + +#define QUICKTHREADS_VARGS_MD0(sp, vabytes) \ + ((qt_t *)(((char *)(sp)) - 4*8 - QUICKTHREADS_STKROUNDUP(vabytes))) + +extern void qt_vstart(void); +#define QUICKTHREADS_VARGS_MD1(sp) (QUICKTHREADS_SPUT (sp, 0, ((qt_word_t *)qt_vstart)[0])) + +#define QUICKTHREADS_VCLEANUP_INDEX (4) +#define QUICKTHREADS_VUSERF_INDEX (3) +#define QUICKTHREADS_VSTARTUP_INDEX (2) +#define QUICKTHREADS_VARGT_INDEX (1) + +#endif /* def QUICKTHREADS_KSR1_H */ diff --git a/ext/systemc/src/sysc/qt/md/ksr1.s b/ext/systemc/src/sysc/qt/md/ksr1.s new file mode 100644 index 000000000..d4d51a0a6 --- /dev/null +++ b/ext/systemc/src/sysc/qt/md/ksr1.s @@ -0,0 +1,424 @@ +/* + * QuickThreads -- Threads-building toolkit. + * Copyright (c) 1993 by David Keppel + * + * Permission to use, copy, modify and distribute this software and + * its documentation for any purpose and without fee is hereby + * granted, provided that the above copyright notice and this notice + * appear in all copies. This software is provided as a + * proof-of-concept and for demonstration purposes; there is no + * representation about the suitability of this software for any + * purpose. + */ + + .file "ksr1.s" + .def .debug; .endef + + .align 128 + .globl qt_blocki + .globl qt_blocki$TXT + .globl qt_block + .globl qt_block$TXT + .globl qt_start$TXT + .globl qt_start + .globl qt_abort$TXT + .globl qt_abort + .globl qt_vstart + .globl qt_vstart$TXT + +# +# KSR convention: on procedure calls, load both the procedure address +# and a pointer to a constant block. The address of function `f' is +# `f$TXT', and the constant block address is `f'. The constant block +# has several reserved values: +# +# 8 bytes fpu register save mask +# 4 bytes ipu register save mask +# 4 bytes ceu register save mask +# f: f$TXT +# ... whatever you want ... (not quite...read on) +# +# Note, by the way, that a pointer to a function is passed as a +# pointer to the constant area, and the constant area has the text +# address. +# + +# +# Procedures that do not return structures prefix their code with +# +# proc$TXT: +# finop; cxnop +# finop; cxnop +# <proc code> +# +# Calls to those procedures branch to a 16 byte offset (4 instrs) in +# to the procedure to skip those instructions. +# +# Procedures that return structures use a different code prefix: +# +# proc$TXT: +# finop; beq.qt %rc, %rc, 24 # return value entry +# finop; cxnop +# finop; movi8 0, %rc # no return value entry +# <proc code> +# +# Calls that want the returned structure branch directly to the +# procedure address. Callers that don't want (or aren't expecting) a +# return value branche 16 bytes in to the procedure, which will zero +# %rc, telling the called procedure not to return a structure. +# + +# +# On entry: +# %i2 -- control block of helper function to run +# (dereference to get helper) +# %i3 -- a1 +# %i4 -- a2 +# %i5 -- sp of new to run +# + + .data + .half 0x0, 0x0, 0x7ffff000, 0x7fff8000 +qt_blocki: +qt_abort: + .word qt_blocki$TXT + .word qt_restore$TXT + + .text +qt_abort$TXT: +qt_blocki$TXT: + finop ; cxnop # entry prefix + finop ; cxnop # entry prefix + add8.ntr 75,%i31,%i31 ; movi8 512,%c5 # ICR; stk adjust + finop ; ssub8.ntr 0,%sp,%c5,%sp + finop ; st8 %fp,504(%sp) # Save caller's fp + finop ; st8 %cp,496(%sp) # Save caller's cp + finop ; ld8 8(%c10),%c5 # ld qt_restore$TXT + finop ; st8 %c14,0(%sp) # Save special ret addr + finop ; mov8_8 %c10, %cp # Our cp + finop ; sadd8.ntr 0,%sp,%c5,%fp # Our frame ptr + finop ; st8 %c5,8(%sp) # st qt_restore$TXT +# +# CEU registers %c15-%c24, %c26-%c30 (%c14 we restore later) +# + finop ; st8 %c15,456(%sp) + finop ; st8 %c16,448(%sp) + finop ; st8 %c17,440(%sp) + finop ; st8 %c18,432(%sp) + finop ; st8 %c19,424(%sp) + finop ; st8 %c20,416(%sp) + finop ; st8 %c21,408(%sp) + finop ; st8 %c22,400(%sp) + finop ; st8 %c23,392(%sp) + finop ; st8 %c24,384(%sp) +# +# %c25 is the Enclosing Frame Pointer (EFP) -- since C doesn't +# use nested procedures, we ignore it (leaving a gap, though) +# + finop ; st8 %c26,368(%sp) + finop ; st8 %c27,360(%sp) + finop ; st8 %c28,352(%sp) + finop ; st8 %c29,344(%sp) + finop ; st8 %c30,336(%sp) +# +# IPU registers %i12-%i30 +# + finop ; st8 %i12,328(%sp) + finop ; st8 %i13,320(%sp) + finop ; st8 %i14,312(%sp) + finop ; st8 %i15,304(%sp) +# (gap to get alignment for st64) +# -- Doesn't work on version 1.1.3 of the OS +# finop ; st64 %i16,256(%sp) + + finop ; st8 %i16,256(%sp) + finop ; st8 %i17,248(%sp) + finop ; st8 %i18,240(%sp) + finop ; st8 %i19,232(%sp) + finop ; st8 %i20,224(%sp) + finop ; st8 %i21,216(%sp) + finop ; st8 %i22,208(%sp) + finop ; st8 %i23,200(%sp) + finop ; st8 %i24,192(%sp) + finop ; st8 %i25,184(%sp) + finop ; st8 %i26,176(%sp) + finop ; st8 %i27,168(%sp) + finop ; st8 %i28,160(%sp) + finop ; st8 %i29,152(%sp) + finop ; st8 %i30,144(%sp) +# +# FPU already saved, or saving not necessary +# + +# +# Switch to the stack passed in as fourth argument to the block +# routine (%i5) and call the helper routine passed in as the first +# argument (%i2). Note that the address of the helper's constant +# block is passed in, so we must derefence it to get the helper's text +# address. +# + finop ; movb8_8 %i2,%c10 # helper's ConstBlock + finop ; cxnop # Delay slot, fill w/ + finop ; cxnop # .. 2 st8 from above + finop ; ld8 0(%c10),%c4 # load addr of helper + finop ; movb8_8 %sp, %i2 # 1st arg to helper + # is this stack; other + # args remain in regs + finop ; movb8_8 %i5,%sp # switch stacks + finop ; jsr %c14,16(%c4) # call helper + movi8 3, %i0 ; movi8 0,%c8 # nargs brain dmg + finop ; cxnop + finop ; cxnop +# +# Here is where behavior differs for threads being restored and threads +# being started. Blocked threads have a pointer to qt_restore$TXT on +# the top of their stacks; manufactured stacks have a pointer to qt_start$TXT +# on the top of their stacks. With this setup, starting threads +# skip the (unecessary) restore operations. +# +# We jump to an offset of 16 to either (1) skip past the two noop pairs +# at the start of qt_start$TXT, or (2) skip past the two noop pairs +# after qt_restore$TXT. +# + finop ; ld8 8(%sp),%c4 + finop ; cxnop + finop ; cxnop + finop ; jmp 16(%c4) +qt_restore$TXT: + finop ; cxnop + finop ; cxnop +# +# Point of Restore: +# +# The helper funtion will return here. Any result it has placed in +# a return register (most likely %i0) will not get overwritten below +# and will consequently be the return value of the blocking routine. +# + +# +# CEU registers %c15-%c24, %c26-%c30 (%c14 we restore later) +# + finop ; ld8 456(%sp),%c15 + finop ; ld8 448(%sp),%c16 + finop ; ld8 440(%sp),%c17 + finop ; ld8 432(%sp),%c18 + finop ; ld8 424(%sp),%c19 + finop ; ld8 416(%sp),%c20 + finop ; ld8 408(%sp),%c21 + finop ; ld8 400(%sp),%c22 + finop ; ld8 392(%sp),%c23 + finop ; ld8 384(%sp),%c24 +# +# %c25 is the Enclosing Frame Pointer (EFP) -- since C doesn't +# use nested procedures, we ignore it (leaving a gap, though) +# + finop ; ld8 368(%sp),%c26 + finop ; ld8 360(%sp),%c27 + finop ; ld8 352(%sp),%c28 + finop ; ld8 344(%sp),%c29 + finop ; ld8 336(%sp),%c30 +# +# IPU registers %i12-%i30 +# + finop ; ld8 328(%sp),%i12 + finop ; ld8 320(%sp),%i13 + finop ; ld8 312(%sp),%i14 + finop ; ld8 304(%sp),%i15 +# (gap to get alignment for ld64) +# -- Doesn't work on version 1.1.3 of the OS +# finop ; ld64 256(%sp),%i16 + + finop ; ld8 256(%sp),%i16 + finop ; ld8 248(%sp),%i17 + finop ; ld8 240(%sp),%i18 + finop ; ld8 232(%sp),%i19 + finop ; ld8 224(%sp),%i20 + finop ; ld8 216(%sp),%i21 + finop ; ld8 208(%sp),%i22 + finop ; ld8 200(%sp),%i23 + finop ; ld8 192(%sp),%i24 + finop ; ld8 184(%sp),%i25 + finop ; ld8 176(%sp),%i26 + finop ; ld8 168(%sp),%i27 + finop ; ld8 160(%sp),%i28 + finop ; ld8 152(%sp),%i29 + finop ; ld8 144(%sp),%i30 + +# +# FPU registers don't need to be loaded, or will be loaded by an +# enclosing scope (e.g., if this is called by qt_block). +# + +# +# Load the special registers. We don't load the stack ptr because +# the new stack is passed in as an argument, we don't load the EFP +# because we don't use it, and we load the return address specially +# off the top of the stack. +# + finop ; ld8 0(%sp),%c14 # return addr + finop ; ld8 496(%sp),%cp + finop ; ld8 504(%sp),%fp + + finop ; jmp 32(%c14) # jump back to thread + finop ; movi8 512,%c5 # stack adjust + finop ; sadd8.ntr 0,%sp,%c5,%sp + + .data + .half 0x0, 0x0, 0x7ffff000, 0x7fff8000 +qt_block: + .word qt_block$TXT + .word qt_error + .word qt_error$TXT + .word qt_blocki +# +# Handle saving and restoring the FPU regs, relying on qt_blocki +# to save and restore the remaining registers. +# + .text +qt_block$TXT: + finop ; cxnop # entry prefix + finop ; cxnop # entry prefix + + add8.ntr 29,%i31,%i31 ; movi8 512,%c5 # ICR; stk adjust + finop ; ssub8.ntr 0,%sp,%c5,%sp + finop ; st8 %fp,504(%sp) # Save caller's fp + finop ; st8 %cp,496(%sp) # Save caller's cp + finop ; st8 %c14,488(%sp) # store ret addr + finop ; sadd8.ntr 0,%sp,%c5,%fp # Our frame ptr + finop ; mov8_8 %c10, %cp # Our cp + +# +# Store 8 registers at once...destination must be a multiple of 64 +# + finop ; st64 %f16,384(%sp) + finop ; st64 %f24,320(%sp) + finop ; st64 %f32,256(%sp) + finop ; st64 %f40,192(%sp) + finop ; st64 %f48,128(%sp) + finop ; st64 %f56,64(%sp) + +# +# Call the integer blocking routine, passing the arguments passed to us +# + finop ; ld8 24(%cp), %c10 + finop ; cxnop + finop ; jsr %c14, qt_blocki$TXT + finop ; cxnop + finop ; cxnop + movi8 4,%i0 ; movi8 0,%c8 # nargs brain dmg + +# +# Load 8 registers at once...source must be a multiple of 64 +# + finop ; ld64 64(%sp),%f56 + finop ; ld64 128(%sp),%f48 + finop ; ld64 192(%sp),%f40 + finop ; ld64 256(%sp),%f32 + finop ; ld64 320(%sp),%f24 + finop ; ld64 384(%sp),%f16 + + finop ; ld8 488(%sp),%c14 + finop ; ld8 496(%sp),%cp + finop ; ld8 504(%sp),%fp + finop ; jmp 32(%c14) # jump back to thread + finop ; movi8 512,%c5 # stack adjust + finop ; sadd8.ntr 0,%sp,%c5,%sp + + + .data + .half 0x0, 0x0, 0x7ffff000, 0x7fff8000 +qt_start: + .word qt_start$TXT +# +# A new thread is set up to "appear" as if it were executing code at +# the beginning of qt_start and then it called a blocking routine +# (qt_blocki). So when a new thread starts to run, it gets unblocked +# by the code above and "returns" to `qt_start$TXT' in the +# restore step of the switch. Blocked threads jump to 16(qt_restore$TXT), +# and starting threads jump to 16(qt_start$TXT). +# + .text +qt_start$TXT: + finop ; cxnop # + finop ; cxnop # + finop ; ld8 40(%sp),%c10 # `only' constant block + finop ; ld8 32(%sp),%i4 # `userf' arg. + finop ; ld8 24(%sp),%i3 # `t' arg. + finop ; ld8 0(%c10),%c4 # `only' text location + finop ; ld8 16(%sp),%i2 # `u' arg. + finop ; cxnop + finop ; jsr %c14,16(%c4) # call `only' +# +# Pop the frame used to store the thread's initial data +# + finop ; sadd8.ntr 0,%sp,128,%sp + finop ; cxnop + movi8 2,%i0 ; movi8 0,%c8 # nargs brain dmg +# +# If we ever return, it's an error. +# + finop ; jmp qt_error$TXT + finop ; cxnop + finop ; cxnop + movi8 0,%i0 ; movi8 0,%c8 # nargs brain dmg + + +# +# This stuff is broken +# + .data + .half 0x0, 0x0, 0x7ffff000, 0x7fff8000 +qt_vstart: + .word qt_vstart$TXT + + .text +qt_vstart$TXT: + finop ; cxnop # entry prefix + finop ; cxnop # entry prefix + finop ; cxnop + finop ; cxnop + add8.ntr 11,%i31,%i31 ; movi8 512,%c5 + finop ; ssub8.ntr 0,%sp,%c5,%sp # fix stack + finop ; ld8 8(%sp),%i2 # load `t' as arg to + finop ; cxnop # `startup' + finop ; cxnop + finop ; ld8 16(%sp),%c10 # `startup' const block + finop ; cxnop + finop ; cxnop + finop ; ld8 0(%c10),%c4 # `startup' text loc. + finop ; cxnop + finop ; cxnop + finop ; jsr %c14,16(%c4) # call `startup' + finop ; cxnop + finop ; cxnop + movi8 1, %i0 ; movi8 0,%c8 # nargs brain dmg +# +# finop ; sadd 0,%sp,128,%sp # alter stack +# + finop ; ld8 8(%sp),%i2 # load `t' as arg to + finop ; ld8 8(%sp),%i2 # load `t' as arg to + finop ; ld8 8(%sp),%i2 # load `t' as arg to + finop ; ld8 8(%sp),%i2 # load `t' as arg to + + finop ; ld8 32(%sp),%c10 # `only' constant block + finop ; ld8 8(%sp),%i2 # `u' arg. + finop ; ld8 16(%sp),%i3 # `t' arg. + finop ; ld8 0(%c10),%c4 # `only' text location + finop ; ld8 24(%sp),%i4 # `userf' arg. + finop ; cxnop + finop ; jsr %c4,16(%c4) # call `only' + finop ; cxnop + finop ; cxnop +# +# If the callee ever calls `nargs', the following instruction (pair) +# will be executed. However, we don't know when we compile this code +# how many args are being passed. So we give our best guess: 0. +# + movi8 0,%i0 ; movi8 0,%c8 # nargs brain dmg +# +# If we ever return, it's an error. +# + finop ; jmp qt_error$TXT + finop ; cxnop + finop ; cxnop + movi8 0,%i0 ; movi8 0,%c8 # nargs brain dmg diff --git a/ext/systemc/src/sysc/qt/md/ksr1_b.s b/ext/systemc/src/sysc/qt/md/ksr1_b.s new file mode 100644 index 000000000..80b0c59eb --- /dev/null +++ b/ext/systemc/src/sysc/qt/md/ksr1_b.s @@ -0,0 +1,49 @@ +/* + * QuickThreads -- Threads-building toolkit. + * Copyright (c) 1993 by David Keppel + * + * Permission to use, copy, modify and distribute this software and + * its documentation for any purpose and without fee is hereby + * granted, provided that the above copyright notice and this notice + * appear in all copies. This software is provided as a + * proof-of-concept and for demonstration purposes; there is no + * representation about the suitability of this software for any + * purpose. + */ + + .file "ksr1_b.s" + .def .debug; .endef + + .globl b_call_reg$TXT + .globl b_call_reg + .globl b_call_imm$TXT + .globl b_call_imm + .globl b_add$TXT + .globl b_add + .globl b_load$TXT + .globl b_load + + +b_call_reg: +b_call_imm: +b_add: +b_load: + .word b_call_reg$TXT + .word qt_error + .word qt_error$TXT + + +b_call_reg$TXT: +b_call_imm$TXT: +b_add$TXT: +b_load$TXT: + finop ; cxnop + finop ; cxnop + finop ; ld8 16(%cp),%c4 + finop ; ld8 8(%cp),%cp + finop ; cxnop + finop ; cxnop + finop ; jsr %c4,0(%c4) + finop ; cxnop + finop ; cxnop + diff --git a/ext/systemc/src/sysc/qt/md/m88k.Makefile b/ext/systemc/src/sysc/qt/md/m88k.Makefile new file mode 100644 index 000000000..608c70690 --- /dev/null +++ b/ext/systemc/src/sysc/qt/md/m88k.Makefile @@ -0,0 +1,6 @@ + +# +# Hosted compilers for 88k for Meerkat. +# +CC = gcc88 -Dm88k -ansi -pedantic -Wall -fno-builtin +AS = as88 diff --git a/ext/systemc/src/sysc/qt/md/m88k.c b/ext/systemc/src/sysc/qt/md/m88k.c new file mode 100644 index 000000000..f2cef00a0 --- /dev/null +++ b/ext/systemc/src/sysc/qt/md/m88k.c @@ -0,0 +1,111 @@ +/* + * QuickThreads -- Threads-building toolkit. + * Copyright (c) 1993 by David Keppel + * + * Permission to use, copy, modify and distribute this software and + * its documentation for any purpose and without fee is hereby + * granted, provided that the above copyright notice and this notice + * appear in all copies. This software is provided as a + * proof-of-concept and for demonstration purposes; there is no + * representation about the suitability of this software for any + * purpose. + */ + +#include <stdarg.h> +#include "qt.h" + +/* Varargs is harder on the m88k. Parameters are saved on the stack as + something like (stack grows down to low memory; low at bottom of + picture): + + | : + | arg8 <-- va_list.__va_stk + +--- + | : + +--- + | arg7 + | : + | iarg0 <-- va_list.__va_reg + +--- + | : + | va_list { __va_arg, __va_stk, __va_reg } + | : + +--- + + Here, `va_list.__va_arg' is the number of word-size arguments + that have already been skipped. Doubles must be double-arligned. + + What this means for us is that the user's routine needs to be + called with an arg list where some of the words in the `__va_stk' + part of the parameter list have to be promoted to registers. + + BUG: doubleword register arguments must be double-aligned. If + something is passed as an even # arg and used as an odd # arg or + vice-versa, the code in the called routine (in the new thread) that + decides how to adjust the index will get it wrong, because it will + be expect it to be, say, doubleword aligned and it will really be + singleword aligned. + + I'm not sure you can solve this without knowing the types of all + the arguments. All in all, we never promised varargs would work + reliably. */ + + + +#define QUICKTHREADS_VADJ(sp) (((char *)sp) - QUICKTHREADS_VSTKBASE) + +/* Always allocate at least enough space for 8 args; waste some space + at the base of the stack to ensure the startup routine doesn't read + off the end of the stack. */ + +#define QUICKTHREADS_VARGS_MD0(sp, vabytes) \ + ((qt_t *)(((char *)(sp)) - 8*4 - QUICKTHREADS_STKROUNDUP(vabytes))) + +extern void qt_vstart(void); +#define QUICKTHREADS_VARGS_MD1(sp) (QUICKTHREADS_SPUT (sp, QUICKTHREADS_1, qt_vstart)) + + + struct qt_t * +qt_vargs (struct qt_t *qsp, int nbytes, void *vargs, + void *pt, qt_function_t *startup, + qt_function_t *vuserf, qt_function_t *cleanup) +{ + va_list ap; + int i; + int n; /* Number of words into original arg list. */ + qt_word_t *sp; + int *reg; /* Where to read passed-in-reg args. */ + int *stk; /* Where to read passed-on-stk args. */ + + ap = *(va_list *)vargs; + qsp = QUICKTHREADS_VARGS_MD0 (qsp, nbytes); + sp = (qt_word_t *)qsp; + + reg = (ap.__va_arg < 8) + ? &ap.__va_reg[ap.__va_arg] + : 0; + stk = &ap.__va_stk[8]; + n = ap.__va_arg; + for (i=0; i<nbytes/sizeof(qt_word_t) && n<8; ++i,++n) { + sp[i] = *reg++; + } + for (; i<nbytes/sizeof(qt_word_t); ++i) { + sp[i] = *stk++; + } + +#ifdef QUICKTHREADS_NDEF + for (i=0; i<nbytes/sizeof(qt_word_t); ++i) { + sp[i] = (n < 8) + ? *reg++ + : *stk++; + ++n; + } +#endif + + QUICKTHREADS_VARGS_MD1 (QUICKTHREADS_VADJ(sp)); + QUICKTHREADS_SPUT (QUICKTHREADS_VADJ(sp), QUICKTHREADS_VARGT_INDEX, pt); + QUICKTHREADS_SPUT (QUICKTHREADS_VADJ(sp), QUICKTHREADS_VSTARTUP_INDEX, startup); + QUICKTHREADS_SPUT (QUICKTHREADS_VADJ(sp), QUICKTHREADS_VUSERF_INDEX, vuserf); + QUICKTHREADS_SPUT (QUICKTHREADS_VADJ(sp), QUICKTHREADS_VCLEANUP_INDEX, cleanup); + return ((qt_t *)QUICKTHREADS_VADJ(sp)); +} diff --git a/ext/systemc/src/sysc/qt/md/m88k.h b/ext/systemc/src/sysc/qt/md/m88k.h new file mode 100644 index 000000000..f9cab5327 --- /dev/null +++ b/ext/systemc/src/sysc/qt/md/m88k.h @@ -0,0 +1,159 @@ +/* + * QuickThreads -- Threads-building toolkit. + * Copyright (c) 1993 by David Keppel + * + * Permission to use, copy, modify and distribute this software and + * its documentation for any purpose and without fee is hereby + * granted, provided that the above copyright notice and this notice + * appear in all copies. This software is provided as a + * proof-of-concept and for demonstration purposes; there is no + * representation about the suitability of this software for any + * purpose. + */ + +#ifndef QUICKTHREADS_M88K_H +#define QUICKTHREADS_M88K_H + +typedef unsigned long qt_word_t; + +#define QUICKTHREADS_GROW_DOWN + +/* Stack layout on the mips: + + Callee-save registers are: $16-$23, $30; $f20-$f30. + Also save $31, return pc. + + Non-varargs: + + +--- + | r30 (fp) on startup === 0 + | r25 + | r24 + | r23 + | r22 + | r21 + | r20 + | r19 + | r18 + | r17 on startup === `only' + | r16 on startup === `userf' + | r15 on startup === `pt' + | r14 on startup === `pu' + | r1 on startup === `qt_start' + | 0 + | 0 + +--- + | 0 + | ... (8 regs worth === 32 bytes of homing area) + | 0 <--- sp + +--- + + Conventions for varargs: + + | : + | arg8 + +--- + | r30 (fp) arg7 + | r25 arg6 + | r24 arg5 + | r23 arg4 + | r22 arg3 + | r21 arg2 + | r20 arg1 + | r19 arg0 + | r18 + | r17 on startup === `startup' + | r16 on startup === `vuserf' + | r15 on startup === `pt' + | r14 on startup === `cleanup' + | r1 on startup === `qt_vstart' + | 0 + | 0 + +--- + | 0 + | ... (8 regs worth === 32 bytes of homing area) + | 0 <--- sp + +--- + + */ + + +/* Stack must be doubleword aligned. */ +#define QUICKTHREADS_STKALIGN (16) /* Doubleword aligned. */ + +/* How much space is allocated to hold all the crud for + initialization: saved registers plus padding to keep the stack + aligned plus 8 words of padding to use as a `homing area' (for + r2-r9) when calling helper functions on the stack of the (not yet + started) thread. The varargs save area is small because it gets + overlapped with the top of the parameter list. In case the + parameter list is less than 8 args, QUICKTHREADS_ARGS_MD0 adds some dead + space at the top of the stack. */ + +#define QUICKTHREADS_STKBASE (16*4 + 8*4) +#define QUICKTHREADS_VSTKBASE (8*4 + 8*4) + + +/* Index of various registers. */ +#define QUICKTHREADS_1 (8+2) +#define QUICKTHREADS_14 (8+3) +#define QUICKTHREADS_15 (8+4) +#define QUICKTHREADS_16 (8+5) +#define QUICKTHREADS_17 (8+6) +#define QUICKTHREADS_30 (8+15) + + +/* When a never-before-run thread is restored, the return pc points + to a fragment of code that starts the thread running. For + non-vargs functions, it sets up arguments and calls the client's + `only' function. For varargs functions, the startup code calls the + startup, user, and cleanup functions. + + For non-varargs functions, we set the frame pointer to 0 to + null-terminate the call chain. + + For varargs functions, the frame pointer register is used to hold + one of the arguments, so that all arguments can be laid out in + memory by the conventional `qt_vargs' varargs initialization + routine. + + The varargs startup routine always reads 8 words of arguments from + the stack. If there are less than 8 words of arguments, then the + arg list could call off the top of the stack. To prevent fall-off, + always allocate 8 words. */ + +extern void qt_start(void); +#define QUICKTHREADS_ARGS_MD(sp) \ + (QUICKTHREADS_SPUT (sp, QUICKTHREADS_1, qt_start), \ + QUICKTHREADS_SPUT (sp, QUICKTHREADS_30, 0)) + + +/* The m88k uses a struct for `va_list', so pass a pointer to the + struct. */ + +typedef void (qt_function_t)(void); + +struct qt_t; +extern struct qt_t *qt_vargs (struct qt_t *sp, int nbytes, + void *vargs, void *pt, + qt_function_t *startup, + qt_function_t *vuserf, + qt_function_t *cleanup); + +#define QUICKTHREADS_VARGS(sp, nbytes, vargs, pt, startup, vuserf, cleanup) \ + (qt_vargs (sp, nbytes, &(vargs), pt, (qt_function_t *)startup, \ + (qt_function_t *)vuserf, (qt_function_t *)cleanup)) + + +/* The *index* (positive offset) of where to put each value. */ +#define QUICKTHREADS_ONLY_INDEX (QUICKTHREADS_17) +#define QUICKTHREADS_USER_INDEX (QUICKTHREADS_16) +#define QUICKTHREADS_ARGT_INDEX (QUICKTHREADS_15) +#define QUICKTHREADS_ARGU_INDEX (QUICKTHREADS_14) + +#define QUICKTHREADS_VCLEANUP_INDEX (QUICKTHREADS_14) +#define QUICKTHREADS_VUSERF_INDEX (QUICKTHREADS_16) +#define QUICKTHREADS_VSTARTUP_INDEX (QUICKTHREADS_17) +#define QUICKTHREADS_VARGT_INDEX (QUICKTHREADS_15) + +#endif /* ndef QUICKTHREADS_M88K_H */ diff --git a/ext/systemc/src/sysc/qt/md/m88k.s b/ext/systemc/src/sysc/qt/md/m88k.s new file mode 100644 index 000000000..42467e8d5 --- /dev/null +++ b/ext/systemc/src/sysc/qt/md/m88k.s @@ -0,0 +1,132 @@ +/* m88k.s -- assembly support. */ + +/* + * QuickThreads -- Threads-building toolkit. + * Copyright (c) 1993 by David Keppel + * + * Permission to use, copy, modify and distribute this software and + * its documentation for any purpose and without fee is hereby + * granted, provided that the above copyright notice and this notice + * appear in all copies. This software is provided as a + * proof-of-concept and for demonstration purposes; there is no + * representation about the suitability of this software for any + * purpose. + */ + +/* Callee-save r14..r25, r31(sp), r30(fp). r1 === return pc. + * Argument registers r2..r9, return value r2..r3. + * + * On startup, restore regs so retpc === call to a function to start. + * + * We're going to call a function (r2) from within the context switch + * routine. Call it on the new thread's stack on behalf of the old + * thread. + */ + + .globl _qt_block + .globl _qt_blocki + .globl _qt_abort + .globl _qt_start + .globl _qt_vstart + + /* + ** r2: ptr to function to call once curr is suspended + ** and control is on r5's stack. + ** r3: 1'th arg to *r2. + ** r4: 2'th arg to *r2. + ** r5: sp of thread to suspend. + ** + ** The helper routine returns a value that is passed on as the + ** return value from the blocking routine. Since we don't + ** touch r2 between the helper's return and the end of + ** function, we get this behavior for free. + ** + ** Same entry for integer-only and floating-point, since there + ** are no separate integer and floating-point registers. + ** + ** Each procedure call sets aside a ``home region'' of 8 regs + ** for r2-r9 for varargs. For context switches we don't use + ** the ``home region'' for varargs so use it to save regs. + ** Allocate 64 bytes of save space -- use 32 bytes of register + ** save area passed in to us plus 32 bytes we allcated, use + ** the other 32 bytes for save area for a save area to call + ** the helper function. + */ +_qt_block: +_qt_blocki: + sub r31, r31,64 /* Allocate reg save space. */ + st r1, r31,8+32 /* Save callee-save registers. */ + st r14, r31,12+32 + st.d r15, r31,16+32 + st.d r17, r31,24+32 + st.d r19, r31,32+32 + st.d r21, r31,40+32 + st.d r23, r31,48+32 + st r25, r31,56+32 + st r30, r31,60+32 + +_qt_abort: + addu r14, r31,0 /* Remember old sp. */ + addu r31, r5,0 /* Set new sp. */ + jsr.n r2 /* Call helper. */ + addu r2, r14,0 /* Pass old sp as an arg0 to helper. */ + + ld r1, r31,8+32 /* Restore callee-save registers. */ + ld r14, r31,12+32 + ld.d r15, r31,16+32 + ld.d r17, r31,24+32 + ld.d r19, r31,32+32 + ld.d r21, r31,40+32 + ld.d r23, r31,48+32 + ld r25, r31,56+32 + ld r30, r31,60+32 + + jmp.n r1 /* Return to new thread's caller. */ + addu r31, r31,64 /* Free register save space. */ + + + /* + ** Non-varargs thread startup. + ** See `m88k.h' for register use conventions. + */ +_qt_start: + addu r2, r14,0 /* Set user arg `pu'. */ + addu r3, r15,0 /* ... user function pt. */ + jsr.n r17 /* Call `only'. */ + addu r4, r16,0 /* ... user function userf. */ + + bsr _qt_error /* `only' erroniously returned. */ + + + /* + ** Varargs thread startup. + ** See `m88k.h' for register use conventions. + ** + ** Call the `startup' function with just argument `pt'. + ** Then call `vuserf' with 8 register args plus any + ** stack args. + ** Then call `cleanup' with `pt' and the return value + ** from `vuserf'. + */ +_qt_vstart: + addu r18, r30,0 /* Remember arg7 to `vuserf'. */ + addu r30, r0,0 /* Null-terminate call chain. */ + + jsr.n r17 /* Call `startup'. */ + addu r2, r15,0 /* `pt' is arg0 to `startup'. */ + + addu r2, r19,0 /* Set arg0. */ + addu r3, r20,0 /* Set arg1. */ + addu r4, r21,0 /* Set arg2. */ + addu r5, r22,0 /* Set arg3. */ + addu r6, r23,0 /* Set arg4. */ + addu r7, r24,0 /* Set arg5. */ + addu r8, r25,0 /* Set arg6. */ + jsr.n r16 /* Call `vuserf'. */ + addu r9, r18,0 /* Set arg7. */ + + addu r3, r2,0 /* Ret. value is arg1 to `cleanup'. */ + jsr.n r14 /* Call `cleanup'. */ + addu r2, r15,0 /* `pt' is arg0 to `cleanup'. */ + + bsr _qt_error /* `cleanup' erroniously returned. */ diff --git a/ext/systemc/src/sysc/qt/md/m88k_b.s b/ext/systemc/src/sysc/qt/md/m88k_b.s new file mode 100644 index 000000000..1926e6ae8 --- /dev/null +++ b/ext/systemc/src/sysc/qt/md/m88k_b.s @@ -0,0 +1,117 @@ +/* + * QuickThreads -- Threads-building toolkit. + * Copyright (c) 1993 by David Keppel + * + * Permission to use, copy, modify and distribute this software and + * its documentation for any purpose and without fee is hereby + * granted, provided that the above copyright notice and this notice + * appear in all copies. This software is provided as a + * proof-of-concept and for demonstration purposes; there is no + * representation about the suitability of this software for any + * purpose. + */ + + .text + .globl _b_call_reg + .globl _b_call_imm + .globl _b_add + .globl _b_load + +_b_null: + jmp r1 + +_b_call_reg: + subu r31, r31,8 /* Alloc ret pc save space. */ + st r1, r31,32 /* Save ret pc. */ + or.u r3, r0,hi16(_b_null) /* Put call addr in a reg. */ + or r3, r3,lo16(_b_null) + jsr r3 +L0: + jsr r3 + jsr r3 + jsr r3 + jsr.n r3 + subu r2, r2,5 /* Decrement #of iter to go. */ + bcnd.n gt0,r2,L0 + jsr r3 + + ld r1, r31,32 + jmp r1 + + +_b_call_imm: + subu r31, r31,8 /* Alloc ret pc save space. */ + st r1, r31,32 /* Save ret pc. */ + bsr _b_null +L1: + bsr _b_null + bsr _b_null + bsr _b_null + bsr.n _b_null + subu r2, r2,5 /* Decrement #of iter to go. */ + bcnd.n gt0,r2,L1 + bsr _b_null + + ld r1, r31,32 + jmp r1 + +_b_add: + add r0, r3,r4 +L2: + add r3, r4,r5 + add r4, r5,r6 + add r5, r6,r7 + add r8, r9,r0 + add r0, r3,r4 + add r3, r4,r5 + add r4, r5,r6 + add r5, r6,r7 + add r8, r9,r0 + + add r0, r3,r4 + add r3, r4,r5 + add r4, r5,r6 + add r5, r6,r7 + add r8, r9,r0 + add r0, r3,r4 + add r3, r4,r5 + add r4, r5,r6 + add r5, r6,r7 + add r8, r9,r0 + + subu r2, r2,20 /* Decrement #of iter to go. */ + bcnd.n gt0,r2,L2 + add r0, r3,r4 + + jmp r1 + + +_b_load: + ld r0, r31,0 +L3: + ld r3, r31,4 + ld r4, r31,8 + ld r5, r31,12 + ld r6, r31,16 + ld r0, r31,0 + ld r3, r31,4 + ld r4, r31,8 + ld r5, r31,12 + ld r6, r31,16 + + ld r0, r31,0 + ld r3, r31,4 + ld r4, r31,8 + ld r5, r31,12 + ld r6, r31,16 + ld r0, r31,0 + ld r3, r31,4 + ld r4, r31,8 + ld r5, r31,12 + ld r6, r31,16 + + subu r2, r2,20 /* Decrement #of iter to go. */ + bcnd.n gt0,r2,L3 + ld r0, r31,0 + + jmp r1 diff --git a/ext/systemc/src/sysc/qt/md/mips-irix5.s b/ext/systemc/src/sysc/qt/md/mips-irix5.s new file mode 100644 index 000000000..234a953ed --- /dev/null +++ b/ext/systemc/src/sysc/qt/md/mips-irix5.s @@ -0,0 +1,182 @@ +/* mips.s -- assembly support. */ + +/* + * QuickThreads -- Threads-building toolkit. + * Copyright (c) 1993 by David Keppel + * + * Permission to use, copy, modify and distribute this software and + * its documentation for any purpose and without fee is hereby + * granted, provided that the above copyright notice and this notice + * appear in all copies. This software is provided as a + * proof-of-concept and for demonstration purposes; there is no + * representation about the suitability of this software for any + * purpose. + */ + +/* Callee-save $16-$23, $30-$31. + * + * $25 is used as a procedure value pointer, used to discover constants + * in a callee. Thus, each caller here sets $25 before the call. + * + * On startup, restore regs so retpc === call to a function to start. + * We're going to call a function ($4) from within this routine. + * We're passing 3 args, therefore need to allocate 12 extra bytes on + * the stack for a save area. The start routine needs a like 16-byte + * save area. Must be doubleword aligned (_mips r3000 risc + * architecture_, gerry kane, pg d-23). + */ + +/* + * Modified by Assar Westerlund <assar@sics.se> to support Irix 5.x + * calling conventions for dynamically-linked code. + */ + + /* Make this position-independent code. */ + .option pic2 + + .globl qt_block + .globl qt_blocki + .globl qt_abort + .globl qt_start + .globl qt_vstart + + /* + ** $4: ptr to function to call once curr is suspended + ** and control is on $7's stack. + ** $5: 1'th arg to $4. + ** $6: 2'th arg to $4 + ** $7: sp of thread to suspend. + ** + ** Totally gross hack: The MIPS calling convention reserves + ** 4 words on the stack for a0..a3. This routine "ought" to + ** allocate space for callee-save registers plus 4 words for + ** the helper function, but instead we use the 4 words + ** provided by the function that called us (we don't need to + ** save our argument registers). So what *appears* to be + ** allocating only 40 bytes is actually allocating 56, by + ** using the caller's 16 bytes. + ** + ** The helper routine returns a value that is passed on as the + ** return value from the blocking routine. Since we don't + ** touch $2 between the helper's return and the end of + ** function, we get this behavior for free. + */ +qt_blocki: + sub $sp,$sp,40 /* Allocate reg save space. */ + sw $16, 0+16($sp) + sw $17, 4+16($sp) + sw $18, 8+16($sp) + sw $19,12+16($sp) + sw $20,16+16($sp) + sw $21,20+16($sp) + sw $22,24+16($sp) + sw $23,28+16($sp) + sw $30,32+16($sp) + sw $31,36+16($sp) + add $2, $sp,$0 /* $2 <= old sp to pass to func@$4. */ +qt_abort: + add $sp, $7,$0 /* $sp <= new sp. */ + .set noreorder + add $25, $4,$0 /* Set helper function procedure value. */ + jal $31,$25 /* Call helper func@$4 . */ + add $4, $2,$0 /* $a0 <= pass old sp as a parameter. */ + .set reorder + lw $31,36+16($sp) /* Restore callee-save regs... */ + lw $30,32+16($sp) + lw $23,28+16($sp) + lw $22,24+16($sp) + lw $21,20+16($sp) + lw $20,16+16($sp) + lw $19,12+16($sp) + lw $18, 8+16($sp) + lw $17, 4+16($sp) + lw $16, 0+16($sp) /* Restore callee-save */ + + add $sp,$sp,40 /* Deallocate reg save space. */ + j $31 /* Return to caller. */ + + /* + ** Non-varargs thread startup. + ** Note: originally, 56 bytes were allocated on the stack. + ** The thread restore routine (_blocki/_abort) removed 40 + ** of them, which means there is still 16 bytes for the + ** argument area required by the MIPS calling convention. + */ +qt_start: + add $4, $16,$0 /* Load up user function pu. */ + add $5, $17,$0 /* ... user function pt. */ + add $6, $18,$0 /* ... user function userf. */ + add $25, $19,$0 /* Set `only' procedure value. */ + jal $31,$25 /* Call `only'. */ + la $25,qt_error /* Set `qt_error' procedure value. */ + j $25 + + + /* + ** Save calle-save floating-point regs $f20-$f30 + ** See comment in `qt_block' about calling conventinos and + ** reserved space. Use the same trick here, but here we + ** actually have to allocate all the bytes since we have to + ** leave 4 words leftover for `qt_blocki'. + ** + ** Return value from `qt_block' is the same as the return from + ** `qt_blocki'. We get that for free since we don't touch $2 + ** between the return from `qt_blocki' and the return from + ** `qt_block'. + */ +qt_block: + sub $sp, $sp,56 /* 6 8-byte regs, saved ret pc, aligned. */ + swc1 $f20, 0+16($sp) + swc1 $f22, 8+16($sp) + swc1 $f24, 16+16($sp) + swc1 $f26, 24+16($sp) + swc1 $f28, 32+16($sp) + swc1 $f30, 40+16($sp) + sw $31, 48+16($sp) + jal qt_blocki + lwc1 $f20, 0+16($sp) + lwc1 $f22, 8+16($sp) + lwc1 $f24, 16+16($sp) + lwc1 $f26, 24+16($sp) + lwc1 $f28, 32+16($sp) + lwc1 $f30, 40+16($sp) + lw $31, 48+16($sp) + add $sp, $sp,56 + j $31 + + + /* + ** First, call `startup' with the `pt' argument. + ** + ** Next, call the user's function with all arguments. + ** Note that we don't know whether args were passed in + ** integer regs, fp regs, or on the stack (See Gerry Kane + ** "MIPS R2000 RISC Architecture" pg D-22), so we reload + ** all the registers, possibly with garbage arguments. + ** + ** Finally, call `cleanup' with the `pt' argument and with + ** the return value from the user's function. It is an error + ** for `cleanup' to return. + */ +qt_vstart: + add $4, $17,$0 /* `pt' is arg0 to `startup'. */ + add $25, $18,$0 /* Set `startup' procedure value. */ + jal $31, $25 /* Call `startup'. */ + + add $sp, $sp,16 /* Free extra save space. */ + lw $4, 0($sp) /* Load up args. */ + lw $5, 4($sp) + lw $6, 8($sp) + lw $7, 12($sp) + lwc1 $f12, 0($sp) /* Load up fp args. */ + lwc1 $f14, 8($sp) + add $25, $19,$0 /* Set `userf' procedure value. */ + jal $31,$25 /* Call `userf'. */ + + add $4, $17,$0 /* `pt' is arg0 to `cleanup'. */ + add $5, $2,$0 /* Ret. val is arg1 to `cleanup'. */ + add $25, $16,$0 /* Set `cleanup' procedure value. */ + jal $31, $25 /* Call `cleanup'. */ + + la $25,qt_error /* Set `qt_error' procedure value. */ + j $25 diff --git a/ext/systemc/src/sysc/qt/md/mips.h b/ext/systemc/src/sysc/qt/md/mips.h new file mode 100644 index 000000000..14d109461 --- /dev/null +++ b/ext/systemc/src/sysc/qt/md/mips.h @@ -0,0 +1,134 @@ +/* + * QuickThreads -- Threads-building toolkit. + * Copyright (c) 1993 by David Keppel + * + * Permission to use, copy, modify and distribute this software and + * its documentation for any purpose and without fee is hereby + * granted, provided that the above copyright notice and this notice + * appear in all copies. This software is provided as a + * proof-of-concept and for demonstration purposes; there is no + * representation about the suitability of this software for any + * purpose. + */ + +#ifndef QUICKTHREADS_MIPS_H +#define QUICKTHREADS_MIPS_H + +typedef unsigned long qt_word_t; + +#define QUICKTHREADS_GROW_DOWN + +/* Stack layout on the mips: + + Callee-save registers are: $16-$23, $30; $f20-$f30. + Also save $31, return pc. + + Non-varargs: + + +--- + | $f30 The first clump is only saved if `qt_block' + | $f28 is called, in which case it saves the fp regs + | $f26 then calls `qt_blocki' to save the int regs. + | $f24 + | $f22 + | $f20 + | $31 === return pc in `qt_block' + +--- + | $31 === return pc; on startup == qt_start + | $30 + | $23 + | $22 + | $21 + | $20 + | $19 on startup === only + | $18 on startup === $a2 === userf + | $17 on startup === $a1 === pt + | $16 on startup === $a0 === pu + | <a3> save area req'd by MIPS calling convention + | <a2> save area req'd by MIPS calling convention + | <a1> save area req'd by MIPS calling convention + | <a0> save area req'd by MIPS calling convention <--- sp + +--- + + Conventions for varargs: + + | args ... + +--- + | : + | : + | $21 + | $20 + | $19 on startup === `userf' + | $18 on startup === `startup' + | $17 on startup === `pt' + | $16 on startup === `cleanup' + | <a3> + | <a2> + | <a1> + | <a0> <--- sp + +--- + + Note: if we wanted to, we could muck about and try to get the 4 + argument registers loaded in to, e.g., $22, $23, $30, and $31, + and the return pc in, say, $20. Then, the first 4 args would + not need to be loaded from memory, they could just use + register-to-register copies. */ + + +/* Stack must be doubleword aligned. */ +#define QUICKTHREADS_STKALIGN (8) /* Doubleword aligned. */ + +/* How much space is allocated to hold all the crud for + initialization: $16-$23, $30, $31. Just do an integer restore, + no need to restore floating-point. Four words are needed for the + argument save area for the helper function that will be called for + the old thread, just before the new thread starts to run. */ + +#define QUICKTHREADS_STKBASE (14 * 4) +#define QUICKTHREADS_VSTKBASE QUICKTHREADS_STKBASE + + +/* Offsets of various registers. */ +#define QUICKTHREADS_31 (9+4) +#define QUICKTHREADS_19 (3+4) +#define QUICKTHREADS_18 (2+4) +#define QUICKTHREADS_17 (1+4) +#define QUICKTHREADS_16 (0+4) + + +/* When a never-before-run thread is restored, the return pc points + to a fragment of code that starts the thread running. For + non-vargs functions, it just calls the client's `only' function. + For varargs functions, it calls the startup, user, and cleanup + functions. + + The varargs startup routine always reads 4 words of arguments from + the stack. If there are less than 4 words of arguments, then the + startup routine can read off the top of the stack. To prevent + errors we always allocate 4 words. If there are more than 3 words + of arguments, the 4 preallocated words are simply wasted. */ + +extern void qt_start(void); +#define QUICKTHREADS_ARGS_MD(sp) (QUICKTHREADS_SPUT (sp, QUICKTHREADS_31, qt_start)) + +#define QUICKTHREADS_VARGS_MD0(sp, vabytes) \ + ((qt_t *)(((char *)(sp)) - 4*4 - QUICKTHREADS_STKROUNDUP(vabytes))) + +extern void qt_vstart(void); +#define QUICKTHREADS_VARGS_MD1(sp) (QUICKTHREADS_SPUT (sp, QUICKTHREADS_31, qt_vstart)) + +#define QUICKTHREADS_VARGS_DEFAULT + + +/* The *index* (positive offset) of where to put each value. */ +#define QUICKTHREADS_ONLY_INDEX (QUICKTHREADS_19) +#define QUICKTHREADS_USER_INDEX (QUICKTHREADS_18) +#define QUICKTHREADS_ARGT_INDEX (QUICKTHREADS_17) +#define QUICKTHREADS_ARGU_INDEX (QUICKTHREADS_16) + +#define QUICKTHREADS_VCLEANUP_INDEX (QUICKTHREADS_16) +#define QUICKTHREADS_VUSERF_INDEX (QUICKTHREADS_19) +#define QUICKTHREADS_VSTARTUP_INDEX (QUICKTHREADS_18) +#define QUICKTHREADS_VARGT_INDEX (QUICKTHREADS_17) + +#endif /* ndef QUICKTHREADS_MIPS_H */ diff --git a/ext/systemc/src/sysc/qt/md/mips.s b/ext/systemc/src/sysc/qt/md/mips.s new file mode 100644 index 000000000..b074b98dc --- /dev/null +++ b/ext/systemc/src/sysc/qt/md/mips.s @@ -0,0 +1,164 @@ +/* mips.s -- assembly support. */ + +/* + * QuickThreads -- Threads-building toolkit. + * Copyright (c) 1993 by David Keppel + * + * Permission to use, copy, modify and distribute this software and + * its documentation for any purpose and without fee is hereby + * granted, provided that the above copyright notice and this notice + * appear in all copies. This software is provided as a + * proof-of-concept and for demonstration purposes; there is no + * representation about the suitability of this software for any + * purpose. + */ + +/* Callee-save $16-$23, $30-$31. + * + * On startup, restore regs so retpc === call to a function to start. + * We're going to call a function ($4) from within this routine. + * We're passing 3 args, therefore need to allocate 12 extra bytes on + * the stack for a save area. The start routine needs a like 16-byte + * save area. Must be doubleword aligned (_mips r3000 risc + * architecture_, gerry kane, pg d-23). + */ + + .globl qt_block + .globl qt_blocki + .globl qt_abort + .globl qt_start + .globl qt_vstart + + /* + ** $4: ptr to function to call once curr is suspended + ** and control is on $7's stack. + ** $5: 1'th arg to $4. + ** $6: 2'th arg to $4 + ** $7: sp of thread to suspend. + ** + ** Totally gross hack: The MIPS calling convention reserves + ** 4 words on the stack for a0..a3. This routine "ought" to + ** allocate space for callee-save registers plus 4 words for + ** the helper function, but instead we use the 4 words + ** provided by the function that called us (we don't need to + ** save our argument registers). So what *appears* to be + ** allocating only 40 bytes is actually allocating 56, by + ** using the caller's 16 bytes. + ** + ** The helper routine returns a value that is passed on as the + ** return value from the blocking routine. Since we don't + ** touch $2 between the helper's return and the end of + ** function, we get this behavior for free. + */ +qt_blocki: + sub $sp,$sp,40 /* Allocate reg save space. */ + sw $16, 0+16($sp) + sw $17, 4+16($sp) + sw $18, 8+16($sp) + sw $19,12+16($sp) + sw $20,16+16($sp) + sw $21,20+16($sp) + sw $22,24+16($sp) + sw $23,28+16($sp) + sw $30,32+16($sp) + sw $31,36+16($sp) + add $2, $sp,$0 /* $2 <= old sp to pass to func@$4. */ +qt_abort: + add $sp, $7,$0 /* $sp <= new sp. */ + .set noreorder + jal $31,$4 /* Call helper func@$4 . */ + add $4, $2,$0 /* $a0 <= pass old sp as a parameter. */ + .set reorder + lw $31,36+16($sp) /* Restore callee-save regs... */ + lw $30,32+16($sp) + lw $23,28+16($sp) + lw $22,24+16($sp) + lw $21,20+16($sp) + lw $20,16+16($sp) + lw $19,12+16($sp) + lw $18, 8+16($sp) + lw $17, 4+16($sp) + lw $16, 0+16($sp) /* Restore callee-save */ + + add $sp,$sp,40 /* Deallocate reg save space. */ + j $31 /* Return to caller. */ + + /* + ** Non-varargs thread startup. + ** Note: originally, 56 bytes were allocated on the stack. + ** The thread restore routine (_blocki/_abort) removed 40 + ** of them, which means there is still 16 bytes for the + ** argument area required by the MIPS calling convention. + */ +qt_start: + add $4, $16,$0 /* Load up user function pu. */ + add $5, $17,$0 /* ... user function pt. */ + add $6, $18,$0 /* ... user function userf. */ + jal $31,$19 /* Call `only'. */ + j qt_error + + + /* + ** Save calle-save floating-point regs $f20-$f30 + ** See comment in `qt_block' about calling conventinos and + ** reserved space. Use the same trick here, but here we + ** actually have to allocate all the bytes since we have to + ** leave 4 words leftover for `qt_blocki'. + ** + ** Return value from `qt_block' is the same as the return from + ** `qt_blocki'. We get that for free since we don't touch $2 + ** between the return from `qt_blocki' and the return from + ** `qt_block'. + */ +qt_block: + sub $sp, $sp,56 /* 6 8-byte regs, saved ret pc, aligned. */ + swc1 $f20, 0+16($sp) + swc1 $f22, 8+16($sp) + swc1 $f24, 16+16($sp) + swc1 $f26, 24+16($sp) + swc1 $f28, 32+16($sp) + swc1 $f30, 40+16($sp) + sw $31, 48+16($sp) + jal qt_blocki + lwc1 $f20, 0+16($sp) + lwc1 $f22, 8+16($sp) + lwc1 $f24, 16+16($sp) + lwc1 $f26, 24+16($sp) + lwc1 $f28, 32+16($sp) + lwc1 $f30, 40+16($sp) + lw $31, 48+16($sp) + add $sp, $sp,56 + j $31 + + + /* + ** First, call `startup' with the `pt' argument. + ** + ** Next, call the user's function with all arguments. + ** Note that we don't know whether args were passed in + ** integer regs, fp regs, or on the stack (See Gerry Kane + ** "MIPS R2000 RISC Architecture" pg D-22), so we reload + ** all the registers, possibly with garbage arguments. + ** + ** Finally, call `cleanup' with the `pt' argument and with + ** the return value from the user's function. It is an error + ** for `cleanup' to return. + */ +qt_vstart: + add $4, $17,$0 /* `pt' is arg0 to `startup'. */ + jal $31, $18 /* Call `startup'. */ + + add $sp, $sp,16 /* Free extra save space. */ + lw $4, 0($sp) /* Load up args. */ + lw $5, 4($sp) + lw $6, 8($sp) + lw $7, 12($sp) + lwc1 $f12, 0($sp) /* Load up fp args. */ + lwc1 $f14, 8($sp) + jal $31,$19 /* Call `userf'. */ + + add $4, $17,$0 /* `pt' is arg0 to `cleanup'. */ + add $5, $2,$0 /* Ret. val is arg1 to `cleanup'. */ + jal $31, $16 /* Call `cleanup'. */ + + j qt_error diff --git a/ext/systemc/src/sysc/qt/md/mips_b.s b/ext/systemc/src/sysc/qt/md/mips_b.s new file mode 100644 index 000000000..5b3740843 --- /dev/null +++ b/ext/systemc/src/sysc/qt/md/mips_b.s @@ -0,0 +1,99 @@ +/* + * QuickThreads -- Threads-building toolkit. + * Copyright (c) 1993 by David Keppel + * + * Permission to use, copy, modify and distribute this software and + * its documentation for any purpose and without fee is hereby + * granted, provided that the above copyright notice and this notice + * appear in all copies. This software is provided as a + * proof-of-concept and for demonstration purposes; there is no + * representation about the suitability of this software for any + * purpose. + */ + + .globl b_call_reg + .globl b_call_imm + .globl b_add + .globl b_load + + .ent b_null +b_null: + j $31 + .end b_null + + .ent b_call_reg +b_call_reg: + la $5,b_null + add $6, $31,0 +$L0: + jal $5 + jal $5 + jal $5 + jal $5 + jal $5 + + sub $4, $4,5 + bgtz $4,$L0 + j $6 + .end + + + .ent b_call_imm +b_call_imm: + add $6, $31,0 +$L1: + jal b_null + jal b_null + jal b_null + jal b_null + jal b_null + + sub $4, $4,5 + bgtz $4,$L1 + j $6 + .end + + + .ent b_add +b_add: + add $5, $0,$4 + add $6, $0,$4 + add $7, $0,$4 + add $8, $0,$4 +$L2: + sub $4, $4,5 + sub $5, $5,5 + sub $6, $6,5 + sub $7, $7,5 + sub $8, $8,5 + + sub $4, $4,5 + sub $5, $5,5 + sub $6, $6,5 + sub $7, $7,5 + sub $8, $8,5 + + bgtz $4,$L2 + j $31 + .end + + + .ent b_load +b_load: +$L3: + ld $0, 0($sp) + ld $0, 4($sp) + ld $0, 8($sp) + ld $0, 12($sp) + ld $0, 16($sp) + + ld $0, 20($sp) + ld $0, 24($sp) + ld $0, 28($sp) + ld $0, 32($sp) + ld $0, 36($sp) + + sub $4, $4,10 + bgtz $4,$L3 + j $31 + .end diff --git a/ext/systemc/src/sysc/qt/md/null.README b/ext/systemc/src/sysc/qt/md/null.README new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/ext/systemc/src/sysc/qt/md/null.README diff --git a/ext/systemc/src/sysc/qt/md/null.c b/ext/systemc/src/sysc/qt/md/null.c new file mode 100644 index 000000000..db1a593ed --- /dev/null +++ b/ext/systemc/src/sysc/qt/md/null.c @@ -0,0 +1,14 @@ +/* + * QuickThreads -- Threads-building toolkit. + * Copyright (c) 1993 by David Keppel + * + * Permission to use, copy, modify and distribute this software and + * its documentation for any purpose and without fee is hereby + * granted, provided that the above copyright notice and this notice + * appear in all copies. This software is provided as a + * proof-of-concept and for demonstration purposes; there is no + * representation about the suitability of this software for any + * purpose. + */ + +char const qtmd_rcsid[] = "$Header: /Users/acg/CVSROOT/systemc-2.3/src/sysc/qt/md/null.c,v 1.1.1.1 2006/12/15 20:20:06 acg Exp $"; diff --git a/ext/systemc/src/sysc/qt/md/null.s b/ext/systemc/src/sysc/qt/md/null.s new file mode 100644 index 000000000..8a2361f9e --- /dev/null +++ b/ext/systemc/src/sysc/qt/md/null.s @@ -0,0 +1,12 @@ +/* + * QuickThreads -- Threads-building toolkit. + * Copyright (c) 1993 by David Keppel + * + * Permission to use, copy, modify and distribute this software and + * its documentation for any purpose and without fee is hereby + * granted, provided that the above copyright notice and this notice + * appear in all copies. This software is provided as a + * proof-of-concept and for demonstration purposes; there is no + * representation about the suitability of this software for any + * purpose. + */ diff --git a/ext/systemc/src/sysc/qt/md/powerpc.README b/ext/systemc/src/sysc/qt/md/powerpc.README new file mode 100644 index 000000000..b98da8b27 --- /dev/null +++ b/ext/systemc/src/sysc/qt/md/powerpc.README @@ -0,0 +1,27 @@ + +PowerPC assembly support + + +1) MacOS X, Darwin, MKLinux and other systems based on Mach kernel ABI: + + - Configuration command: ./config powerpc-darwin + + - See documentation inside powerpc_mach.h, powerpc_mach.s, powerpc.c. + + +2) LinuxPPC, and other systems based on System V ABI: + + - Configuration command: ./config powerpc + + - See documentation inside powerpc_sys5.h, powerpc_sys5.s, powerpc.c. + + +Marco Bucci <marco.bucci@inwind.it> +December 2002 + + + * This software is largely based on the original PowerPC-Linux porting + * developed by Ken Aaker <kenaaker@silverbacksystems.com> + * + * Marco Bucci <marco.bucci@inwind.it> + * December 2002 diff --git a/ext/systemc/src/sysc/qt/md/powerpc.c b/ext/systemc/src/sysc/qt/md/powerpc.c new file mode 100644 index 000000000..fb374f3f2 --- /dev/null +++ b/ext/systemc/src/sysc/qt/md/powerpc.c @@ -0,0 +1,69 @@ +/* + * QuickThreads -- Threads-building toolkit. + * Copyright (c) 1993 by David Keppel + * + * Permission to use, copy, modify and distribute this software and + * its documentation for any purpose and without fee is hereby + * granted, provided that the above copyright notice and this notice + * appear in all copies. This software is provided as a + * proof-of-concept and for demonstration purposes; there is no + * representation about the suitability of this software for any + * purpose. + */ + + +#include <stdarg.h> +#include "qt.h" + +// This static is used to find the end of the stack for variable + +static void *qt_sp_bottom_save; + +/* We actually don't know how the compiler accomodates arguments in the + * va_list. In some implementation (e.g. Linux PPC) we cannot scan the + * list as an array. To avoid this problem, this version of "qt_varg", + * retrieves arguments by means of the standard "va_arg" macro defined + * in stdargs.h. + * + * Notice that we still suppose that the number of arguments is given + * by nbytes/sizeof(qt_word_t) and we load the stack of "qt_vstart" + * assuming that all parameters are alligned to the size of qt_word_t. + * + * Marco Bucci <marco.bucci@inwind.it> + * December 2002 + */ + +/* + +qt_t *qt_vargs (qt_t *sp, int nbytes, void *vargs, + void *pt, qt_startup_t *startup, + qt_vuserf_t *vuserf, qt_cleanup_t *cleanup) + +*/ + + qt_t * +qt_vargs_stdarg (qt_t *sp, int nbytes, va_list vargs, + void *pt, qt_startup_t *startup, + qt_vuserf_t *vuserf, qt_cleanup_t *cleanup) + + + +{ + int i; + qt_word_t arg; + + sp = QUICKTHREADS_VARGS_MD0 (sp, nbytes); + + for ( i=0;i<(int)(nbytes/sizeof(qt_word_t)); i++) + { + arg = va_arg(vargs, qt_word_t); + QUICKTHREADS_SPUT (QUICKTHREADS_VARGS_ADJUST(sp), i, arg); + } + + QUICKTHREADS_VARGS_MD1 (QUICKTHREADS_VADJ(sp)); + QUICKTHREADS_SPUT (QUICKTHREADS_VADJ(sp), QUICKTHREADS_VARGT_INDEX, pt); + QUICKTHREADS_SPUT (QUICKTHREADS_VADJ(sp), QUICKTHREADS_VSTARTUP_INDEX, startup); + QUICKTHREADS_SPUT (QUICKTHREADS_VADJ(sp), QUICKTHREADS_VUSERF_INDEX, vuserf); + QUICKTHREADS_SPUT (QUICKTHREADS_VADJ(sp), QUICKTHREADS_VCLEANUP_INDEX, cleanup); + return ((qt_t *)QUICKTHREADS_VADJ(sp)); +} diff --git a/ext/systemc/src/sysc/qt/md/powerpc_mach.h b/ext/systemc/src/sysc/qt/md/powerpc_mach.h new file mode 100644 index 000000000..677808c5c --- /dev/null +++ b/ext/systemc/src/sysc/qt/md/powerpc_mach.h @@ -0,0 +1,611 @@ +/* + + * QuickThreads -- Threads-building toolkit. + + * Copyright (c) 1993 by David Keppel + + * + + * Permission to use, copy, modify and distribute this software and + + * its documentation for any purpose and without fee is hereby + + * granted, provided that the above copyright notice and this notice + + * appear in all copies. This software is provided as a + + * proof-of-concept and for demonstration purposes; there is no + + * representation about the suitability of this software for any + + * purpose. + + * + + + * PowerPC-Mach thread switching module. + + * + + * This software is largely based on the original PowerPC-Linux porting + + * developed by Ken Aaker <kenaaker@silverbacksystems.com> + + * + + * Marco Bucci <marco.bucci@inwind.it> + + * December 2002 + + * + + */ + + +#ifndef QUICKTHREADS_POWERPC_H +#define QUICKTHREADS_POWERPC_H + + +/***************************************************************************** + * + * DESCRIPTION + * + * This is the QuickThreads switching module implementation for PowerPC + * running under Mach kernel. It was developed and tested under MacOS X, that + * is under Darwin (the UNIX-BSD fundation of MacOS X). + * + * Notice that the Mach PowerPC ABI (Application Binary Interface) [1] is + * not the same than System V ABI [2] used by most of the LINUX PowerPC + * implementations. + * + * IMPLEMENTATION NOTES + * + * 1) Porting on System V ABI + * Excluding the variant argument calling convention, Mach and System V ABI + * are enough similar and it could be possible to use some simple macro, to + * adapt the code for both the ABIs. Actually, the only relevant difference + * is in the linkage area structure and in the position where the Link and + * the Condition registers are saved. As to the calling conventions, there + * are differences with floating points argument passing and with variant + * argument lists. Notice that, on Mach, the caller's stack frame allocates + * space to hold all arguments ([1] p.51), while on System V, the caller's + * stack frame allocates space to hold just the arguments that don't fit into + * registers ([2] p.3.18). + * + * 2) Variant argument list implementation + * Variant argument calling on a RISC machine is not easy to implement since + * parameters are passed via registers instead of via stack. In a general + * variant argument implementation, the caller's stack must map the whole + * parameter list following the rules related to the use of the GPR and FPR + * parameter registers and the stack alignment ([1] p.54). + * This implementation is quite simple and not general. It works under the + * hypothesis that arguments are 4-bytes aligned integers. + * + * 3) This heather file organisation + * I preferred to not make confusion between macros that are needed (i.e. + * directly used) by QuickThreads and internal "implementation" macros. You + * will find QuickThreds macros in the end of this header. Sometime they just + * refer to an analogous "internal" macro. On the top, there are the macros + * that I used to make more clean (I hope) the implementation. I could include + * some system heather (as to stack layout definitions, prologs and epilogs, + * etc.), but I preferred to have a self-contained heather in order to make + * all more clear for mantaining and for possible porting on another ABI. + * + * + * REFERENCES + * + * [1] - Mach-O Runtime Architecture + * Runtime Concepts and Conventions for Mac OS X Programs + * Preliminary July 2002 + * + * [2] - SYSTEM V APPLICATION BINARY INTERFACE + * PowerPC Processor Supplement + * September 1995 + * + * On MacOS X, more documentation is available by installing the "Developer + * Tools". Useful macros and documentation can be found in the system headers + * files such as asm.h, asm_help.h etc. (see /usr/architecture/ppc/ or + * /System/Library/Frameworks/Kernel.framework/Headers/architecture/ppc/). + + *****************************************************************************/ + +/***************************************************************************** + * + * PowerPC Mach-O Stack frame (see [1]) + * + + ................ + + + + | | reserved + + CALLER'S LINKAGE AREA + + | | Caller's LR + + + + | | Caller's CR + + + + backchain -> | | Caller's backchain + +==========================+ + | | FPR31 + + FPR SAVE AREA + + .............. + + + + | | FPRn + +--------------------------+ + | | GPR31 + + GPR SAVE AREA + + .............. + + + + | | GPRn + +--------------------------+ + | | + + ALIGNMEBNT PAD + + .............. + + (if needed) + + | | + +--------------------------+ + | | + + LOCAL VARIABLES AREA + + .............. + + + + | | + +--------------------------+ + | | PAR(n) + + + + | | + + PARAMETER AREA + + .............. + + for FUTURE call + + | | PAR(1) + + + + SP + 24 -> | | PAR(0) + +--------------------------+ + SP + 20 -> | | Caller's TOC + + + + SP + 16 -> | | reserved + + + + SP + 12 -> | | reserved + + LINKAGE AREA + + SP + 8 -> | | LR callee-save for FUTURE call + + + + SP + 4 -> | | CR callee-save for FUTURE call + + + + SP -> | | backchain + +==========================+ + STACK TOP (lower address) + + Stack grows down + | + V + * NOTE: + * + * 1) Parameter are allocated in the CALLER's parameter area. This area must + * be large enough to hold all parameters regardless if they are or not passed + * in registers. + * + * The caller parameter area is used: + * - by the caller, to store parameters to the callee that cannot fit in + * registers (no more parameter registers are available); + * - by the callee, to save parameter registers (for istance because they are + * needed for a further call). + * + * Obviously, the callee saves parameter registers, in the location in which + * they are mapped on the caller's stack frame. So, be aware that, if + * something else is stored in that location, it could be deleted after a call. + * + * 2) The callee saves LR and CR in the caller's linkage area. All other + * callee's state are saved in its own stack frame. + * + + *****************************************************************************/ + + +/***************************************************************************** + * + * Stack initialization for a single argument thread + * + + + top + QUICKTHREADS_STKBASE -> STACK BOTTOM (higher address) + +==========================+ + | | + + + + .............. + + + + | | + +--------------------------+ + top + QUICKTHREADS_ONLY_INDEX * 4 -> | only param | PAR(3) + + + + top + QUICKTHREADS_USER_INDEX * 4 -> | userf param | PAR(2) + + + + top + QUICKTHREADS_ARGT_INDEX * 4 -> | t param | PAR(1) + + + + top + QUICKTHREADS_ARGU_INDEX * 4 -> | u param | PAR(0) + +--------------------------+ + | | + + + + .............. + + + + top + QUICKTHREADS_RETURN_INDEX * 4 -> | qt_start | LR save + + + + .............. + + + + top + QUICKTHREADS_BLOCKI_FRAME_SIZE -> | top + QUICKTHREADS_STKBASE | backchain + +==========================+ + | | + + + + .............. + + + + | | + +--------------------------+ + | | + + + + .............. + + + + top -> |top + QUICKTHREADS_BLOCKI_FRAME_SIZE| backchain + +==========================+ + STACK TOP (lower address) + + Stack grows down + | + V + + ***************************************************************************** + * + * Stack initialization for a variant argument thread + * + + bottom -> STACK BOTTOM (higher address) + +==========================+ + | | + + + + .............. + + + + top + QUICKTHREADS_VSTKBASE -> | arg(0) | PAR(4) + +--------------------------+ + top + QUICKTHREADS_CLEANUP_INDEX * 4 -> | cleanup param | PAR(3) + + + + top + QUICKTHREADS_USER_INDEX * 4 -> | userf param | PAR(2) + + + + top + QUICKTHREADS_VSTARTUP_INDEX * 4 ->| startup param | PAR(1) + + + + top + QUICKTHREADS_ARGT_INDEX * 4 -> | t param | PAR(0) + +--------------------------+ + | | + + + + .............. + + + + top + QUICKTHREADS_RETURN_INDEX * 4 -> | qt_start | LR save + + + + .............. + top + QUICKTHREADS_BLOCKI_FRAME_SIZE -> | top + QUICKTHREADS_STKBASE | backchain + +==========================+ + | | + + + + .............. + + + + | | + +--------------------------+ + | | + + + + .............. + + + + top -> |top + QUICKTHREADS_BLOCKI_FRAME_SIZE| backchain + +==========================+ + STACK TOP (lower address) + + Stack grows down + | + V + +* NOTE: +* +* Parameters are passed to "qt_start" or to "qt_vstart" putting them into +* the stack frames of "qt_start" or "qt_vstart" themselves. This not a +* conventional parameter passing because parameters should be put into the +* caller's stack, not into the callee's one. Actually we must consider +* that as a preload of the parameter area that "qt_start" or "qt_vstart" +* will use for their own calls. +* Be aware of the fact that, during a call, the caller's parameter area is, +* in a certain sense, volatile. In facts, the callee can save parameter +* registers on the caller's parameter area. +* + *****************************************************************************/ + + +/***************************************************************************** + + Define PowerPC Mach-O related macros + + *****************************************************************************/ + + + +typedef unsigned long PPC_W; + +/* Stack pointer must always be a multiple of 16 */ +#define PPC_STACK_INCR 16 +#define PPC_ROUND_STACK(length) \ + (((length)+PPC_STACK_INCR-1) & ~(PPC_STACK_INCR-1)) + + +#define PPC_LINKAGE_AREA 24 +#define PPC_CR_SAVE 4 +#define PPC_LR_SAVE 8 + +#define PPC_PARAM_AREA(n) (4*(n)) + +#define PPC_GPR_SAVE_AREA (4*19) /* GPR13-GPR31 must be saved */ +#define PPC_FPR_SAVE_AREA (8*18) /* FPR14-FPR31 must be saved */ + +/* Define parameter offset on the stack. + * NOTICE: Parameters are numbered 0, 1, ..., n. +*/ +#define PPC_PAR(i) (PPC_LINKAGE_AREA+(i)*4) + +/***************************************************************************** + + Define stack frames + + *****************************************************************************/ + + +/* Define the "qt_blocki" and "qt_abort" stack frame. We use the same stack + * frame for both. + * + + top + S -> + +==========================+ + top + S - 4 -> | | GPR31 + + GPR SAVE AREA + + .............. + + + + top + S - 19 * 4 -> | | GPR13 + +--------------------------+ + | | + + ALIGNMEBNT PAD + + .............. + + (if needed) + + | | + +--------------------------+ + | | + + + + | | + + PARAMETER AREA + + | | + + + + top + 24 -> | | + +--------------------------+ + | | + + LINKAGE AREA + + top -> | | + +==========================+ + */ + +#define QUICKTHREADS_BLOCKI_FRAME_SIZE \ + PPC_ROUND_STACK(PPC_LINKAGE_AREA+PPC_PARAM_AREA(4)+PPC_GPR_SAVE_AREA) + +/* Offset to the base of the GPR save area. Save from GPR13 to GPR31 + * increasing address. + */ +#define QUICKTHREADS_BLOCKI_GPR_SAVE(i) (QUICKTHREADS_BLOCKI_FRAME_SIZE-4+(i-31)*4) + + + +/* Define the "qt_block" stack frame. Notice that since "qt_black" calls + * "qt_blocki", GPR registers are saved into "qt_blocki" stack frame. + * + + top + S -> + +==========================+ + top + S - 8 -> | | FPR31 + + FPR SAVE AREA + + .............. + + + + top + S - 18 * 8 -> | | FPR14 + +--------------------------+ + | | + + ALIGNMEBNT PAD + + .............. + + (if needed) + + | | + +--------------------------+ + | | + + + + | | + + PARAMETER AREA + + | | + + + + top + 24 -> | | + +--------------------------+ + | | + + LINKAGE AREA + + top -> | | + +==========================+ + */ + +#define QUICKTHREADS_BLOCK_FRAME_SIZE \ + PPC_ROUND_STACK(PPC_LINKAGE_AREA+PPC_PARAM_AREA(4)+PPC_FPR_SAVE_AREA) + +/* Offset to the location where registers are saved. + */ +#define QUICKTHREADS_BLOCK_FPR_SAVE(i) (QUICKTHREADS_BLOCK_FRAME_SIZE-8+(i-31)*8) + + +/* Define the "qt_start" frame size. It consists just of the linkage area and + * the parameter area. + * + + +==========================+ + | | + + ALIGNMEBNT PAD + + .............. + + (if needed) + + | | + +--------------------------+ + | | only par + + + + | | userf par + + PARAMETER AREA + + | | t par + + + + top + 24 -> | | u par + +--------------------------+ + | | + + LINKAGE AREA + + top -> | | + +==========================+ + + */ +#define QUICKTHREADS_START_FRAME_SIZE PPC_ROUND_STACK(PPC_LINKAGE_AREA+PPC_PARAM_AREA(4)) + + + +/* Define the "qt_vstart" frame. It consists of the linkage area, the fix parameter + * area, the variant argument list and a local variable area used in "qt_vstart" + * implementation. + * + + backchain -> + +==========================+ + backchain - 4 -> | | + + LOCAL VARIABLES AREA + + .............. + + + + | | + +--------------------------+ + | | + + ALIGNMEBNT PAD + + .............. + + (if needed) + + | | + +--------------------------+ + | | arg(n) + + + + | | + + VARIABLE ARGUMENT LIST + + .............. + + for userf call + + | | arg(1) + + + + top + 24 + 16 -> | | arg(0) + +--------------------------+ + | | cleanup par + + + + | | userf par + + PARAMETER AREA + + | | startup par + + + + top + 24 -> | | t par + +--------------------------+ + | | + + LINKAGE AREA + + top -> | | + +==========================+ + + */ +#define QUICKTHREADS_VARGS_LOCAL_AREA (4*4) /* local variable area */ + +/* The offset the stack will be moved back before to call "userf(...)". + * The linckage area must be moved to be adiacent to the part of the variant + * argument list that is in the stack. + */ +#define QUICKTHREADS_VARGS_BKOFF PPC_PARAM_AREA(4) + +#define QUICKTHREADS_VSTART_FRAME_SIZE(varbytes) \ + PPC_ROUND_STACK(PPC_LINKAGE_AREA+PPC_PARAM_AREA(4)+(varbytes)+ \ + QUICKTHREADS_VARGS_LOCAL_AREA) + +/* Offset to the base of the varian argument list */ +#define QUICKTHREADS_VSTART_LIST_BASE (PPC_LINKAGE_AREA+PPC_PARAM_AREA(4)) + + +/* Notice that qt_start and qt_vstart have no parameters, actually their + * parameters are written in their stack frame during thread initialization + */ +extern void qt_start(void); +extern void qt_vstart(void); + + + +/* Offset (in words) of the location where the block routine saves its return + * address (i.e. LR). SP points the top of the block routine stack and, + * following ppc calling conventions, the return address is saved in the + * previous (caller's) stack frame. + */ +#define QUICKTHREADS_RETURN_INDEX ((QUICKTHREADS_BLOCKI_FRAME_SIZE+PPC_LR_SAVE)/sizeof(PPC_W)) + +/* static variable used to get the stack bottom in "VARGS" initialization */ +/* static void *qt_sp_bottom_save; */ + +#define QUICKTHREADS_ARG_INDEX(i) ((QUICKTHREADS_BLOCKI_FRAME_SIZE+PPC_PAR(i))/sizeof(PPC_W)) + +/***************************************************************************** + + QuickThreads needed definitions + + *****************************************************************************/ + + +#define QUICKTHREADS_GROW_DOWN +#define QUICKTHREADS_STKALIGN PPC_STACK_INCR +typedef PPC_W qt_word_t; + + +/* This macro is used by "QUICKTHREADS_ARGS" to initialize a single argument thread. + * - set "qt_start" as the "qt_block" or "qt_blocki" return address; + * - set the top of the stack backchain; + * - set the next backchain (not needed, but just to be "clean"). + */ +#define QUICKTHREADS_ARGS_MD(sp) \ + (QUICKTHREADS_SPUT (sp, QUICKTHREADS_RETURN_INDEX, qt_start), \ + QUICKTHREADS_SPUT (sp, 0, sp+QUICKTHREADS_BLOCKI_FRAME_SIZE), \ + QUICKTHREADS_SPUT (sp, QUICKTHREADS_BLOCKI_FRAME_SIZE/sizeof(PPC_W), \ + sp+QUICKTHREADS_BLOCKI_FRAME_SIZE+QUICKTHREADS_START_FRAME_SIZE)) + + +/* This macro is used by "QUICKTHREADS_VARGS" to initialize a variant argument thread. + * It returns the pointer to the top of the argument list. + * We also use it to get the stack bottom via a static variable. This is a bit + * "dirty", it could be better to do it in "qt_vargs", but we don't want change + * anything out of this file. + * We need the stack bottom to allocate a local variable area used by + * "qt_vstart". + */ +#define QUICKTHREADS_VARGS_MD0(sp, varbytes) \ + ((qt_sp_bottom_save = sp), \ + ((qt_t *)(((char *)(sp)) - \ + (QUICKTHREADS_VSTART_FRAME_SIZE(varbytes)-QUICKTHREADS_VSTART_LIST_BASE)))) + + +/* This macro is used by "QUICKTHREADS_VARGS" to initialize a variant argument thread. + * - set "qt_start" as the "qt_block" or "qt_blocki" return address; + * - set the top of the stackback chain; + * - set the next backchain (it points the stack botton). + */ +#define QUICKTHREADS_VARGS_MD1(sp) \ + (QUICKTHREADS_SPUT (sp, QUICKTHREADS_RETURN_INDEX, qt_vstart), \ + QUICKTHREADS_SPUT (sp, 0, sp+QUICKTHREADS_BLOCKI_FRAME_SIZE), \ + QUICKTHREADS_SPUT (sp, (QUICKTHREADS_BLOCKI_FRAME_SIZE)/sizeof(PPC_W), \ + qt_sp_bottom_save)) + + +/* Activate "qt_vargs" as the initialization routine for the variant + * argument threads + */ +#define QUICKTHREADS_VARGS_DEFAULT + +/* Override "qt_vargs" with "qt_vargs_stdarg". + * On LinuxPPC "qt_vargs" doesn't work, "qt_vargs_stdarg" uses a more + * standard way to retrieve arguments from the variant list. + */ +#define QUICKTHREADS_VARGS(sp, nbytes, vargs, pt, startup, vuserf, cleanup) \ + ((qt_t *)qt_vargs_stdarg (sp, nbytes, vargs, pt, startup, vuserf, cleanup)) + + +/* This macro is used by "QUICKTHREADS_ADJ(sp)" to get the stack top form the stack + * bottom during a single argument thread initialization. + * It is the space we need to allocate for a single argument thread: the stack + * frame for the block routine ("qt_block" or "qt_blocki") and for "qt_start". + */ +#define QUICKTHREADS_STKBASE \ + (QUICKTHREADS_BLOCKI_FRAME_SIZE+QUICKTHREADS_START_FRAME_SIZE) + +/* This macro is used by "QUICKTHREADS_VADJ(sp)" to get the stack top from the base + * of the variant argument list during a variant argument thread initialization. + */ +#define QUICKTHREADS_VSTKBASE (QUICKTHREADS_BLOCKI_FRAME_SIZE+QUICKTHREADS_VSTART_LIST_BASE) + +/* The *index* (positive offset) of where to put each value. */ + +#define QUICKTHREADS_ARGU_INDEX QUICKTHREADS_ARG_INDEX(0) +#define QUICKTHREADS_ARGT_INDEX QUICKTHREADS_ARG_INDEX(1) +#define QUICKTHREADS_USER_INDEX QUICKTHREADS_ARG_INDEX(2) +#define QUICKTHREADS_ONLY_INDEX QUICKTHREADS_ARG_INDEX(3) + + +#define QUICKTHREADS_VARGT_INDEX QUICKTHREADS_ARG_INDEX(0) +#define QUICKTHREADS_VSTARTUP_INDEX QUICKTHREADS_ARG_INDEX(1) +#define QUICKTHREADS_VUSERF_INDEX QUICKTHREADS_ARG_INDEX(2) +#define QUICKTHREADS_VCLEANUP_INDEX QUICKTHREADS_ARG_INDEX(3) + +#endif /* ndef QUICKTHREADS_POWERPC_H */ + diff --git a/ext/systemc/src/sysc/qt/md/powerpc_mach.s b/ext/systemc/src/sysc/qt/md/powerpc_mach.s new file mode 100644 index 000000000..63414b05d --- /dev/null +++ b/ext/systemc/src/sysc/qt/md/powerpc_mach.s @@ -0,0 +1,641 @@ +/* powerpc_mach.s -- assembly support. */ + +/* + * QuickThreads -- Threads-building toolkit. + * Copyright (c) 1993 by David Keppel + * + * Permission to use, copy, modify and distribute this software and + * its documentation for any purpose and without fee is hereby + * granted, provided that the above copyright notice and this notice + * appear in all copies. This software is provided as a + * proof-of-concept and for demonstration purposes; there is no + * representation about the suitability of this software for any + * purpose. + + + * PowerPC-Mach thread switching module. + * Darwin (MacOS X) assembly + * + * NOTICE: Syntax for register names is not the GNU one. Register are + * named "rx" and "fx", not "%rx" and "%fx" as usual for the GNU "as" tool. + * Darwin "as" tool is based on GNU "as" but follows the "official" PowerPC + * syntax. + * + * + * This software is largely based on the original PowerPC-Linux porting + * developed by Ken Aaker <kenaaker@silverbacksystems.com> + * + * Marco Bucci <marco.bucci@inwind.it> + * December 2002 + * + */ + + +/* + * + * PowerPC Register convections: + * + * r0 volatile + * r1 SP + * r2 system reserved + * r3-r4 volatile for parameter passing and function return + * r5-r10 volatile for parameter passing + * r11-r12 volatile + * r13-r14 non volatile registers + * f0 volatile + * f1 volatile for parameter passing and function return + * f2-f13 volatile for parameter passing + * f14-f31 non volatile + * + * cr2-cr4 non volatile + * + * + * See on the heather file for more documentation. + * + * + * + * IMPLEMENTATION NOTES + * + * + * 1) Condition register saving + * On most machines, the condition code register is caller-save. + * On the PPC, the condition code register is callee-save, so the + * thread context switch must preserve it. + * + * + * 2) Floating point registers saving + * On resuming a thread, floating point registers are or not restored just + * depending on which block routine suspended the thread (i.e. regardless + * whether "qt_block", "qt_blocki" or "qt_abort" is used to resume it). + * This behaviour is obtained by implementing "qt_block" by means af a nested + * call to "qt_blocki". As a result, the blocking of a thread always goes + * and returns through "qt_blocki and, if a thread was blocked by "qt_block", + * its execution resumes from the floating point restoring code on exit + * of "qt_block". + * + * Thanks to David Keppel that explained me this "simple" trick. + * + * + * 3) C languace code debugging + * This software was developed and debugged using the Metrowerks + * Code Warrior PPC integrated assembler. It can be still used with the + * Code Warrior compiler by means of the file "powerpc_mach_asm_debug.c" + * that include it. + * In order to avoid "copy and paste" bugs, and make easyer the maintaining, + * I made the minimal changes, so you can find some strange code as: + * + * #if 0 + * .if 0 + * C code here + * .endif + * #endif + * + * This is just to embed some C code that is needed by the Code Warrior + * integrated assembler. + * + * + * 4) Assembly constants generation + * Constants used in the assembly code are generated by running + * the C code in the sequel (commented). It uses the C macros declared in + * the C heather in order to guarantee that the C interface and the assebly + * code are "aligned". I avoided the use of an assebler preprocessor since + * they are not so standard and moreover using macro espressions makes the + * assembly debugging more difficult. + * + * + + +#include <iostream> +#include "powerpc_mach.h" + +int main() +{ + using namespace std; + + int i; + + cout << ".set LR_SAVE, " << PPC_LR_SAVE << endl; + cout << ".set CR_SAVE, " << PPC_CR_SAVE << endl; + cout << ".set BLOCKI_FSIZE, " << QUICKTHREADS_BLOCKI_FRAME_SIZE << endl; + cout << ".set BLOCK_FSIZE, " << QUICKTHREADS_BLOCK_FRAME_SIZE << endl; + + cout << endl; + for(i=0; i<12; i++) + cout << ".set PAR_" << i << ", " << PPC_PAR(i) << endl; + + cout << endl; + i = 13; + cout << ".set GPR_SAVE_" << i << ", " << QUICKTHREADS_BLOCKI_GPR_SAVE(i) << endl; + + cout << endl; + for(i=31; i>13; i--) + cout << ".set FPR_SAVE_" << i << ", " << QUICKTHREADS_BLOCK_FPR_SAVE(i) << endl; + + cout << endl; + cout << ".set VARGS_BKOFF, " << QUICKTHREADS_VARGS_BKOFF << endl; + + + cout << endl << endl << endl; + + for(i=31; i>13; i--) + cout << "\tstfd\tf" << i << ",FPR_SAVE_" << i << "(r1)" << endl; + + cout << endl; + for(i=31; i>13; i--) + cout << "\tlfd \tf" << i << ",FPR_SAVE_" << i << "(r1)" << endl; + + cout << endl << endl << endl; + + + return 0; +} + + + * + * + * + */ + + +#if 0 + + .text + .align 4 + + .globl qt_block + .globl _qt_block + .globl qt_blocki + .globl _qt_blocki + .globl qt_abort + .globl _qt_abort + .globl qt_start + .globl _qt_start + .globl qt_vstart + .globl _qt_vstart + + +.set LR_SAVE, 8 +.set CR_SAVE, 4 +.set BLOCKI_FSIZE, 128 +.set BLOCK_FSIZE, 192 + +.set PAR_0, 24 +.set PAR_1, 28 +.set PAR_2, 32 +.set PAR_3, 36 +.set PAR_4, 40 +.set PAR_5, 44 +.set PAR_6, 48 +.set PAR_7, 52 +.set PAR_8, 56 +.set PAR_9, 60 +.set PAR_10, 64 +.set PAR_11, 68 + +.set GPR_SAVE_13, 52 + +.set FPR_SAVE_31, 184 +.set FPR_SAVE_30, 176 +.set FPR_SAVE_29, 168 +.set FPR_SAVE_28, 160 +.set FPR_SAVE_27, 152 +.set FPR_SAVE_26, 144 +.set FPR_SAVE_25, 136 +.set FPR_SAVE_24, 128 +.set FPR_SAVE_23, 120 +.set FPR_SAVE_22, 112 +.set FPR_SAVE_21, 104 +.set FPR_SAVE_20, 96 +.set FPR_SAVE_19, 88 +.set FPR_SAVE_18, 80 +.set FPR_SAVE_17, 72 +.set FPR_SAVE_16, 64 +.set FPR_SAVE_15, 56 +.set FPR_SAVE_14, 48 + + +/* various offsets used by "qt_varg" */ +.set P_T, PAR_0 +.set P_STARTUP, PAR_1 +.set P_USERF, PAR_2 +.set P_CLEANUP, PAR_3 + /* the offset used to move back the linkage area to be adiacent to + * the variant argument list before calling "userf(...) */ +.set VARGS_BKOFF, 16 /* skip "t", "startup", "userf" and "cleanup" */ + + /* location where "t" and "cleanup" are saved (with respect of + * the stack frame base) */ +.set P_T_SAVE, -4 +.set P_CLEANUP_SAVE, -8 + +#endif + + + +/* Block the current thread saving all integer non volatile registers and + * start a new thread. + */ +#if 0 +.if 0 +#endif +void *qt_blocki (void *helper, void *a0, void *a1, void *newthread); +asm void *qt_blocki (void *helper, void *a0, void *a1, void *newthread) +{ +#if 0 +.endif +#endif + +#if 0 +qt_blocki: +_qt_blocki: +#endif +/* prolog code */ + stwu r1,-BLOCKI_FSIZE(r1) /* allocate the stack frame */ + mflr r0 /* return addr in r0 */ + mfcr r11 /* CR in r11 */ + stw r0,LR_SAVE+BLOCKI_FSIZE(r1) /* save return addr in the stack */ + stw r11,CR_SAVE+BLOCKI_FSIZE(r1) /* save CR in the stack */ + stmw r13,GPR_SAVE_13(r1) /* save non-volatile reg */ + +/* call helper(qt_t *old, void *a0, void *a1) */ + mtlr r3 /* "helper" addr in the link reg */ + mr r3,r1 /* current thread (i.e. the SP) in arg "old" */ + mr r1,r6 /* swap to the new thread (i.e. to its SP) */ + blrl /* jump to "helper" */ +/* the "helper" return value is returned (since r3 is not changed) */ + +/* epilog code: return to the new thread's "qt_blocki" caller */ + lmw r13,GPR_SAVE_13(r1) /* restore non-volatile reg */ + lwz r0,LR_SAVE+BLOCKI_FSIZE(r1) /* recover return addr */ + lwz r11,CR_SAVE+BLOCKI_FSIZE(r1) /* recover CR */ + mtlr r0 /* return address in the link reg */ + mtcr r11 /* restore CR */ + addi r1,r1,BLOCKI_FSIZE /* free the stack frame */ + blr /* return */ + +#if 0 +.if 0 +#endif +} +#if 0 +.endif +#endif + + + +/* Abort the current thread and start a new thread. + */ +#if 0 +.if 0 +#endif +void qt_abort (void *helper, void *a0, void *a1, void *newthread); +asm void qt_abort (void *helper, void *a0, void *a1, void *newthread) +{ +#if 0 +.endif +#endif + +#if 0 +qt_abort: +_qt_abort: +#endif +/* prolog code */ +/* there is no prolog. It will never come back */ + +/* call helper(qt_t *old, void *a0, void *a1) */ + mtlr r3 /* "helper" addr in the link reg */ + mr r1,r6 /* swap to the new thread (i.e. to its SP) */ +/* we don't need to set "old", we can pass just garbage. Actually, since r3 + is not changed, "old" is set to "helper" (don't care) */ + blrl /* call "helper" */ +/* the "helper" return value is returned (since r3 is not changed) */ + +/* epilog code: return to the new thread's "qt_blocki" caller */ + lmw r13,GPR_SAVE_13(r1) /* restore non-volatile reg */ + lwz r0,LR_SAVE+BLOCKI_FSIZE(r1) /* recover return addr */ + lwz r11,CR_SAVE+BLOCKI_FSIZE(r1) /* recover CR */ + mtlr r0 /* return address in the link reg */ + mtcr r11 /* restore CR */ + addi r1,r1,BLOCKI_FSIZE /* free the stack frame */ + blr /* return */ + +#if 0 +.if 0 +#endif +} +#if 0 +.endif +#endif + + + +/* Block the current thread saving all non volatile registers and start + * a new thread. + */ +#if 0 +.if 0 +#endif +void *qt_block (void *helper, void *a0, void *a1, void *newthread); +asm void *qt_block (void *helper, void *a0, void *a1, void *newthread) +{ +#if 0 +.endif +#endif + +# if 0 +qt_block: +_qt_block: +#endif +/* prolog code */ + stwu r1,-BLOCK_FSIZE(r1) /* allocate the stack frame */ + mflr r0 /* return addr in r0 */ + stw r0,LR_SAVE+BLOCK_FSIZE(r1) /* save return addr in the stack */ + +/* save non-volatile fp reg */ + stfd f31,FPR_SAVE_31(r1) + stfd f30,FPR_SAVE_30(r1) + stfd f29,FPR_SAVE_29(r1) + stfd f28,FPR_SAVE_28(r1) + stfd f27,FPR_SAVE_27(r1) + stfd f26,FPR_SAVE_26(r1) + stfd f25,FPR_SAVE_25(r1) + stfd f24,FPR_SAVE_24(r1) + stfd f23,FPR_SAVE_23(r1) + stfd f22,FPR_SAVE_22(r1) + stfd f21,FPR_SAVE_21(r1) + stfd f20,FPR_SAVE_20(r1) + stfd f19,FPR_SAVE_19(r1) + stfd f18,FPR_SAVE_18(r1) + stfd f17,FPR_SAVE_17(r1) + stfd f16,FPR_SAVE_16(r1) + stfd f15,FPR_SAVE_15(r1) + stfd f14,FPR_SAVE_14(r1) +/* block the thread */ + bl qt_blocki +/* the thread is going to be resumed */ +/* restore non-volatile fp reg */ + lfd f31,FPR_SAVE_31(r1) + lfd f30,FPR_SAVE_30(r1) + lfd f29,FPR_SAVE_29(r1) + lfd f28,FPR_SAVE_28(r1) + lfd f27,FPR_SAVE_27(r1) + lfd f26,FPR_SAVE_26(r1) + lfd f25,FPR_SAVE_25(r1) + lfd f24,FPR_SAVE_24(r1) + lfd f23,FPR_SAVE_23(r1) + lfd f22,FPR_SAVE_22(r1) + lfd f21,FPR_SAVE_21(r1) + lfd f20,FPR_SAVE_20(r1) + lfd f19,FPR_SAVE_19(r1) + lfd f18,FPR_SAVE_18(r1) + lfd f17,FPR_SAVE_17(r1) + lfd f16,FPR_SAVE_16(r1) + lfd f15,FPR_SAVE_15(r1) + lfd f14,FPR_SAVE_14(r1) + + lwz r0,LR_SAVE+BLOCK_FSIZE(r1) /* recover return addr */ + mtlr r0 /* return address in the link reg */ + addi r1,r1,BLOCK_FSIZE /* free the stack frame */ + blr /* return */ + +#if 0 +.if 0 +#endif +} +#if 0 +.endif +#endif + + + +/* Start a single argument thread using parameters preloaded in the stack + * during thread initialization (see comments on stack initialization in the + * heather file). + * + * Executes: + * + * only(u, t, userf); + */ +#if 0 +.if 0 +#endif +void qt_start(void); +asm void qt_start(void) +{ +#if 0 +.endif +#endif + +#if 0 +qt_start: +_qt_start: +#endif + lwz r3,PAR_0(r1) /* "u" in r3 */ + lwz r4,PAR_1(r1) /* "t" in r4 */ + lwz r5,PAR_2(r1) /* "userf" in r5 */ + lwz r6,PAR_3(r1) /* "only" in r6 */ + mtlr r6 /* "only" address in the link reg */ +/* call only(u, t, userf) */ + blrl /* jump to "only" */ +/* error if it returns */ + b _qt_error +/* dead code (some inline asm "wants" the epilog, or they genetare it) */ + blr + +#if 0 +.if 0 +#endif +} +#if 0 +.endif +#endif + + + +/* Start a variant argument thread using parameters preloaded in the stack + * during thread initialization (see comments on stack initialization in the + * heather file). + * + * Executes: + * + * startup(t); + * userf_return = userf(...); + * cleanup(pt, userf_return); + * + + + ***** Stack layout on start ***** + + + backchain -> STACK BOTTOM (higher address) + +==========================+ + backchain - 4 -> | | + + LOCAL VARIABLES AREA + + .............. + + + + | | + +--------------------------+ + | | + + ALIGNMEBNT PAD + + .............. + + (if needed) + + | | + +--------------------------+ + | | arg(n) + + + + | | + + VARIABLE ARGUMENT LIST + + .............. + + for userf call + + SP + PAR(5) -> | | arg(1) + + + + SP + PAR(4) -> | | arg(0) + +--------------------------+ + SP + PAR(3) -> | | cleanup par + + + + SP + PAR(2) -> | | userf par + + PARAMETER AREA + + SP + PAR(1) -> | | startup par + + + + SP + PAR(0) -> | | t par + +--------------------------+ + | | + + LINKAGE AREA + + SP -> | | + +==========================+ + STACK TOP (lower address) + + Stack grows down + | + V + + + + ***** Stack layout before call userf ***** + + + backchain -> STACK BOTTOM (higher address) + +==========================+ + backchain - 4 -> | | + + LOCAL VARIABLES AREA + + .............. + + + + | | + +--------------------------+ + | | + + ALIGNMEBNT PAD + + .............. + + (if needed) + + | | + +--------------------------+ + | | arg(n) + + + + | | + + VARIABLE ARGUMENT LIST + + .............. + + for userf call + + SP + PAR(1) -> | | arg(1) + + + + SP + PAR(0) -> | | arg(0) + +--------------------------+ + | | + + LINKAGE AREA + + SP -> | | + +==========================+ + STACK TOP (lower address) + + Stack grows down + | + V + + + * To call "userf(...)", the argument list must be adiacent to the linkage + * area. Instead of copy the argument list, we move back the linkage area + * (actually, we just increase the SP and copy the backchain). "t" and + * "cleanup" are saved in a local variable area in order to call + * cleanup(pt, userf_return). + +*/ + + +#if 0 +.if 0 +#endif +void qt_vstart(void); +asm void qt_vstart(void) +{ +#if 0 +.endif +#endif + +#if 0 +qt_vstart: +_qt_vstart: +#endif +/* NOTICE: the callee routines could save parameter registers in the caller's + * stack parameter area. We put "t" in PAR(0) in such a way, if startup(t) + * will save "t", it will be saved on the same location thus not delething + * any other parameter. + */ + +/* since we will move back the linckage area (to make it adiacent to the + * parameter list), we need to save "t" and "cleanup". We have made room for + * this on the bottom of the stack frame. */ + +/* save parameters in the local variable area */ + lwz r11,0(r1) /* get the backchain */ + lwz r3,P_T(r1) + lwz r4,P_CLEANUP(r1) + stw r3,P_T_SAVE(r11) /* save "pt" */ + stw r4,P_CLEANUP_SAVE(r11) /* save "cleanup" */ + +/* call startup(t) */ + lwz r5,P_STARTUP(r1) + mtlr r5 + blrl /* call "startup" */ + +/* call userf(...) */ + lwz r11,0(r1) /* reload backchain (r11 is volatile) */ + lwz r4,P_USERF(r1) /* load "userf" */ + mtlr r4 + + /* first eight parameter of the variant list must be copyed in + * GPR3-GPR10. There is a four places offset due to "t", "startup", + * userf" and "cleanup" */ + + lwz r3,PAR_4(r1) + lwz r4,PAR_5(r1) + lwz r5,PAR_6(r1) + lwz r6,PAR_7(r1) + lwz r7,PAR_8(r1) + lwz r8,PAR_9(r1) + lwz r9,PAR_10(r1) + lwz r10,PAR_11(r1) + + + /* move the linkage area to be adiacent to the argument list */ + stw r11,VARGS_BKOFF(r1) /* copy backchain */ + addi r1,r1,VARGS_BKOFF /* move back the stack */ + + blrl /* call "userf" */ + +/* call qt_cleanup(void *pt, void *vuserf_return) */ + lwz r11,0(r1) /* reload backchain (r11 is volatile) */ + + mr r4,r3 /* push "userf" return as 2nd parameter */ + lwz r3,P_T_SAVE(r11) /* reload "pt" */ + lwz r5,P_CLEANUP_SAVE(r11) /* reload "cleanup" */ + mtlr r5 + blrl + b _qt_error +/* dead code (some inline asm "wanst" the epilog, or they genetare it) */ + blr + +#if 0 +.if 0 +#endif +} +#if 0 +.endif +#endif + diff --git a/ext/systemc/src/sysc/qt/md/powerpc_mach_b.s b/ext/systemc/src/sysc/qt/md/powerpc_mach_b.s new file mode 100644 index 000000000..f0fd23fcb --- /dev/null +++ b/ext/systemc/src/sysc/qt/md/powerpc_mach_b.s @@ -0,0 +1,290 @@ +/* speed test for basic CPU operations */ + + +/* Marco Bucci <marco.bucci@inwind.it> */ + +/* This code was developed with the Code Warrior integrate ppc assembler. + * Macros are use to hide illegal constructs whether you are using a + * "normal" assembler or the "C integrated" assembler. + */ + +#if 0 + + + .text + .align 4 + + .globl b_call_reg + .globl _b_call_reg + .globl b_call_imm + .globl _b_call_imm + .globl b_add + .globl _b_add + .globl b_load + .globl _b_load + +.set fsize, 64 +.set lrsave, 8 + +#else + +#define fsize 64 +#define lrsave 8 + +#endif + + + + +#if 0 +.if 0 +#endif +asm void b_null(void) +{ +#if 0 +.endif +#endif + +#if 0 +b_null: +#endif + + blr + +#if 0 +.if 0 +#endif +} +#if 0 +.endif +#endif + + +/* actually the same as the following. How to get "b_null" address? + * I didnt find the right sintax or the right way. + * I should take the current PC, then the difference to "b_null" + * (making the difference beween the labels), perform the sum and go?! + */ +#if 0 +.if 0 +#endif +asm void b_call_reg(long n) +{ +#if 0 +.endif +#endif + +#if 0 +b_call_reg: +_b_call_reg: +#endif + + mflr r0 + stw r31,-4(r1) + stw r30,-8(r1) + stw r0,lrsave(r1) + stwu r1,-fsize(r1) + mr r30,r3 + li r31,0 + + b L1 +L0: + bl b_null + bl b_null + bl b_null + bl b_null + bl b_null + + addi r31,r31,5 +L1: + cmpw r31,r30 + blt L0 + + + lwz r0,lrsave+fsize(r1) + mtlr r0 + lwz r31,-4+fsize(r1) + lwz r30,-8+fsize(r1) + addi r1,r1,fsize + blr + +#if 0 +.if 0 +#endif +} +#if 0 +.endif +#endif + + + + +#if 0 +.if 0 +#endif +asm void b_call_imm(long n) +{ +#if 0 +.endif +#endif + +#if 0 +b_call_imm: +_b_call_imm: +#endif + + mflr r0 + stw r31,-4(r1) + stw r30,-8(r1) + stw r0,lrsave(r1) + stwu r1,-fsize(r1) + mr r30,r3 + li r31,0 + + b L3 +L2: + bl b_null + bl b_null + bl b_null + bl b_null + bl b_null + + addi r31,r31,5 +L3: + cmpw r31,r30 + blt L2 + + + lwz r0,lrsave+fsize(r1) + mtlr r0 + lwz r31,-4+fsize(r1) + lwz r30,-8+fsize(r1) + addi r1,r1,fsize + blr + +#if 0 +.if 0 +#endif +} +#if 0 +.endif +#endif + + + +#if 0 +.if 0 +#endif +asm void b_add(long n) +{ +#if 0 +.endif +#endif + +#if 0 +b_add: +_b_add: +#endif + + mflr r0 + stw r31,-4(r1) + stw r30,-8(r1) + stw r0,lrsave(r1) + stwu r1,-fsize(r1) + mr r30,r3 + li r31,0 + + b L5 +L4: + addi r3,r3,5 + addi r4,r4,5 + addi r5,r5,5 + addi r6,r6,5 + addi r7,r7,5 + + addi r3,r3,5 + addi r4,r4,5 + addi r5,r5,5 + addi r6,r6,5 + addi r7,r7,5 + + addi r31,r31,10 +L5: + cmpw r31,r30 + blt L4 + + + lwz r0,lrsave+fsize(r1) + mtlr r0 + lwz r31,-4+fsize(r1) + lwz r30,-8+fsize(r1) + addi r1,r1,fsize + blr + +#if 0 +.if 0 +#endif +} +#if 0 +.endif +#endif + + + +#if 0 +.if 0 +#endif +asm void b_load(long n) +{ +#if 0 +.endif +#endif + +#if 0 +b_load: +_b_load: +#endif + + mflr r0 + stw r31,-4(r1) + stw r30,-8(r1) + stw r0,lrsave(r1) + stwu r1,-fsize(r1) + mr r30,r3 + li r31,0 + + b L7 +L6: + lwz r3,4(r1) + lwz r4,8(r1) + lwz r5,12(r1) + lwz r6,16(r1) + lwz r7,20(r1) + + lwz r3,24(r1) + lwz r4,28(r1) + lwz r5,32(r1) + lwz r6,36(r1) + lwz r7,40(r1) + + + addi r31,r31,10 +L7: + cmpw r31,r30 + blt L6 + + + lwz r0,lrsave+fsize(r1) + mtlr r0 + lwz r31,-4+fsize(r1) + lwz r30,-8+fsize(r1) + addi r1,r1,fsize + blr + +#if 0 +.if 0 +#endif +} +#if 0 +.endif +#endif diff --git a/ext/systemc/src/sysc/qt/md/powerpc_sys5.h b/ext/systemc/src/sysc/qt/md/powerpc_sys5.h new file mode 100644 index 000000000..8c0730704 --- /dev/null +++ b/ext/systemc/src/sysc/qt/md/powerpc_sys5.h @@ -0,0 +1,566 @@ +/* + + * QuickThreads -- Threads-building toolkit. + + * Copyright (c) 1993 by David Keppel + + * + + * Permission to use, copy, modify and distribute this software and + + * its documentation for any purpose and without fee is hereby + + * granted, provided that the above copyright notice and this notice + + * appear in all copies. This software is provided as a + + * proof-of-concept and for demonstration purposes; there is no + + * representation about the suitability of this software for any + + * purpose. + + * + + + * PowerPC-Sys5 thread switching module. + + * + + * This software is largely based on the original PowerPC-Linux porting + + * developed by Ken Aaker <kenaaker@silverbacksystems.com> + + * + + * Marco Bucci <marco.bucci@inwind.it> + + * December 2002 + + * + + */ + + +#ifndef QUICKTHREADS_POWERPC_H +#define QUICKTHREADS_POWERPC_H + + +/***************************************************************************** + * + * DESCRIPTION + * + * This is the QuickThreads switching module implementation for PowerPC + * running under System V ABI (Application Binary Interface) [2]. It was + * developed by porting the MacOS X version and tested under LinuxPPC. + * + * Notice that this is not the same than the PowerPC Mach ABI used by MacOSX + * [1]. + * + * IMPLEMENTATION NOTES + * + * 1) Porting on System V ABI + * Excluding the variant argument calling convention, Mach and System V ABI + * are enough similar and it could be possible to use some simple macro, to + * adapt the code for both the ABIs. Actually, the only relevant difference + * is in the linkage area structure and in the position where the Link and + * the Condition registers are saved. As to the calling conventions, there + * are differences with floating points argument passing and with variant + * argument lists. Notice that, on Mach, the caller's stack frame allocates + * space to hold all arguments ([1] p.51), while on System V, the caller's + * stack frame allocates space to hold just the arguments that don't fit into + * registers ([2] p.3.18). + * + * 2) Variant argument list implementation + * Variant argument calling on a RISC machine is not easy to implement since + * parameters are passed via registers instead of via stack. In a general + * variant argument implementation, the caller's stack must map the whole + * parameter list following the rules related to the use of the GPR and FPR + * parameter registers and the stack alignment ([2] p.3-21). + * This implementation is quite simple and not general. It works under the + * hypothesis that arguments are 4-bytes aligned integers. + * + * 3) This heather file organisation + * I preferred to not make confusion between macros that are needed (i.e. + * directly used) by QuickThreads and internal "implementation" macros. You + * will find QuickThreds macros in the end of this header. Sometime they just + * refer to an analogous "internal" macro. On the top, there are the macros + * that I used to make more clean (I hope) the implementation. I could include + * some system heather (as to stack layout definitions, prologs and epilogs, + * etc.), but I preferred to have a self-contained heather in order to make + * all more clear for mantaining and for possible porting on another ABI. + * + * + * REFERENCES + * + * [1] - Mach-O Runtime Architecture + * Runtime Concepts and Conventions for Mac OS X Programs + * Preliminary July 2002 + * + * [2] - SYSTEM V APPLICATION BINARY INTERFACE + * PowerPC Processor Supplement + * September 1995 + * + + *****************************************************************************/ + +/***************************************************************************** + * + * PowerPC System V Stack frame (see [2]) + * + + ................ + + + + | | + +--------------------------+ + | | Caller's LR + + CALLER'S LINKAGE AREA + + backchain -> | | Caller's backchain + +==========================+ + | | FPR31 + + FPR SAVE AREA + + .............. + + + + | | FPRn + +--------------------------+ + | | GPR31 + + GPR SAVE AREA + + .............. + + + + | | GPRn + +--------------------------+ + | | + + ALIGNMEBNT PAD + + .............. + + (if needed) + + | | + +--------------------------+ + | CR SAVE | + +--------------------------+ + | | + + LOCAL VARIABLES AREA + + .............. + + + + | | + +--------------------------+ + | | PAR(n-7) + + + + | | + + PARAMETER AREA + + .............. + + for FUTURE call + + | | PAR(9) + + + + SP + 8 -> | | PAR(8) + +--------------------------+ + SP + 4 -> | | LR callee-save for FUTURE call + + LINKAGE AREA + + SP -> | | backchain + +==========================+ + STACK TOP (lower address) + + Stack grows down + | + V + + + * NOTE: + * + * 1) In this figure parameter are supposed to be integer 4-bytes aligned and + * are numbered 0, 1, 2,... n. + * + * 2) Parameter are allocated in the CALLER's parameter area. This area must + * be large enough to hold all parameters that cannot fit in registers (no + * more parameter registers are available); + * + * 3) The callee saves LR in the caller's linkage area. CR as all other + * callee's state are saved in its own stack frame. + * + + *****************************************************************************/ + + +/***************************************************************************** + * + * Stack initialization for a single argument thread + * + + + top + QUICKTHREADS_STKBASE -> STACK BOTTOM (higher address) + +==========================+ + | | + + + + .............. + + + + | | + +--------------------------+ + top + QUICKTHREADS_ONLY_INDEX * 4 -> | only param | PAR(3) + + + + top + QUICKTHREADS_USER_INDEX * 4 -> | userf param | PAR(2) + + + + top + QUICKTHREADS_ARGT_INDEX * 4 -> | t param | PAR(1) + + + + top + QUICKTHREADS_ARGU_INDEX * 4 -> | u param | PAR(0) + +--------------------------+ + top + QUICKTHREADS_RETURN_INDEX * 4 -> | qt_start | LR save + + + + top + QUICKTHREADS_BLOCKI_FRAME_SIZE -> | top + QUICKTHREADS_STKBASE | backchain + +==========================+ + | | + + + + .............. + + + + | | + +--------------------------+ + | | + + + + top -> |top + QUICKTHREADS_BLOCKI_FRAME_SIZE| backchain + +==========================+ + STACK TOP (lower address) + + Stack grows down + | + V + + ***************************************************************************** + * + * Stack initialization for a variant argument thread + * + + bottom -> STACK BOTTOM (higher address) + +==========================+ + | | + + + + .............. + + + + top + QUICKTHREADS_VSTKBASE -> | arg(0) | PAR(4) + +--------------------------+ + top + QUICKTHREADS_CLEANUP_INDEX * 4 -> | cleanup param | PAR(3) + + + + top + QUICKTHREADS_USER_INDEX * 4 -> | userf param | PAR(2) + + + + top + QUICKTHREADS_VSTARTUP_INDEX * 4 ->| startup param | PAR(1) + + + + top + QUICKTHREADS_ARGT_INDEX * 4 -> | t param | PAR(0) + +--------------------------+ + top + QUICKTHREADS_RETURN_INDEX * 4 -> | qt_start | LR save + + + + top + QUICKTHREADS_BLOCKI_FRAME_SIZE -> | top + QUICKTHREADS_STKBASE | backchain + +==========================+ + | | + + + + .............. + + + + | | + +--------------------------+ + | | + + + + top -> |top + QUICKTHREADS_BLOCKI_FRAME_SIZE| backchain + +==========================+ + STACK TOP (lower address) + + Stack grows down + | + V + +* NOTE: +* +* Parameters are passed to "qt_start" or to "qt_vstart" putting them into +* the stack frames of "qt_start" or "qt_vstart" themselves. This not a +* conventional parameter passing because parameters should be put into the +* caller's stack, not into the callee's one. Actually we must consider +* that as a preload of the parameter area that "qt_start" or "qt_vstart" +* will use for their own calls. +* Be aware of the fact that, during a call, the caller's parameter area is, +* in a certain sense, volatile. In facts, the callee can save parameter +* registers on the caller's parameter area. +* + *****************************************************************************/ + + +/***************************************************************************** + + Define PowerPC System V related macros + + *****************************************************************************/ + + + +typedef unsigned long PPC_W; + +/* Stack pointer must always be a multiple of 16 */ +#define PPC_STACK_INCR 16 +#define PPC_ROUND_STACK(length) \ + (((length)+PPC_STACK_INCR-1) & ~(PPC_STACK_INCR-1)) + + +#define PPC_LINKAGE_AREA 8 +#define PPC_LR_SAVE 4 + +#define PPC_PARAM_AREA(n) (4*(n)) + +#define PPC_GPR_SAVE_AREA (4*19) /* GPR13-GPR31 must be saved */ +#define PPC_FPR_SAVE_AREA (8*18) /* FPR14-FPR31 must be saved */ + +/* Define parameter offset on the stack. + * NOTICE: Parameters are numbered 0, 1, ..., n. +*/ +#define PPC_PAR(i) (PPC_LINKAGE_AREA+(i)*4) + +/***************************************************************************** + + Define stack frames + + *****************************************************************************/ + + +/* Define the "qt_blocki" and "qt_abort" stack frame. We use the same stack + * frame for both. + * + + top + S -> + +==========================+ + top + S - 4 -> | | GPR31 + + GPR SAVE AREA + + .............. + + + + top + S - 19 * 4 -> | | GPR13 + +--------------------------+ + | | + + ALIGNMEBNT PAD + + .............. + + (if needed) + + | | + +--------------------------+ + top + 8 -> | CR SAVE | + +--------------------------+ + | | + + LINKAGE AREA + + top -> | | + +==========================+ + */ + +#define QUICKTHREADS_BLOCKI_FRAME_SIZE \ + PPC_ROUND_STACK(PPC_LINKAGE_AREA+4+PPC_GPR_SAVE_AREA) + +#define QUICKTHREADS_BLOCKI_CR_SAVE 8 + +/* Offset to the base of the GPR save area. Save from GPR13 to GPR31 + * increasing address. + */ +#define QUICKTHREADS_BLOCKI_GPR_SAVE(i) (QUICKTHREADS_BLOCKI_FRAME_SIZE-4+(i-31)*4) + + + +/* Define the "qt_block" stack frame. Notice that since "qt_black" calls + * "qt_blocki", GPR registers are saved into "qt_blocki" stack frame. + * + + top + S -> + +==========================+ + top + S - 8 -> | | FPR31 + + FPR SAVE AREA + + .............. + + + + top + S - 18 * 8 -> | | FPR14 + +--------------------------+ + | | + + ALIGNMEBNT PAD + + .............. + + (if needed) + + | | + +--------------------------+ + | | + + LINKAGE AREA + + top -> | | + +==========================+ + */ + +#define QUICKTHREADS_BLOCK_FRAME_SIZE \ + PPC_ROUND_STACK(PPC_LINKAGE_AREA+PPC_FPR_SAVE_AREA) + +/* Offset to the location where registers are saved. + */ +#define QUICKTHREADS_BLOCK_FPR_SAVE(i) (QUICKTHREADS_BLOCK_FRAME_SIZE-8+(i-31)*8) + + +/* Define the "qt_start" frame size. It consists just of the linkage area and + * the parameter area. + * + + +==========================+ + | | + + ALIGNMEBNT PAD + + .............. + + (if needed) + + | | + +--------------------------+ + | | only par + + + + | | userf par + + PARAMETER AREA + + | | t par + + + + top + 8 -> | | u par + +--------------------------+ + | | + + LINKAGE AREA + + top -> | | + +==========================+ + + */ +#define QUICKTHREADS_START_FRAME_SIZE PPC_ROUND_STACK(PPC_LINKAGE_AREA+PPC_PARAM_AREA(4)) + + + +/* Define the "qt_vstart" frame. It consists of the linkage area, the fix parameter + * area, the variant argument list and a local variable area used in "qt_vstart" + * implementation. + * + + backchain -> + +==========================+ + backchain - 4 -> | | + + LOCAL VARIABLES AREA + + .............. + + + + | | + +--------------------------+ + | | + + ALIGNMEBNT PAD + + .............. + + (if needed) + + | | + +--------------------------+ + | | arg(n) + + + + | | + + VARIABLE ARGUMENT LIST + + .............. + + for userf call + + | | arg(1) + + + + top + 8 + 16 -> | | arg(0) + +--------------------------+ + | | cleanup par + + + + | | userf par + + PARAMETER AREA + + | | startup par + + + + top + 8 -> | | t par + +--------------------------+ + | | + + LINKAGE AREA + + top -> | | + +==========================+ + + */ +#define QUICKTHREADS_VARGS_LOCAL_AREA (4*4) /* local variable area */ + +/* The offset the stack will be moved back before to call "userf(...)". + * The linckage area must be moved to be adiacent to the part of the variant + * argument list that is in the stack. Notice that, since the first 8 + * parameters are passed via registers, the offset is equal to the size of + * 4+8 parameters. */ +#define QUICKTHREADS_VARGS_BKOFF PPC_PARAM_AREA(4+8) + +#define QUICKTHREADS_VSTART_FRAME_SIZE(varbytes) \ + PPC_ROUND_STACK(PPC_LINKAGE_AREA+QUICKTHREADS_VARGS_BKOFF+(varbytes)+ \ + QUICKTHREADS_VARGS_LOCAL_AREA) + +/* Offset to the base of the varian argument list */ +#define QUICKTHREADS_VSTART_LIST_BASE (PPC_LINKAGE_AREA+PPC_PARAM_AREA(4)) + + +/* Notice that qt_start and qt_vstart have no parameters, actually their + * parameters are written in their stack frame during thread initialization + */ +extern void qt_start(void); +extern void qt_vstart(void); + + + +/* Offset (in words) of the location where the block routine saves its return + * address (i.e. LR). SP points the top of the block routine stack and, + * following ppc calling conventions, the return address is saved in the + * previous (caller's) stack frame. + */ +#define QUICKTHREADS_RETURN_INDEX ((QUICKTHREADS_BLOCKI_FRAME_SIZE+PPC_LR_SAVE)/sizeof(PPC_W)) + +/* static variable used to get the stack bottom in "VARGS" initialization */ +static void *qt_sp_bottom_save; + +#define QUICKTHREADS_ARG_INDEX(i) ((QUICKTHREADS_BLOCKI_FRAME_SIZE+PPC_PAR(i))/sizeof(PPC_W)) + +/***************************************************************************** + + QuickThreads needed definitions + + *****************************************************************************/ + + +#define QUICKTHREADS_GROW_DOWN +#define QUICKTHREADS_STKALIGN PPC_STACK_INCR +typedef PPC_W qt_word_t; + + +/* This macro is used by "QUICKTHREADS_ARGS" to initialize a single argument thread. + * - set "qt_start" as the "qt_block" or "qt_blocki" return address; + * - set the top of the stack backchain; + * - set the next backchain (not needed, but just to be "clean"). + */ +#define QUICKTHREADS_ARGS_MD(sp) \ + (QUICKTHREADS_SPUT (sp, QUICKTHREADS_RETURN_INDEX, qt_start), \ + QUICKTHREADS_SPUT (sp, 0, sp+QUICKTHREADS_BLOCKI_FRAME_SIZE), \ + QUICKTHREADS_SPUT (sp, QUICKTHREADS_BLOCKI_FRAME_SIZE/sizeof(PPC_W), \ + sp+QUICKTHREADS_BLOCKI_FRAME_SIZE+QUICKTHREADS_START_FRAME_SIZE)) + + +/* This macro is used by "QUICKTHREADS_VARGS" to initialize a variant argument thread. + * It returns the pointer to the top of the argument list. + * We also use it to get the stack bottom via a static variable. This is a bit + * "dirty", it could be better to do it in "qt_vargs", but we don't want change + * anything out of this file. + * We need the stack bottom to allocate a local variable area used by + * "qt_vstart". + */ +#define QUICKTHREADS_VARGS_MD0(sp, varbytes) \ + ((qt_sp_bottom_save = sp), \ + ((qt_t *)(((char *)(sp)) - \ + (QUICKTHREADS_VSTART_FRAME_SIZE(varbytes)-QUICKTHREADS_VSTART_LIST_BASE)))) + + +/* This macro is used by "QUICKTHREADS_VARGS" to initialize a variant argument thread. + * - set "qt_start" as the "qt_block" or "qt_blocki" return address; + * - set the top of the stackback chain; + * - set the next backchain (it points the stack botton). + */ +#define QUICKTHREADS_VARGS_MD1(sp) \ + (QUICKTHREADS_SPUT (sp, QUICKTHREADS_RETURN_INDEX, qt_vstart), \ + QUICKTHREADS_SPUT (sp, 0, sp+QUICKTHREADS_BLOCKI_FRAME_SIZE), \ + QUICKTHREADS_SPUT (sp, (QUICKTHREADS_BLOCKI_FRAME_SIZE)/sizeof(PPC_W), \ + qt_sp_bottom_save)) + + +/* Activate "qt_vargs" as the initialization routine for the variant + * argument threads + */ +#define QUICKTHREADS_VARGS_DEFAULT + +/* Override "qt_vargs" with "qt_vargs_stdarg". + * On LinuxPPC "qt_vargs" doesn't work, "qt_vargs_stdarg" uses a more + * standard way to retrieve arguments from the variant list. + */ +#define QUICKTHREADS_VARGS(sp, nbytes, vargs, pt, startup, vuserf, cleanup) \ + ((qt_t *)qt_vargs_stdarg (sp, nbytes, vargs, pt, startup, vuserf, cleanup)) + + +/* This macro is used by "QUICKTHREADS_ADJ(sp)" to get the stack top form the stack + * bottom during a single argument thread initialization. + * It is the space we need to allocate for a single argument thread: the stack + * frame for the block routine ("qt_block" or "qt_blocki") and for "qt_start". + */ +#define QUICKTHREADS_STKBASE \ + (QUICKTHREADS_BLOCKI_FRAME_SIZE+QUICKTHREADS_START_FRAME_SIZE) + +/* This macro is used by "QUICKTHREADS_VADJ(sp)" to get the stack top from the base + * of the variant argument list during a variant argument thread initialization. + */ +#define QUICKTHREADS_VSTKBASE (QUICKTHREADS_BLOCKI_FRAME_SIZE+QUICKTHREADS_VSTART_LIST_BASE) + +/* The *index* (positive offset) of where to put each value. */ + +#define QUICKTHREADS_ARGU_INDEX QUICKTHREADS_ARG_INDEX(0) +#define QUICKTHREADS_ARGT_INDEX QUICKTHREADS_ARG_INDEX(1) +#define QUICKTHREADS_USER_INDEX QUICKTHREADS_ARG_INDEX(2) +#define QUICKTHREADS_ONLY_INDEX QUICKTHREADS_ARG_INDEX(3) + + +#define QUICKTHREADS_VARGT_INDEX QUICKTHREADS_ARG_INDEX(0) +#define QUICKTHREADS_VSTARTUP_INDEX QUICKTHREADS_ARG_INDEX(1) +#define QUICKTHREADS_VUSERF_INDEX QUICKTHREADS_ARG_INDEX(2) +#define QUICKTHREADS_VCLEANUP_INDEX QUICKTHREADS_ARG_INDEX(3) + +#endif /* ndef QUICKTHREADS_POWERPC_H */ + diff --git a/ext/systemc/src/sysc/qt/md/powerpc_sys5.s b/ext/systemc/src/sysc/qt/md/powerpc_sys5.s new file mode 100644 index 000000000..d9dc9332d --- /dev/null +++ b/ext/systemc/src/sysc/qt/md/powerpc_sys5.s @@ -0,0 +1,639 @@ +/* powerpc-sys5.s -- assembly support. */ + +/* + * QuickThreads -- Threads-building toolkit. + * Copyright (c) 1993 by David Keppel + * + * Permission to use, copy, modify and distribute this software and + * its documentation for any purpose and without fee is hereby + * granted, provided that the above copyright notice and this notice + * appear in all copies. This software is provided as a + * proof-of-concept and for demonstration purposes; there is no + * representation about the suitability of this software for any + * purpose. + + + * PowerPC-System V thread switching module. + * + * This software is largely based on the original PowerPC-Linux porting + * developed by Ken Aaker <kenaaker@silverbacksystems.com> + * + * Marco Bucci <marco.bucci@inwind.it> + * December 2002 + * + */ + + +/* + * + * PowerPC Register convections: + * + * r0 volatile + * r1 SP + * r2 system reserved + * r3-r4 volatile for parameter passing and function return + * r5-r10 volatile for parameter passing + * r11-r12 volatile + * r13-r14 non volatile registers + * f0 volatile + * f1 volatile for parameter passing and function return + * f2-f13 volatile for parameter passing + * f14-f31 non volatile + * + * cr2-cr4 non volatile + * + * + * See on the heather file for more documentation. + * + * + * + * IMPLEMENTATION NOTES + * + * + * 1) Condition register saving + * On most machines, the condition code register is caller-save. + * On the PPC, the condition code register is callee-save, so the + * thread context switch must preserve it. + * + * + * 2) Floating point registers saving + * On resuming a thread, floating point registers are or not restored just + * depending on which block routine suspended the thread (i.e. regardless + * whether "qt_block", "qt_blocki" or "qt_abort" is used to resume it). + * This behaviour is obtained by implementing "qt_block" by means af a nested + * call to "qt_blocki". As a result, the blocking of a thread always goes + * and returns through "qt_blocki and, if a thread was blocked by "qt_block", + * its execution resumes from the floating point restoring code on exit + * of "qt_block". + * + * Thanks to David Keppel that explained me this "simple" trick. + * + * + * 3) C languace code debugging + * The original version of this software was developed and debugged under + * MacOS X using the Metrowerks Code Warrior PPC integrated assembler. + * It could be still used with a C inline assembler by means of a suitable + * file to include it. + * In order to avoid "copy and paste" bugs, and make easyer the maintaining, + * I made the minimal changes, so you can find some strange code as: + * + * #if 0 + * .if 0 + * C code here + * .endif + * #endif + * + * This is just to embed some C code that is needed by the Code Warrior + * integrated assembler. + * + * + * 4) Assembly constants generation + * Constants used in the assembly code are generated by running + * the C code in the sequel (commented). It uses the C macros declared in + * the C heather in order to guarantee that the C interface and the assebly + * code are "aligned". I avoided the use of an assebler preprocessor since + * they are not so standard and moreover using macro espressions makes the + * assembly debugging more difficult. + * + * + + +#include <iostream> +#include "powerpc_sys5.h" + +int main() +{ + using namespace std; + + int i; + + cout << ".set LR_SAVE, " << PPC_LR_SAVE << endl; + cout << ".set BLOCKI_FSIZE, " << QUICKTHREADS_BLOCKI_FRAME_SIZE << endl; + cout << ".set BLOCKI_CR_SAVE, " << QUICKTHREADS_BLOCKI_CR_SAVE << endl; + cout << ".set BLOCK_FSIZE, " << QUICKTHREADS_BLOCK_FRAME_SIZE << endl; + + cout << endl; + for(i=0; i<12; i++) + cout << ".set PAR_" << i << ", " << PPC_PAR(i) << endl; + + cout << endl; + i = 13; + cout << ".set GPR_SAVE_" << i << ", " << QUICKTHREADS_BLOCKI_GPR_SAVE(i) << endl; + + cout << endl; + for(i=31; i>13; i--) + cout << ".set FPR_SAVE_" << i << ", " << QUICKTHREADS_BLOCK_FPR_SAVE(i) << endl; + + cout << endl; + cout << ".set VARGS_BKOFF, " << QUICKTHREADS_VARGS_BKOFF << endl; + + + cout << endl << endl << endl; + + for(i=31; i>13; i--) + cout << "\tstfd\tf" << i << ",FPR_SAVE_" << i << "(%r1)" << endl; + + cout << endl; + for(i=31; i>13; i--) + cout << "\tlfd \tf" << i << ",FPR_SAVE_" << i << "(%r1)" << endl; + + cout << endl << endl << endl; + + + return 0; +} + + + + * + * + * + */ + + +#if 0 + + .text + .align 4 + + .globl qt_block + .globl _qt_block + .globl qt_blocki + .globl _qt_blocki + .globl qt_abort + .globl _qt_abort + .globl qt_start + .globl _qt_start + .globl qt_vstart + .globl _qt_vstart + + +.set LR_SAVE, 4 +.set BLOCKI_FSIZE, 96 +.set BLOCKI_CR_SAVE, 8 /* CR is saved into the callee's stack frame */ +.set BLOCK_FSIZE, 160 + +.set PAR_0, 8 +.set PAR_1, 12 +.set PAR_2, 16 +.set PAR_3, 20 +.set PAR_4, 24 +.set PAR_5, 28 +.set PAR_6, 32 +.set PAR_7, 36 +.set PAR_8, 40 +.set PAR_9, 44 +.set PAR_10, 48 +.set PAR_11, 52 + +.set GPR_SAVE_13, 20 + +.set FPR_SAVE_31, 152 +.set FPR_SAVE_30, 144 +.set FPR_SAVE_29, 136 +.set FPR_SAVE_28, 128 +.set FPR_SAVE_27, 120 +.set FPR_SAVE_26, 112 +.set FPR_SAVE_25, 104 +.set FPR_SAVE_24, 96 +.set FPR_SAVE_23, 88 +.set FPR_SAVE_22, 80 +.set FPR_SAVE_21, 72 +.set FPR_SAVE_20, 64 +.set FPR_SAVE_19, 56 +.set FPR_SAVE_18, 48 +.set FPR_SAVE_17, 40 +.set FPR_SAVE_16, 32 +.set FPR_SAVE_15, 24 +.set FPR_SAVE_14, 16 + + + + +/* various offsets used by "qt_varg" */ +.set P_T, PAR_0 +.set P_STARTUP, PAR_1 +.set P_USERF, PAR_2 +.set P_CLEANUP, PAR_3 + /* the offset used to move back the linkage area to be adiacent to + * the variant argument list before calling "userf(...). + * Skip "t", "startup", "userf", "cleanup" and first + * 8 parameters (since they are passed via registers) */ +.set VARGS_BKOFF, 48 + + /* location where "t" and "cleanup" are saved (with respect of + * the stack frame base) */ +.set P_T_SAVE, -4 +.set P_CLEANUP_SAVE, -8 + +#endif + + + +/* Block the current thread saving all integer non volatile registers and + * start a new thread. + */ +#if 0 +.if 0 +#endif +void *qt_blocki (void *helper, void *a0, void *a1, void *newthread); +asm void *qt_blocki (void *helper, void *a0, void *a1, void *newthread) +{ +#if 0 +.endif +#endif + +#if 0 +qt_blocki: +_qt_blocki: +#endif +/* prolog code */ + stwu %r1,-BLOCKI_FSIZE(%r1) /* allocate the stack frame */ + mflr %r0 /* return addr in r0 */ + mfcr %r11 /* CR in r11 */ + stw %r0,LR_SAVE+BLOCKI_FSIZE(%r1) /* save return addr in the stack */ + stw %r11,BLOCKI_CR_SAVE(%r1) /* save CR in the stack */ + stmw %r13,GPR_SAVE_13(%r1) /* save non-volatile reg */ + +/* call helper(qt_t *old, void *a0, void *a1) */ + mtlr %r3 /* "helper" addr in the link reg */ + mr %r3,%r1 /* current thread (i.e. the SP) in arg "old" */ + mr %r1,%r6 /* swap to the new thread (i.e. to its SP) */ + blrl /* jump to "helper" */ +/* the "helper" return value is returned (since r3 is not changed) */ + +/* epilog code: return to the new thread's "qt_blocki" caller */ + lmw %r13,GPR_SAVE_13(%r1) /* restore non-volatile reg */ + lwz %r0,LR_SAVE+BLOCKI_FSIZE(%r1) /* recover return addr */ + lwz %r11,BLOCKI_CR_SAVE(%r1) /* recover CR */ + mtlr %r0 /* return address in the link reg */ + mtcr %r11 /* restore CR */ + addi %r1,%r1,BLOCKI_FSIZE /* free the stack frame */ + blr /* return */ + +#if 0 +.if 0 +#endif +} +#if 0 +.endif +#endif + + + +/* Abort the current thread and start a new thread. + */ +#if 0 +.if 0 +#endif +void qt_abort (void *helper, void *a0, void *a1, void *newthread); +asm void qt_abort (void *helper, void *a0, void *a1, void *newthread) +{ +#if 0 +.endif +#endif + +#if 0 +qt_abort: +_qt_abort: +#endif +/* prolog code */ +/* there is no prolog. It will never come back */ + +/* call helper(qt_t *old, void *a0, void *a1) */ + mtlr %r3 /* "helper" addr in the link reg */ + mr %r1,%r6 /* swap to the new thread (i.e. to its SP) */ +/* we don't need to set "old", we can pass just garbage. Actually, since r3 + is not changed, "old" is set to "helper" (don't care) */ + blrl /* call "helper" */ +/* the "helper" return value is returned (since r3 is not changed) */ + +/* epilog code: return to the new thread's "qt_blocki" caller */ + lmw %r13,GPR_SAVE_13(%r1) /* restore non-volatile reg */ + lwz %r0,LR_SAVE+BLOCKI_FSIZE(%r1) /* recover return addr */ + lwz %r11,BLOCKI_CR_SAVE(%r1) /* recover CR */ + mtlr %r0 /* return address in the link reg */ + mtcr %r11 /* restore CR */ + addi %r1,%r1,BLOCKI_FSIZE /* free the stack frame */ + blr /* return */ + +#if 0 +.if 0 +#endif +} +#if 0 +.endif +#endif + + + +/* Block the current thread saving all non volatile registers and start + * a new thread. + */ +#if 0 +.if 0 +#endif +void *qt_block (void *helper, void *a0, void *a1, void *newthread); +asm void *qt_block (void *helper, void *a0, void *a1, void *newthread) +{ +#if 0 +.endif +#endif + +# if 0 +qt_block: +_qt_block: +#endif +/* prolog code */ + stwu %r1,-BLOCK_FSIZE(%r1) /* allocate the stack frame */ + mflr %r0 /* return addr in r0 */ + stw %r0,LR_SAVE+BLOCK_FSIZE(%r1) /* save return addr in the stack */ + +/* save non-volatile fp reg */ + stfd %f31,FPR_SAVE_31(%r1) + stfd %f30,FPR_SAVE_30(%r1) + stfd %f29,FPR_SAVE_29(%r1) + stfd %f28,FPR_SAVE_28(%r1) + stfd %f27,FPR_SAVE_27(%r1) + stfd %f26,FPR_SAVE_26(%r1) + stfd %f25,FPR_SAVE_25(%r1) + stfd %f24,FPR_SAVE_24(%r1) + stfd %f23,FPR_SAVE_23(%r1) + stfd %f22,FPR_SAVE_22(%r1) + stfd %f21,FPR_SAVE_21(%r1) + stfd %f20,FPR_SAVE_20(%r1) + stfd %f19,FPR_SAVE_19(%r1) + stfd %f18,FPR_SAVE_18(%r1) + stfd %f17,FPR_SAVE_17(%r1) + stfd %f16,FPR_SAVE_16(%r1) + stfd %f15,FPR_SAVE_15(%r1) + stfd %f14,FPR_SAVE_14(%r1) +/* block the thread */ + bl qt_blocki +/* the thread is going to be resumed */ +/* restore non-volatile fp reg */ + lfd %f31,FPR_SAVE_31(%r1) + lfd %f30,FPR_SAVE_30(%r1) + lfd %f29,FPR_SAVE_29(%r1) + lfd %f28,FPR_SAVE_28(%r1) + lfd %f27,FPR_SAVE_27(%r1) + lfd %f26,FPR_SAVE_26(%r1) + lfd %f25,FPR_SAVE_25(%r1) + lfd %f24,FPR_SAVE_24(%r1) + lfd %f23,FPR_SAVE_23(%r1) + lfd %f22,FPR_SAVE_22(%r1) + lfd %f21,FPR_SAVE_21(%r1) + lfd %f20,FPR_SAVE_20(%r1) + lfd %f19,FPR_SAVE_19(%r1) + lfd %f18,FPR_SAVE_18(%r1) + lfd %f17,FPR_SAVE_17(%r1) + lfd %f16,FPR_SAVE_16(%r1) + lfd %f15,FPR_SAVE_15(%r1) + lfd %f14,FPR_SAVE_14(%r1) + + lwz %r0,LR_SAVE+BLOCK_FSIZE(%r1) /* recover return addr */ + mtlr %r0 /* return address in the link reg */ + addi %r1,%r1,BLOCK_FSIZE /* free the stack frame */ + blr /* return */ + +#if 0 +.if 0 +#endif +} +#if 0 +.endif +#endif + + + +/* Start a single argument thread using parameters preloaded in the stack + * during thread initialization (see comments on stack initialization in the + * heather file). + * + * Executes: + * + * only(u, t, userf); + */ +#if 0 +.if 0 +#endif +void qt_start(void); +asm void qt_start(void) +{ +#if 0 +.endif +#endif + +#if 0 +qt_start: +_qt_start: +#endif + lwz %r3,PAR_0(%r1) /* "u" in r3 */ + lwz %r4,PAR_1(%r1) /* "t" in r4 */ + lwz %r5,PAR_2(%r1) /* "userf" in r5 */ + lwz %r6,PAR_3(%r1) /* "only" in r6 */ + mtlr %r6 /* "only" address in the link reg */ +/* call only(u, t, userf) */ + blrl /* jump to "only" */ +/* error if it returns */ + b qt_error +/* dead code (some inline asm "wants" the epilog, or they genetare it) */ + blr + +#if 0 +.if 0 +#endif +} +#if 0 +.endif +#endif + + + +/* Start a variant argument thread using parameters preloaded in the stack + * during thread initialization (see comments on stack initialization in the + * heather file). + * + * Executes: + * + * startup(t); + * userf_return = userf(...); + * cleanup(pt, userf_return); + * + + + ***** Stack layout on start ***** + + + backchain -> STACK BOTTOM (higher address) + +==========================+ + backchain - 4 -> | | + + LOCAL VARIABLES AREA + + .............. + + + + | | + +--------------------------+ + | | + + ALIGNMEBNT PAD + + .............. + + (if needed) + + | | + +--------------------------+ + | | arg(n) + + + + | | + + VARIABLE ARGUMENT LIST + + .............. + + for userf call + + SP + PAR(5) -> | | arg(1) + + + + SP + PAR(4) -> | | arg(0) + +--------------------------+ + SP + PAR(3) -> | | cleanup par + + + + SP + PAR(2) -> | | userf par + + PARAMETER AREA + + SP + PAR(1) -> | | startup par + + + + SP + PAR(0) -> | | t par + +--------------------------+ + | | + + LINKAGE AREA + + SP -> | | + +==========================+ + STACK TOP (lower address) + + Stack grows down + | + V + + + + ***** Stack layout before call userf ***** + + + backchain -> STACK BOTTOM (higher address) + +==========================+ + backchain - 4 -> | | + + LOCAL VARIABLES AREA + + .............. + + + + | | + +--------------------------+ + | | + + ALIGNMEBNT PAD + + .............. + + (if needed) + + | | + +--------------------------+ + | | arg(n) + + + + | | + + VARIABLE ARGUMENT LIST + + .............. + + for userf call + + SP + PAR(1) -> | | arg(1) + + + + SP + PAR(0) -> | | arg(0) + +--------------------------+ + | | + + LINKAGE AREA + + SP -> | | + +==========================+ + STACK TOP (lower address) + + Stack grows down + | + V + + + * To call "userf(...)", the argument list must be adiacent to the linkage + * area. Instead of copy the argument list, we move back the linkage area + * (actually, we just increase the SP and copy the backchain). "t" and + * "cleanup" are saved in a local variable area in order to call + * cleanup(pt, userf_return). + +*/ + + +#if 0 +.if 0 +#endif +void qt_vstart(void); +asm void qt_vstart(void) +{ +#if 0 +.endif +#endif + +#if 0 +qt_vstart: +_qt_vstart: +#endif +/* NOTICE: the callee routines could save parameter registers in the caller's + * stack parameter area. We put "t" in PAR(0) in such a way, if startup(t) + * will save "t", it will be saved on the same location thus not delething + * any other parameter. + */ + +/* since we will move back the linckage area (to make it adiacent to the + * parameter list), we need to save "t" and "cleanup". We have made room for + * this on the bottom of the stack frame. */ + +/* save parameters in the local variable area */ + lwz %r11,0(%r1) /* get the backchain */ + lwz %r3,P_T(%r1) + lwz %r4,P_CLEANUP(%r1) + stw %r3,P_T_SAVE(%r11) /* save "pt" */ + stw %r4,P_CLEANUP_SAVE(%r11) /* save "cleanup" */ + +/* call startup(t) */ + lwz %r5,P_STARTUP(%r1) + mtlr %r5 + blrl /* call "startup" */ + +/* call userf(...) */ + lwz %r11,0(%r1) /* reload backchain (r11 is volatile) */ + lwz %r4,P_USERF(%r1) /* load "userf" */ + mtlr %r4 + + /* first eight parameter of the variant list must be copyed in + * GPR3-GPR10. There is a four places offset due to "t", "startup", + * userf" and "cleanup" */ + + lwz %r3,PAR_4(%r1) + lwz %r4,PAR_5(%r1) + lwz %r5,PAR_6(%r1) + lwz %r6,PAR_7(%r1) + lwz %r7,PAR_8(%r1) + lwz %r8,PAR_9(%r1) + lwz %r9,PAR_10(%r1) + lwz %r10,PAR_11(%r1) + + + /* move the linkage area to be adiacent to the argument list */ + stw %r11,VARGS_BKOFF(%r1) /* copy backchain */ + addi %r1,%r1,VARGS_BKOFF /* move back the stack */ + + blrl /* call "userf" */ + +/* call qt_cleanup(void *pt, void *vuserf_return) */ + lwz %r11,0(%r1) /* reload backchain (r11 is volatile) */ + + mr %r4,%r3 /* push "userf" return as 2nd parameter */ + lwz %r3,P_T_SAVE(%r11) /* reload "pt" */ + lwz %r5,P_CLEANUP_SAVE(%r11) /* reload "cleanup" */ + mtlr %r5 + blrl + b qt_error +/* dead code (some inline asm "wants" the epilog, or they genetare it) */ + blr + +#if 0 +.if 0 +#endif +} +#if 0 +.endif +#endif + diff --git a/ext/systemc/src/sysc/qt/md/powerpc_sys5_b.s b/ext/systemc/src/sysc/qt/md/powerpc_sys5_b.s new file mode 100644 index 000000000..e57a20e2e --- /dev/null +++ b/ext/systemc/src/sysc/qt/md/powerpc_sys5_b.s @@ -0,0 +1,290 @@ +/* speed test for basic CPU operations */ + + +/* Marco Bucci <marco.bucci@inwind.it> */ + +/* This code was developed with the Code Warrior integrate ppc assembler. + * Macros are use to hide illegal constructs whether you are using a + * "normal" assembler or the "C integrated" assembler. + */ + +#if 0 + + + .text + .align 4 + + .globl b_call_reg + .globl _b_call_reg + .globl b_call_imm + .globl _b_call_imm + .globl b_add + .globl _b_add + .globl b_load + .globl _b_load + +.set fsize, 64 +.set lrsave, 4 + +#else + +#define fsize 64 +#define lrsave 4 + +#endif + + + + +#if 0 +.if 0 +#endif +asm void b_null(void) +{ +#if 0 +.endif +#endif + +#if 0 +b_null: +#endif + + blr + +#if 0 +.if 0 +#endif +} +#if 0 +.endif +#endif + + +/* actually the same as the following. How to get "b_null" address? + * I didnt find the right sintax or the right way. + * I should take the current PC, then the difference to "b_null" + * (making the difference beween the labels), perform the sum and go?! + */ +#if 0 +.if 0 +#endif +asm void b_call_reg(long n) +{ +#if 0 +.endif +#endif + +#if 0 +b_call_reg: +_b_call_reg: +#endif + + mflr %r0 + stw %r31,-4(%r1) + stw %r30,-8(%r1) + stw %r0,lrsave(%r1) + stwu %r1,-fsize(%r1) + mr %r30,%r3 + li %r31,0 + + b L1 +L0: + bl b_null + bl b_null + bl b_null + bl b_null + bl b_null + + addi %r31,%r31,5 +L1: + cmpw %r31,%r30 + blt L0 + + + lwz %r0,lrsave+fsize(%r1) + mtlr %r0 + lwz %r31,-4+fsize(%r1) + lwz %r30,-8+fsize(%r1) + addi %r1,%r1,fsize + blr + +#if 0 +.if 0 +#endif +} +#if 0 +.endif +#endif + + + + +#if 0 +.if 0 +#endif +asm void b_call_imm(long n) +{ +#if 0 +.endif +#endif + +#if 0 +b_call_imm: +_b_call_imm: +#endif + + mflr %r0 + stw %r31,-4(%r1) + stw %r30,-8(%r1) + stw %r0,lrsave(%r1) + stwu %r1,-fsize(%r1) + mr %r30,%r3 + li %r31,0 + + b L3 +L2: + bl b_null + bl b_null + bl b_null + bl b_null + bl b_null + + addi %r31,%r31,5 +L3: + cmpw %r31,%r30 + blt L2 + + + lwz %r0,lrsave+fsize(%r1) + mtlr %r0 + lwz %r31,-4+fsize(%r1) + lwz %r30,-8+fsize(%r1) + addi %r1,%r1,fsize + blr + +#if 0 +.if 0 +#endif +} +#if 0 +.endif +#endif + + + +#if 0 +.if 0 +#endif +asm void b_add(long n) +{ +#if 0 +.endif +#endif + +#if 0 +b_add: +_b_add: +#endif + + mflr %r0 + stw %r31,-4(%r1) + stw %r30,-8(%r1) + stw %r0,lrsave(%r1) + stwu %r1,-fsize(%r1) + mr %r30,%r3 + li %r31,0 + + b L5 +L4: + addi %r3,%r3,5 + addi %r4,%r4,5 + addi %r5,%r5,5 + addi %r6,%r6,5 + addi %r7,%r7,5 + + addi %r3,%r3,5 + addi %r4,%r4,5 + addi %r5,%r5,5 + addi %r6,%r6,5 + addi %r7,%r7,5 + + addi %r31,%r31,10 +L5: + cmpw %r31,%r30 + blt L4 + + + lwz %r0,lrsave+fsize(%r1) + mtlr %r0 + lwz %r31,-4+fsize(%r1) + lwz %r30,-8+fsize(%r1) + addi %r1,%r1,fsize + blr + +#if 0 +.if 0 +#endif +} +#if 0 +.endif +#endif + + + +#if 0 +.if 0 +#endif +asm void b_load(long n) +{ +#if 0 +.endif +#endif + +#if 0 +b_load: +_b_load: +#endif + + mflr %r0 + stw %r31,-4(%r1) + stw %r30,-8(%r1) + stw %r0,lrsave(%r1) + stwu %r1,-fsize(%r1) + mr %r30,%r3 + li %r31,0 + + b L7 +L6: + lwz %r3,4(%r1) + lwz %r4,8(%r1) + lwz %r5,12(%r1) + lwz %r6,16(%r1) + lwz %r7,20(%r1) + + lwz %r3,24(%r1) + lwz %r4,28(%r1) + lwz %r5,32(%r1) + lwz %r6,36(%r1) + lwz %r7,40(%r1) + + + addi %r31,%r31,10 +L7: + cmpw %r31,%r30 + blt L6 + + + lwz %r0,lrsave+fsize(%r1) + mtlr %r0 + lwz %r31,-4+fsize(%r1) + lwz %r30,-8+fsize(%r1) + addi %r1,%r1,fsize + blr + +#if 0 +.if 0 +#endif +} +#if 0 +.endif +#endif diff --git a/ext/systemc/src/sysc/qt/md/pthreads.Makefile b/ext/systemc/src/sysc/qt/md/pthreads.Makefile new file mode 100644 index 000000000..f722fbe19 --- /dev/null +++ b/ext/systemc/src/sysc/qt/md/pthreads.Makefile @@ -0,0 +1,108 @@ +# Generated automatically from Makefile.in by configure. +# Makefile.in generated automatically by automake 1.4 from Makefile.am + +# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + + +SHELL = /bin/sh + +all: + +mostlyclean-noinstLIBRARIES: + +clean-noinstLIBRARIES: + +distclean-noinstLIBRARIES: + +maintainer-clean-noinstLIBRARIES: + +mostlyclean-compile: + +clean-compile: + +distclean-compile: + +maintainer-clean-compile: + +tags: + +ID: + +TAGS: + +mostlyclean-tags: + +clean-tags: + +distclean-tags: + +maintainer-clean-tags: + +distdir: + +info-am: +info: +dvi-am: +dvi: dvi-am +check-am: all-am +check: check-am +installcheck-am: +installcheck: installcheck-am +install-exec-am: +install-exec: install-exec-am + +install-data-am: install-data-local +install-data: install-data-am + +install-am: all-am +install: install-am +uninstall-am: uninstall-local +uninstall: uninstall-am +all-am: +all-redirect: +install-strip: +installdirs: + + +mostlyclean-generic: + +clean-generic: + +distclean-generic: + +maintainer-clean-generic: +mostlyclean-am: + +mostlyclean: + +clean-am: + +clean: + +distclean-am: + +distclean: + +maintainer-clean-am: + +maintainer-clean: + +.PHONY: + + +configuration: + +clean: + +install-data-local: + +uninstall-local: + diff --git a/ext/systemc/src/sysc/qt/md/solaris.README b/ext/systemc/src/sysc/qt/md/solaris.README new file mode 100644 index 000000000..04f855c44 --- /dev/null +++ b/ext/systemc/src/sysc/qt/md/solaris.README @@ -0,0 +1,19 @@ +Solaris 2.x is like System V (maybe it *is* System V?) and is different +from older versions in that it uses no leading underscore for variable +and function names. That is, the old convention was: + + foo(){} + +got compiled as + + .globl _foo + _foo: + +and is now compiled as + + .globl foo + foo: + +The `config' script should fix up the older (leading underscore) versions +of the machine-dependent files to use the newer (no leading underscore) +calling conventions. diff --git a/ext/systemc/src/sysc/qt/md/sparc.h b/ext/systemc/src/sysc/qt/md/sparc.h new file mode 100644 index 000000000..edaf5325e --- /dev/null +++ b/ext/systemc/src/sysc/qt/md/sparc.h @@ -0,0 +1,140 @@ +/* + * QuickThreads -- Threads-building toolkit. + * Copyright (c) 1993 by David Keppel + * + * Permission to use, copy, modify and distribute this software and + * its documentation for any purpose and without fee is hereby + * granted, provided that the above copyright notice and this notice + * appear in all copies. This software is provided as a + * proof-of-concept and for demonstration purposes; there is no + * representation about the suitability of this software for any + * purpose. + */ + +#ifndef QUICKTHREADS_SPARC_H +#define QUICKTHREADS_SPARC_H + +typedef unsigned long qt_word_t; + +/* Stack layout on the sparc: + + non-varargs: + + +--- + | <blank space for alignment> + | %o7 == return address -> qt_start + | %i7 + | %i6 == frame pointer -> 0 (NULL-terminated stack frame chain) + | %i5 -> only + | %i4 -> userf + | %i3 + | %i2 -> pt + | %i1 -> pu + | %i0 + | %l7 + | %l6 + | %l5 + | %l4 + | %l3 + | %l2 + | %l1 + | %l0 <--- qt_t.sp + +--- + + varargs: + + | : + | : + | argument list + | one-word aggregate return pointer + +--- + | <blank space for alignment> + | %o7 == return address -> qt_vstart + | %i7 + | %i6 == frame pointer -> 0 (NULL-terminated stack frame chain) + | %i5 -> startup + | %i4 -> userf + | %i3 -> cleanup + | %i2 -> pt + | %i1 + | %i0 + | %l7 + | %l6 + | %l5 + | %l4 + | %l3 + | %l2 + | %l1 + | %l0 <--- qt_t.sp + +--- + + */ + + +/* What to do to start a thread running. */ +extern void qt_start (void); +extern void qt_vstart (void); + + +/* Hold 17 saved registers + 1 word for alignment. */ +#define QUICKTHREADS_STKBASE (18 * 4) +#define QUICKTHREADS_VSTKBASE QUICKTHREADS_STKBASE + + +/* Stack must be doubleword aligned. */ +#define QUICKTHREADS_STKALIGN (8) /* Doubleword aligned. */ + +#define QUICKTHREADS_ONLY_INDEX (QUICKTHREADS_I5) +#define QUICKTHREADS_USER_INDEX (QUICKTHREADS_I4) +#define QUICKTHREADS_ARGT_INDEX (QUICKTHREADS_I2) +#define QUICKTHREADS_ARGU_INDEX (QUICKTHREADS_I1) + +#define QUICKTHREADS_VSTARTUP_INDEX (QUICKTHREADS_I5) +#define QUICKTHREADS_VUSERF_INDEX (QUICKTHREADS_I4) +#define QUICKTHREADS_VCLEANUP_INDEX (QUICKTHREADS_I3) +#define QUICKTHREADS_VARGT_INDEX (QUICKTHREADS_I2) + +#define QUICKTHREADS_O7 (16) +#define QUICKTHREADS_I6 (14) +#define QUICKTHREADS_I5 (13) +#define QUICKTHREADS_I4 (12) +#define QUICKTHREADS_I3 (11) +#define QUICKTHREADS_I2 (10) +#define QUICKTHREADS_I1 ( 9) + + +/* The thread will ``return'' to the `qt_start' routine to get things + going. The normal return sequence takes us to QUICKTHREADS_O7+8, so we + pre-subtract 8. The frame pointer chain is 0-terminated to prevent + the trap handler from chasing off in to random memory when flushing + stack windows. */ + +#define QUICKTHREADS_ARGS_MD(top) \ + (QUICKTHREADS_SPUT ((top), QUICKTHREADS_O7, ((void *)(((int)qt_start)-8))), \ + QUICKTHREADS_SPUT ((top), QUICKTHREADS_I6, 0)) + + +/* The varargs startup routine always reads 6 words of arguments + (6 argument registers) from the stack, offset by one word to + allow for an aggregate return area pointer. If the varargs + routine actually pushed fewer words than that, qt_vstart could read + off the top of the stack. To prevent errors, we always allocate 8 + words. The space is often just wasted. */ + +#define QUICKTHREADS_VARGS_MD0(sp, vabytes) \ + ((qt_t *)(((char *)(sp)) - 8*4 - QUICKTHREADS_STKROUNDUP(vabytes))) + +#define QUICKTHREADS_VARGS_MD1(sp) \ + (QUICKTHREADS_SPUT (sp, QUICKTHREADS_O7, ((void *)(((int)qt_vstart)-8)))) + +/* The SPARC has wierdo calling conventions which stores a hidden + parameter for returning aggregate values, so the rest of the + parameters are shoved up the stack by one place. */ +#define QUICKTHREADS_VARGS_ADJUST(sp) (((char *)sp)+4) + +#define QUICKTHREADS_VARGS_DEFAULT + + +#define QUICKTHREADS_GROW_DOWN + +#endif /* ndef QUICKTHREADS_SPARC_H */ diff --git a/ext/systemc/src/sysc/qt/md/sparc.s b/ext/systemc/src/sysc/qt/md/sparc.s new file mode 100644 index 000000000..d61236b54 --- /dev/null +++ b/ext/systemc/src/sysc/qt/md/sparc.s @@ -0,0 +1,142 @@ +/* sparc.s -- assembly support for the `qt' thread building kit. */ + +/* + * QuickThreads -- Threads-building toolkit. + * Copyright (c) 1993 by David Keppel + * + * Permission to use, copy, modify and distribute this software and + * its documentation for any purpose and without fee is hereby + * granted, provided that the above copyright notice and this notice + * appear in all copies. This software is provided as a + * proof-of-concept and for demonstration purposes; there is no + * representation about the suitability of this software for any + * purpose. + */ + +/* #include <machine/trap.h> */ + + .text + .align 4 + .global _qt_blocki + .global _qt_block + .global _qt_abort + .global _qt_start + .global _qt_vstart + +/* Register assignment: +// %o0: incoming `helper' function to call after cswap +// also used as outgoing sp of old thread (qt_t *) +// %o1, %o2: +// parameters to `helper' function called after cswap +// %o3: sp of new thread +// %o5: tmp used to save old thread sp, while using %o0 +// to call `helper' f() after cswap. +// +// +// Aborting a thread is easy if there are no cached register window +// frames: just switch to the new stack and away we go. If there are +// cached register window frames they must all be written back to the +// old stack before we move to the new stack. If we fail to do the +// writeback then the old stack memory can be written with register +// window contents e.g., after the stack memory has been freed and +// reused. +// +// If you don't believe this, try setting the frame pointer to zero +// once we're on the new stack. This will not affect correctnes +// otherwise because the frame pointer will eventually get reloaded w/ +// the new thread's frame pointer. But it will be zero briefly before +// the reload. You will eventually (100,000 cswaps later on a small +// SPARC machine that I tried) get an illegal instruction trap from +// the kernel trying to flush a cached window to location 0x0. +// +// Solution: flush windows before switching stacks, which invalidates +// all the other register windows. We could do the trap +// conditionally: if we're in the lowest frame of a thread, the fp is +// zero already so we know there's nothing cached. But we expect most +// aborts will be done from a first function that does a `save', so we +// will rarely save anything and always pay the cost of testing to see +// if we should flush. +// +// All floating-point registers are caller-save, so this routine +// doesn't need to do anything to save and restore them. +// +// `qt_block' and `qt_blocki' return the same value as the value +// returned by the helper function. We get this ``for free'' +// since we don't touch the return value register between the +// return from the helper function and return from qt_block{,i}. +*/ + +_qt_block: +_qt_blocki: + sub %sp, 8, %sp /* Allocate save area for return pc. */ + st %o7, [%sp+64] /* Save return pc. */ +_qt_abort: + ta 0x03 /* Save locals and ins. */ + mov %sp, %o5 /* Remember old sp w/o chng ins/locals. */ + sub %o3, 96, %sp /* Allocate kwsa, switch stacks. */ + call %o0, 0 /* Call `helper' routine. */ + mov %o5, %o0 /* Pass old thread to qt_after_t() */ + /* .. along w/ args in %o1 & %o2. */ + + /* Restore callee-save regs. The kwsa + // is on this stack, so offset all + // loads by sizeof(kwsa), 64 bytes. + */ + ldd [%sp+ 0+96], %l0 + ldd [%sp+ 8+96], %l2 + ldd [%sp+16+96], %l4 + ldd [%sp+24+96], %l6 + ldd [%sp+32+96], %i0 + ldd [%sp+40+96], %i2 + ldd [%sp+48+96], %i4 + ldd [%sp+56+96], %i6 + ld [%sp+64+96], %o7 /* Restore return pc. */ + + retl /* Return to address in %o7. */ + add %sp, 104, %sp /* Deallocate kwsa, ret pc area. */ + + +/* The function calling conventions say there has to be a 1-word area +// in the caller's stack to hold a pointer to space for aggregate +// return values. It also says there should be a 6-word area to hold +// %o0..%o5 if the callee wants to save them (why? I don't know...) +// Round up to 8 words to maintain alignment. +// +// Parameter values were stored in callee-save regs and are moved to +// the parameter registers. +*/ +_qt_start: + mov %i1, %o0 /* `pu': Set up args to `only'. */ + mov %i2, %o1 /* `pt'. */ + mov %i4, %o2 /* `userf'. */ + call %i5, 0 /* Call client function. */ + sub %sp, 32, %sp /* Allocate 6-word callee space. */ + + call _qt_error, 0 /* `only' erroniously returned. */ + nop + + +/* Same comments as `_qt_start' about allocating rounded-up 7-word +// save areas. */ + +_qt_vstart: + sub %sp, 32, %sp /* Allocate 7-word callee space. */ + call %i5, 0 /* call `startup'. */ + mov %i2, %o0 /* .. with argument `pt'. */ + + add %sp, 32, %sp /* Use 7-word space in varargs. */ + ld [%sp+ 4+64], %o0 /* Load arg0 ... */ + ld [%sp+ 8+64], %o1 + ld [%sp+12+64], %o2 + ld [%sp+16+64], %o3 + ld [%sp+20+64], %o4 + call %i4, 0 /* Call `userf'. */ + ld [%sp+24+64], %o5 + + /* Use 6-word space in varargs. */ + mov %o0, %o1 /* Pass return value from userf */ + call %i3, 0 /* .. when call `cleanup. */ + mov %i2, %o0 /* .. along with argument `pt'. */ + + call _qt_error, 0 /* `cleanup' erroniously returned. */ + nop diff --git a/ext/systemc/src/sysc/qt/md/sparc_b.s b/ext/systemc/src/sysc/qt/md/sparc_b.s new file mode 100644 index 000000000..cd26672d7 --- /dev/null +++ b/ext/systemc/src/sysc/qt/md/sparc_b.s @@ -0,0 +1,106 @@ +/* + * QuickThreads -- Threads-building toolkit. + * Copyright (c) 1993 by David Keppel + * + * Permission to use, copy, modify and distribute this software and + * its documentation for any purpose and without fee is hereby + * granted, provided that the above copyright notice and this notice + * appear in all copies. This software is provided as a + * proof-of-concept and for demonstration purposes; there is no + * representation about the suitability of this software for any + * purpose. + */ + + .globl _b_call_reg + .globl _b_call_imm + .globl _b_add + .globl _b_load + +_b_null: + retl + nop + +_b_call_reg: + sethi %hi(_b_null),%o4 + or %o4,%lo(_b_null),%o4 + add %o7,%g0, %o3 +L0: + call %o4 + nop + call %o4 + nop + call %o4 + nop + call %o4 + nop + call %o4 + nop + + subcc %o0,1,%o0 + bg L0 + nop + add %o3,%g0, %o7 + retl + nop + +_b_call_imm: + sethi %hi(_b_null),%o4 + or %o4,%lo(_b_null),%o4 + add %o7,%g0, %o3 +L1: + call _b_null + call _b_null + call _b_null + call _b_null + call _b_null + + subcc %o0,1,%o0 + bg L0 + nop + add %o3,%g0, %o7 + retl + nop + + +_b_add: + add %o0,%g0,%o1 + add %o0,%g0,%o2 + add %o0,%g0,%o3 + add %o0,%g0,%o4 +L2: + sub %o0,5,%o0 + sub %o1,5,%o1 + sub %o2,5,%o2 + sub %o3,5,%o3 + sub %o4,5,%o4 + + subcc %o0,5,%o0 + sub %o1,5,%o1 + sub %o2,5,%o2 + sub %o3,5,%o3 + sub %o4,5,%o4 + + bg L2 + nop + retl + nop + + +_b_load: + ld [%sp+ 0], %g0 +L3: + ld [%sp+ 4],%g0 + ld [%sp+ 8],%g0 + ld [%sp+12],%g0 + ld [%sp+16],%g0 + ld [%sp+20],%g0 + ld [%sp+24],%g0 + ld [%sp+28],%g0 + ld [%sp+32],%g0 + ld [%sp+36],%g0 + + subcc %o0,10,%o0 + bg L3 + ld [%sp+ 0],%g0 + retl + nop diff --git a/ext/systemc/src/sysc/qt/md/vax.h b/ext/systemc/src/sysc/qt/md/vax.h new file mode 100644 index 000000000..1948c6fbd --- /dev/null +++ b/ext/systemc/src/sysc/qt/md/vax.h @@ -0,0 +1,130 @@ +/* + * QuickThreads -- Threads-building toolkit. + * Copyright (c) 1993 by David Keppel + * + * Permission to use, copy, modify and distribute this software and + * its documentation for any purpose and without fee is hereby + * granted, provided that the above copyright notice and this notice + * appear in all copies. This software is provided as a + * proof-of-concept and for demonstration purposes; there is no + * representation about the suitability of this software for any + * purpose. + */ + +#ifndef QUICKTHREADS_VAX_H +#define QUICKTHREADS_VAX_H + +typedef unsigned long qt_word_t; + +/* Thread's initial stack layout on the VAX: + + non-varargs: + + +--- + | arg[2] === `userf' on startup + | arg[1] === `pt' on startup + | arg[0] === `pu' on startup + | ... === `only' on startup. + +--- + | ret pc === `qt_start' on startup + | fp === 0 on startup + | ap === 0 on startup + | <mask> + | 0 (handler) <--- qt_t.sp + +--- + + When a non-varargs thread is started, it ``returns'' to the start + routine, which calls the client's `only' function. + + The varargs case is clearly bad code. The various values should be + stored in a save area and snarfed in to callee-save registers on + startup. However, it's too painful to figure out the register + mask (right now), so do it the slow way. + + +--- + | arg[n-1] + | .. + | arg[0] + | nargs + +--- + | === `cleanup' + | === `vuserf' + | === `startup' + | === `pt' + +--- + | ret pc === `qt_start' on startup + | fp === 0 on startup + | ap === 0 on startup + | <mask> + | 0 (handler) <--- qt_t.sp + +--- + + When a varargs thread is started, it ``returns'' to the `qt_vstart' + startup code. The startup code pops all the extra arguments, then + calls the appropriate functions. */ + + +/* What to do to start a thread running. */ +extern void qt_start (void); +extern void qt_vstart (void); + + +/* Initial call frame for non-varargs and varargs cases. */ +#define QUICKTHREADS_STKBASE (10 * 4) +#define QUICKTHREADS_VSTKBASE (9 * 4) + + +/* Stack "must be" 4-byte aligned. (Actually, no, but it's + easiest and probably fastest to do so.) */ + +#define QUICKTHREADS_STKALIGN (4) + + +/* Where to place various arguments. */ +#define QUICKTHREADS_ONLY_INDEX (5) +#define QUICKTHREADS_USER_INDEX (8) +#define QUICKTHREADS_ARGT_INDEX (7) +#define QUICKTHREADS_ARGU_INDEX (6) + +#define QUICKTHREADS_VSTARTUP_INDEX (6) +#define QUICKTHREADS_VUSERF_INDEX (7) +#define QUICKTHREADS_VCLEANUP_INDEX (8) +#define QUICKTHREADS_VARGT_INDEX (5) + + +/* Stack grows down. The top of the stack is the first thing to + pop off (predecrement, postincrement). */ +#define QUICKTHREADS_GROW_DOWN + + +extern void qt_error (void); + +#define QUICKTHREADS_VAX_GMASK_NOREGS (0) + +/* Push on the error return address, null termination to call chains, + number of arguments to `only', register save mask (save no + registers). */ + +#define QUICKTHREADS_ARGS_MD(sto) \ + (QUICKTHREADS_SPUT (sto, 0, 0), \ + QUICKTHREADS_SPUT (sto, 1, QUICKTHREADS_VAX_GMASK_NOREGS), \ + QUICKTHREADS_SPUT (sto, 2, 0), \ + QUICKTHREADS_SPUT (sto, 3, 0), \ + QUICKTHREADS_SPUT (sto, 4, qt_start)) + +#define QUICKTHREADS_VARGS_MD0(sto, nbytes) \ + (QUICKTHREADS_SPUT (sto, (-(nbytes)/4)-1, (nbytes)/4), \ + ((char *)(((sto)-4) - QUICKTHREADS_STKROUNDUP(nbytes)))) + +#define QUICKTHREADS_VARGS_ADJUST(sp) ((char *)sp + 4) + +#define QUICKTHREADS_VARGS_MD1(sto) \ + (QUICKTHREADS_SPUT (sto, 0, 0), \ + QUICKTHREADS_SPUT (sto, 1, QUICKTHREADS_VAX_GMASK_NOREGS), \ + QUICKTHREADS_SPUT (sto, 2, 0), \ + QUICKTHREADS_SPUT (sto, 3, 0), \ + QUICKTHREADS_SPUT (sto, 4, qt_vstart)) + +#define QUICKTHREADS_VARGS_DEFAULT + +#endif /* QUICKTHREADS_VAX_H */ diff --git a/ext/systemc/src/sysc/qt/md/vax.s b/ext/systemc/src/sysc/qt/md/vax.s new file mode 100644 index 000000000..fed03f043 --- /dev/null +++ b/ext/systemc/src/sysc/qt/md/vax.s @@ -0,0 +1,69 @@ +/* + * QuickThreads -- Threads-building toolkit. + * Copyright (c) 1993 by David Keppel + * + * Permission to use, copy, modify and distribute this software and + * its documentation for any purpose and without fee is hereby + * granted, provided that the above copyright notice and this notice + * appear in all copies. This software is provided as a + * proof-of-concept and for demonstration purposes; there is no + * representation about the suitability of this software for any + * purpose. + */ + + .text + + .globl _qt_abort + .globl _qt_block + .globl _qt_blocki + .globl _qt_start + .globl _qt_vstart + + +/* +// Calls to these routines have the signature +// +// void *block (func, arg1, arg2, newsp) +// +// Since the prologue saves 5 registers, nargs, pc, fp, ap, mask, and +// a condition handler (at sp+0), the first argument is 40=4*10 bytes +// offset from the stack pointer. +*/ +_qt_block: +_qt_blocki: +_qt_abort: + .word 0x7c0 /* Callee-save mask: 5 registers. */ + movl 56(sp),r1 /* Get stack pointer of new thread. */ + movl 52(sp),-(r1) /* Push arg2 */ + movl 48(sp),-(r1) /* Push arg1 */ + movl sp,-(r1) /* Push arg0 */ + + movl 44(sp),r0 /* Get helper to call. */ + movl r1,sp /* Move to new thread's stack. */ + addl3 sp,$12,fp /* .. including the frame pointer. */ + calls $3,(r0) /* Call helper. */ + + ret + +_qt_start: + movl (sp)+,r0 /* Get `only'. */ + calls $3,(r0) /* Call `only'. */ + calls $0,_qt_error /* `only' erroniously returned. */ + + +_qt_vstart: + movl (sp)+,r10 /* Get `pt'. */ + movl (sp)+,r9 /* Get `startup'. */ + movl (sp)+,r8 /* Get `vuserf'. */ + movl (sp)+,r7 /* Get `cleanup'. */ + + pushl r10 /* Push `qt'. */ + calls $1,(r9) /* Call `startup', pop `qt' on return. */ + + calls (sp)+,(r8) /* Call user's function. */ + + pushl r0 /* Push `vuserf_retval'. */ + pushl r10 /* Push `qt'. */ + calls $2,(r7) /* Call `cleanup', never return. */ + + calls $0,_qt_error /* `cleanup' erroniously returned. */ diff --git a/ext/systemc/src/sysc/qt/md/vax_b.s b/ext/systemc/src/sysc/qt/md/vax_b.s new file mode 100644 index 000000000..2db2d4fec --- /dev/null +++ b/ext/systemc/src/sysc/qt/md/vax_b.s @@ -0,0 +1,92 @@ +/* + * QuickThreads -- Threads-building toolkit. + * Copyright (c) 1993 by David Keppel + * + * Permission to use, copy, modify and distribute this software and + * its documentation for any purpose and without fee is hereby + * granted, provided that the above copyright notice and this notice + * appear in all copies. This software is provided as a + * proof-of-concept and for demonstration purposes; there is no + * representation about the suitability of this software for any + * purpose. + */ + + .text + .globl _b_call_reg + .globl _b_call_imm + .globl _b_add + .globl _b_load + +_b_null: + .word 0x0 + ret + +_b_call_reg: + .word 0x0 + movl 4(ap),r0 + moval _b_null,r1 +L0: + calls $0,(r1) + calls $0,(r1) + calls $0,(r1) + calls $0,(r1) + calls $0,(r1) + + subl2 $5,r0 + bgtr L0 + ret + + +_b_call_imm: + .word 0x0 + movl 4(ap),r0 +L1: + calls $0,_b_null + calls $0,_b_null + calls $0,_b_null + calls $0,_b_null + calls $0,_b_null + + subl2 $5,r0 + bgtr L1 + ret + + +_b_add: + .word 0x0 + movl 4(ap),r0 +L2: + subl2 $1,r0 + subl2 $1,r0 + subl2 $1,r0 + subl2 $1,r0 + subl2 $1,r0 + + subl2 $1,r0 + subl2 $1,r0 + subl2 $1,r0 + subl2 $1,r0 + subl2 $1,r0 + + bgtr L2 + ret + + +_b_load: + .word 0x0 + movl 4(ap),r0 +L3: + movl 0(sp),r1 + movl 4(sp),r1 + movl 8(sp),r1 + movl 12(sp),r1 + movl 16(sp),r1 + movl 20(sp),r1 + movl 24(sp),r1 + movl 28(sp),r1 + movl 32(sp),r1 + movl 36(sp),r1 + + subl2 $1,r0 + bgtr L3 + ret diff --git a/ext/systemc/src/sysc/qt/meas.c b/ext/systemc/src/sysc/qt/meas.c new file mode 100644 index 000000000..3faab3c52 --- /dev/null +++ b/ext/systemc/src/sysc/qt/meas.c @@ -0,0 +1,1049 @@ +/* meas.c -- measure qt stuff. */ + +#include "copyright.h" + +/* Need this to get assertions under Mach on the Sequent/i386: */ +#ifdef __i386__ +#define assert(ex) \ + do { \ + if (!(ex)) { \ + fprintf (stderr, "[%s:%d] Assertion " #ex " failed\n", __FILE__, __LINE__); \ + abort(); \ + } \ + } while (0) +#else +#include <assert.h> +#endif + +/* This really ought to be defined in some ANSI include file (*I* + think...), but it's defined here instead, which leads us to another + machine dependency. + + The `iaddr_t' type is an integer representation of a pointer, + suited for doing arithmetic on addresses, e.g. to round an address + to an alignment boundary. */ +typedef unsigned long iaddr_t; + +#include <stdarg.h> /* For varargs tryout. */ +#include <stdio.h> +#include "b.h" +#include "qt.h" +#include "stp.h" + +extern void exit (int status); +extern int atoi (char const *s); +extern int fprintf (FILE *out, char const *fmt, ...); +extern int fputs (char const *s, FILE *fp); +extern void free (void *sto); +extern void *malloc (unsigned nbytes); +extern void perror (char const *s); + +void usage (void); +void tracer(void); + +/* Round `v' to be `a'-aligned, assuming `a' is a power of two. */ +#define ROUND(v, a) (((v) + (a) - 1) & ~((a)-1)) + +typedef struct thread_t { + qt_t *qt; /* Pointer to thread of function... */ + void *stk; + void *top; /* Set top of stack if reuse. */ + struct thread_t *next; +} thread_t; + + + static thread_t * +t_alloc (void) +{ + thread_t *t; + int ssz = 0x1000; + + t = malloc (sizeof(thread_t)); + if (!t) { + perror ("malloc"); + exit (1); + } + assert (ssz > QT_STKBASE); + t->stk = malloc (ssz); + t->stk = (void *)ROUND (((iaddr_t)t->stk), QT_STKALIGN); + if (!t->stk) { + perror ("malloc"); + exit (1); + } + assert ((((iaddr_t)t->stk) & (QT_STKALIGN-1)) == 0); + t->top = QT_SP (t->stk, ssz - QT_STKBASE); + + return (t); +} + + + static thread_t * +t_create (qt_only_t *starter, void *p0, qt_userf_t *f) +{ + thread_t *t; + + t = t_alloc(); + t->qt = QT_ARGS (t->top, p0, t, f, starter); + return (t); +} + + + static void +t_free (thread_t *t) +{ + free (t->stk); + free (t); +} + + + static void * +t_null (qt_t *old, void *p1, void *p2) +{ + /* return (garbage); */ +} + + + static void * +t_splat (qt_t *old, void *oldp, void *null) +{ + *(qt_t **)oldp = old; + /* return (garbage); */ +} + + +static char const test01_msg[] = + "*QT_SP(sto,sz), QT_ARGS(top,p0,p1,userf,first)"; + +static char const *test01_descr[] = { + "Performs 1 QT_SP and one QT_ARGS per iteration.", + NULL +}; + +/* This test gives a guess on how long it takes to initalize + a thread. */ + + static void +test01 (int n) +{ + char stack[QT_STKBASE+QT_STKALIGN]; + char *stk; + qt_t *top; + + stk = (char *)ROUND (((iaddr_t)stack), QT_STKALIGN); + + { + int i; + + for (i=0; i<QT_STKBASE; ++i) { + stk[i] = 0; + } + } + + while (n>0) { + /* RETVALUSED */ + top = QT_SP (stk, QT_STKBASE); QT_ARGS (top, 0, 0, 0, 0); +#ifdef NDEF + top = QT_SP (stk, QT_STKBASE); QT_ARGS (top, 0, 0, 0, 0); + top = QT_SP (stk, QT_STKBASE); QT_ARGS (top, 0, 0, 0, 0); + top = QT_SP (stk, QT_STKBASE); QT_ARGS (top, 0, 0, 0, 0); + top = QT_SP (stk, QT_STKBASE); QT_ARGS (top, 0, 0, 0, 0); + + top = QT_SP (stk, QT_STKBASE); QT_ARGS (top, 0, 0, 0, 0); + top = QT_SP (stk, QT_STKBASE); QT_ARGS (top, 0, 0, 0, 0); + top = QT_SP (stk, QT_STKBASE); QT_ARGS (top, 0, 0, 0, 0); + top = QT_SP (stk, QT_STKBASE); QT_ARGS (top, 0, 0, 0, 0); + top = QT_SP (stk, QT_STKBASE); QT_ARGS (top, 0, 0, 0, 0); + + n -= 10; +#else + n -= 1; +#endif + } +} + + +static char const test02_msg[] = "QT_BLOCKI (0, 0, test02_aux, t->qt)"; +static qt_t *rootthread; + + static void +test02_aux1 (void *pu, void *pt, qt_userf_t *f) +{ + QT_ABORT (t_null, 0, 0, rootthread); +} + + static void * +test02_aux2 (qt_t *old, void *farg1, void *farg2) +{ + rootthread = old; + /* return (garbage); */ +} + + static void +test02 (int n) +{ + thread_t *t; + + while (n>0) { + t = t_create (test02_aux1, 0, 0); + QT_BLOCKI (test02_aux2, 0, 0, t->qt); + t_free (t); + t = t_create (test02_aux1, 0, 0); + QT_BLOCKI (test02_aux2, 0, 0, t->qt); + t_free (t); + t = t_create (test02_aux1, 0, 0); + QT_BLOCKI (test02_aux2, 0, 0, t->qt); + t_free (t); + t = t_create (test02_aux1, 0, 0); + QT_BLOCKI (test02_aux2, 0, 0, t->qt); + t_free (t); + t = t_create (test02_aux1, 0, 0); + QT_BLOCKI (test02_aux2, 0, 0, t->qt); + t_free (t); + + n -= 5; + } +} + + +static char const test03_msg[] = "QT_BLOCKI (...) test vals are right."; + + +/* Called by the thread function when it wants to shut down. + Return a value to the main thread. */ + + static void * +test03_aux0 (qt_t *old_is_garbage, void *farg1, void *farg2) +{ + assert (farg1 == (void *)5); + assert (farg2 == (void *)6); + return ((void *)15); /* Some unlikely value. */ +} + + +/* Called during new thread startup by main thread. Since the new + thread has never run before, return value is ignored. */ + + static void * +test03_aux1 (qt_t *old, void *farg1, void *farg2) +{ + assert (old != NULL); + assert (farg1 == (void *)5); + assert (farg2 == (void *)6); + rootthread = old; + return ((void *)16); /* Different than `15'. */ +} + + static void +test03_aux2 (void *pu, void *pt, qt_userf_t *f) +{ + assert (pu == (void *)1); + assert (f == (qt_userf_t *)4); + QT_ABORT (test03_aux0, (void *)5, (void *)6, rootthread); +} + + static void +test03 (int n) +{ + thread_t *t; + void *rv; + + while (n>0) { + t = t_create (test03_aux2, (void *)1, (qt_userf_t *)4); + rv = QT_BLOCKI (test03_aux1, (void *)5, (void *)6, t->qt); + assert (rv == (void *)15); + t_free (t); + + --n; + } +} + + +static char const test04_msg[] = "stp_start w/ no threads."; + + static void +test04 (int n) +{ + while (n>0) { + stp_init(); stp_start(); + stp_init(); stp_start(); + stp_init(); stp_start(); + stp_init(); stp_start(); + stp_init(); stp_start(); + + stp_init(); stp_start(); + stp_init(); stp_start(); + stp_init(); stp_start(); + stp_init(); stp_start(); + stp_init(); stp_start(); + + n -= 10; + } +} + + +static char const test05_msg[] = "stp w/ 2 yielding thread."; + + static void +test05_aux (void *null) +{ + stp_yield(); + stp_yield(); +} + + static void +test05 (int n) +{ + while (n>0) { + stp_init(); + stp_create (test05_aux, 0); + stp_create (test05_aux, 0); + stp_start(); + + --n; + } +} + + +static char const test06_msg[] = "*QT_ARGS(...), QT_BLOCKI one thread"; + +static char const *test06_descr[] = { + "Does a QT_ARGS, QT_BLOCKI to a helper function that saves the", + "stack pointer of the main thread, calls an `only' function that", + "saves aborts the thread, calling a null helper function.", + ":: start/stop = QT_ARGS + QT_BLOCKI + QT_ABORT + 3 procedure calls.", + NULL +}; + +/* This test initializes a thread, runs it, then returns to the main + program, which reinitializes the thread, runs it again, etc. Each + iteration corresponds to 1 init, 1 abort, 1 block. */ + +static qt_t *test06_sp; + + + static void +test06_aux2 (void *null0a, void *null1b, void *null2b, qt_userf_t *null) +{ + QT_ABORT (t_null, 0, 0, test06_sp); +} + + + static void * +test06_aux3 (qt_t *sp, void *null0c, void *null1c) +{ + test06_sp = sp; + /* return (garbage); */ +} + + + static void +test06 (int n) +{ + thread_t *t; + + t = t_create (0, 0, 0); + + while (n>0) { + /* RETVALUSED */ + QT_ARGS (t->top, 0, 0, 0, test06_aux2); + QT_BLOCKI (test06_aux3, 0, 0, t->qt); +#ifdef NDEF + /* RETVALUSED */ + QT_ARGS (t->top, 0, 0, 0, test06_aux2); + QT_BLOCKI (test06_aux3, 0, 0, t->qt); + + /* RETVALUSED */ + QT_ARGS (t->top, 0, 0, 0, test06_aux2); + QT_BLOCKI (test06_aux3, 0, 0, t->qt); + + /* RETVALUSED */ + QT_ARGS (t->top, 0, 0, 0, test06_aux2); + QT_BLOCKI (test06_aux3, 0, 0, t->qt); + + /* RETVALUSED */ + QT_ARGS (t->top, 0, 0, 0, test06_aux2); + QT_BLOCKI (test06_aux3, 0, 0, t->qt); + + n -= 5; +#else + --n; +#endif + } +} + +static char test07_msg[] = "*cswap between threads"; + +static char const *test07_descr[] = { + "Build a chain of threads where each thread has a fixed successor.", + "There is no scheduling performed. Each thread but one is a loop", + "that simply blocks with QT_BLOCKI, calling a helper that saves the", + "current stack pointer. The last thread decrements a count, and,", + "if zero, aborts back to the main thread. Else it continues with", + "the blocking chain. The count is divided by the number of threads", + "in the chain, so `n' is the number of integer block operations.", + ":: integer cswap = QT_BLOCKI + a procedure call.", + NULL +}; + +/* This test repeatedly blocks a bunch of threads. + Each iteration corresponds to one block operation. + + The threads are arranged so that there are TEST07_N-1 of them that + run `test07_aux2'. Each one of those blocks saving it's sp to + storage owned by the preceding thread; a pointer to that storage is + passed in via `mep'. Each thread has a handle on it's own storage + for the next thread, referenced by `nxtp', and it blocks by passing + control to `*nxtp', telling the helper function to save its state + in `*mep'. The last thread in the chain decrements a count and, if + it's gone below zero, returns to `test07'; otherwise, it invokes + the first thread in the chain. */ + +static qt_t *test07_heavy; + +#define TEST07_N (4) + + + static void +test07_aux2 (void *null0, void *mep, void *nxtp, qt_userf_t *null) +{ + qt_t *nxt; + + while (1) { + nxt = *(qt_t **)nxtp; +#ifdef NDEF + printf ("Helper 0x%p\n", nxtp); +#endif + QT_BLOCKI (t_splat, mep, 0, nxt); + } +} + + static void +test07_aux3 (void *np, void *mep, void *nxtp, qt_userf_t *null) +{ + int n; + + n = *(int *)np; + while (1) { + n -= TEST07_N; + if (n<0) { + QT_ABORT (t_splat, mep, 0, test07_heavy); + } + QT_BLOCKI (t_splat, mep, 0, *(qt_t **)nxtp); + } +} + + + static void +test07 (int n) +{ + int i; + thread_t *t[TEST07_N]; + + for (i=0; i<TEST07_N; ++i) { + t[i] = t_create (0, 0, 0); + } + for (i=0; i<TEST07_N-1; ++i) { + /* RETVALUSED */ + QT_ARGS (t[i]->top, 0, &t[i]->qt, &t[i+1]->qt, test07_aux2); + } + /* RETVALUSED */ + QT_ARGS (t[i]->top, &n, &t[TEST07_N-1]->qt, &t[0]->qt, test07_aux3); + QT_BLOCKI (t_splat, &test07_heavy, 0, t[0]->qt); +} + + +static char test08_msg[] = "Floating-point cswap between threads"; + +static char const *test08_descr[] = { + "Measure context switch times including floating-point, use QT_BLOCK.", + NULL +}; + +static qt_t *test08_heavy; + +#define TEST08_N (4) + + + static void +test08_aux2 (void *null0, void *mep, void *nxtp, qt_userf_t *null) +{ + qt_t *nxt; + + while (1) { + nxt = *(qt_t **)nxtp; + QT_BLOCK (t_splat, mep, 0, nxt); + } +} + + static void +test08_aux3 (void *np, void *mep, void *nxtp, qt_userf_t *null) +{ + int n; + + n = *(int *)np; + while (1) { + n -= TEST08_N; + if (n<0) { + QT_ABORT (t_splat, mep, 0, test08_heavy); + } + QT_BLOCK (t_splat, mep, 0, *(qt_t **)nxtp); + } +} + + + static void +test08 (int n) +{ + int i; + thread_t *t[TEST08_N]; + + for (i=0; i<TEST08_N; ++i) { + t[i] = t_create (0, 0, 0); + } + for (i=0; i<TEST08_N-1; ++i) { + /* RETVALUSED */ + QT_ARGS (t[i]->top, 0, &t[i]->qt, &t[i+1]->qt, test08_aux2); + } + /* RETVALUSED */ + QT_ARGS (t[i]->top, &n, &t[TEST08_N-1]->qt, &t[0]->qt, test08_aux3); + QT_BLOCK (t_splat, &test08_heavy, 0, t[0]->qt); +} + + +/* Test the varargs procedure calling. */ + +char const test09_msg[] = { "Start and run threads using varargs." }; + +thread_t *test09_t0, *test09_t1, *test09_t2, *test09_main; + + thread_t * +test09_create (qt_startup_t *start, qt_vuserf_t *f, + qt_cleanup_t *cleanup, int nbytes, ...) +{ + va_list ap; + thread_t *t; + + t = t_alloc(); + va_start (ap, nbytes); + t->qt = QT_VARGS (t->top, nbytes, ap, t, start, f, cleanup); + va_end (ap); + return (t); +} + + + static void +test09_cleanup (void *pt, void *vuserf_retval) +{ + assert (vuserf_retval == (void *)17); + QT_ABORT (t_splat, &((thread_t *)pt)->qt, 0, + ((thread_t *)pt)->next->qt); +} + + + static void +test09_start (void *pt) +{ +} + + + static void * +test09_user0 (void) +{ + QT_BLOCKI (t_splat, &test09_t0->qt, 0, test09_t1->qt); + return ((void *)17); +} + + static void * +test09_user2 (int one, int two) +{ + assert (one == 1); + assert (two == 2); + QT_BLOCKI (t_splat, &test09_t1->qt, 0, test09_t2->qt); + assert (one == 1); + assert (two == 2); + return ((void *)17); +} + + static void * +test09_user10 (int one, int two, int three, int four, int five, + int six, int seven, int eight, int nine, int ten) +{ + assert (one == 1); + assert (two == 2); + assert (three == 3); + assert (four == 4); + assert (five == 5); + assert (six == 6); + assert (seven == 7); + assert (eight == 8); + assert (nine == 9); + assert (ten == 10); + QT_BLOCKI (t_splat, &test09_t2->qt, 0, test09_main->qt); + assert (one == 1); + assert (two == 2); + assert (three == 3); + assert (four == 4); + assert (five == 5); + assert (six == 6); + assert (seven == 7); + assert (eight == 8); + assert (nine == 9); + assert (ten == 10); + return ((void *)17); +} + + + void +test09 (int n) +{ + thread_t main; + + test09_main = &main; + + while (--n >= 0) { + test09_t0 = test09_create (test09_start, (qt_vuserf_t*)test09_user0, + test09_cleanup, 0); + test09_t1 = test09_create (test09_start, (qt_vuserf_t*)test09_user2, + test09_cleanup, 2 * sizeof(qt_word_t), 1, 2); + test09_t2 = test09_create (test09_start, (qt_vuserf_t*)test09_user10, + test09_cleanup, 10 * sizeof(qt_word_t), + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10); + + /* Chaining used by `test09_cleanup' to determine who is next. */ + test09_t0->next = test09_t1; + test09_t1->next = test09_t2; + test09_t2->next = test09_main; + + QT_BLOCKI (t_splat, &test09_main->qt, 0, test09_t0->qt); + QT_BLOCKI (t_splat, &test09_main->qt, 0, test09_t0->qt); + + t_free (test09_t0); + t_free (test09_t1); + t_free (test09_t2); + } +} + + +/* Test 10/11/12: time the cost of various number of args. */ + +char const test10_msg[] = { "*Test varargs init & startup w/ 0 args." }; + +char const *test10_descr[] = { + "Start and stop threads that use variant argument lists (varargs).", + "Each thread is initialized by calling a routine that calls", + "QT_VARARGS. Then runs the thread by calling QT_BLOCKI to hald the", + "main thread, a helper that saves the main thread's stack pointer,", + "a null startup function, a null user function, a cleanup function", + "that calls QT_ABORT and restarts the main thread. Copies no user", + "parameters.", + ":: varargs start/stop = QT_BLOCKI + QT_ABORT + 6 function calls.", + NULL +}; + +/* Helper function to send control back to main. + Don't save anything. */ + + +/* Helper function for starting the varargs thread. Save the stack + pointer of the main thread so we can get back there eventually. */ + + +/* Startup function for a varargs thread. */ + + static void +test10_startup (void *pt) +{ +} + + +/* User function for a varargs thread. */ + + static void * +test10_run (int arg0, ...) +{ + /* return (garbage); */ +} + + +/* Cleanup function for a varargs thread. Send control + back to the main thread. Don't save any state from the thread that + is halting. */ + + void +test10_cleanup (void *pt, void *vuserf_retval) +{ + QT_ABORT (t_null, 0, 0, ((thread_t *)pt)->qt); +} + + + void +test10_init (thread_t *new, thread_t *next, int nbytes, ...) +{ + va_list ap; + + va_start (ap, nbytes); + new->qt = QT_VARGS (new->top, nbytes, ap, next, test10_startup, + test10_run, test10_cleanup); + va_end (ap); +} + + + void +test10 (int n) +{ + thread_t main; + thread_t *t; + + t = t_alloc(); + t->next = &main; + + while (--n >= 0) { + test10_init (t, &main, 0); + QT_BLOCKI (t_splat, &main.qt, 0, t->qt); + } + t_free (t); +} + + +char const test11_msg[] = { "*Test varargs init & startup w/ 2 args." }; + +char const *test11_descr[] = { + "Varargs initialization/run. Copies 2 user arguments.", + ":: varargs 2 start/stop = QT_VARGS(2 args), QT_BLOCKI, QT_ABORT, 6 f() calls.", + NULL +}; + + + void +test11 (int n) +{ + thread_t main; + thread_t *t; + + t = t_alloc(); + t->next = &main; + + while (--n >= 0) { + test10_init (t, &main, 2 * sizeof(int), 2, 1); + QT_BLOCKI (t_splat, &main.qt, 0, t->qt); + } + t_free (t); +} + +char const test12_msg[] = { "*Test varargs init & startup w/ 4 args." }; + +char const *test12_descr[] = { + "Varargs initialization/run. Copies 4 user arguments.", + ":: varargs 4 start/stop = QT_VARGS(4 args), QT_BLOCKI, QT_ABORT, 6 f() calls.", + NULL +}; + + + void +test12 (int n) +{ + thread_t main; + thread_t *t; + + t = t_alloc(); + t->next = &main; + + while (--n >= 0) { + test10_init (t, &main, 4 * sizeof(int), 4, 3, 2, 1); + QT_BLOCKI (t_splat, &main.qt, 0, t->qt); + } + t_free (t); +} + + +char const test13_msg[] = { "*Test varargs init & startup w/ 8 args." }; + +char const *test13_descr[] = { + "Varargs initialization/run. Copies 8 user arguments.", + ":: varargs 8 start/stop = QT_VARGS(8 args), QT_BLOCKI, QT_ABORT, 6 f() calls.", + NULL +}; + + void +test13 (int n) +{ + thread_t main; + thread_t *t; + + t = t_alloc(); + t->next = &main; + + while (--n >= 0) { + test10_init (t, &main, 8 * sizeof(int), 8, 7, 6, 5, 4, 3, 2, 1); + QT_BLOCKI (t_splat, &main.qt, 0, t->qt); + } + t_free (t); +} + + +char const test14_msg[] = { "*Test varargs initialization w/ 0 args." }; + +char const *test14_descr[] = { + "Varargs initialization without running the thread. Just calls", + "QT_VARGS.", + ":: varargs 0 init = QT_VARGS()", + NULL +}; + + void +test14 (int n) +{ + thread_t main; + thread_t *t; + + t = t_alloc(); + t->next = &main; + + while (--n >= 0) { + test10_init (t, &main, 0 * sizeof(int)); + } + t_free (t); +} + + +char const test15_msg[] = { "*Test varargs initialization w/ 2 args." }; + +char const *test15_descr[] = { + "Varargs initialization without running the thread. Just calls", + "QT_VARGS.", + ":: varargs 2 init = QT_VARGS(2 args)", + NULL +}; + + void +test15 (int n) +{ + thread_t main; + thread_t *t; + + t = t_alloc(); + t->next = &main; + + while (--n >= 0) { + test10_init (t, &main, 2 * sizeof(int), 2, 1); + } + t_free (t); +} + +char const test16_msg[] = { "*Test varargs initialization w/ 4 args." }; + +char const *test16_descr[] = { + "Varargs initialization without running the thread. Just calls", + "QT_VARGS.", + ":: varargs 4 init = QT_VARGS(4 args)", + NULL +}; + + + void +test16 (int n) +{ + thread_t main; + thread_t *t; + + t = t_alloc(); + t->next = &main; + + while (--n >= 0) { + test10_init (t, &main, 4 * sizeof(int), 4, 3, 2, 1); + } + t_free (t); +} + + +char const test17_msg[] = { "*Test varargs initialization w/ 8 args." }; + +char const *test17_descr[] = { + "Varargs initialization without running the thread. Just calls", + "QT_VARGS.", + ":: varargs 8 init = QT_VARGS(8 args)", + NULL +}; + + + void +test17 (int n) +{ + thread_t main; + thread_t *t; + + t = t_alloc(); + t->next = &main; + + while (--n >= 0) { + test10_init (t, &main, 8 * sizeof(int), 8, 7, 6, 5, 4, 3, 2, 1); + } + t_free (t); +} + +/* Test times for basic machine operations. */ + +char const test18_msg[] = { "*Call register indirect." }; +char const *test18_descr[] = { NULL }; + + void +test18 (int n) +{ + b_call_reg (n); +} + + +char const test19_msg[] = { "*Call immediate." }; +char const *test19_descr[] = { NULL }; + + void +test19 (int n) +{ + b_call_imm (n); +} + + +char const test20_msg[] = { "*Add register-to-register." }; +char const *test20_descr[] = { NULL }; + + void +test20 (int n) +{ + b_add (n); +} + + +char const test21_msg[] = { "*Load memory to a register." }; +char const *test21_descr[] = { NULL }; + + void +test21 (int n) +{ + b_load (n); +} + +/* Driver. */ + +typedef struct foo_t { + char const *msg; /* Message to print for generic help. */ + char const **descr; /* A description of what is done by the test. */ + void (*f)(int n); +} foo_t; + + +static foo_t foo[] = { + { "Usage:\n", NULL, (void(*)(int n))usage }, + { test01_msg, test01_descr, test01 }, + { test02_msg, NULL, test02 }, + { test03_msg, NULL, test03 }, + { test04_msg, NULL, test04 }, + { test05_msg, NULL, test05 }, + { test06_msg, test06_descr, test06 }, + { test07_msg, test07_descr, test07 }, + { test08_msg, test08_descr, test08 }, + { test09_msg, NULL, test09 }, + { test10_msg, test10_descr, test10 }, + { test11_msg, test11_descr, test11 }, + { test12_msg, test12_descr, test12 }, + { test13_msg, test13_descr, test13 }, + { test14_msg, test14_descr, test14 }, + { test15_msg, test15_descr, test15 }, + { test16_msg, test16_descr, test16 }, + { test17_msg, test17_descr, test17 }, + { test18_msg, test18_descr, test18 }, + { test19_msg, test19_descr, test19 }, + { test20_msg, test20_descr, test20 }, + { test21_msg, test21_descr, test21 }, + { 0, 0 } +}; + +static int tv = 0; + + void +tracer () +{ + + fprintf (stderr, "tracer\t%d\n", tv++); + fflush (stderr); +} + + void +tracer2 (void *val) +{ + fprintf (stderr, "tracer2\t%d val=0x%p", tv++, val); + fflush (stderr); +} + + + void +describe() +{ + int i; + FILE *out = stdout; + + for (i=0; foo[i].msg; ++i) { + if (foo[i].descr) { + int j; + + putc ('\n', out); + fprintf (out, "[%d]\n", i); + for (j=0; foo[i].descr[j]; ++j) { + fputs (foo[i].descr[j], out); + putc ('\n', out); + } + } + } + exit (0); +} + + + void +usage() +{ + int i; + + fputs (foo[0].msg, stderr); + for (i=1; foo[i].msg; ++i) { + fprintf (stderr, "%2d\t%s\n", i, foo[i].msg); + } + exit (1); +} + + + void +args (int *which, int *n, int argc, char **argv) +{ + static int nfuncs = 0; + + if (argc == 2 && argv[1][0] == '-' && argv[1][1] == 'h') { + describe(); + } + + if (nfuncs == 0) { + for (nfuncs=0; foo[nfuncs].msg; ++nfuncs) + ; + } + + if (argc != 2 && argc != 3) { + usage(); + } + + *which = atoi (argv[1]); + if (*which < 0 || *which >= nfuncs) { + usage(); + } + *n = (argc == 3) + ? atoi (argv[2]) + : 1; +} + + + int +main (int argc, char **argv) +{ + int which, n; + args (&which, &n, argc, argv); + (*(foo[which].f))(n); + exit (0); + return (0); +} diff --git a/ext/systemc/src/sysc/qt/qt.c b/ext/systemc/src/sysc/qt/qt.c new file mode 100644 index 000000000..204d38397 --- /dev/null +++ b/ext/systemc/src/sysc/qt/qt.c @@ -0,0 +1,56 @@ +#include "copyright.h" +#include "qt.h" + +// static void *qt_sp_bottom_save; + +#ifdef QT_VARGS_DEFAULT + +/* If the stack grows down, `vargs' is a pointer to the lowest + address in the block of arguments. If the stack grows up, it is a + pointer to the highest address in the block. */ + + qt_t * +qt_vargs (qt_t *sp, int nbytes, void *vargs, + void *pt, qt_startup_t *startup, + qt_vuserf_t *vuserf, qt_cleanup_t *cleanup) +{ + int i; + + sp = QT_VARGS_MD0 (sp, nbytes); +#ifdef QT_GROW_UP + for (i=nbytes/sizeof(qt_word_t); i>0; --i) { + QT_SPUT (QT_VARGS_ADJUST(sp), i, ((qt_word_t *)vargs)[-i]); + } +#else + for (i=nbytes/sizeof(qt_word_t); i>0; --i) { + QT_SPUT (QT_VARGS_ADJUST(sp), i-1, ((qt_word_t *)vargs)[i-1]); + } +#endif + + QT_VARGS_MD1 (QT_VADJ(sp)); + QT_SPUT (QT_VADJ(sp), QT_VARGT_INDEX, pt); + QT_SPUT (QT_VADJ(sp), QT_VSTARTUP_INDEX, startup); + QT_SPUT (QT_VADJ(sp), QT_VUSERF_INDEX, vuserf); + QT_SPUT (QT_VADJ(sp), QT_VCLEANUP_INDEX, cleanup); + return ((qt_t *)QT_VADJ(sp)); +} +#endif /* def QT_VARGS_DEFAULT */ + +#ifdef __cplusplus +extern "C" +#endif + void +qt_null (void) +{ +} + +#ifdef __cplusplus +extern "C" +#endif + void +qt_error (void) +{ + extern void abort(void); + + abort(); +} diff --git a/ext/systemc/src/sysc/qt/qt.h b/ext/systemc/src/sysc/qt/qt.h new file mode 100644 index 000000000..40a9f531b --- /dev/null +++ b/ext/systemc/src/sysc/qt/qt.h @@ -0,0 +1,192 @@ +/* + * QuickThreads -- Threads-building toolkit. + * Copyright (c) 1993 by David Keppel + * + * Permission to use, copy, modify and distribute this software and + * its documentation for any purpose and without fee is hereby + * granted, provided that the above copyright notice and this notice + * appear in all copies. This software is provided as a + * proof-of-concept and for demonstration purposes; there is no + * representation about the suitability of this software for any + * purpose. + */ + +#ifndef QUICKTHREADS_QT_H +#define QUICKTHREADS_QT_H + +#if !defined(SC_USE_PTHREADS) + +#ifdef __cplusplus +extern "C" { +#endif + +#include <sysc/qt/qtmd.h> + + +/* A QuickThreads thread is represented by it's current stack pointer. + To restart a thread, you merely need pass the current sp (qt_t*) to + a QuickThreads primitive. `qt_t*' is a location on the stack. To + improve type checking, represent it by a particular struct. */ + +typedef struct qt_t { + char dummy; +} qt_t; + + +/* Alignment is guaranteed to be a power of two. */ +#ifndef QUICKTHREADS_STKALIGN + #error "Need to know the machine-dependent stack alignment." +#endif + +#define QUICKTHREADS_STKROUNDUP(bytes) \ + (((bytes)+QUICKTHREADS_STKALIGN) & ~(QUICKTHREADS_STKALIGN-1)) + + +/* Find ``top'' of the stack, space on the stack. */ +#ifndef QUICKTHREADS_SP +#ifdef QUICKTHREADS_GROW_DOWN +#define QUICKTHREADS_SP(sto, size) ((qt_t *)(&((char *)(sto))[(size)])) +#endif +#ifdef QUICKTHREADS_GROW_UP +#define QUICKTHREADS_SP(sto, size) ((qt_t *)(sto)) +#endif +#if !defined(QUICKTHREADS_SP) + #error "QUICKTHREADS_QT_H: Stack must grow up or down!" +#endif +#endif + + +/* The type of the user function: + For non-varargs, takes one void* function. + For varargs, takes some number of arguments. */ +typedef void *(qt_userf_t)(void *pu); +typedef void *(qt_vuserf_t)(int arg0, ...); + +/* For non-varargs, just call a client-supplied function, + it does all startup and cleanup, and also calls the user's + function. */ +typedef void (qt_only_t)(void *pu, void *pt, qt_userf_t *userf); + +/* For varargs, call `startup', then call the user's function, + then call `cleanup'. */ +typedef void (qt_startup_t)(void *pt); +typedef void (qt_cleanup_t)(void *pt, void *vuserf_return); + + +/* Internal helper for putting stuff on stack. */ +#ifndef QUICKTHREADS_SPUT +#define QUICKTHREADS_SPUT(top, at, val) \ + (((qt_word_t *)(top))[(at)] = (qt_word_t)(val)) +#endif + + +/* Push arguments for the non-varargs case. */ +#ifndef QUICKTHREADS_ARGS + +#ifndef QUICKTHREADS_ARGS_MD +#define QUICKTHREADS_ARGS_MD (0) +#endif + +#ifndef QUICKTHREADS_STKBASE + #error "Need to know the machine-dependent stack allocation." +#endif + +/* All things are put on the stack relative to the final value of + the stack pointer. */ +#ifdef QUICKTHREADS_GROW_DOWN +#define QUICKTHREADS_ADJ(sp) (((char *)sp) - QUICKTHREADS_STKBASE) +#else +#define QUICKTHREADS_ADJ(sp) (((char *)sp) + QUICKTHREADS_STKBASE) +#endif + +#define QUICKTHREADS_ARGS(sp, pu, pt, userf, only) \ + (QUICKTHREADS_ARGS_MD (QUICKTHREADS_ADJ(sp)), \ + QUICKTHREADS_SPUT (QUICKTHREADS_ADJ(sp), QUICKTHREADS_ONLY_INDEX, only), \ + QUICKTHREADS_SPUT (QUICKTHREADS_ADJ(sp), QUICKTHREADS_USER_INDEX, userf), \ + QUICKTHREADS_SPUT (QUICKTHREADS_ADJ(sp), QUICKTHREADS_ARGT_INDEX, pt), \ + QUICKTHREADS_SPUT (QUICKTHREADS_ADJ(sp), QUICKTHREADS_ARGU_INDEX, pu), \ + ((qt_t *)QUICKTHREADS_ADJ(sp))) + +#endif + + +/* Push arguments for the varargs case. + Has to be a function call because initialization is an expression + and we need to loop to copy nbytes of stuff on to the stack. + But that's probably OK, it's not terribly cheap, anyway. */ + +#ifdef QUICKTHREADS_VARGS_DEFAULT +#ifndef QUICKTHREADS_VARGS_MD0 +#define QUICKTHREADS_VARGS_MD0(sp, vasize) (sp) +#endif +#ifndef QUICKTHREADS_VARGS_MD1 +#define QUICKTHREADS_VARGS_MD1(sp) do { ; } while (0) +#endif + +#ifndef QUICKTHREADS_VSTKBASE + #error "Need base stack size for varargs functions." +#endif + +/* Sometimes the stack pointer needs to munged a bit when storing + the list of arguments. */ +#ifndef QUICKTHREADS_VARGS_ADJUST +#define QUICKTHREADS_VARGS_ADJUST(sp) (sp) +#endif + +/* All things are put on the stack relative to the final value of + the stack pointer. */ +#ifdef QUICKTHREADS_GROW_DOWN +#define QUICKTHREADS_VADJ(sp) (((char *)sp) - QUICKTHREADS_VSTKBASE) +#else +#define QUICKTHREADS_VADJ(sp) (((char *)sp) + QUICKTHREADS_VSTKBASE) +#endif + +extern qt_t *qt_vargs (qt_t *sp, int nbytes, void *vargs, + void *pt, qt_startup_t *startup, + qt_vuserf_t *vuserf, qt_cleanup_t *cleanup); + +#ifndef QUICKTHREADS_VARGS +#define QUICKTHREADS_VARGS(sp, nbytes, vargs, pt, startup, vuserf, cleanup) \ + (qt_vargs (sp, nbytes, vargs, pt, startup, vuserf, cleanup)) +#endif + +#endif + + +/* Save the state of the thread and call the helper function + using the stack of the new thread. */ +typedef void *(qt_helper_t)(qt_t *old, void *a0, void *a1); +typedef void *(qt_block_t)(qt_helper_t *helper, void *a0, void *a1, + qt_t *newthread); + +/* Rearrange the parameters so that things passed to the helper + function are already in the right argument registers. */ +#ifndef QUICKTHREADS_ABORT +extern void *qt_abort (qt_helper_t *h, void *a0, void *a1, qt_t *newthread); +/* The following does, technically, `return' a value, but the + user had better not rely on it, since the function never + returns. */ +#define QUICKTHREADS_ABORT(h, a0, a1, newthread) \ + do { qt_abort (h, a0, a1, newthread); } while (0) +#endif + +#ifndef QUICKTHREADS_BLOCK +extern void *qt_block (qt_helper_t *h, void *a0, void *a1, + qt_t *newthread); +#define QUICKTHREADS_BLOCK(h, a0, a1, newthread) \ + (qt_block (h, a0, a1, newthread)) +#endif + +#ifndef QUICKTHREADS_BLOCKI +extern void *qt_blocki (qt_helper_t *h, void *a0, void *a1, + qt_t *newthread); +#define QUICKTHREADS_BLOCKI(h, a0, a1, newthread) \ + (qt_blocki (h, a0, a1, newthread)) +#endif + +#ifdef __cplusplus +} /* Match `extern "C" {' at top. */ +#endif + +#endif // !defined(SC_USE_PTHREADS) +#endif /* ndef QUICKTHREADS_H */ diff --git a/ext/systemc/src/sysc/qt/qtmd.h b/ext/systemc/src/sysc/qt/qtmd.h new file mode 100644 index 000000000..f33203815 --- /dev/null +++ b/ext/systemc/src/sysc/qt/qtmd.h @@ -0,0 +1,13 @@ +#if defined( __sparc ) || defined( __sparc__ ) +#include "sysc/qt/md/sparc.h" +#elif defined( __hppa ) +#include "sysc/qt/md/hppa.h" +#elif defined( __x86_64__ ) +#include "sysc/qt/md/iX86_64.h" +#elif defined( __i386 ) +#include "sysc/qt/md/i386.h" +#elif defined( __ppc__ ) +#include "sysc/qt/md/powerpc_mach.h" +#elif defined( __powerpc ) +#include "sysc/qt/md/powerpc_sys5.h" +#endif diff --git a/ext/systemc/src/sysc/qt/stp.c b/ext/systemc/src/sysc/qt/stp.c new file mode 100644 index 000000000..bfacc893b --- /dev/null +++ b/ext/systemc/src/sysc/qt/stp.c @@ -0,0 +1,199 @@ +#include "copyright.h" +#include "qt.h" +#include "stp.h" + +#ifndef NULL +#define NULL 0 +#endif + +#define STP_STKSIZE (0x1000) + +/* `alignment' must be a power of 2. */ +#define STP_STKALIGN(sp, alignment) \ + ((void *)((((qt_word_t)(sp)) + (alignment) - 1) & ~((alignment)-1))) + + +/* The notion of a thread is merged with the notion of a queue. + Thread stuff: thread status (sp) and stuff to use during + (re)initialization. Queue stuff: next thread in the queue + (next). */ + +struct stp_t { + qt_t *sp; /* QuickThreads handle. */ + void *sto; /* `malloc'-allocated stack. */ + struct stp_t *next; /* Next thread in the queue. */ +}; + + +/* A queue is a circular list of threads. The queue head is a + designated list element. If this is a uniprocessor-only + implementation we can store the `main' thread in this, but in a + multiprocessor there are several `heavy' threads but only one run + queue. A fancier implementation might have private run queues, + which would lead to a simpler (trivial) implementation */ + +typedef struct stp_q_t { + stp_t t; + stp_t *tail; +} stp_q_t; + + +/* Helper functions. */ + +extern void *malloc (unsigned size); +extern void perror (char const *msg); +extern void free (void *sto); + + void * +xmalloc (unsigned size) +{ + void *sto; + + sto = malloc (size); + if (!sto) { + perror ("malloc"); + exit (1); + } + return (sto); +} + +/* Queue access functions. */ + + static void +stp_qinit (stp_q_t *q) +{ + q->t.next = q->tail = &q->t; +} + + + static stp_t * +stp_qget (stp_q_t *q) +{ + stp_t *t; + + t = q->t.next; + q->t.next = t->next; + if (t->next == &q->t) { + if (t == &q->t) { /* If it was already empty .. */ + return (NULL); /* .. say so. */ + } + q->tail = &q->t; /* Else now it is empty. */ + } + return (t); +} + + + static void +stp_qput (stp_q_t *q, stp_t *t) +{ + q->tail->next = t; + t->next = &q->t; + q->tail = t; +} + + +/* Thread routines. */ + +static stp_q_t stp_global_runq; /* A queue of runable threads. */ +static stp_t stp_global_main; /* Thread for the process. */ +static stp_t *stp_global_curr; /* Currently-executing thread. */ + +static void *stp_starthelp (qt_t *old, void *ignore0, void *ignore1); +static void stp_only (void *pu, void *pt, qt_userf_t *f); +static void *stp_aborthelp (qt_t *sp, void *old, void *null); +static void *stp_yieldhelp (qt_t *sp, void *old, void *blockq); + + + void +stp_init() +{ + stp_qinit (&stp_global_runq); +} + + + void +stp_start() +{ + stp_t *next; + + while ((next = stp_qget (&stp_global_runq)) != NULL) { + stp_global_curr = next; + QT_BLOCK (stp_starthelp, 0, 0, next->sp); + } +} + + + static void * +stp_starthelp (qt_t *old, void *ignore0, void *ignore1) +{ + stp_global_main.sp = old; + stp_qput (&stp_global_runq, &stp_global_main); + /* return (garbage); */ +} + + + void +stp_create (stp_userf_t *f, void *pu) +{ + stp_t *t; + void *sto; + + t = xmalloc (sizeof(stp_t)); + t->sto = xmalloc (STP_STKSIZE); + sto = STP_STKALIGN (t->sto, QT_STKALIGN); + t->sp = QT_SP (sto, STP_STKSIZE - QT_STKALIGN); + t->sp = QT_ARGS (t->sp, pu, t, (qt_userf_t *)f, stp_only); + stp_qput (&stp_global_runq, t); +} + + + static void +stp_only (void *pu, void *pt, qt_userf_t *f) +{ + stp_global_curr = (stp_t *)pt; + (*(stp_userf_t *)f)(pu); + stp_abort(); + /* NOTREACHED */ +} + + + void +stp_abort (void) +{ + stp_t *old, *newthread; + + newthread = stp_qget (&stp_global_runq); + old = stp_global_curr; + stp_global_curr = newthread; + QT_ABORT (stp_aborthelp, old, (void *)NULL, newthread->sp); +} + + + static void * +stp_aborthelp (qt_t *sp, void *old, void *null) +{ + free (((stp_t *)old)->sto); + free (old); + /* return (garbage); */ +} + + + void +stp_yield() +{ + stp_t *old, *newthread; + + newthread = stp_qget (&stp_global_runq); + old = stp_global_curr; + stp_global_curr = newthread; + QT_BLOCK (stp_yieldhelp, old, &stp_global_runq, newthread->sp); +} + + + static void * +stp_yieldhelp (qt_t *sp, void *old, void *blockq) +{ + ((stp_t *)old)->sp = sp; + stp_qput ((stp_q_t *)blockq, (stp_t *)old); + /* return (garbage); */ +} diff --git a/ext/systemc/src/sysc/qt/stp.h b/ext/systemc/src/sysc/qt/stp.h new file mode 100644 index 000000000..1220e47e2 --- /dev/null +++ b/ext/systemc/src/sysc/qt/stp.h @@ -0,0 +1,51 @@ +#ifndef STP_H +#define STP_H + +/* + * QuickThreads -- Threads-building toolkit. + * Copyright (c) 1993 by David Keppel + * + * Permission to use, copy, modify and distribute this software and + * its documentation for any purpose and without fee is hereby + * granted, provided that the above copyright notice and this notice + * appear in all copies. This software is provided as a + * proof-of-concept and for demonstration purposes; there is no + * representation about the suitability of this software for any + * purpose. + */ + +typedef struct stp_t stp_t; + +/* Each thread starts by calling a user-supplied function of this + type. */ + +typedef void (stp_userf_t)(void *p0); + +/* Call this before any other primitives. */ +extern void stp_init(); + +/* When one or more threads are created by the main thread, + the system goes multithread when this is called. It is done + (no more runable threads) when this returns. */ + +extern void stp_start (void); + +/* Create a thread and make it runable. When the thread starts + running it will call `f' with arguments `p0' and `p1'. */ + +extern void stp_create (stp_userf_t *f, void *p0); + +/* The current thread stops running but stays runable. + It is an error to call `stp_yield' before `stp_start' + is called or after `stp_start' returns. */ + +extern void stp_yield (void); + +/* Like `stp_yield' but the thread is discarded. Any intermediate + state is lost. The thread can also terminate by simply + returning. */ + +extern void stp_abort (void); + + +#endif /* ndef STP_H */ diff --git a/ext/systemc/src/sysc/qt/time/README.time b/ext/systemc/src/sysc/qt/time/README.time new file mode 100644 index 000000000..4bb190e18 --- /dev/null +++ b/ext/systemc/src/sysc/qt/time/README.time @@ -0,0 +1,17 @@ +The program `raw', when run in `..' runs the program `run' produced +from `meas.c'. It produces a raw output file (see `../tmp/*.raw'). +`raw' will die with an error if run in the current directory. Note +that some versions of `time' produce output in an unexpected format; +edit them by hand. + +`prim', `init', `cswap' and `go' produce formatted table entries used +in the documentation (in `../doc'). For example, from `..', + + foreach i (tmp/*.raw) + time/prim $i + end + +See notes in the QuickThreads document about the applicability of +these microbenchmark measurements -- in general, you can expect all +QuickThreads operations to be a bit slower when used in a real +application. diff --git a/ext/systemc/src/sysc/qt/time/assim b/ext/systemc/src/sysc/qt/time/assim new file mode 100755 index 000000000..6c4c52183 --- /dev/null +++ b/ext/systemc/src/sysc/qt/time/assim @@ -0,0 +1,42 @@ +#! /bin/awk -f + +BEGIN { + nmach = 0; + + init_test = "1"; + abort_test = "6"; + blocki_test = "7"; + block_test = "8"; +} + +{ + mach = $1 + test = $2 + iter = $3 + time = $6 + $8 + + if (machi[mach] == 0) { + machn[nmach] = mach; + machi[mach] = 1; + ++nmach; + } + + us_per_op = time / iter * 1000000 + times[mach "_" test] = us_per_op; +} + + +END { + for (i=0; i<nmach; ++i) { + m = machn[i]; + init = times[m "_" init_test]; + printf ("init %s | %f\n", m, init); + + init_abort_blocki = times[m "_" abort_test]; + abort_blocki = init_abort_blocki - init; + blocki = times[m "_" blocki_test]; + abort = abort_blocki - blocki; + blockf = times[m "_" block_test]; + printf ("swap %s | %f | %f | %f\n", m, abort, blocki, blockf); + } +} diff --git a/ext/systemc/src/sysc/qt/time/cswap b/ext/systemc/src/sysc/qt/time/cswap new file mode 100755 index 000000000..0ec811bcd --- /dev/null +++ b/ext/systemc/src/sysc/qt/time/cswap @@ -0,0 +1,37 @@ +#! /bin/awk -f + +BEGIN { + purpose = "report time used by int only and int+fp cswaps"; + + nmach = 0; + + test_int = "7"; + test_fp = "8"; +} + +{ + mach = $1 + test = $2 + iter = $3 + time = $6 + $8 + + if (machi[mach] == 0) { + machn[nmach] = mach; + machi[mach] = 1; + ++nmach; + } + + us_per_op = time / iter * 1000000 + times[mach "_" test] = us_per_op; +} + + +END { + for (i=0; i<nmach; ++i) { + m = machn[i]; + + integer = times[m "_" test_int]; + fp = times[m "_" test_fp]; + printf ("%s|%3.1f|%3.1f\n", m, integer, fp); + } +} diff --git a/ext/systemc/src/sysc/qt/time/go b/ext/systemc/src/sysc/qt/time/go new file mode 100755 index 000000000..489d53882 --- /dev/null +++ b/ext/systemc/src/sysc/qt/time/go @@ -0,0 +1,43 @@ +#! /bin/awk -f + +BEGIN { + purpose = "report times used for init/start/stop"; + + nmach = 0; + + test_single = "6"; + test_v0 = "10"; + test_v2 = "11"; + test_v4 = "12"; + test_v8 = "13"; +} + +{ + mach = $1 + test = $2 + iter = $3 + time = $6 + $8 + + if (machi[mach] == 0) { + machn[nmach] = mach; + machi[mach] = 1; + ++nmach; + } + + us_per_op = time / iter * 1000000 + times[mach "_" test] = us_per_op; +} + + +END { + for (i=0; i<nmach; ++i) { + m = machn[i]; + + single = times[m "_" test_single]; + v0 = times[m "_" test_v0]; + v2 = times[m "_" test_v2]; + v4 = times[m "_" test_v4]; + v8 = times[m "_" test_v8]; + printf ("%s|%3.1f|%3.1f|%3.1f|%3.1f|%3.1f\n", m, single, v0, v2, v4, v8); + } +} diff --git a/ext/systemc/src/sysc/qt/time/init b/ext/systemc/src/sysc/qt/time/init new file mode 100755 index 000000000..8bcbf3428 --- /dev/null +++ b/ext/systemc/src/sysc/qt/time/init @@ -0,0 +1,42 @@ +#! /bin/awk -f + +BEGIN { + purpose = "Report time used to initialize a thread." + nmach = 0; + + test_single = "1"; + test_v0 = "14"; + test_v2 = "15"; + test_v4 = "16"; + test_v8 = "17"; +} + +{ + mach = $1 + test = $2 + iter = $3 + time = $6 + $8 + + if (machi[mach] == 0) { + machn[nmach] = mach; + machi[mach] = 1; + ++nmach; + } + + us_per_op = time / iter * 1000000 + times[mach "_" test] = us_per_op; +} + + +END { + for (i=0; i<nmach; ++i) { + m = machn[i]; + + single = times[m "_" test_single]; + v0 = times[m "_" test_v0]; + v2 = times[m "_" test_v2]; + v4 = times[m "_" test_v4]; + v8 = times[m "_" test_v8]; + printf ("%s|%3.1f|%3.1f|%3.1f|%3.1f|%3.1f\n", m, single, v0, v2, v4, v8); + } +} diff --git a/ext/systemc/src/sysc/qt/time/prim b/ext/systemc/src/sysc/qt/time/prim new file mode 100755 index 000000000..22b323f6f --- /dev/null +++ b/ext/systemc/src/sysc/qt/time/prim @@ -0,0 +1,41 @@ +#! /bin/awk -f + +BEGIN { + purpose = "report times for microbenchmarks" + + nmach = 0; + + test_callind = "18"; + test_callimm = "18"; + test_addreg = "20"; + test_loadreg = "21"; +} + +{ + mach = $1 + test = $2 + iter = $3 + time = $6 + $8 + + if (machi[mach] == 0) { + machn[nmach] = mach; + machi[mach] = 1; + ++nmach; + } + + ns_per_op = time / iter * 1000000 + times[mach "_" test] = ns_per_op; +} + + +END { + for (i=0; i<nmach; ++i) { + m = machn[i]; + + ind = times[m "_" test_callind]; + imm = times[m "_" test_callimm]; + add = times[m "_" test_addreg]; + load = times[m "_" test_loadreg]; + printf ("%s|%1.3f|%1.3f|%1.3f|%1.3f\n", m, ind, imm, add, load); + } +} diff --git a/ext/systemc/src/sysc/qt/time/raw b/ext/systemc/src/sysc/qt/time/raw new file mode 100755 index 000000000..96ae10ad1 --- /dev/null +++ b/ext/systemc/src/sysc/qt/time/raw @@ -0,0 +1,58 @@ +#! /bin/csh + +rm -f timed + +set init=1 +set runone=6 +set blockint=7 +set blockfloat=8 +set vainit0=14 +set vainit2=15 +set vainit4=16 +set vainit8=17 +set vastart0=10 +set vastart2=11 +set vastart4=12 +set vastart8=13 +set bench_regcall=18 +set bench_immcall=19 +set bench_add=20 +set bench_load=21 + +source configuration + +echo -n $config_machine $init $config_init +/bin/time run $init $config_init +echo -n $config_machine $runone $config_runone +/bin/time run $runone $config_runone +echo -n $config_machine $blockint $config_blockint +/bin/time run $blockint $config_blockint +echo -n $config_machine $blockfloat $config_blockfloat +/bin/time run $blockfloat $config_blockfloat + +echo -n $config_machine $vainit0 $config_vainit0 +/bin/time run $vainit0 $config_vainit0 +echo -n $config_machine $vainit2 $config_vainit2 +/bin/time run $vainit2 $config_vainit2 +echo -n $config_machine $vainit4 $config_vainit4 +/bin/time run $vainit4 $config_vainit4 +echo -n $config_machine $vainit8 $config_vainit8 +/bin/time run $vainit8 $config_vainit8 + +echo -n $config_machine $vastart0 $config_vastart0 +/bin/time run $vastart0 $config_vastart0 +echo -n $config_machine $vastart2 $config_vastart2 +/bin/time run $vastart2 $config_vastart2 +echo -n $config_machine $vastart4 $config_vastart4 +/bin/time run $vastart4 $config_vastart4 +echo -n $config_machine $vastart8 $config_vastart8 +/bin/time run $vastart8 $config_vastart8 + +echo -n $config_machine $bench_regcall $config_bcall_reg +/bin/time run $bench_regcall $config_bcall_reg +echo -n $config_machine $bench_immcall $config_bcall_imm +/bin/time run $bench_immcall $config_bcall_imm +echo -n $config_machine $bench_add $config_b_add +/bin/time run $bench_add $config_b_add +echo -n $config_machine $bench_load $config_b_load +/bin/time run $bench_load $config_b_load diff --git a/ext/systemc/src/sysc/systemc.pc.in b/ext/systemc/src/sysc/systemc.pc.in new file mode 100644 index 000000000..63d2e3cb7 --- /dev/null +++ b/ext/systemc/src/sysc/systemc.pc.in @@ -0,0 +1,41 @@ +# Licensed to Accellera Systems Initiative Inc. (Accellera) under one or +# more contributor license agreements. See the NOTICE file distributed +# with this work for additional information regarding copyright ownership. +# Accellera licenses this file to you under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. See the License for the specific language governing +# permissions and limitations under the License. +# +# ------------------------------------------------------------------------- +# +# systemc.pc.in -- +# pkg-config definition file (template) for SystemC +# (http://www.freedesktop.org/wiki/Software/pkg-config/) +# +# Author: Philipp A. Hartmann, OFFIS, 2013-05-07 +# +# Note: The "real" definition (systemc.pc) is generated by "configure" +# during the build configuration. +# +# ------------------------------------------------------------------------- +# +TARGET_ARCH=@TARGET_ARCH@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libarchdir=@libdir@@LIB_ARCH_SUFFIX@ +includedir=@includedir@ + +Name: @PACKAGE_NAME@ +Description: Accellera @PACKAGE_NAME@ proof-of-concept library +Version: @PACKAGE_VERSION@ +URL: @PACKAGE_URL@ +Libs: -L${libarchdir} -l@PACKAGE@ +Libs.private: @PKGCONFIG_LDPRIV@ +Cflags: @PKGCONFIG_CFLAGS@ @PKGCONFIG_DEFINES@ -I${includedir} diff --git a/ext/systemc/src/sysc/tracing/sc_trace.cpp b/ext/systemc/src/sysc/tracing/sc_trace.cpp new file mode 100644 index 000000000..09a2fa3b2 --- /dev/null +++ b/ext/systemc/src/sysc/tracing/sc_trace.cpp @@ -0,0 +1,217 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_trace.cpp - Functions for tracing signals and variables. + + Original Author: Abhijit Ghosh, Synopsys, Inc. + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + +/***************************************************************************** + + Acknowledgement: The tracing mechanism is based on the tracing + mechanism developed at Infineon (formerly Siemens HL). Though this + code is somewhat different, the basics are identical to what was + originally contributed by Infineon. The contribution of Infineon + in the development of this tracing technology is hereby + acknowledged. + + *****************************************************************************/ + +#include <stdarg.h> +#include <stdio.h> + +#include "sysc/tracing/sc_trace.h" +#include "sysc/tracing/sc_tracing_ids.h" +#include "sysc/communication/sc_signal_ifs.h" +#include "sysc/utils/sc_report.h" +#include "sysc/utils/sc_utils_ids.h" + +namespace sc_core { + +// Trace file common functions. + +sc_trace_file::sc_trace_file() +{ + /* Intentionally blank */ +} + +void tprintf(sc_trace_file* tf, const char* format, ...) +{ + static char buffer[4096]; + va_list ap; + va_start(ap, format); + (void) vsprintf(buffer, format, ap); + va_end(ap); + if (tf) tf->write_comment(buffer); +} + +void sc_trace_file::space(int) +{ + /* Intentionally blank */ +} + +void sc_trace_file::delta_cycles(bool) +{ + /* Intentionally blank */ +} + + +void +sc_trace( sc_trace_file* tf, + const sc_signal_in_if<char>& object, + const std::string& name, + int width ) +{ + if( tf ) { + tf->trace( object.read(), name, width ); + } +} + +void +sc_trace( sc_trace_file* tf, + const sc_signal_in_if<short>& object, + const std::string& name, + int width ) +{ + if( tf ) { + tf->trace( object.read(), name, width ); + } +} + +void +sc_trace( sc_trace_file* tf, + const sc_signal_in_if<int>& object, + const std::string& name, + int width ) +{ + if( tf ) { + tf->trace( object.read(), name, width ); + } +} + +void +sc_trace( sc_trace_file* tf, + const sc_signal_in_if<long>& object, + const std::string& name, + int width ) +{ + if( tf ) { + tf->trace( object.read(), name, width ); + } +} + + +void +sc_trace(sc_trace_file* /* not used */, + const void* /* not used */, + const std::string& name) +{ + SC_REPORT_WARNING( SC_ID_TRACING_OBJECT_IGNORED_, name.c_str() ); +} + + + +void double_to_special_int64(double in, unsigned* high, unsigned* low) +{ + double invar = in; + if(invar > 5e17) invar = 5e17; // Saturation limit + if(invar < 0.0) invar = 0.0; + invar += .5; + *high = (unsigned)(invar / 1e9); + double rest = invar - 1e9 * (*high); + if(rest < 0) *low = 0; + else *low = (unsigned)rest; +} + + +// ---------------------------------------------------------------------------- + +#define DEFN_TRACE_FUNC_REF_A(tp) \ +void \ +sc_trace( sc_trace_file* tf, const tp& object, const std::string& name ) \ +{ \ + if( tf ) { \ + tf->trace( object, name ); \ + } \ +} + +#define DEFN_TRACE_FUNC_PTR_A(tp) \ +void \ +sc_trace( sc_trace_file* tf, const tp* object, const std::string& name ) \ +{ \ + if( tf ) { \ + tf->trace( *object, name ); \ + } \ +} + +#define DEFN_TRACE_FUNC_A(tp) \ +DEFN_TRACE_FUNC_REF_A(tp) \ +DEFN_TRACE_FUNC_PTR_A(tp) + + +DEFN_TRACE_FUNC_A( sc_dt::sc_bit ) +DEFN_TRACE_FUNC_A( sc_dt::sc_logic ) + +DEFN_TRACE_FUNC_A( sc_dt::sc_int_base ) +DEFN_TRACE_FUNC_A( sc_dt::sc_uint_base ) +DEFN_TRACE_FUNC_A( sc_dt::sc_signed ) +DEFN_TRACE_FUNC_A( sc_dt::sc_unsigned ) + +DEFN_TRACE_FUNC_REF_A( sc_dt::sc_bv_base ) +DEFN_TRACE_FUNC_REF_A( sc_dt::sc_lv_base ) + + +#undef DEFN_TRACE_FUNC_REF_A +#undef DEFN_TRACE_FUNC_PTR_A +#undef DEFN_TRACE_FUNC_A + + +void +sc_trace( sc_trace_file* tf, + const unsigned int& object, + const std::string& name, + const char** enum_literals ) +{ + static bool warn_sc_trace_literals=true; + if ( warn_sc_trace_literals ) + { + warn_sc_trace_literals=false; + SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, + "tracing of enumerated literals is deprecated" ); + } + + if( tf ) tf->trace( object, name, enum_literals ); +} + +} // namespace sc_core + +// Taf! diff --git a/ext/systemc/src/sysc/tracing/sc_trace.h b/ext/systemc/src/sysc/tracing/sc_trace.h new file mode 100644 index 000000000..256e430a7 --- /dev/null +++ b/ext/systemc/src/sysc/tracing/sc_trace.h @@ -0,0 +1,397 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_trace.h - Functions for tracing signals and variables. + + Author: Abhijit Ghosh, Synopsys, Inc. + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + +/***************************************************************************** + + Acknowledgement: The tracing mechanism is based on the tracing + mechanism developed at Infineon (formerly Siemens HL). Though this + code is somewhat different, the basics are identical to what was + originally contributed by Infineon. The contribution of Infineon + in the development of this tracing technology is hereby + acknowledged. + + *****************************************************************************/ + +#ifndef SC_TRACE_H +#define SC_TRACE_H + +#include <cstdio> + +#include "sysc/datatypes/int/sc_nbdefs.h" +#include "sysc/kernel/sc_time.h" + +// Some forward declarations +namespace sc_dt +{ + class sc_bit; + class sc_logic; + class sc_bv_base; + class sc_lv_base; + class sc_signed; + class sc_unsigned; + class sc_int_base; + class sc_uint_base; + class sc_fxval; + class sc_fxval_fast; + class sc_fxnum; + class sc_fxnum_fast; +} + +namespace sc_core { + +class sc_time; + +template <class T> class sc_signal_in_if; + + +// Base class for all kinds of trace files. + +class sc_trace_file +{ + friend class sc_simcontext; + +public: + + // Constructor + sc_trace_file(); + + // All functions are pure virtual because they need to be defined by the + // particular tracing mechanism + + +#define DECL_TRACE_METHOD_A(tp) \ + virtual void trace( const tp& object, \ + const std::string& name ) = 0; + +#define DECL_TRACE_METHOD_B(tp) \ + virtual void trace( const tp& object, \ + const std::string& name, \ + int width ) = 0; + + + DECL_TRACE_METHOD_A( bool ) + DECL_TRACE_METHOD_A( sc_dt::sc_bit ) + DECL_TRACE_METHOD_A( sc_dt::sc_logic ) + + DECL_TRACE_METHOD_B( unsigned char ) + DECL_TRACE_METHOD_B( unsigned short ) + DECL_TRACE_METHOD_B( unsigned int ) + DECL_TRACE_METHOD_B( unsigned long ) + DECL_TRACE_METHOD_B( char ) + DECL_TRACE_METHOD_B( short ) + DECL_TRACE_METHOD_B( int ) + DECL_TRACE_METHOD_B( long ) + DECL_TRACE_METHOD_B( sc_dt::int64 ) + DECL_TRACE_METHOD_B( sc_dt::uint64 ) + + DECL_TRACE_METHOD_A( float ) + DECL_TRACE_METHOD_A( double ) + DECL_TRACE_METHOD_A( sc_dt::sc_int_base ) + DECL_TRACE_METHOD_A( sc_dt::sc_uint_base ) + DECL_TRACE_METHOD_A( sc_dt::sc_signed ) + DECL_TRACE_METHOD_A( sc_dt::sc_unsigned ) + + DECL_TRACE_METHOD_A( sc_dt::sc_fxval ) + DECL_TRACE_METHOD_A( sc_dt::sc_fxval_fast ) + DECL_TRACE_METHOD_A( sc_dt::sc_fxnum ) + DECL_TRACE_METHOD_A( sc_dt::sc_fxnum_fast ) + + DECL_TRACE_METHOD_A( sc_dt::sc_bv_base ) + DECL_TRACE_METHOD_A( sc_dt::sc_lv_base ) + + +#undef DECL_TRACE_METHOD_A +#undef DECL_TRACE_METHOD_B + + // Trace an enumerated object - where possible output the enumeration + // literals in the trace file. Enum literals is a null terminated array + // of null terminated char* literal strings. + virtual void trace( const unsigned int& object, + const std::string& name, + const char** enum_literals ) = 0; + + // Output a comment to the trace file + virtual void write_comment( const std::string& comment ) = 0; + + // Set the amount of space before next column + // (For most formats this does nothing) + virtual void space( int n ); + + // Also trace transitions between delta cycles if flag is true. + virtual void delta_cycles( bool flag ); + + // Set time unit. + virtual void set_time_unit( double v, sc_time_unit tu )=0; + +protected: + + // Write trace info for cycle + virtual void cycle( bool delta_cycle ) = 0; + + // Flush results and close file + virtual ~sc_trace_file() + { /* Intentionally blank */ } +}; + +/*****************************************************************************/ + +// Now comes all the SystemC defined tracing functions. +// We define two sc_trace() versions for scalar types; one where the object to +// be traced is passed as a reference and the other where a pointer to the +// tracing object is passed. + +#define DECL_TRACE_FUNC_REF_A(tp) \ +void \ +sc_trace( sc_trace_file* tf, \ + const tp& object, \ + const std::string& name ); + +#define DECL_TRACE_FUNC_PTR_A(tp) \ +void \ +sc_trace( sc_trace_file* tf, \ + const tp* object, \ + const std::string& name ); \ + +#define DECL_TRACE_FUNC_A(tp) \ +DECL_TRACE_FUNC_REF_A(tp) \ +DECL_TRACE_FUNC_PTR_A(tp) + + +DECL_TRACE_FUNC_A( sc_dt::sc_bit ) +DECL_TRACE_FUNC_A( sc_dt::sc_logic ) + +DECL_TRACE_FUNC_A( sc_dt::sc_int_base ) +DECL_TRACE_FUNC_A( sc_dt::sc_uint_base ) +DECL_TRACE_FUNC_A( sc_dt::sc_signed ) +DECL_TRACE_FUNC_A( sc_dt::sc_unsigned ) + +DECL_TRACE_FUNC_REF_A( sc_dt::sc_bv_base ) +DECL_TRACE_FUNC_REF_A( sc_dt::sc_lv_base ) + + +#undef DECL_TRACE_FUNC_REF_A +#undef DECL_TRACE_FUNC_PTR_A +#undef DECL_TRACE_FUNC_A + + +// ---------------------------------------------------------------------------- + +#define DEFN_TRACE_FUNC_REF_A(tp) \ +inline \ +void \ +sc_trace( sc_trace_file* tf, const tp& object, const std::string& name ) \ +{ \ + if( tf ) { \ + tf->trace( object, name ); \ + } \ +} + +#define DEFN_TRACE_FUNC_PTR_A(tp) \ +inline \ +void \ +sc_trace( sc_trace_file* tf, const tp* object, const std::string& name ) \ +{ \ + if( tf ) { \ + tf->trace( *object, name ); \ + } \ +} + +#define DEFN_TRACE_FUNC_A(tp) \ +DEFN_TRACE_FUNC_REF_A(tp) \ +DEFN_TRACE_FUNC_PTR_A(tp) + + +#define DEFN_TRACE_FUNC_REF_B(tp) \ +inline \ +void \ +sc_trace( sc_trace_file* tf, const tp& object, const std::string& name, \ + int width = 8 * sizeof( tp ) ) \ +{ \ + if( tf ) { \ + tf->trace( object, name, width ); \ + } \ +} + +#define DEFN_TRACE_FUNC_PTR_B(tp) \ +inline \ +void \ +sc_trace( sc_trace_file* tf, const tp* object, const std::string& name, \ + int width = 8 * sizeof( tp ) ) \ +{ \ + if( tf ) { \ + tf->trace( *object, name, width ); \ + } \ +} + + +#define DEFN_TRACE_FUNC_B(tp) \ +DEFN_TRACE_FUNC_REF_B(tp) \ +DEFN_TRACE_FUNC_PTR_B(tp) + + +DEFN_TRACE_FUNC_A( bool ) +DEFN_TRACE_FUNC_A( float ) +DEFN_TRACE_FUNC_A( double ) + +DEFN_TRACE_FUNC_B( unsigned char ) +DEFN_TRACE_FUNC_B( unsigned short ) +DEFN_TRACE_FUNC_B( unsigned int ) +DEFN_TRACE_FUNC_B( unsigned long ) +DEFN_TRACE_FUNC_B( char ) +DEFN_TRACE_FUNC_B( short ) +DEFN_TRACE_FUNC_B( int ) +DEFN_TRACE_FUNC_B( long ) +DEFN_TRACE_FUNC_B( sc_dt::int64 ) +DEFN_TRACE_FUNC_B( sc_dt::uint64 ) + + +#undef DEFN_TRACE_FUNC_REF_A +#undef DEFN_TRACE_FUNC_PTR_A +#undef DEFN_TRACE_FUNC_A + +#undef DEFN_TRACE_FUNC_REF_B +#undef DEFN_TRACE_FUNC_PTR_B +#undef DEFN_TRACE_FUNC_B + + +template <class T> +inline +void +sc_trace( sc_trace_file* tf, + const sc_signal_in_if<T>& object, + const std::string& name ) +{ + sc_trace( tf, object.read(), name ); +} + +template< class T > +inline +void +sc_trace( sc_trace_file* tf, + const sc_signal_in_if<T>& object, + const char* name ) +{ + sc_trace( tf, object.read(), name ); +} + + +// specializations for signals of type char, short, int, long + +void sc_trace( sc_trace_file* tf, + const sc_signal_in_if<char>& object, + const std::string& name, + int width ); + +void sc_trace( sc_trace_file* tf, + const sc_signal_in_if<short>& object, + const std::string& name, + int width ); + +void sc_trace( sc_trace_file* tf, + const sc_signal_in_if<int>& object, + const std::string& name, + int width ); + +void sc_trace( sc_trace_file* tf, + const sc_signal_in_if<long>& object, + const std::string& name, + int width ); + + +// 1. non-template function is better than template +// 2. more-specialized template is better than less-specialized +// 3. no partial specialization for template functions + + +// Trace an enumerated object - where possible output the enumeration literals +// in the trace file. Enum literals is a null terminated array of null +// terminated char* literal strings. + +void +sc_trace( sc_trace_file* tf, + const unsigned int& object, + const std::string& name, + const char** enum_literals ); + + +// Dummy function for arbitrary types of value, does nothing + +extern void sc_trace( sc_trace_file* tf, + const void* object, + const std::string& name ); + + +// Turn on/off delta cycle tracing on trace file `tf'. +// Default is to turn on delta cycle tracing. + +inline +void +sc_trace_delta_cycles( sc_trace_file* tf, bool on = true ) +{ + if( tf ) tf->delta_cycles( on ); +} + + +// Output a comment to the trace file + +inline +void +sc_write_comment( sc_trace_file* tf, const std::string& comment ) +{ + if( tf ) tf->write_comment( comment ); +} + + +// Equivalent of std::fprintf for trace files! + +void tprintf( sc_trace_file* tf, const char* format, ... ); + +// ---------------------------------------------------------------------------- +// Create VCD file +extern sc_trace_file *sc_create_vcd_trace_file(const char* name); +extern void sc_close_vcd_trace_file( sc_trace_file* tf ); + + +// ---------------------------------------------------------------------------- +// Create WIF file +extern sc_trace_file *sc_create_wif_trace_file(const char *name); +extern void sc_close_wif_trace_file( sc_trace_file* tf ); + +} // namespace sc_core + +#endif // SC_TRACE_H +// Taf diff --git a/ext/systemc/src/sysc/tracing/sc_trace_file_base.cpp b/ext/systemc/src/sysc/tracing/sc_trace_file_base.cpp new file mode 100644 index 000000000..4f4345468 --- /dev/null +++ b/ext/systemc/src/sysc/tracing/sc_trace_file_base.cpp @@ -0,0 +1,273 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_trace_file_base.cpp - Shared internal tracing implementation + + Original Author: Philipp A. Hartmann, OFFIS, 2013-11-15 + + CHANGE LOG AT END OF FILE + *****************************************************************************/ + +/***************************************************************************** + + Acknowledgement: The tracing mechanism is based on the tracing + mechanism developed at Infineon (formerly Siemens HL). Though this + code is somewhat different, and significantly enhanced, the basics + are identical to what was originally contributed by Infineon. The + contribution of Infineon in the development of this tracing + technology is hereby acknowledged. + + *****************************************************************************/ + +#include <ctime> + +#include "sysc/tracing/sc_trace_file_base.h" +#include "sysc/kernel/sc_simcontext.h" +#include "sysc/kernel/sc_simcontext_int.h" + +#if SC_TRACING_PHASE_CALLBACKS_ +# include "sysc/kernel/sc_object_int.h" +#endif + +namespace sc_core { + +bool sc_trace_file_base::tracing_initialized_ = false; + + +sc_trace_file_base::sc_trace_file_base( const char* name, const char* extension ) + : sc_trace_file() +#if SC_TRACING_PHASE_CALLBACKS_ + , sc_object( sc_gen_unique_name("$$$$kernel_tracefile$$$$") ) +#endif + , fp(0) + , timescale_unit() + , timescale_set_by_user(false) + , filename_() + , initialized_(false) + , trace_delta_cycles_(false) +{ + if( !name || !*name ) { + SC_REPORT_ERROR( SC_ID_TRACING_FOPEN_FAILED_, "no name given" ); + return; + } else { + std::stringstream ss; + ss << name << "." << extension; + ss.str().swap( filename_ ); + } + +#if SC_TRACING_PHASE_CALLBACKS_ == 1 + // remove from hierarchy + sc_object::detach(); + // register regular (non-delta) callbacks + sc_object::register_simulation_phase_callback( + // Note: Usually, one would expect to dump the initial values + // of the traced variables at the end of the initialization + // phase. The "non-callback" implementation dumps those + // values only after the first delta cycle, though. + // SC_END_OF_INITIALIZATION | + SC_BEFORE_TIMESTEP | + SC_PAUSED | SC_STOPPED + ); +#else // explicitly register with simcontext + sc_get_curr_simcontext()->add_trace_file( this ); +#endif +} + +sc_trace_file_base::~sc_trace_file_base() +{ + if( fp ) + fclose(fp); + +#if SC_TRACING_PHASE_CALLBACKS_ == 0 + // unregister from simcontext + sc_get_curr_simcontext()->remove_trace_file( this ); +#endif +} + +/*****************************************************************************/ +// simulation phase callback based trigger +// +// The tracing updates are triggered +// (- at the end of the initialization phase [disabled for now]) +// - before an update of the simulation time +// - before returning to sc_start (via sc_pause() or sc_stop()) +// - after an update phase (if delta cycles need to be traced) +// +#if SC_TRACING_PHASE_CALLBACKS_ +void +sc_trace_file_base::simulation_phase_callback() +{ + // delta cycle is traced at the end of an update phase + cycle( simcontext()->get_status() == SC_END_OF_UPDATE ); +} +#endif // SC_TRACING_PHASE_CALLBACKS_ + +/*****************************************************************************/ + +bool +sc_trace_file_base::initialize() +{ + if( initialized_ ) + return false; + + initialized_ = true; + + if( !tracing_initialized_ ) { + tracing_initialized_ = true; + bool running_regression = ( getenv( "SYSTEMC_REGRESSION" ) != NULL ); + + // hide some messages during regression + if( running_regression ) { + sc_report_handler::set_actions( SC_ID_TRACING_TIMESCALE_DEFAULT_ + , SC_INFO, SC_DO_NOTHING ); + sc_report_handler::set_actions( SC_ID_TRACING_VCD_DUPLICATE_TIME_ + , SC_WARNING, SC_DO_NOTHING ); + } + } + + // open trace file + if(!fp) open_fp(); + + // setup timescale + if( !timescale_set_by_user ) + { + timescale_unit = sc_get_time_resolution().to_seconds(); + + std::stringstream ss; + ss << sc_get_time_resolution() << " (" << filename_ << ")"; + SC_REPORT_INFO( SC_ID_TRACING_TIMESCALE_DEFAULT_ + , ss.str().c_str() ); + } + + // initialize derived tracing implementation class (VCD/WIF) + do_initialize(); + + return initialized_; +} + +void +sc_trace_file_base::open_fp() +{ + sc_assert( !fp ); + fp = fopen( filename(), "w" ); + if( !fp ) { + SC_REPORT_ERROR( SC_ID_TRACING_FOPEN_FAILED_, filename() ); + std::terminate(); // can't recover from here + } +} + +void +sc_trace_file_base::delta_cycles( bool flag ) +{ + trace_delta_cycles_ = flag; +#if SC_TRACING_PHASE_CALLBACKS_ + if( trace_delta_cycles_ ) { + sc_object::register_simulation_phase_callback( SC_END_OF_UPDATE ); + } else { + sc_object::unregister_simulation_phase_callback( SC_END_OF_UPDATE ); + } +#endif +} + +void +sc_trace_file_base::set_time_unit( double v, sc_time_unit tu ) +{ + if( initialized_ ) + { + std::stringstream ss; + ss << filename_ << "\n" + "\tTimescale unit cannot be changed once tracing has begun.\n" + "\tTo change the scale, create a new trace file."; + SC_REPORT_ERROR( SC_ID_TRACING_ALREADY_INITIALIZED_ + , ss.str().c_str() ); + return; + } + + switch ( tu ) + { + case SC_FS: v = v * 1e-15; break; + case SC_PS: v = v * 1e-12; break; + case SC_NS: v = v * 1e-9; break; + case SC_US: v = v * 1e-6; break; + case SC_MS: v = v * 1e-3; break; + case SC_SEC: break; + default: { + std::stringstream ss; + ss << "unknown time unit:" << tu + << " (" << filename_ << ")"; + SC_REPORT_WARNING( SC_ID_TRACING_TIMESCALE_UNIT_ + , ss.str().c_str() ); + } + } + + timescale_set_by_user = true; + timescale_unit = v; + + // EMIT ADVISORY MESSAGE ABOUT CHANGE IN TIME SCALE: + { + std::stringstream ss; + ss << sc_time( timescale_unit, SC_SEC ) + << " (" << filename_ << ")"; + SC_REPORT_INFO( SC_ID_TRACING_TIMESCALE_UNIT_, ss.str().c_str() ); + } +} + +bool +sc_trace_file_base::add_trace_check( const std::string & name ) const +{ + if( !initialized_ ) return true; + + std::stringstream ss; + ss << "sc_trace() failed:\n" + "\tNo traces can be added to " + "'" << filename_ << "'" + " once trace recording has started.\n" + "\tTo add tracing of '" << name << "', create a new trace file."; + + SC_REPORT_ERROR( SC_ID_TRACING_ALREADY_INITIALIZED_ + , ss.str().c_str() ); + return false; +} + +// obtain formatted time string +std::string localtime_string() +{ + char buf[200]; + time_t long_time; + time(&long_time); + struct tm* p_tm = localtime(&long_time); + strftime(buf, 199, "%b %d, %Y %H:%M:%S", p_tm); + return buf; +} + + +} // namespace sc_core + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ +// Taf! diff --git a/ext/systemc/src/sysc/tracing/sc_trace_file_base.h b/ext/systemc/src/sysc/tracing/sc_trace_file_base.h new file mode 100644 index 000000000..c0217266f --- /dev/null +++ b/ext/systemc/src/sysc/tracing/sc_trace_file_base.h @@ -0,0 +1,140 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_trace_file_base.h - Shared internal tracing implementation + + Original Author: Philipp A. Hartmann, OFFIS, 2013-11-15 + + CHANGE LOG AT END OF FILE + *****************************************************************************/ + +/***************************************************************************** + + Acknowledgement: The tracing mechanism is based on the tracing + mechanism developed at Infineon (formerly Siemens HL). Though this + code is somewhat different, and significantly enhanced, the basics + are identical to what was originally contributed by Infineon. The + contribution of Infineon in the development of this tracing + technology is hereby acknowledged. + + *****************************************************************************/ + +#ifndef SC_TRACE_FILE_BASE_H_INCLUDED_ +#define SC_TRACE_FILE_BASE_H_INCLUDED_ + +#include <cstdio> + +// use callback-based tracing implementation +#if defined( SC_ENABLE_SIMULATION_PHASE_CALLBACKS_TRACING ) +# define SC_TRACING_PHASE_CALLBACKS_ 1 +# include "sysc/kernel/sc_object.h" +#else +# define SC_TRACING_PHASE_CALLBACKS_ 0 +#endif + +#include "sysc/tracing/sc_trace.h" +#include "sysc/tracing/sc_tracing_ids.h" + +namespace sc_core { + +// shared implementation of trace files +class sc_trace_file_base + : public sc_trace_file +#if SC_TRACING_PHASE_CALLBACKS_ + , private sc_object // to be used as callback target +#endif +{ +public: + const char* filename() const + { return filename_.c_str(); } + + bool delta_cycles() const + { return trace_delta_cycles_; } + + // Also trace transitions between delta cycles if flag is true. + virtual void delta_cycles(bool flag); + + // set a user-define timescale unit for the trace file + virtual void set_time_unit( double v, sc_time_unit tu); + +protected: + sc_trace_file_base( const char* name, const char* extension ); + + // returns true, iff initialization has been performed + bool initialize(); + // ensure that file has been opened (needed for early write_comment()) + void open_fp(); + // perform format specific initialization + virtual void do_initialize() = 0; + + // returns true, if new trace objects can still be added + // (i.e. trace file is not yet initialized) + bool add_trace_check( const std::string& name ) const; + + // Flush results and close file. + virtual ~sc_trace_file_base(); + +#if SC_TRACING_PHASE_CALLBACKS_ +private: + virtual void simulation_phase_callback(); +#endif // SC_TRACING_PHASE_CALLBACKS_ + +protected: + FILE* fp; // pointer to the trace file + double timescale_unit; // in seconds + bool timescale_set_by_user; // = true means set by user + +private: + std::string filename_; // name of the file (for reporting) + bool initialized_; // tracing started? + bool trace_delta_cycles_; // also trace delta transitions? + + static bool tracing_initialized_; // shared setup of tracing implementation + +private: // disabled + sc_trace_file_base( const sc_trace_file_base& ) /* = delete */; + sc_trace_file_base& operator=( const sc_trace_file_base& ) /* = delete */; + +}; // class sc_trace_file_base + +// ----------------------------------------------------------------------- + +// Convert double time to 64-bit integer + +void double_to_special_int64( double in, unsigned* high, unsigned* low ); + +// obtain formatted time string +std::string localtime_string(); + +} // namespace sc_core + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + +#endif // SC_TRACE_FILE_BASE_H_INCLUDED_ +// Taf! diff --git a/ext/systemc/src/sysc/tracing/sc_tracing_ids.h b/ext/systemc/src/sysc/tracing/sc_tracing_ids.h new file mode 100644 index 000000000..dacdb9451 --- /dev/null +++ b/ext/systemc/src/sysc/tracing/sc_tracing_ids.h @@ -0,0 +1,79 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_tracing_ids.h -- Report ids for the tracing code. + + Original Author: Philipp A. Hartmann, OFFIS, 2013-11-17 + + CHANGE LOG AT END OF FILE + *****************************************************************************/ + +#ifndef SC_TRACING_IDS_H +#define SC_TRACING_IDS_H + +// ---------------------------------------------------------------------------- +// Report ids (tracing) +// +// Report ids in the range of 700-799. +// ---------------------------------------------------------------------------- + +#ifndef SC_DEFINE_MESSAGE +#define SC_DEFINE_MESSAGE(id,unused1,unused2) \ + namespace sc_core { extern const char id[]; } +#endif + +SC_DEFINE_MESSAGE( SC_ID_TRACING_FOPEN_FAILED_, 701, + "cannot open tracefile for writing" ) + +SC_DEFINE_MESSAGE( SC_ID_TRACING_TIMESCALE_DEFAULT_, 702, + "default timescale unit used for tracing" ) +SC_DEFINE_MESSAGE( SC_ID_TRACING_TIMESCALE_UNIT_, 703, + "tracing timescale unit set" ) +SC_DEFINE_MESSAGE( SC_ID_TRACING_VCD_DELTA_CYCLE_, 704, + "VCD delta cycle tracing with pseudo timesteps (1 unit)" ) +/* unused IDs 705-709 */ +SC_DEFINE_MESSAGE( SC_ID_TRACING_OBJECT_IGNORED_, 710, + "object cannot not be traced" ) +SC_DEFINE_MESSAGE( SC_ID_TRACING_OBJECT_NAME_FILTERED_, 711, + "traced object name filtered" ) +SC_DEFINE_MESSAGE( SC_ID_TRACING_INVALID_ENUM_VALUE_, 712, + "traced value of enumerated type undefined" ) +SC_DEFINE_MESSAGE( SC_ID_TRACING_VCD_DUPLICATE_TIME_, 713, + "multiple VCD tracing cycles with the same time detected" ) +SC_DEFINE_MESSAGE( SC_ID_TRACING_VCD_REVERSED_TIME_, 714, + "VCD tracing cycle with falling time detected" ) +/* unused IDs 715-719 */ +SC_DEFINE_MESSAGE( SC_ID_TRACING_ALREADY_INITIALIZED_, 720, + "sc_trace_file already initialized" ) + + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + +#endif // SC_TRACING_IDS_H +// Taf! diff --git a/ext/systemc/src/sysc/tracing/sc_vcd_trace.cpp b/ext/systemc/src/sysc/tracing/sc_vcd_trace.cpp new file mode 100644 index 000000000..616d6274d --- /dev/null +++ b/ext/systemc/src/sysc/tracing/sc_vcd_trace.cpp @@ -0,0 +1,2175 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_vcd_trace.cpp - Implementation of VCD tracing. + + Original Author - Abhijit Ghosh, Synopsys, Inc. + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: Ali Dasdan, Synopsys, Inc. + Description of Modification: - Replaced 'width' of sc_(u)int with their + 'bitwidth()'. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + +/***************************************************************************** + + Acknowledgement: The tracing mechanism is based on the tracing + mechanism developed at Infineon (formerly Siemens HL). Though this + code is somewhat different, and significantly enhanced, the basics + are identical to what was originally contributed by Infineon. The + contribution of Infineon in the development of this tracing + technology is hereby acknowledged. + + *****************************************************************************/ + + +#include <cstdlib> +#include <string.h> +#include <vector> + +#define SC_DISABLE_API_VERSION_CHECK // for in-library sc_ver.h inclusion + +#include "sysc/kernel/sc_simcontext.h" +#include "sysc/kernel/sc_ver.h" +#include "sysc/datatypes/bit/sc_bit.h" +#include "sysc/datatypes/bit/sc_logic.h" +#include "sysc/datatypes/bit/sc_lv_base.h" +#include "sysc/datatypes/int/sc_signed.h" +#include "sysc/datatypes/int/sc_unsigned.h" +#include "sysc/datatypes/int/sc_int_base.h" +#include "sysc/datatypes/int/sc_uint_base.h" +#include "sysc/datatypes/fx/fx.h" +#include "sysc/tracing/sc_vcd_trace.h" + +namespace sc_core { + +// Forward declarations for functions that come later in the file +// Map sc_dt::sc_logic to printable VCD +static char map_sc_logic_state_to_vcd_state(char in_char); + +// Remove name problems associated with [] in vcd names +static void remove_vcd_name_problems(vcd_trace const* vcd, std::string& name); + +const char* vcd_types[vcd_trace_file::VCD_LAST]={"wire","real"}; + + +// ---------------------------------------------------------------------------- +// CLASS : vcd_trace +// +// Base class for VCD traces. +// ---------------------------------------------------------------------------- + +class vcd_trace +{ +public: + + vcd_trace(const std::string& name_, const std::string& vcd_name_); + + // Needs to be pure virtual as has to be defined by the particular + // type being traced + virtual void write(FILE* f) = 0; + + virtual void set_width(); + + static const char* strip_leading_bits(const char* originalbuf); + + // Comparison function needs to be pure virtual too + virtual bool changed() = 0; + + // Make this virtual as some derived classes may overwrite + virtual void print_variable_declaration_line(FILE* f); + + void compose_data_line(char* rawdata, char* compdata); + std::string compose_line(const std::string& data); + + virtual ~vcd_trace(); + + const std::string name; + const std::string vcd_name; + const char* vcd_var_typ_name; + int bit_width; +}; + + +vcd_trace::vcd_trace(const std::string& name_, const std::string& vcd_name_) +: name(name_), vcd_name(vcd_name_), vcd_var_typ_name(0), bit_width(0) +{ + /* Intentionally blank */ +} + +void +vcd_trace::compose_data_line(char* rawdata, char* compdata) +{ + sc_assert(rawdata != compdata); + + if(bit_width == 0) + { + compdata[0] = '\0'; + } + else + { + if(bit_width == 1) + { + compdata[0] = rawdata[0]; + strcpy(&(compdata[1]), vcd_name.c_str()); + } + else + { + const char* effective_begin = strip_leading_bits(rawdata); + std::sprintf(compdata, "b%s %s", effective_begin, vcd_name.c_str()); + } + } +} + +// same as above but not that ugly +std::string +vcd_trace::compose_line(const std::string& data) +{ + if(bit_width == 0) + return ""; + if(bit_width == 1) + return data + vcd_name; + return std::string("b")+strip_leading_bits(data.c_str())+" "+vcd_name; +} + +void +vcd_trace::print_variable_declaration_line(FILE* f) +{ + char buf[2000]; + + if ( bit_width <= 0 ) + { + std::stringstream ss; + ss << "'" << name << "' has 0 bits"; + SC_REPORT_ERROR( SC_ID_TRACING_OBJECT_IGNORED_ + , ss.str().c_str() ); + return; + } + + std::string namecopy = name; + remove_vcd_name_problems(this, namecopy); + if ( bit_width == 1 ) + { + std::sprintf(buf, "$var %s % 3d %s %s $end\n", + vcd_var_typ_name, + bit_width, + vcd_name.c_str(), + namecopy.c_str()); + } + else + { + std::sprintf(buf, "$var %s % 3d %s %s [%d:0] $end\n", + vcd_var_typ_name, + bit_width, + vcd_name.c_str(), + namecopy.c_str(), + bit_width-1); + } + std::fputs(buf, f); +} + +void +vcd_trace::set_width() +{ + /* Intentionally Blank, should be defined for each type separately */ +} + +const char* +vcd_trace::strip_leading_bits(const char* originalbuf) +{ + //********************************************************************* + // - Remove multiple leading 0,z,x, and replace by only one + // - For example, + // b000z100 -> b0z100 + // b00000xxx -> b0xxx + // b000 -> b0 + // bzzzzz1 -> bz1 + // bxxxz10 -> xz10 + // - For leading 0's followed by 1, remove all leading 0's + // b0000010101 -> b10101 + + const char* position = originalbuf; + + if( strlen(originalbuf) < 2 || + (originalbuf[0] != 'z' && originalbuf[0] != 'x' && + originalbuf[0] != '0' )) + return originalbuf; + + char first_char = *position; + while(*position == first_char) + { + position++; + } + + if(first_char == '0' && *position == '1') + return position; + // else + return position-1; +} + +vcd_trace::~vcd_trace() +{ + /* Intentionally Blank */ +} + + +template <class T> +class vcd_T_trace : public vcd_trace +{ + public: + + vcd_T_trace( const T& object_, + const std::string& name_, + const std::string& vcd_name_, + vcd_trace_file::vcd_enum type_ ) + : vcd_trace( name_, vcd_name_ ), + object( object_ ), + old_value( object_ ) + { + vcd_var_typ_name = vcd_types[type_]; + } + + void write( FILE* f ) + { + std::fprintf( f, "%s", compose_line( object.to_string() ).c_str() ); + old_value = object; + } + + bool changed() + { return !(object == old_value); } + + void set_width() + { bit_width = object.length(); } + +protected: + + const T& object; + T old_value; +}; + +typedef vcd_T_trace<sc_dt::sc_bv_base> vcd_sc_bv_trace; +typedef vcd_T_trace<sc_dt::sc_lv_base> vcd_sc_lv_trace; + +// Trace sc_dt::sc_bv_base (sc_dt::sc_bv) +void +vcd_trace_file::trace( + const sc_dt::sc_bv_base& object, const std::string& name) +{ + traceT(object,name); +} + +// Trace sc_dt::sc_lv_base (sc_dt::sc_lv) +void +vcd_trace_file::trace( + const sc_dt::sc_lv_base& object, const std::string& name) +{ + traceT(object,name); +} + +/*****************************************************************************/ + +class vcd_bool_trace : public vcd_trace { +public: + vcd_bool_trace(const bool& object_, + const std::string& name_, + const std::string& vcd_name_); + void write(FILE* f); + bool changed(); + +protected: + const bool& object; + bool old_value; +}; + +vcd_bool_trace::vcd_bool_trace(const bool& object_, + const std::string& name_, + const std::string& vcd_name_) +: vcd_trace(name_, vcd_name_), object(object_), old_value(object_) +{ + vcd_var_typ_name = "wire"; + bit_width = 1; +} + +bool +vcd_bool_trace::changed() +{ + return object != old_value; +} + +void +vcd_bool_trace::write(FILE* f) +{ + if (object == true) std::fputc('1', f); + else std::fputc('0', f); + + std::fprintf(f,"%s", vcd_name.c_str()); + + old_value = object; +} + +//***************************************************************************** + +class vcd_sc_bit_trace : public vcd_trace { +public: + vcd_sc_bit_trace(const sc_dt::sc_bit& , const std::string& , + const std::string& ); + void write(FILE* f); + bool changed(); + +protected: + const sc_dt::sc_bit& object; + sc_dt::sc_bit old_value; +}; + +vcd_sc_bit_trace::vcd_sc_bit_trace( const sc_dt::sc_bit& object_, + const std::string& name, + const std::string& vcd_name) +: vcd_trace(name, vcd_name), object( object_ ), old_value( object_ ) +{ + vcd_var_typ_name = "wire"; + bit_width = 1; +} + +bool +vcd_sc_bit_trace::changed() +{ + return object != old_value; +} + +void +vcd_sc_bit_trace::write(FILE* f) +{ + if (object == true) std::fputc('1', f); + else std::fputc('0', f); + + std::fprintf(f,"%s", vcd_name.c_str()); + + old_value = object; +} + +/*****************************************************************************/ + +class vcd_sc_logic_trace : public vcd_trace { +public: + vcd_sc_logic_trace(const sc_dt::sc_logic& object_, + const std::string& name_, + const std::string& vcd_name_); + void write(FILE* f); + bool changed(); + +protected: + const sc_dt::sc_logic& object; + sc_dt::sc_logic old_value; +}; + + +vcd_sc_logic_trace::vcd_sc_logic_trace(const sc_dt::sc_logic& object_, + const std::string& name_, + const std::string& vcd_name_) +: vcd_trace(name_, vcd_name_), object(object_), old_value(object_) +{ + vcd_var_typ_name = "wire"; + bit_width = 1; +} + + +bool +vcd_sc_logic_trace::changed() +{ + return object != old_value; +} + + +void +vcd_sc_logic_trace::write(FILE* f) +{ + char out_char; + out_char = map_sc_logic_state_to_vcd_state(object.to_char()); + std::fputc(out_char, f); + + std::fprintf(f,"%s", vcd_name.c_str()); + + old_value = object; +} + + +/*****************************************************************************/ + +class vcd_sc_unsigned_trace : public vcd_trace { +public: + vcd_sc_unsigned_trace(const sc_dt::sc_unsigned& object, + const std::string& name_, + const std::string& vcd_name_); + void write(FILE* f); + bool changed(); + void set_width(); + +protected: + const sc_dt::sc_unsigned& object; + sc_dt::sc_unsigned old_value; +}; + + +vcd_sc_unsigned_trace::vcd_sc_unsigned_trace(const sc_dt::sc_unsigned& object_, + const std::string& name_, + const std::string& vcd_name_) +: vcd_trace(name_, vcd_name_), object(object_), old_value(object_.length()) +// The last may look strange, but is correct +{ + vcd_var_typ_name = "wire"; + old_value = object; +} + +bool +vcd_sc_unsigned_trace::changed() +{ + return object != old_value; +} + +void +vcd_sc_unsigned_trace::write(FILE* f) +{ + static std::vector<char> compdata(1024), rawdata(1024); + typedef std::vector<char>::size_type size_t; + + if ( compdata.size() < (size_t)object.length() ) { + size_t sz = ( (size_t)object.length() + 4096 ) & (~(size_t)(4096-1)); + std::vector<char>( sz ).swap( compdata ); // resize without copying values + std::vector<char>( sz ).swap( rawdata ); + } + char *rawdata_ptr = &rawdata[0]; + + for (int bitindex = object.length() - 1; bitindex >= 0; --bitindex) { + *rawdata_ptr++ = "01"[object[bitindex].to_bool()]; + } + *rawdata_ptr = '\0'; + compose_data_line(&rawdata[0], &compdata[0]); + + std::fputs(&compdata[0], f); + old_value = object; +} + +void +vcd_sc_unsigned_trace::set_width() +{ + bit_width = object.length(); +} + + +/*****************************************************************************/ + +class vcd_sc_signed_trace : public vcd_trace { +public: + vcd_sc_signed_trace(const sc_dt::sc_signed& object, + const std::string& name_, + const std::string& vcd_name_); + void write(FILE* f); + bool changed(); + void set_width(); + +protected: + const sc_dt::sc_signed& object; + sc_dt::sc_signed old_value; +}; + + +vcd_sc_signed_trace::vcd_sc_signed_trace(const sc_dt::sc_signed& object_, + const std::string& name_, + const std::string& vcd_name_) +: vcd_trace(name_, vcd_name_), object(object_), old_value(object_.length()) +{ + vcd_var_typ_name = "wire"; + old_value = object; +} + +bool +vcd_sc_signed_trace::changed() +{ + return object != old_value; +} + +void +vcd_sc_signed_trace::write(FILE* f) +{ + static std::vector<char> compdata(1024), rawdata(1024); + typedef std::vector<char>::size_type size_t; + + if ( compdata.size() < (size_t)object.length() ) { + size_t sz = ( (size_t)object.length() + 4096 ) & (~(size_t)(4096-1)); + std::vector<char>( sz ).swap( compdata ); // resize without copying values + std::vector<char>( sz ).swap( rawdata ); + } + char *rawdata_ptr = &rawdata[0]; + + for (int bitindex = object.length() - 1; bitindex >= 0; --bitindex) { + *rawdata_ptr++ = "01"[object[bitindex].to_bool()]; + } + *rawdata_ptr = '\0'; + compose_data_line(&rawdata[0], &compdata[0]); + + std::fputs(&compdata[0], f); + old_value = object; +} + +void +vcd_sc_signed_trace::set_width() +{ + bit_width = object.length(); +} + +/*****************************************************************************/ + +class vcd_sc_uint_base_trace : public vcd_trace { +public: + vcd_sc_uint_base_trace(const sc_dt::sc_uint_base& object, + const std::string& name_, + const std::string& vcd_name_); + void write(FILE* f); + bool changed(); + void set_width(); + +protected: + const sc_dt::sc_uint_base& object; + sc_dt::sc_uint_base old_value; +}; + + +vcd_sc_uint_base_trace::vcd_sc_uint_base_trace( + const sc_dt::sc_uint_base& object_, + const std::string& name_, + const std::string& vcd_name_) +: vcd_trace(name_, vcd_name_), object(object_), old_value(object_.length()) +// The last may look strange, but is correct +{ + vcd_var_typ_name = "wire"; + old_value = object; +} + +bool +vcd_sc_uint_base_trace::changed() +{ + return object != old_value; +} + +void +vcd_sc_uint_base_trace::write(FILE* f) +{ + char rawdata[1000], *rawdata_ptr = rawdata; + char compdata[1000]; + + int bitindex; + for (bitindex = object.length()-1; bitindex >= 0; --bitindex) { + *rawdata_ptr++ = "01"[object[bitindex].to_bool()]; + } + *rawdata_ptr = '\0'; + compose_data_line(rawdata, compdata); + + std::fputs(compdata, f); + old_value = object; +} + +void +vcd_sc_uint_base_trace::set_width() +{ + bit_width = object.length(); +} + + +/*****************************************************************************/ + +class vcd_sc_int_base_trace : public vcd_trace { +public: + vcd_sc_int_base_trace(const sc_dt::sc_int_base& object, + const std::string& name_, + const std::string& vcd_name_); + void write(FILE* f); + bool changed(); + void set_width(); + +protected: + const sc_dt::sc_int_base& object; + sc_dt::sc_int_base old_value; +}; + + +vcd_sc_int_base_trace::vcd_sc_int_base_trace(const sc_dt::sc_int_base& object_, + const std::string& name_, + const std::string& vcd_name_) +: vcd_trace(name_, vcd_name_), object(object_), old_value(object_.length()) +{ + vcd_var_typ_name = "wire"; + old_value = object; +} + +bool +vcd_sc_int_base_trace::changed() +{ + return object != old_value; +} + +void +vcd_sc_int_base_trace::write(FILE* f) +{ + char rawdata[1000], *rawdata_ptr = rawdata; + char compdata[1000]; + + int bitindex; + for (bitindex = object.length()-1; bitindex >= 0; --bitindex) { + *rawdata_ptr++ = "01"[object[bitindex].to_bool()]; + } + *rawdata_ptr = '\0'; + compose_data_line(rawdata, compdata); + + std::fputs(compdata, f); + old_value = object; +} + +void +vcd_sc_int_base_trace::set_width() +{ + bit_width = object.length(); +} + + +/*****************************************************************************/ + +class vcd_sc_fxval_trace : public vcd_trace +{ +public: + + vcd_sc_fxval_trace( const sc_dt::sc_fxval& object, + const std::string& name_, + const std::string& vcd_name_ ); + void write( FILE* f ); + bool changed(); + +protected: + + const sc_dt::sc_fxval& object; + sc_dt::sc_fxval old_value; + +}; + +vcd_sc_fxval_trace::vcd_sc_fxval_trace( const sc_dt::sc_fxval& object_, + const std::string& name_, + const std::string& vcd_name_ ) +: vcd_trace( name_, vcd_name_ ), + object( object_ ), old_value( object_ ) +{ + vcd_var_typ_name = "real"; + bit_width = 1; +} + +bool +vcd_sc_fxval_trace::changed() +{ + return object != old_value; +} + +void +vcd_sc_fxval_trace::write( FILE* f ) +{ + std::fprintf( f, "r%.16g %s", object.to_double(), vcd_name.c_str() ); + old_value = object; +} + +/*****************************************************************************/ + +class vcd_sc_fxval_fast_trace : public vcd_trace +{ +public: + + vcd_sc_fxval_fast_trace( const sc_dt::sc_fxval_fast& object, + const std::string& name_, + const std::string& vcd_name_ ); + void write( FILE* f ); + bool changed(); + +protected: + + const sc_dt::sc_fxval_fast& object; + sc_dt::sc_fxval_fast old_value; + +}; + +vcd_sc_fxval_fast_trace::vcd_sc_fxval_fast_trace( + const sc_dt::sc_fxval_fast& object_, + const std::string& name_, + const std::string& vcd_name_ ) +: vcd_trace( name_, vcd_name_ ), + object( object_ ), old_value( object_ ) +{ + vcd_var_typ_name = "real"; + bit_width = 1; +} + +bool +vcd_sc_fxval_fast_trace::changed() +{ + return object != old_value; +} + +void +vcd_sc_fxval_fast_trace::write( FILE* f ) +{ + std::fprintf( f, "r%.16g %s", object.to_double(), vcd_name.c_str() ); + old_value = object; +} + +/*****************************************************************************/ + +class vcd_sc_fxnum_trace : public vcd_trace +{ +public: + + vcd_sc_fxnum_trace( const sc_dt::sc_fxnum& object, + const std::string& name_, + const std::string& vcd_name_ ); + void write( FILE* f ); + bool changed(); + void set_width(); + +protected: + + const sc_dt::sc_fxnum& object; + sc_dt::sc_fxnum old_value; + +}; + +vcd_sc_fxnum_trace::vcd_sc_fxnum_trace( const sc_dt::sc_fxnum& object_, + const std::string& name_, + const std::string& vcd_name_ ) +: vcd_trace( name_, vcd_name_ ), + object( object_ ), + old_value( object_.m_params.type_params(), + object_.m_params.enc(), + object_.m_params.cast_switch(), + 0 ) +{ + vcd_var_typ_name = "wire"; + old_value = object; +} + +bool +vcd_sc_fxnum_trace::changed() +{ + return object != old_value; +} + +void +vcd_sc_fxnum_trace::write( FILE* f ) +{ + static std::vector<char> compdata(1024), rawdata(1024); + typedef std::vector<char>::size_type size_t; + + if ( compdata.size() < (size_t)object.wl() ) { + size_t sz = ( (size_t)object.wl() + 4096 ) & (~(size_t)(4096-1)); + std::vector<char>( sz ).swap( compdata ); // resize without copying values + std::vector<char>( sz ).swap( rawdata ); + } + char *rawdata_ptr = &rawdata[0]; + + for(int bitindex = object.wl() - 1; bitindex >= 0; -- bitindex ) + { + *rawdata_ptr ++ = "01"[object[bitindex]]; + } + *rawdata_ptr = '\0'; + compose_data_line( &rawdata[0], &compdata[0] ); + + std::fputs( &compdata[0], f ); + old_value = object; +} + +void +vcd_sc_fxnum_trace::set_width() +{ + bit_width = object.wl(); +} + +/*****************************************************************************/ + +class vcd_sc_fxnum_fast_trace : public vcd_trace +{ +public: + + vcd_sc_fxnum_fast_trace( const sc_dt::sc_fxnum_fast& object, + const std::string& name_, + const std::string& vcd_name_ ); + void write( FILE* f ); + bool changed(); + void set_width(); + +protected: + + const sc_dt::sc_fxnum_fast& object; + sc_dt::sc_fxnum_fast old_value; + +}; + +vcd_sc_fxnum_fast_trace::vcd_sc_fxnum_fast_trace( + const sc_dt::sc_fxnum_fast& object_, + const std::string& name_, + const std::string& vcd_name_ ) +: vcd_trace( name_, vcd_name_ ), + object( object_ ), + old_value( object_.m_params.type_params(), + object_.m_params.enc(), + object_.m_params.cast_switch(), + 0 ) +{ + vcd_var_typ_name = "wire"; + old_value = object; +} + +bool +vcd_sc_fxnum_fast_trace::changed() +{ + return object != old_value; +} + +void +vcd_sc_fxnum_fast_trace::write( FILE* f ) +{ + static std::vector<char> compdata(1024), rawdata(1024); + typedef std::vector<char>::size_type size_t; + + if ( compdata.size() < (size_t)object.wl() ) { + size_t sz = ( (size_t)object.wl() + 4096 ) & (~(size_t)(4096-1)); + std::vector<char>( sz ).swap( compdata ); // resize without copying values + std::vector<char>( sz ).swap( rawdata ); + } + char *rawdata_ptr = &rawdata[0]; + + for(int bitindex = object.wl() - 1; bitindex >= 0; -- bitindex ) + { + *rawdata_ptr ++ = "01"[object[bitindex]]; + } + *rawdata_ptr = '\0'; + compose_data_line( &rawdata[0], &compdata[0] ); + + std::fputs( &compdata[0], f ); + old_value = object; +} + +void +vcd_sc_fxnum_fast_trace::set_width() +{ + bit_width = object.wl(); +} + + +/*****************************************************************************/ + +class vcd_unsigned_int_trace : public vcd_trace { +public: + vcd_unsigned_int_trace(const unsigned& object, + const std::string& name_, + const std::string& vcd_name_, + int width_); + void write(FILE* f); + bool changed(); + +protected: + const unsigned& object; + unsigned old_value; + unsigned mask; +}; + + +vcd_unsigned_int_trace::vcd_unsigned_int_trace( + const unsigned& object_, + const std::string& name_, + const std::string& vcd_name_, + int width_) +: vcd_trace(name_, vcd_name_), object(object_), old_value( object_ ), + mask((unsigned)-1) +{ + bit_width = width_; + if (bit_width < 32) mask = ~(-1 << bit_width); + + vcd_var_typ_name = "wire"; +} + + +bool +vcd_unsigned_int_trace::changed() +{ + return object != old_value; +} + + +void +vcd_unsigned_int_trace::write(FILE* f) +{ + char rawdata[1000]; + char compdata[1000]; + int bitindex; + + // Check for overflow + if ((object & mask) != object) { + for (bitindex = 0; bitindex < bit_width; bitindex++){ + rawdata[bitindex] = 'x'; + } + } + else{ + unsigned bit_mask = 1 << (bit_width-1); + for (bitindex = 0; bitindex < bit_width; bitindex++) { + rawdata[bitindex] = (object & bit_mask)? '1' : '0'; + bit_mask = bit_mask >> 1; + } + } + rawdata[bitindex] = '\0'; + compose_data_line(rawdata, compdata); + std::fputs(compdata, f); + old_value = object; +} + +/*****************************************************************************/ + +class vcd_unsigned_short_trace : public vcd_trace { +public: + vcd_unsigned_short_trace(const unsigned short& object, + const std::string& name_, + const std::string& vcd_name_, + int width_); + void write(FILE* f); + bool changed(); + +protected: + const unsigned short& object; + unsigned short old_value; + unsigned short mask; +}; + + +vcd_unsigned_short_trace::vcd_unsigned_short_trace( + const unsigned short& object_, + const std::string& name_, + const std::string& vcd_name_, + int width_) +: vcd_trace(name_, vcd_name_), object(object_), old_value(object_), mask(0xffff) +{ + bit_width = width_; + if (bit_width < 16) mask = (unsigned short)~(-1 << bit_width); + + vcd_var_typ_name = "wire"; +} + + +bool +vcd_unsigned_short_trace::changed() +{ + return object != old_value; +} + + +void +vcd_unsigned_short_trace::write(FILE* f) +{ + char rawdata[1000]; + char compdata[1000]; + int bitindex; + + // Check for overflow + if ((object & mask) != object) { + for (bitindex = 0; bitindex < bit_width; bitindex++){ + rawdata[bitindex] = 'x'; + } + } + else{ + unsigned bit_mask = 1 << (bit_width-1); + for (bitindex = 0; bitindex < bit_width; bitindex++) { + rawdata[bitindex] = (object & bit_mask)? '1' : '0'; + bit_mask = bit_mask >> 1; + } + } + rawdata[bitindex] = '\0'; + compose_data_line(rawdata, compdata); + std::fputs(compdata, f); + old_value = object; +} + +/*****************************************************************************/ + +class vcd_unsigned_char_trace : public vcd_trace { +public: + vcd_unsigned_char_trace(const unsigned char& object, + const std::string& name_, + const std::string& vcd_name_, + int width_); + void write(FILE* f); + bool changed(); + +protected: + const unsigned char& object; + unsigned char old_value; + unsigned char mask; +}; + + +vcd_unsigned_char_trace::vcd_unsigned_char_trace( + const unsigned char& object_, + const std::string& name_, + const std::string& vcd_name_, + int width_) +: vcd_trace(name_, vcd_name_), object(object_), old_value(object_), mask(0xff) +{ + bit_width = width_; + if (bit_width < 8) mask = (unsigned char)~(-1 << bit_width); + vcd_var_typ_name = "wire"; +} + + +bool vcd_unsigned_char_trace::changed() +{ + return object != old_value; +} + + +void vcd_unsigned_char_trace::write(FILE* f) +{ + char rawdata[1000]; + char compdata[1000]; + int bitindex; + + // Check for overflow + if ((object & mask) != object) { + for (bitindex = 0; bitindex < bit_width; bitindex++){ + rawdata[bitindex] = 'x'; + } + } + else{ + unsigned bit_mask = 1 << (bit_width-1); + for (bitindex = 0; bitindex < bit_width; bitindex++) { + rawdata[bitindex] = (object & bit_mask)? '1' : '0'; + bit_mask = bit_mask >> 1; + } + } + rawdata[bitindex] = '\0'; + compose_data_line(rawdata, compdata); + std::fputs(compdata, f); + old_value = object; +} + +/*****************************************************************************/ + +class vcd_unsigned_long_trace : public vcd_trace { +public: + vcd_unsigned_long_trace(const unsigned long& object, + const std::string& name_, + const std::string& vcd_name_, + int width_); + void write(FILE* f); + bool changed(); + +protected: + const unsigned long& object; + unsigned long old_value; + unsigned long mask; +}; + + +vcd_unsigned_long_trace::vcd_unsigned_long_trace( + const unsigned long& object_, + const std::string& name_, + const std::string& vcd_name_, + int width_) +: vcd_trace(name_, vcd_name_), object(object_), old_value(object_), + mask((unsigned long)-1) +{ + bit_width = width_; + if ( bit_width < (int)(sizeof(unsigned long)*8) ) + mask = ~(-1L << bit_width); + + vcd_var_typ_name = "wire"; +} + + +bool vcd_unsigned_long_trace::changed() +{ + return object != old_value; +} + + +void vcd_unsigned_long_trace::write(FILE* f) +{ + char rawdata[1000]; + char compdata[1000]; + int bitindex; + + // Check for overflow + if ((object & mask) != object) { + for (bitindex = 0; bitindex < bit_width; bitindex++){ + rawdata[bitindex] = 'x'; + } + } + else{ + unsigned long bit_mask = 1ul << (bit_width-1); + for (bitindex = 0; bitindex < bit_width; bitindex++) { + rawdata[bitindex] = (object & bit_mask)? '1' : '0'; + bit_mask = bit_mask >> 1; + } + } + rawdata[bitindex] = '\0'; + compose_data_line(rawdata, compdata); + std::fputs(compdata, f); + old_value = object; +} + +/*****************************************************************************/ + +class vcd_signed_int_trace : public vcd_trace { +public: + vcd_signed_int_trace(const int& object, + const std::string& name_, + const std::string& vcd_name_, + int width_); + void write(FILE* f); + bool changed(); + +protected: + const int& object; + int old_value; + unsigned mask; +}; + + +vcd_signed_int_trace::vcd_signed_int_trace(const signed& object_, + const std::string& name_, + const std::string& vcd_name_, + int width_) +: vcd_trace(name_, vcd_name_), object(object_), old_value(object_), + mask((unsigned)-1) +{ + bit_width = width_; + if (bit_width < 32) mask = ~(-1 << bit_width); + + vcd_var_typ_name = "wire"; +} + + +bool vcd_signed_int_trace::changed() +{ + return object != old_value; +} + + +void vcd_signed_int_trace::write(FILE* f) +{ + char rawdata[1000]; + char compdata[1000]; + int bitindex; + + // Check for overflow + if (((unsigned) object & mask) != (unsigned) object) { + for (bitindex = 0; bitindex < bit_width; bitindex++){ + rawdata[bitindex] = 'x'; + } + } + else{ + unsigned bit_mask = 1 << (bit_width-1); + for (bitindex = 0; bitindex < bit_width; bitindex++) { + rawdata[bitindex] = (object & bit_mask)? '1' : '0'; + bit_mask = bit_mask >> 1; + } + } + rawdata[bitindex] = '\0'; + compose_data_line(rawdata, compdata); + std::fputs(compdata, f); + old_value = object; +} + +/*****************************************************************************/ + +class vcd_signed_short_trace : public vcd_trace { +public: + vcd_signed_short_trace(const short& object, + const std::string& name_, + const std::string& vcd_name_, + int width_); + void write(FILE* f); + bool changed(); + +protected: + const short& object; + short old_value; + unsigned short mask; +}; + + +vcd_signed_short_trace::vcd_signed_short_trace( + const short& object_, + const std::string& name_, + const std::string& vcd_name_, + int width_) +: vcd_trace(name_, vcd_name_), object(object_), old_value(object_), mask(0xffff) +{ + bit_width = width_; + if (bit_width < 16) mask = (unsigned short)~(-1 << bit_width); + + vcd_var_typ_name = "wire"; +} + + +bool vcd_signed_short_trace::changed() +{ + return object != old_value; +} + + +void vcd_signed_short_trace::write(FILE* f) +{ + char rawdata[1000]; + char compdata[1000]; + int bitindex; + + // Check for overflow + if (((unsigned short) object & mask) != (unsigned short) object) { + for (bitindex = 0; bitindex < bit_width; bitindex++){ + rawdata[bitindex] = 'x'; + } + } + else{ + unsigned bit_mask = 1 << (bit_width-1); + for (bitindex = 0; bitindex < bit_width; bitindex++) { + rawdata[bitindex] = (object & bit_mask)? '1' : '0'; + bit_mask = bit_mask >> 1; + } + } + rawdata[bitindex] = '\0'; + compose_data_line(rawdata, compdata); + std::fputs(compdata, f); + old_value = object; +} + +/*****************************************************************************/ + +class vcd_signed_char_trace : public vcd_trace { +public: + vcd_signed_char_trace(const char& object, + const std::string& name_, + const std::string& vcd_name_, + int width_); + void write(FILE* f); + bool changed(); + +protected: + const char& object; + char old_value; + unsigned char mask; +}; + + +vcd_signed_char_trace::vcd_signed_char_trace(const char& object_, + const std::string& name_, + const std::string& vcd_name_, + int width_) +: vcd_trace(name_, vcd_name_), object(object_), old_value(object_), mask(0xff) +{ + bit_width = width_; + if (bit_width < 8) mask = (unsigned char)~(-1 << bit_width); + + vcd_var_typ_name = "wire"; +} + + +bool vcd_signed_char_trace::changed() +{ + return object != old_value; +} + + +void vcd_signed_char_trace::write(FILE* f) +{ + char rawdata[1000]; + char compdata[1000]; + int bitindex; + + // Check for overflow + if (((unsigned char) object & mask) != (unsigned char) object) { + for (bitindex = 0; bitindex < bit_width; bitindex++){ + rawdata[bitindex] = 'x'; + } + } + else{ + unsigned bit_mask = 1 << (bit_width-1); + for (bitindex = 0; bitindex < bit_width; bitindex++) { + rawdata[bitindex] = (object & bit_mask)? '1' : '0'; + bit_mask = bit_mask >> 1; + } + } + rawdata[bitindex] = '\0'; + compose_data_line(rawdata, compdata); + std::fputs(compdata, f); + old_value = object; +} + +/*****************************************************************************/ + +class vcd_int64_trace : public vcd_trace { +public: + vcd_int64_trace(const sc_dt::int64& object, + const std::string& name_, + const std::string& vcd_name_, + int width_); + void write(FILE* f); + bool changed(); + +protected: + const sc_dt::int64& object; + sc_dt::int64 old_value; + sc_dt::uint64 mask; +}; + + +vcd_int64_trace::vcd_int64_trace(const sc_dt::int64& object_, + const std::string& name_, + const std::string& vcd_name_, + int width_) +: vcd_trace(name_, vcd_name_), object(object_), old_value(object_), + mask((sc_dt::uint64)-1) +{ + bit_width = width_; + if (bit_width < 64) mask = ~(mask << bit_width); + vcd_var_typ_name = "wire"; +} + + +bool vcd_int64_trace::changed() +{ + return object != old_value; +} + + +void vcd_int64_trace::write(FILE* f) +{ + char rawdata[1000]; + char compdata[1000]; + int bitindex; + + // Check for overflow + if (((sc_dt::uint64) object & mask) != (sc_dt::uint64) object) + { + for (bitindex = 0; bitindex < bit_width; bitindex++) + { + rawdata[bitindex] = 'x'; + } + } + else + { + sc_dt::uint64 bit_mask = 1; + bit_mask = bit_mask << (bit_width-1); + for (bitindex = 0; bitindex < bit_width; bitindex++) { + rawdata[bitindex] = (object & bit_mask)? '1' : '0'; + bit_mask = bit_mask >> 1; + } + } + rawdata[bitindex] = '\0'; + compose_data_line(rawdata, compdata); + std::fputs(compdata, f); + old_value = object; +} + + +/*****************************************************************************/ + +class vcd_uint64_trace : public vcd_trace { +public: + vcd_uint64_trace(const sc_dt::uint64& object, + const std::string& name_, + const std::string& vcd_name_, + int width_); + void write(FILE* f); + bool changed(); + +protected: + const sc_dt::uint64& object; + sc_dt::uint64 old_value; + sc_dt::uint64 mask; +}; + + +vcd_uint64_trace::vcd_uint64_trace( const sc_dt::uint64& object_, + const std::string& name_, + const std::string& vcd_name_, + int width_) +: vcd_trace(name_, vcd_name_), object(object_), old_value(object_), + mask((sc_dt::uint64)-1) +{ + bit_width = width_; + if ( bit_width < 64 ) mask = ~(mask << bit_width); + vcd_var_typ_name = "wire"; +} + + +bool vcd_uint64_trace::changed() +{ + return object != old_value; +} + + +void vcd_uint64_trace::write(FILE* f) +{ + char rawdata[1000]; + char compdata[1000]; + int bitindex; + + // Check for overflow + if ((object & mask) != object) + { + for (bitindex = 0; bitindex < bit_width; bitindex++){ + rawdata[bitindex] = 'x'; + } + } + else + { + sc_dt::uint64 bit_mask = 1; + bit_mask = bit_mask << (bit_width-1); + for (bitindex = 0; bitindex < bit_width; bitindex++) + { + rawdata[bitindex] = (object & bit_mask)? '1' : '0'; + bit_mask = bit_mask >> 1; + } + } + rawdata[bitindex] = '\0'; + compose_data_line(rawdata, compdata); + std::fputs(compdata, f); + old_value = object; +} + + +/*****************************************************************************/ + +class vcd_signed_long_trace : public vcd_trace { +public: + vcd_signed_long_trace(const long& object, + const std::string& name_, + const std::string& vcd_name_, + int width_); + void write(FILE* f); + bool changed(); + +protected: + const long& object; + long old_value; + unsigned long mask; +}; + + +vcd_signed_long_trace::vcd_signed_long_trace(const long& object_, + const std::string& name_, + const std::string& vcd_name_, + int width_) +: vcd_trace(name_, vcd_name_), object(object_), old_value(object_), + mask((unsigned long)-1) +{ + bit_width = width_; + if ( bit_width < (int)(sizeof(long)*8) ) + mask = ~(-1L << bit_width); + vcd_var_typ_name = "wire"; +} + + +bool vcd_signed_long_trace::changed() +{ + return object != old_value; +} + + +void vcd_signed_long_trace::write(FILE* f) +{ + char rawdata[1000]; + char compdata[1000]; + int bitindex; + + // Check for overflow + if (((unsigned long) object & mask) != (unsigned long) object) { + for (bitindex = 0; bitindex < bit_width; bitindex++){ + rawdata[bitindex] = 'x'; + } + } + else{ + unsigned long bit_mask = 1ul << (bit_width-1); + for (bitindex = 0; bitindex < bit_width; bitindex++) { + rawdata[bitindex] = (object & bit_mask)? '1' : '0'; + bit_mask = bit_mask >> 1; + } + } + rawdata[bitindex] = '\0'; + compose_data_line(rawdata, compdata); + std::fputs(compdata, f); + old_value = object; +} + + +/*****************************************************************************/ + +class vcd_float_trace : public vcd_trace { +public: + vcd_float_trace(const float& object, + const std::string& name_, + const std::string& vcd_name_); + void write(FILE* f); + bool changed(); + +protected: + const float& object; + float old_value; +}; + +vcd_float_trace::vcd_float_trace(const float& object_, + const std::string& name_, + const std::string& vcd_name_) +: vcd_trace(name_, vcd_name_), object(object_) +{ + vcd_var_typ_name = "real"; + bit_width = 1; + old_value = object; +} + +bool vcd_float_trace::changed() +{ + return object != old_value; +} + +void vcd_float_trace::write(FILE* f) +{ + std::fprintf(f, "r%.16g %s", object, vcd_name.c_str()); + old_value = object; +} + +/*****************************************************************************/ + +class vcd_double_trace : public vcd_trace { +public: + vcd_double_trace(const double& object, + const std::string& name_, + const std::string& vcd_name_); + void write(FILE* f); + bool changed(); + +protected: + const double& object; + double old_value; +}; + +vcd_double_trace::vcd_double_trace(const double& object_, + const std::string& name_, + const std::string& vcd_name_) +: vcd_trace(name_, vcd_name_), object(object_), old_value(object_) +{ + vcd_var_typ_name = "real"; + bit_width = 1; +} + +bool vcd_double_trace::changed() +{ + return object != old_value; +} + +void vcd_double_trace::write(FILE* f) +{ + std::fprintf(f, "r%.16g %s", object, vcd_name.c_str()); + old_value = object; +} + + +/*****************************************************************************/ + +class vcd_enum_trace : public vcd_trace { +public: + vcd_enum_trace(const unsigned& object_, + const std::string& name_, + const std::string& vcd_name_, + const char** enum_literals); + void write(FILE* f); + bool changed(); + +protected: + const unsigned& object; + unsigned old_value; + unsigned mask; + const char** literals; + unsigned nliterals; +}; + + +vcd_enum_trace::vcd_enum_trace(const unsigned& object_, + const std::string& name_, + const std::string& vcd_name_, + const char** enum_literals_) +: vcd_trace(name_, vcd_name_), object(object_), old_value(object_), + mask(0xffffffff), literals(enum_literals_), nliterals(0) +{ + // find number of bits required to represent enumeration literal - counting loop + for (nliterals = 0; enum_literals_[nliterals]; nliterals++) continue; + + // Figure out number of bits required to represent the number of literals + bit_width = 0; + unsigned shifted_maxindex = nliterals-1; + while(shifted_maxindex != 0){ + shifted_maxindex >>= 1; + bit_width++; + } + + // Set the mask + if (bit_width < 32) { + mask = ~(-1 << bit_width); + } else { + mask = 0xffffffff; + } + + vcd_var_typ_name = "wire"; +} + +bool vcd_enum_trace::changed() +{ + return object != old_value; +} + +void vcd_enum_trace::write(FILE* f) +{ + char rawdata[1000]; + char compdata[1000]; + int bitindex; + + // Check for overflow + if ((object & mask) != object) { + for (bitindex = 0; bitindex < bit_width; bitindex++){ + rawdata[bitindex] = 'x'; + } + } else { + unsigned long bit_mask = 1ul << (bit_width-1); + for (bitindex = 0; bitindex < bit_width; bitindex++) { + rawdata[bitindex] = (object & bit_mask)? '1' : '0'; + bit_mask = bit_mask >> 1; + } + } + rawdata[bitindex] = '\0'; + compose_data_line(rawdata, compdata); + std::fputs(compdata, f); + old_value = object; +} + + +/***************************************************************************** + vcd_trace_file functions + *****************************************************************************/ + +vcd_trace_file::vcd_trace_file(const char *name) + : sc_trace_file_base( name, "vcd" ) + , vcd_name_index(0) + , previous_time_units_low(0) + , previous_time_units_high(0) + , traces() +{} + + +void +vcd_trace_file::do_initialize() +{ + char buf[2000]; + + //date: + std::fprintf(fp, "$date\n %s\n$end\n\n", localtime_string().c_str() ); + + //version: + std::fprintf(fp, "$version\n %s\n$end\n\n", sc_version()); + + //timescale: + static struct SC_TIMESCALE_TO_TEXT { + double unit; + const char* text; + } timescale_to_text [] = { + { sc_time(1, SC_FS).to_seconds(), "1 fs" }, + { sc_time(10, SC_FS).to_seconds(), "10 fs" }, + { sc_time(100, SC_FS).to_seconds(),"100 fs" }, + { sc_time(1, SC_PS).to_seconds(), "1 ps" }, + { sc_time(10, SC_PS).to_seconds(), "10 ps" }, + { sc_time(100, SC_PS).to_seconds(),"100 ps" }, + { sc_time(1, SC_NS).to_seconds(), "1 ns" }, + { sc_time(10, SC_NS).to_seconds(), "10 ns" }, + { sc_time(100, SC_NS).to_seconds(),"100 ns" }, + { sc_time(1, SC_US).to_seconds(), "1 us" }, + { sc_time(10, SC_US).to_seconds(), "10 us" }, + { sc_time(100, SC_US).to_seconds(),"100 us" }, + { sc_time(1, SC_MS).to_seconds(), "1 ms" }, + { sc_time(10, SC_MS).to_seconds(), "10 ms" }, + { sc_time(100, SC_MS).to_seconds(),"100 ms" }, + { sc_time(1, SC_SEC).to_seconds(), "1 sec" }, + { sc_time(10, SC_SEC).to_seconds(), "10 sec" }, + { sc_time(100, SC_SEC).to_seconds(),"100 sec" } + }; + static int timescale_to_text_n = + sizeof(timescale_to_text)/sizeof(SC_TIMESCALE_TO_TEXT); + + for ( int time_i = 0; time_i < timescale_to_text_n; time_i++ ) + { + if (timescale_unit == timescale_to_text[time_i].unit) + { + std::fprintf(fp,"$timescale\n %s\n$end\n\n", + timescale_to_text[time_i].text); + break; + } + } + + // Create a dummy scope + std::fputs("$scope module SystemC $end\n", fp); + + //variable definitions: + for (int i = 0; i < (int)traces.size(); i++) { + vcd_trace* t = traces[i]; + t->set_width(); // needed for all vectors + t->print_variable_declaration_line(fp); + } + + std::fputs("$upscope $end\n", fp); + + std::fputs("$enddefinitions $end\n\n", fp); + + // double inittime = sc_simulation_time(); + double inittime = sc_time_stamp().to_seconds(); + + std::sprintf(buf, + "All initial values are dumped below at time " + "%g sec = %g timescale units.", + inittime, inittime/timescale_unit + ); + write_comment(buf); + + double_to_special_int64(inittime/timescale_unit, + &previous_time_units_high, + &previous_time_units_low ); + + + std::fputs("$dumpvars\n",fp); + for (int i = 0; i < (int)traces.size(); i++) { + traces[i]->write(fp); + std::fputc('\n', fp); + } + std::fputs("$end\n\n", fp); +} + + +// ---------------------------------------------------------------------------- + +#define DEFN_TRACE_METHOD(tp) \ +void \ +vcd_trace_file::trace(const tp& object_, const std::string& name_) \ +{ \ + if( add_trace_check(name_) ) \ + traces.push_back( new vcd_ ## tp ## _trace( object_, \ + name_, \ + obtain_name() ) ); \ +} + +DEFN_TRACE_METHOD(bool) +DEFN_TRACE_METHOD(float) +DEFN_TRACE_METHOD(double) + +#undef DEFN_TRACE_METHOD +#define DEFN_TRACE_METHOD(tp) \ +void \ +vcd_trace_file::trace(const sc_dt::tp& object_, const std::string& name_) \ +{ \ + if( add_trace_check(name_) ) \ + traces.push_back( new vcd_ ## tp ## _trace( object_, \ + name_, \ + obtain_name() ) ); \ +} + +DEFN_TRACE_METHOD(sc_bit) +DEFN_TRACE_METHOD(sc_logic) + +DEFN_TRACE_METHOD(sc_signed) +DEFN_TRACE_METHOD(sc_unsigned) +DEFN_TRACE_METHOD(sc_int_base) +DEFN_TRACE_METHOD(sc_uint_base) + +DEFN_TRACE_METHOD(sc_fxval) +DEFN_TRACE_METHOD(sc_fxval_fast) +DEFN_TRACE_METHOD(sc_fxnum) +DEFN_TRACE_METHOD(sc_fxnum_fast) + +#undef DEFN_TRACE_METHOD + + +#define DEFN_TRACE_METHOD_SIGNED(tp) \ +void \ +vcd_trace_file::trace( const tp& object_, \ + const std::string& name_, \ + int width_ ) \ +{ \ + if( add_trace_check(name_) ) \ + traces.push_back( new vcd_signed_ ## tp ## _trace( object_, \ + name_, \ + obtain_name(), \ + width_ ) ); \ +} + +#define DEFN_TRACE_METHOD_UNSIGNED(tp) \ +void \ +vcd_trace_file::trace( const unsigned tp& object_, \ + const std::string& name_, \ + int width_ ) \ +{ \ + if( add_trace_check(name_) ) \ + traces.push_back( new vcd_unsigned_ ## tp ## _trace( object_, \ + name_, \ + obtain_name(), \ + width_ ) ); \ +} + +DEFN_TRACE_METHOD_SIGNED(char) +DEFN_TRACE_METHOD_SIGNED(short) +DEFN_TRACE_METHOD_SIGNED(int) +DEFN_TRACE_METHOD_SIGNED(long) + +DEFN_TRACE_METHOD_UNSIGNED(char) +DEFN_TRACE_METHOD_UNSIGNED(short) +DEFN_TRACE_METHOD_UNSIGNED(int) +DEFN_TRACE_METHOD_UNSIGNED(long) + +#undef DEFN_TRACE_METHOD_SIGNED +#undef DEFN_TRACE_METHOD_UNSIGNED + +#define DEFN_TRACE_METHOD_LONG_LONG(tp) \ +void \ +vcd_trace_file::trace( const sc_dt::tp& object_, \ + const std::string& name_, \ + int width_ ) \ +{ \ + if( add_trace_check(name_) ) \ + traces.push_back( new vcd_ ## tp ## _trace( object_, \ + name_, \ + obtain_name(), \ + width_ ) ); \ +} + +DEFN_TRACE_METHOD_LONG_LONG(int64) +DEFN_TRACE_METHOD_LONG_LONG(uint64) + +#undef DEFN_TRACE_METHOD_LONG_LONG + +void +vcd_trace_file::trace( const unsigned& object_, + const std::string& name_, + const char** enum_literals_ ) +{ + if( add_trace_check(name_) ) + traces.push_back( new vcd_enum_trace( object_, + name_, + obtain_name(), + enum_literals_ ) ); +} + + +void +vcd_trace_file::write_comment(const std::string& comment) +{ + if(!fp) open_fp(); + //no newline in comments allowed, as some viewers may crash + std::fputs("$comment\n", fp); + std::fputs(comment.c_str(), fp); + std::fputs("\n$end\n\n", fp); +} + +void +vcd_trace_file::cycle(bool this_is_a_delta_cycle) +{ + unsigned this_time_units_high, this_time_units_low; + + // Just to make g++ shut up in the optimized mode + this_time_units_high = this_time_units_low = 0; + + // Trace delta cycles only when enabled + if (!delta_cycles() && this_is_a_delta_cycle) return; + + // Check for initialization + if( initialize() ) { + return; + }; + + + double now_units = sc_time_stamp().to_seconds() / timescale_unit; + unsigned now_units_high, now_units_low; + double_to_special_int64(now_units, &now_units_high, &now_units_low ); + + bool now_later_than_previous_time = false; + if( (now_units_low > previous_time_units_low + && now_units_high == previous_time_units_high) + || now_units_high > previous_time_units_high){ + now_later_than_previous_time = true; + } + + bool now_equals_previous_time = false; + if(now_later_than_previous_time){ + this_time_units_high = now_units_high; + this_time_units_low = now_units_low; + } else { + if( now_units_low == previous_time_units_low + && now_units_high == previous_time_units_high){ + now_equals_previous_time = true; + this_time_units_high = now_units_high; + this_time_units_low = now_units_low; + } + } + + // Since VCD does not understand 0 time progression, we have to fake + // delta cycles with progressing time by one unit + if(this_is_a_delta_cycle){ + this_time_units_high = previous_time_units_high; + this_time_units_low = previous_time_units_low + 1; + if(this_time_units_low == 1000000000){ + this_time_units_high++; + this_time_units_low=0; + } + static bool warned = false; + if(!warned){ + SC_REPORT_INFO( SC_ID_TRACING_VCD_DELTA_CYCLE_ + , sc_time( timescale_unit, SC_SEC ) + .to_string().c_str() ); + warned = true; + } + } + + + // Not a delta cycle and time has not progressed + if( ! this_is_a_delta_cycle && now_equals_previous_time && + ( now_units_high != 0 || now_units_low != 0 ) ) { + // Don't print the message at time zero + static bool warned = false; + if( ! warned ) { + std::stringstream ss; + ss << "units count: " << now_units_low << "\n" + "\tWaveform viewers will only show the states of the last one.\n" + "\tUse `tracefile->set_time_unit(double, sc_time_unit);'" + " to increase the time resolution."; + SC_REPORT_WARNING( SC_ID_TRACING_VCD_DUPLICATE_TIME_ + , ss.str().c_str() ); + // warned = true; + } + } + + // Not a delta cycle and time has gone backward + // This will happen with large number of delta cycles between two real + // advances of time + if(!this_is_a_delta_cycle && !now_equals_previous_time && + !now_later_than_previous_time){ + static bool warned = false; + if(!warned) { + std::stringstream ss; + ss << "units count (" + << previous_time_units_low << "->" << now_units_low << ")\n" + "\tThis can occur when delta cycling is activated." + " Cycles with falling time are not shown.\n" + "\tUse `tracefile->set_time_unit(double, sc_time_unit);'" + " to increase the time resolution."; + SC_REPORT_WARNING( SC_ID_TRACING_VCD_DUPLICATE_TIME_ + , ss.str().c_str() ); + // warned = true; + } + // Note that we don't set this_time_units_high/low to any value only + // in this case because we are not going to do any tracing. In the + // optimized mode, the compiler complains because of this. Therefore, + // we include the lines at the very beginning of this function to make + // the compiler shut up. + return; + } + + // Now do the actual printing + bool time_printed = false; + vcd_trace* const* const l_traces = &traces[0]; + for (int i = 0; i < (int)traces.size(); i++) { + vcd_trace* t = l_traces[i]; + if(t->changed()){ + if(time_printed == false){ + char buf[200]; + if(this_time_units_high){ + std::sprintf(buf, "#%u%09u", this_time_units_high, this_time_units_low); + } + else{ + std::sprintf(buf, "#%u", this_time_units_low); + } + std::fputs(buf, fp); + std::fputc('\n', fp); + time_printed = true; + } + + // Write the variable + t->write(fp); + std::fputc('\n', fp); + } + } + // Put another newline after all values are printed + if(time_printed) std::fputc('\n', fp); + + if(time_printed){ + // We update previous_time_units only when we print time because + // this field stores the previous time that was printed, not the + // previous time this function was called + previous_time_units_high = this_time_units_high; + previous_time_units_low = this_time_units_low; + } +} + +#if 0 +void +vcd_trace_file::create_vcd_name(std::string* p_destination) +{ + obtain_name.swap( *p_destination ); +} +#endif + +// Create a VCD name for a variable +std::string +vcd_trace_file::obtain_name() +{ + const char first_type_used = 'a'; + const int used_types_count = 'z' - 'a' + 1; + int result; + + result = vcd_name_index; + char char6 = (char)(vcd_name_index % used_types_count); + + result = result / used_types_count; + char char5 = (char)(result % used_types_count); + + result = result / used_types_count; + char char4 = (char)(result % used_types_count); + + result = result / used_types_count; + char char3 = (char)(result % used_types_count); + + result = result / used_types_count; + char char2 = (char)(result % used_types_count); + + char buf[20]; + std::sprintf(buf, "%c%c%c%c%c", + char2 + first_type_used, + char3 + first_type_used, + char4 + first_type_used, + char5 + first_type_used, + char6 + first_type_used); + vcd_name_index++; + return std::string(buf); +} + +vcd_trace_file::~vcd_trace_file() +{ + for( int i = 0; i < (int)traces.size(); i++ ) { + vcd_trace* t = traces[i]; + delete t; + } +} + + +// Functions specific to VCD tracing + +static char +map_sc_logic_state_to_vcd_state(char in_char) +{ + char out_char; + + switch(in_char){ + case 'U': + case 'X': + case 'W': + case 'D': + out_char = 'x'; + break; + case '0': + case 'L': + out_char = '0'; + break; + case '1': + case 'H': + out_char = '1'; + break; + case 'Z': + out_char = 'z'; + break; + default: + out_char = '?'; + } + + return out_char; +} + + + + +static +void +remove_vcd_name_problems(vcd_trace const* vcd, std::string& name) +{ + static bool warned = false; + bool braces_removed = false; + for (unsigned int i = 0; i< name.length(); i++) { + if (name[i] == '[') { + name[i] = '('; + braces_removed = true; + } + else if (name[i] == ']') { + name[i] = ')'; + braces_removed = true; + } + } + + if(braces_removed && !warned){ + std::stringstream ss; + ss << vcd->name << ":\n" + "\tTraced objects found with name containing [], which may be\n" + "\tinterpreted by the waveform viewer in unexpected ways.\n" + "\tSo the [] is automatically replaced by ()."; + + SC_REPORT_WARNING( SC_ID_TRACING_OBJECT_NAME_FILTERED_ + , ss.str().c_str() ); + } +} + +// ---------------------------------------------------------------------------- + +sc_trace_file* +sc_create_vcd_trace_file(const char * name) +{ + sc_trace_file * tf = new vcd_trace_file(name); + return tf; +} + +void +sc_close_vcd_trace_file( sc_trace_file* tf ) +{ + vcd_trace_file* vcd_tf = static_cast<vcd_trace_file*>(tf); + delete vcd_tf; +} + +} // namespace sc_core diff --git a/ext/systemc/src/sysc/tracing/sc_vcd_trace.h b/ext/systemc/src/sysc/tracing/sc_vcd_trace.h new file mode 100644 index 000000000..760949ffb --- /dev/null +++ b/ext/systemc/src/sysc/tracing/sc_vcd_trace.h @@ -0,0 +1,228 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_vcd_trace.h - Implementation of VCD tracing. + + Original Author - Abhijit Ghosh, Synopsys, Inc. + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + +/***************************************************************************** + + Acknowledgement: The tracing mechanism is based on the tracing + mechanism developed at Infineon (formerly Siemens HL). Though this + code is somewhat different, and significantly enhanced, the basics + are identical to what was originally contributed by Infineon. The + contribution of Infineon in the development of this tracing + technology is hereby acknowledged. + + *****************************************************************************/ + +#ifndef SC_VCD_TRACE_H +#define SC_VCD_TRACE_H + +#include "sysc/tracing/sc_trace_file_base.h" + +namespace sc_core { + +class vcd_trace; // defined in vcd_trace.cpp +template<class T> class vcd_T_trace; + + +// ---------------------------------------------------------------------------- +// CLASS : vcd_trace_file +// +// ... +// ---------------------------------------------------------------------------- + +class vcd_trace_file + : public sc_trace_file_base +{ +public: + + enum vcd_enum {VCD_WIRE=0, VCD_REAL=1, VCD_LAST}; + + // sc_set_vcd_time_unit is deprecated. +#if 0 // deprecated + inline void sc_set_vcd_time_unit(int exponent10_seconds) + { set_time_unit(exponent10_seconds); } +#endif + + // Create a Vcd trace file. + // `Name' forms the base of the name to which `.vcd' is added. + vcd_trace_file(const char *name); + + // Flush results and close file. + ~vcd_trace_file(); + +protected: + + // These are all virtual functions in sc_trace_file and + // they need to be defined here. + + // Trace a boolean object (single bit) + void trace(const bool& object, const std::string& name); + + // Trace a sc_bit object (single bit) + virtual void trace( const sc_dt::sc_bit& object, + const std::string& name); + + // Trace a sc_logic object (single bit) + void trace(const sc_dt::sc_logic& object, const std::string& name); + + // Trace an unsigned char with the given width + void trace(const unsigned char& object, const std::string& name, + int width); + + // Trace an unsigned short with the given width + void trace(const unsigned short& object, const std::string& name, + int width); + + // Trace an unsigned int with the given width + void trace(const unsigned int& object, const std::string& name, + int width); + + // Trace an unsigned long with the given width + void trace(const unsigned long& object, const std::string& name, + int width); + + // Trace a signed char with the given width + void trace(const char& object, const std::string& name, int width); + + // Trace a signed short with the given width + void trace(const short& object, const std::string& name, int width); + + // Trace a signed int with the given width + void trace(const int& object, const std::string& name, int width); + + // Trace a signed long with the given width + void trace(const long& object, const std::string& name, int width); + + // Trace an int64 with a given width + void trace(const sc_dt::int64& object, const std::string& name, + int width); + + // Trace a uint64 with a given width + void trace(const sc_dt::uint64& object, const std::string& name, + int width); + + // Trace a float + void trace(const float& object, const std::string& name); + + // Trace a double + void trace(const double& object, const std::string& name); + + // Trace sc_dt::sc_uint_base + void trace (const sc_dt::sc_uint_base& object, + const std::string& name); + + // Trace sc_dt::sc_int_base + void trace (const sc_dt::sc_int_base& object, + const std::string& name); + + // Trace sc_dt::sc_unsigned + void trace (const sc_dt::sc_unsigned& object, + const std::string& name); + + // Trace sc_dt::sc_signed + void trace (const sc_dt::sc_signed& object, const std::string& name); + + // Trace sc_dt::sc_fxval + void trace( const sc_dt::sc_fxval& object, const std::string& name ); + + // Trace sc_dt::sc_fxval_fast + void trace( const sc_dt::sc_fxval_fast& object, + const std::string& name ); + + // Trace sc_dt::sc_fxnum + void trace( const sc_dt::sc_fxnum& object, const std::string& name ); + + // Trace sc_dt::sc_fxnum_fast + void trace( const sc_dt::sc_fxnum_fast& object, + const std::string& name ); + + template<class T> + void traceT(const T& object, const std::string& name, + vcd_enum type=VCD_WIRE) + { + if( add_trace_check(name) ) + traces.push_back(new vcd_T_trace<T>( object, name + , obtain_name(),type) ); + } + + // Trace sc_dt::sc_bv_base (sc_dt::sc_bv) + virtual void trace(const sc_dt::sc_bv_base& object, + const std::string& name); + + // Trace sc_dt::sc_lv_base (sc_dt::sc_lv) + virtual void trace(const sc_dt::sc_lv_base& object, + const std::string& name); + // Trace an enumerated object - where possible output the enumeration literals + // in the trace file. Enum literals is a null terminated array of null + // terminated char* literal strings. + void trace(const unsigned& object, const std::string& name, + const char** enum_literals); + + // Output a comment to the trace file + void write_comment(const std::string& comment); + + // Write trace info for cycle. + void cycle(bool delta_cycle); + +private: + +#if SC_TRACING_PHASE_CALLBACKS_ + // avoid hidden overload warnings + virtual void trace( sc_trace_file* ) const { sc_assert(false); } +#endif // SC_TRACING_PHASE_CALLBACKS_ + + // Initialize the VCD tracing + virtual void do_initialize(); + + unsigned vcd_name_index; // Number of variables traced + + unsigned previous_time_units_low; // Previous time unit as 64-bit integer + unsigned previous_time_units_high; + +public: + + // Array to store the variables traced + std::vector<vcd_trace*> traces; + + // Create VCD names for each variable + std::string obtain_name(); + +}; + +} // namespace sc_core + +#endif // SC_VCD_TRACE_H +// Taf! diff --git a/ext/systemc/src/sysc/tracing/sc_wif_trace.cpp b/ext/systemc/src/sysc/tracing/sc_wif_trace.cpp new file mode 100644 index 000000000..b2bacee7d --- /dev/null +++ b/ext/systemc/src/sysc/tracing/sc_wif_trace.cpp @@ -0,0 +1,1911 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_wif_trace.cpp - Implementation of WIF tracing. + + Original Author - Abhijit Ghosh, Synopsys, Inc. + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affliation, date and + changes you are making here. + + Name, Affiliation, Date: Ali Dasdan, Synopsys, Inc. + Description of Modification: - Replaced 'width' of sc_(u)int with their + 'bitwidth()'. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + +/***************************************************************************** + + Acknowledgement: The tracing mechanism is based on the tracing + mechanism developed at Infineon (formerly Siemens HL). Though this + code is somewhat different, and significantly enhanced, the basics + are identical to what was originally contributed by Infineon. The + contribution of Infineon in the development of this tracing + technology is hereby acknowledged. + + *****************************************************************************/ + +/***************************************************************************** + + Instead of creating the binary WIF format, we create the ASCII + WIF format which can be converted to the binary format using + a2wif (utility that comes with VSS from Synopsys). This way, + a user who does not have Synopsys VSS can still create WIF + files, but they can only be viewed by users who have VSS. + + *****************************************************************************/ + + +#include <cstdlib> +#include <vector> + +#define SC_DISABLE_API_VERSION_CHECK // for in-library sc_ver.h inclusion + +#include "sysc/kernel/sc_simcontext.h" +#include "sysc/kernel/sc_ver.h" +#include "sysc/datatypes/bit/sc_bit.h" +#include "sysc/datatypes/bit/sc_logic.h" +#include "sysc/datatypes/bit/sc_lv_base.h" +#include "sysc/datatypes/int/sc_signed.h" +#include "sysc/datatypes/int/sc_unsigned.h" +#include "sysc/datatypes/int/sc_int_base.h" +#include "sysc/datatypes/int/sc_uint_base.h" +#include "sysc/datatypes/fx/fx.h" +#include "sysc/tracing/sc_wif_trace.h" + +namespace sc_core { + +// Forward declarations for functions that come later in the file +static char map_sc_logic_state_to_wif_state(char in_char); + +const char* wif_names[wif_trace_file::WIF_LAST] = {"BIT","MVL","real"}; + + +// ---------------------------------------------------------------------------- +// CLASS : wif_trace +// +// Base class for WIF traces. +// ---------------------------------------------------------------------------- + +class wif_trace +{ +public: + + wif_trace(const std::string& name_, const std::string& wif_name_); + + // Needs to be pure virtual as has to be defined by the particular + // type being traced + virtual void write(FILE* f) = 0; + + virtual void set_width(); + + // Comparison function needs to be pure virtual too + virtual bool changed() = 0; + + // Got to declare this virtual as this will be overwritten + // by one base class + virtual void print_variable_declaration_line(FILE* f); + + virtual ~wif_trace(); + + const std::string name; // Name of the variable + const std::string wif_name; // Name of the variable in WIF file + const char* wif_type; // WIF data type + int bit_width; +}; + + +wif_trace::wif_trace(const std::string& name_, + const std::string& wif_name_) + : name(name_), wif_name(wif_name_), wif_type(0), bit_width(-1) +{ + /* Intentionally blank */ +} + +void +wif_trace::print_variable_declaration_line( FILE* f ) +{ + if( bit_width < 0 ) + { + std::stringstream ss; + ss << "'" << name << "' has < 0 bits"; + SC_REPORT_ERROR( SC_ID_TRACING_OBJECT_IGNORED_ + , ss.str().c_str() ); + return; + } + + std::fprintf( f, "declare %s \"%s\" %s ", + wif_name.c_str(), name.c_str(), wif_type ); + + if( bit_width > 0 ) { + std::fprintf( f, "0 %d ", bit_width - 1 ); + } + std::fprintf( f, "variable ;\n" ); + std::fprintf( f, "start_trace %s ;\n", wif_name.c_str() ); +} + +void +wif_trace::set_width() +{ + /* Intentionally Blank, should be defined for each type separately */ +} + +wif_trace::~wif_trace() +{ + /* Intentionally Blank */ +} + +// Classes for tracing individual data types + +/*****************************************************************************/ + +class wif_uint64_trace: public wif_trace { +public: + wif_uint64_trace(const sc_dt::uint64& object_, + const std::string& name_, + const std::string& wif_name_, + int width_); + void write(FILE* f); + bool changed(); + +protected: + const sc_dt::uint64& object; + sc_dt::uint64 old_value; + sc_dt::uint64 mask; +}; + + +wif_uint64_trace::wif_uint64_trace(const sc_dt::uint64& object_, + const std::string& name_, + const std::string& wif_name_, + int width_) +: wif_trace(name_, wif_name_), object(object_), old_value(object_), + mask(static_cast<sc_dt::uint64>(-1)) +{ + bit_width = width_; + if (bit_width < (int)(sizeof(sc_dt::uint64)*BITS_PER_BYTE)) + mask = ~(mask << bit_width); + wif_type = "BIT"; +} + + +bool wif_uint64_trace::changed() +{ + return object != old_value; +} + + +void wif_uint64_trace::write(FILE* f) +{ + char buf[1000]; + int bitindex; + + // Check for overflow + if ((object & mask) != object) + { + for (bitindex = 0; bitindex < bit_width; bitindex++) + { + buf[bitindex]='0'; + } + } + else + { + sc_dt::uint64 bit_mask = 1; + bit_mask = bit_mask << (bit_width-1); + for (bitindex = 0; bitindex < bit_width; bitindex++) + { + buf[bitindex] = (object & bit_mask)? '1' : '0'; + bit_mask = bit_mask >> 1; + } + } + buf[bitindex] = '\0'; + std::fprintf(f, "assign %s \"%s\" ;\n", wif_name.c_str(), buf); + old_value = object; +} + +/*****************************************************************************/ + +class wif_int64_trace: public wif_trace { +public: + wif_int64_trace(const sc_dt::int64& object_, + const std::string& name_, + const std::string& wif_name_, + int width_); + void write(FILE* f); + bool changed(); + +protected: + const sc_dt::int64& object; + sc_dt::int64 old_value; + sc_dt::uint64 mask; +}; + + +wif_int64_trace::wif_int64_trace(const sc_dt::int64& object_, + const std::string& name_, + const std::string& wif_name_, + int width_) +: wif_trace(name_, wif_name_), object(object_), old_value(object_), + mask(static_cast<sc_dt::uint64>(-1)) +{ + bit_width = width_; + if (bit_width < (int)(sizeof(sc_dt::int64)*BITS_PER_BYTE)) + mask = ~(mask << bit_width); + wif_type = "BIT"; +} + + +bool wif_int64_trace::changed() +{ + return object != old_value; +} + + +void wif_int64_trace::write(FILE* f) +{ + char buf[1000]; + int bitindex; + + // Check for overflow + if ((object & mask) != (sc_dt::uint64)object) + { + for (bitindex = 0; bitindex < bit_width; bitindex++) + { + buf[bitindex]='0'; + } + } + else + { + sc_dt::uint64 bit_mask = 1; + bit_mask = bit_mask << (bit_width-1); + for (bitindex = 0; bitindex < bit_width; bitindex++) + { + buf[bitindex] = (object & bit_mask)? '1' : '0'; + bit_mask = bit_mask >> 1; + } + } + buf[bitindex] = '\0'; + std::fprintf(f, "assign %s \"%s\" ;\n", wif_name.c_str(), buf); + old_value = object; +} + +/*****************************************************************************/ + +class wif_bool_trace +: public wif_trace +{ +public: + + wif_bool_trace( const bool& object_, + const std::string& name_, + const std::string& wif_name_ ); + void write( FILE* f ); + bool changed(); + +protected: + + const bool& object; + bool old_value; +}; + +wif_bool_trace::wif_bool_trace( const bool& object_, + const std::string& name_, + const std::string& wif_name_ ) +: wif_trace( name_, wif_name_ ), object( object_ ), old_value( object_ ) +{ + bit_width = 0; + wif_type = "BIT"; +} + +bool +wif_bool_trace::changed() +{ + return object != old_value; +} + +void +wif_bool_trace::write( FILE* f ) +{ + if( object == true ) { + std::fprintf( f, "assign %s \'1\' ;\n", wif_name.c_str() ); + } else { + std::fprintf( f, "assign %s \'0\' ;\n", wif_name.c_str() ); + } + old_value = object; +} + +//***************************************************************************** + +class wif_sc_bit_trace : public wif_trace { +public: + wif_sc_bit_trace(const sc_dt::sc_bit& object_, + const std::string& name_, + const std::string& wif_name_); + void write(FILE* f); + bool changed(); + +protected: + const sc_dt::sc_bit& object; + sc_dt::sc_bit old_value; +}; + +wif_sc_bit_trace::wif_sc_bit_trace(const sc_dt::sc_bit& object_, + const std::string& name_, + const std::string& wif_name_) +: wif_trace(name_, wif_name_), object(object_), old_value(object_) +{ + bit_width = 0; + wif_type = "BIT"; +} + +bool wif_sc_bit_trace::changed() +{ + return object != old_value; +} + +void wif_sc_bit_trace::write(FILE* f) +{ + if (object == true) { + std::fprintf(f, "assign %s \'1\' ;\n", wif_name.c_str()); + } else { + std::fprintf(f, "assign %s \'0\' ;\n", wif_name.c_str()); + } + old_value = object; +} + +/*****************************************************************************/ + +class wif_sc_logic_trace: public wif_trace { +public: + wif_sc_logic_trace(const sc_dt::sc_logic& object_, + const std::string& name_, + const std::string& wif_name_); + void write(FILE* f); + bool changed(); + +protected: + const sc_dt::sc_logic& object; + sc_dt::sc_logic old_value; +}; + + +wif_sc_logic_trace::wif_sc_logic_trace(const sc_dt::sc_logic& object_, + const std::string& name_, + const std::string& wif_name_) +: wif_trace(name_, wif_name_), object(object_), old_value(object_) +{ + bit_width = 0; + wif_type = "MVL"; +} + + +bool wif_sc_logic_trace::changed() +{ + return object != old_value; +} + + +void wif_sc_logic_trace::write(FILE* f) +{ + char wif_char; + std::fprintf(f, "assign %s \'", wif_name.c_str()); + wif_char = map_sc_logic_state_to_wif_state(object.to_char()); + std::fputc(wif_char, f); + std::fprintf(f,"\' ;\n"); + old_value = object; +} + + +/*****************************************************************************/ + +class wif_sc_unsigned_trace: public wif_trace { +public: + wif_sc_unsigned_trace(const sc_dt::sc_unsigned& object_, + const std::string& name_, + const std::string& wif_name_); + void write(FILE* f); + bool changed(); + void set_width(); + +protected: + const sc_dt::sc_unsigned& object; + sc_dt::sc_unsigned old_value; +}; + + +wif_sc_unsigned_trace::wif_sc_unsigned_trace(const sc_dt::sc_unsigned& object_, + const std::string& name_, + const std::string& wif_name_) +: wif_trace(name_, wif_name_), object(object_), old_value(object_.length()) +{ + old_value = object; + wif_type = "BIT"; +} + +bool wif_sc_unsigned_trace::changed() +{ + return object != old_value; +} + +void wif_sc_unsigned_trace::write(FILE* f) +{ + static std::vector<char> buf(1024); + typedef std::vector<char>::size_type size_t; + + if ( buf.size() < (size_t)object.length() ) { + size_t sz = ( (size_t)object.length() + 4096 ) & (~(size_t)(4096-1)); + std::vector<char>( sz ).swap( buf ); // resize without copying values + } + char *buf_ptr = &buf[0]; + + for(int bitindex = object.length() - 1; bitindex >= 0; --bitindex) { + *buf_ptr++ = "01"[object[bitindex].to_bool()]; + } + *buf_ptr = '\0'; + std::fprintf(f, "assign %s \"%s\" ;\n", wif_name.c_str(), &buf[0]); + old_value = object; +} + +void wif_sc_unsigned_trace::set_width() +{ + bit_width = object.length(); +} + + +/*****************************************************************************/ + +class wif_sc_signed_trace: public wif_trace { +public: + wif_sc_signed_trace(const sc_dt::sc_signed& object_, + const std::string& name_, + const std::string& wif_name_); + void write(FILE* f); + bool changed(); + void set_width(); + +protected: + const sc_dt::sc_signed& object; + sc_dt::sc_signed old_value; +}; + + +wif_sc_signed_trace::wif_sc_signed_trace(const sc_dt::sc_signed& object_, + const std::string& name_, + const std::string& wif_name_) +: wif_trace(name_, wif_name_), object(object_), old_value(object_.length()) +{ + old_value = object; + wif_type = "BIT"; +} + +bool wif_sc_signed_trace::changed() +{ + return object != old_value; +} + +void wif_sc_signed_trace::write(FILE* f) +{ + static std::vector<char> buf(1024); + typedef std::vector<char>::size_type size_t; + + if ( buf.size() < (size_t)object.length() ) { + size_t sz = ( (size_t)object.length() + 4096 ) & (~(size_t)(4096-1)); + std::vector<char>( sz ).swap( buf ); // resize without copying values + } + char *buf_ptr = &buf[0]; + + for(int bitindex = object.length() - 1; bitindex >= 0; --bitindex) { + *buf_ptr++ = "01"[object[bitindex].to_bool()]; + } + *buf_ptr = '\0'; + + std::fprintf(f, "assign %s \"%s\" ;\n", wif_name.c_str(), &buf[0]); + old_value = object; +} + +void wif_sc_signed_trace::set_width() +{ + bit_width = object.length(); +} + +/*****************************************************************************/ + +class wif_sc_uint_base_trace: public wif_trace { +public: + wif_sc_uint_base_trace(const sc_dt::sc_uint_base& object_, + const std::string& name_, + const std::string& wif_name_); + void write(FILE* f); + bool changed(); + void set_width(); + +protected: + const sc_dt::sc_uint_base& object; + sc_dt::sc_uint_base old_value; +}; + + +wif_sc_uint_base_trace::wif_sc_uint_base_trace( + const sc_dt::sc_uint_base& object_, + const std::string& name_, + const std::string& wif_name_) +: wif_trace(name_, wif_name_), object(object_), old_value(object_.length()) +{ + old_value = object; + wif_type = "BIT"; +} + +bool wif_sc_uint_base_trace::changed() +{ + return object != old_value; +} + +void wif_sc_uint_base_trace::write(FILE* f) +{ + char buf[1000], *buf_ptr = buf; + + int bitindex; + for(bitindex = object.length() - 1; bitindex >= 0; --bitindex) { + *buf_ptr++ = "01"[object[bitindex].to_bool()]; + } + *buf_ptr = '\0'; + std::fprintf(f, "assign %s \"%s\" ;\n", wif_name.c_str(), buf); + old_value = object; +} + +void wif_sc_uint_base_trace::set_width() +{ + bit_width = object.length(); +} + + +/*****************************************************************************/ + +class wif_sc_int_base_trace: public wif_trace { +public: + wif_sc_int_base_trace(const sc_dt::sc_int_base& object_, + const std::string& name_, + const std::string& wif_name_); + void write(FILE* f); + bool changed(); + void set_width(); + +protected: + const sc_dt::sc_int_base& object; + sc_dt::sc_int_base old_value; +}; + + +wif_sc_int_base_trace::wif_sc_int_base_trace(const sc_dt::sc_int_base& object_, + const std::string& name_, + const std::string& wif_name_) +: wif_trace(name_, wif_name_), object(object_), old_value(object_.length()) +{ + old_value = object; + wif_type = "BIT"; +} + +bool wif_sc_int_base_trace::changed() +{ + return object != old_value; +} + +void wif_sc_int_base_trace::write(FILE* f) +{ + char buf[1000], *buf_ptr = buf; + + int bitindex; + for(bitindex = object.length() - 1; bitindex >= 0; --bitindex) { + *buf_ptr++ = "01"[object[bitindex].to_bool()]; + } + *buf_ptr = '\0'; + + std::fprintf(f, "assign %s \"%s\" ;\n", wif_name.c_str(), buf); + old_value = object; +} + +void wif_sc_int_base_trace::set_width() +{ + bit_width = object.length(); +} + + +/*****************************************************************************/ + +class wif_sc_fxval_trace: public wif_trace +{ +public: + + wif_sc_fxval_trace( const sc_dt::sc_fxval& object_, + const std::string& name_, + const std::string& wif_name_ ); + void write( FILE* f ); + bool changed(); + +protected: + + const sc_dt::sc_fxval& object; + sc_dt::sc_fxval old_value; + +}; + +wif_sc_fxval_trace::wif_sc_fxval_trace( const sc_dt::sc_fxval& object_, + const std::string& name_, + const std::string& wif_name_ ) +: wif_trace( name_, wif_name_ ), object( object_ ), old_value( object_ ) +{ + bit_width = 0; + wif_type = "real"; +} + +bool +wif_sc_fxval_trace::changed() +{ + return object != old_value; +} + +void +wif_sc_fxval_trace::write( FILE* f ) +{ + std::fprintf( f, "assign %s %f ; \n", wif_name.c_str(), object.to_double() ); + old_value = object; +} + +/*****************************************************************************/ + +class wif_sc_fxval_fast_trace: public wif_trace +{ +public: + + wif_sc_fxval_fast_trace( const sc_dt::sc_fxval_fast& object_, + const std::string& name_, + const std::string& wif_name_ ); + void write( FILE* f ); + bool changed(); + +protected: + + const sc_dt::sc_fxval_fast& object; + sc_dt::sc_fxval_fast old_value; + +}; + +wif_sc_fxval_fast_trace::wif_sc_fxval_fast_trace( + const sc_dt::sc_fxval_fast& object_, + const std::string& name_, + const std::string& wif_name_ ) +: wif_trace(name_, wif_name_), object( object_ ), old_value( object_ ) +{ + bit_width = 0; + wif_type = "real"; +} + +bool +wif_sc_fxval_fast_trace::changed() +{ + return object != old_value; +} + +void +wif_sc_fxval_fast_trace::write( FILE* f ) +{ + std::fprintf( f, "assign %s %f ; \n", wif_name.c_str(), object.to_double() ); + old_value = object; +} + +/*****************************************************************************/ + +class wif_sc_fxnum_trace: public wif_trace +{ +public: + + wif_sc_fxnum_trace( const sc_dt::sc_fxnum& object_, + const std::string& name_, + const std::string& wif_name_ ); + void write( FILE* f ); + bool changed(); + void set_width(); + +protected: + + const sc_dt::sc_fxnum& object; + sc_dt::sc_fxnum old_value; + +}; + +wif_sc_fxnum_trace::wif_sc_fxnum_trace( const sc_dt::sc_fxnum& object_, + const std::string& name_, + const std::string& wif_name_ ) +: wif_trace( name_, wif_name_ ), + object( object_ ), + old_value( object_.m_params.type_params(), + object_.m_params.enc(), + object_.m_params.cast_switch(), + 0 ) +{ + old_value = object; + wif_type = "BIT"; +} + +bool +wif_sc_fxnum_trace::changed() +{ + return object != old_value; +} + +void +wif_sc_fxnum_trace::write( FILE* f ) +{ + static std::vector<char> buf(1024); + typedef std::vector<char>::size_type size_t; + + if ( buf.size() < (size_t)object.wl() ) { + size_t sz = ( (size_t)object.wl() + 4096 ) & (~(size_t)(4096-1)); + std::vector<char>( sz ).swap( buf ); // resize without copying values + } + char *buf_ptr = &buf[0]; + + for(int bitindex = object.wl() - 1; bitindex >= 0; --bitindex) + { + *buf_ptr ++ = "01"[object[bitindex]]; + } + *buf_ptr = '\0'; + + std::fprintf( f, "assign %s \"%s\" ;\n", wif_name.c_str(), &buf[0]); + old_value = object; +} + +void +wif_sc_fxnum_trace::set_width() +{ + bit_width = object.wl(); +} + +/*****************************************************************************/ + +class wif_sc_fxnum_fast_trace: public wif_trace +{ +public: + + wif_sc_fxnum_fast_trace( const sc_dt::sc_fxnum_fast& object_, + const std::string& name_, + const std::string& wif_name_ ); + void write( FILE* f ); + bool changed(); + void set_width(); + +protected: + + const sc_dt::sc_fxnum_fast& object; + sc_dt::sc_fxnum_fast old_value; + +}; + +wif_sc_fxnum_fast_trace::wif_sc_fxnum_fast_trace( + const sc_dt::sc_fxnum_fast& object_, + const std::string& name_, + const std::string& wif_name_ ) +: wif_trace( name_, wif_name_ ), + object( object_ ), + old_value( object_.m_params.type_params(), + object_.m_params.enc(), + object_.m_params.cast_switch(), + 0 ) +{ + old_value = object; + wif_type = "BIT"; +} + +bool +wif_sc_fxnum_fast_trace::changed() +{ + return object != old_value; +} + +void +wif_sc_fxnum_fast_trace::write( FILE* f ) +{ + static std::vector<char> buf(1024); + typedef std::vector<char>::size_type size_t; + + if ( buf.size() < (size_t)object.wl() ) { + size_t sz = ( (size_t)object.wl() + 4096 ) & (~(size_t)(4096-1)); + std::vector<char>( sz ).swap( buf ); // resize without copying values + } + char *buf_ptr = &buf[0]; + + for(int bitindex = object.wl() - 1; bitindex >= 0; --bitindex) + { + *buf_ptr ++ = "01"[object[bitindex]]; + } + *buf_ptr = '\0'; + + std::fprintf( f, "assign %s \"%s\" ;\n", wif_name.c_str(), &buf[0]); + old_value = object; +} + +void +wif_sc_fxnum_fast_trace::set_width() +{ + bit_width = object.wl(); +} + + +/*****************************************************************************/ + +class wif_unsigned_int_trace: public wif_trace { +public: + wif_unsigned_int_trace(const unsigned& object_, + const std::string& name_, + const std::string& wif_name_, int width_); + void write(FILE* f); + bool changed(); + +protected: + const unsigned& object; + unsigned old_value; + unsigned mask; +}; + + +wif_unsigned_int_trace::wif_unsigned_int_trace(const unsigned& object_, + const std::string& name_, + const std::string& wif_name_, + int width_) +: wif_trace(name_, wif_name_), object(object_), old_value(object_), + mask(0xffffffff) +{ + bit_width = width_; + if (bit_width < 32) { + mask = ~(-1 << bit_width); + } + + wif_type = "BIT"; +} + + +bool wif_unsigned_int_trace::changed() +{ + return object != old_value; +} + + +void wif_unsigned_int_trace::write(FILE* f) +{ + char buf[1000]; + int bitindex; + + // Check for overflow + if ((object & mask) != object) { + for (bitindex = 0; bitindex < bit_width; bitindex++){ + buf[bitindex] = '0'; + } + } + else{ + unsigned bit_mask = 1 << (bit_width-1); + for (bitindex = 0; bitindex < bit_width; bitindex++) { + buf[bitindex] = (object & bit_mask)? '1' : '0'; + bit_mask = bit_mask >> 1; + } + } + buf[bitindex] = '\0'; + std::fprintf(f, "assign %s \"%s\" ;\n", wif_name.c_str(), buf); + old_value = object; +} + + +/*****************************************************************************/ + +class wif_unsigned_short_trace: public wif_trace { +public: + wif_unsigned_short_trace(const unsigned short& object_, + const std::string& name_, + const std::string& wif_name_, + int width_); + void write(FILE* f); + bool changed(); + +protected: + const unsigned short& object; + unsigned short old_value; + unsigned short mask; +}; + + +wif_unsigned_short_trace::wif_unsigned_short_trace( + const unsigned short& object_, + const std::string& name_, + const std::string& wif_name_, + int width_) +: wif_trace(name_, wif_name_), object(object_), old_value(object_), mask(0xffff) +{ + bit_width = width_; + if (bit_width < 16) { + mask = (unsigned short)~(-1 << bit_width); + } + + wif_type = "BIT"; +} + + +bool wif_unsigned_short_trace::changed() +{ + return object != old_value; +} + + +void wif_unsigned_short_trace::write(FILE* f) +{ + char buf[1000]; + int bitindex; + + // Check for overflow + if ((object & mask) != object) { + for (bitindex = 0; bitindex < bit_width; bitindex++){ + buf[bitindex]='0'; + } + } + else{ + unsigned bit_mask = 1 << (bit_width-1); + for (bitindex = 0; bitindex < bit_width; bitindex++) { + buf[bitindex] = (object & bit_mask)? '1' : '0'; + bit_mask = bit_mask >> 1; + } + } + buf[bitindex] = '\0'; + std::fprintf(f, "assign %s \"%s\" ;\n", wif_name.c_str(), buf); + old_value = object; +} + +/*****************************************************************************/ + +class wif_unsigned_char_trace: public wif_trace { +public: + wif_unsigned_char_trace(const unsigned char& object_, + const std::string& name_, + const std::string& wif_name_, + int width_); + void write(FILE* f); + bool changed(); + +protected: + const unsigned char& object; + unsigned char old_value; + unsigned char mask; +}; + + +wif_unsigned_char_trace::wif_unsigned_char_trace(const unsigned char& object_, + const std::string& name_, + const std::string& wif_name_, + int width_) +: wif_trace(name_, wif_name_), object(object_), old_value(object_), mask(0xff) +{ + bit_width = width_; + if (bit_width < 8) { + mask = (unsigned char)~(-1 << bit_width); + } + + wif_type = "BIT"; +} + + +bool wif_unsigned_char_trace::changed() +{ + return object != old_value; +} + + +void wif_unsigned_char_trace::write(FILE* f) +{ + char buf[1000]; + int bitindex; + + // Check for overflow + if ((object & mask) != object) { + for (bitindex = 0; bitindex < bit_width; bitindex++){ + buf[bitindex]='0'; + } + } + else{ + unsigned bit_mask = 1 << (bit_width-1); + for (bitindex = 0; bitindex < bit_width; bitindex++) { + buf[bitindex] = (object & bit_mask)? '1' : '0'; + bit_mask = bit_mask >> 1; + } + } + buf[bitindex] = '\0'; + std::fprintf(f, "assign %s \"%s\" ;\n", wif_name.c_str(), buf); + old_value = object; +} + +/*****************************************************************************/ + +class wif_unsigned_long_trace: public wif_trace { +public: + wif_unsigned_long_trace(const unsigned long& object_, + const std::string& name_, + const std::string& wif_name_, + int width_); + void write(FILE* f); + bool changed(); + +protected: + const unsigned long& object; + unsigned long old_value; + unsigned long mask; +}; + + +wif_unsigned_long_trace::wif_unsigned_long_trace(const unsigned long& object_, + const std::string& name_, + const std::string& wif_name_, + int width_) +: wif_trace(name_, wif_name_), object(object_), old_value(object_), + mask((unsigned long)-1L) +{ + bit_width = width_; + if (bit_width < (int)(sizeof(unsigned long)*BITS_PER_BYTE)) { + mask = ~(-1L << bit_width); + } + + wif_type = "BIT"; +} + + +bool wif_unsigned_long_trace::changed() +{ + return object != old_value; +} + + +void wif_unsigned_long_trace::write(FILE* f) +{ + char buf[1000]; + int bitindex; + + // Check for overflow + if ((object & mask) != object) { + for (bitindex = 0; bitindex < bit_width; bitindex++){ + buf[bitindex]='0'; + } + } + else{ + unsigned long bit_mask = 1ul << (bit_width-1); + for (bitindex = 0; bitindex < bit_width; bitindex++) { + buf[bitindex] = (object & bit_mask)? '1' : '0'; + bit_mask = bit_mask >> 1; + } + } + buf[bitindex] = '\0'; + std::fprintf(f, "assign %s \"%s\" ;\n", wif_name.c_str(), buf); + old_value = object; +} + +/*****************************************************************************/ + +class wif_signed_int_trace: public wif_trace { +public: + wif_signed_int_trace(const int& object_, + const std::string& name_, + const std::string& wif_name_, + int width_); + void write(FILE* f); + bool changed(); + +protected: + const int& object; + int old_value; + unsigned mask; +}; + + +wif_signed_int_trace::wif_signed_int_trace(const signed& object_, + const std::string& name_, + const std::string& wif_name_, + int width_) +: wif_trace(name_, wif_name_), object(object_), old_value(object_), + mask(0xffffffff) +{ + bit_width = width_; + if (bit_width < 32) { + mask = ~(-1 << bit_width); + } + + wif_type = "BIT"; +} + + +bool wif_signed_int_trace::changed() +{ + return object != old_value; +} + + +void wif_signed_int_trace::write(FILE* f) +{ + char buf[1000]; + int bitindex; + + // Check for overflow + if (((unsigned) object & mask) != (unsigned) object) { + for (bitindex = 0; bitindex < bit_width; bitindex++){ + buf[bitindex]='0'; + } + } + else{ + unsigned bit_mask = 1 << (bit_width-1); + for (bitindex = 0; bitindex < bit_width; bitindex++) { + buf[bitindex] = (object & bit_mask)? '1' : '0'; + bit_mask = bit_mask >> 1; + } + } + buf[bitindex] = '\0'; + std::fprintf(f, "assign %s \"%s\" ;\n", wif_name.c_str(), buf); + old_value = object; +} + +/*****************************************************************************/ + +class wif_signed_short_trace: public wif_trace { +public: + wif_signed_short_trace(const short& object_, + const std::string& name_, + const std::string& wif_name_, + int width_); + void write(FILE* f); + bool changed(); + +protected: + const short& object; + short old_value; + unsigned short mask; +}; + + +wif_signed_short_trace::wif_signed_short_trace(const short& object_, + const std::string& name_, + const std::string& wif_name_, + int width_) +: wif_trace(name_, wif_name_), object(object_), old_value(object_), mask(0xffff) +{ + bit_width = width_; + if (bit_width < 16) { + mask = (unsigned short)~(-1 << bit_width); + } + + wif_type = "BIT"; +} + + +bool wif_signed_short_trace::changed() +{ + return object != old_value; +} + + +void wif_signed_short_trace::write(FILE* f) +{ + char buf[1000]; + int bitindex; + + // Check for overflow + if (((unsigned short) object & mask) != (unsigned short) object) { + for (bitindex = 0; bitindex < bit_width; bitindex++){ + buf[bitindex]='0'; + } + } + else{ + unsigned bit_mask = 1 << (bit_width-1); + for (bitindex = 0; bitindex < bit_width; bitindex++) { + buf[bitindex] = (object & bit_mask)? '1' : '0'; + bit_mask = bit_mask >> 1; + } + } + buf[bitindex] = '\0'; + std::fprintf(f, "assign %s \"%s\" ;\n", wif_name.c_str(), buf); + old_value = object; +} + +/*****************************************************************************/ + +class wif_signed_char_trace: public wif_trace { +public: + wif_signed_char_trace(const char& object_, + const std::string& name_, + const std::string& wif_name_, + int width_); + void write(FILE* f); + bool changed(); + +protected: + const char& object; + char old_value; + unsigned char mask; +}; + + +wif_signed_char_trace::wif_signed_char_trace(const char& object_, + const std::string& name_, + const std::string& wif_name_, + int width_) +: wif_trace(name_, wif_name_), object(object_), old_value(object_), mask(0xff) +{ + bit_width = width_; + if (bit_width < 8) { + mask = (unsigned char)~(-1 << bit_width); + } + + wif_type = "BIT"; +} + + +bool wif_signed_char_trace::changed() +{ + return object != old_value; +} + + +void wif_signed_char_trace::write(FILE* f) +{ + char buf[1000]; + int bitindex; + + // Check for overflow + if (((unsigned char) object & mask) != (unsigned char) object) { + for (bitindex = 0; bitindex < bit_width; bitindex++){ + buf[bitindex]='0'; + } + } + else{ + unsigned bit_mask = 1 << (bit_width-1); + for (bitindex = 0; bitindex < bit_width; bitindex++) { + buf[bitindex] = (object & bit_mask)? '1' : '0'; + bit_mask = bit_mask >> 1; + } + } + buf[bitindex] = '\0'; + std::fprintf(f, "assign %s \"%s\" ;\n", wif_name.c_str(), buf); + old_value = object; +} + +/*****************************************************************************/ + +class wif_signed_long_trace: public wif_trace { +public: + wif_signed_long_trace(const long& object_, + const std::string& name_, + const std::string& wif_name_, + int width_); + void write(FILE* f); + bool changed(); + +protected: + const long& object; + long old_value; + unsigned long mask; +}; + + +wif_signed_long_trace::wif_signed_long_trace(const long& object_, + const std::string& name_, + const std::string& wif_name_, + int width_) +: wif_trace(name_, wif_name_), object(object_), old_value(object_), + mask((unsigned long)-1L) +{ + bit_width = width_; + if (bit_width < (int)(sizeof(long)*BITS_PER_BYTE)) { + mask = ~(-1L << bit_width); + } + + wif_type = "BIT"; +} + + +bool wif_signed_long_trace::changed() +{ + return object != old_value; +} + + +void wif_signed_long_trace::write(FILE* f) +{ + char buf[1000]; + int bitindex; + + // Check for overflow + if (((unsigned long) object & mask) != (unsigned long) object) { + for (bitindex = 0; bitindex < bit_width; bitindex++){ + buf[bitindex]='0'; + } + } else { + unsigned long bit_mask = 1ul << (bit_width-1); + for (bitindex = 0; bitindex < bit_width; bitindex++) { + buf[bitindex] = (object & bit_mask)? '1' : '0'; + bit_mask = bit_mask >> 1; + } + } + buf[bitindex] = '\0'; + std::fprintf(f, "assign %s \"%s\" ;\n", wif_name.c_str(), buf); + old_value = object; +} + + +/*****************************************************************************/ + +class wif_float_trace: public wif_trace { +public: + wif_float_trace(const float& object_, + const std::string& name_, + const std::string& wif_name_); + void write(FILE* f); + bool changed(); + +protected: + const float& object; + float old_value; +}; + +wif_float_trace::wif_float_trace(const float& object_, + const std::string& name_, + const std::string& wif_name_) +: wif_trace(name_, wif_name_), object(object_), old_value(object_) +{ + bit_width = 0; + wif_type = "real"; +} + +bool wif_float_trace::changed() +{ + return object != old_value; +} + +void wif_float_trace::write(FILE* f) +{ + std::fprintf(f,"assign %s %f ; \n", wif_name.c_str(), object); + old_value = object; +} + +/*****************************************************************************/ + +class wif_double_trace: public wif_trace { +public: + wif_double_trace(const double& object_, + const std::string& name_, + const std::string& wif_name_); + void write(FILE* f); + bool changed(); + +protected: + const double& object; + double old_value; +}; + +wif_double_trace::wif_double_trace(const double& object_, + const std::string& name_, + const std::string& wif_name_) +: wif_trace(name_, wif_name_), object(object_), old_value(object_) +{ + bit_width = 0; + wif_type = "real"; +} + +bool wif_double_trace::changed() +{ + return object != old_value; +} + +void wif_double_trace::write(FILE* f) +{ + std::fprintf(f,"assign %s %f ; \n", wif_name.c_str(), object); + old_value = object; +} + + +/*****************************************************************************/ + +class wif_enum_trace : public wif_trace { +public: + wif_enum_trace(const unsigned& object_, + const std::string& name_, + const std::string& wif_name_, + const char** enum_literals); + void write(FILE* f); + bool changed(); + // Hides the definition of the same (virtual) function in wif_trace + void print_variable_declaration_line(FILE* f); + +protected: + const unsigned& object; + unsigned old_value; + + const char** literals; + unsigned nliterals; + std::string type_name; + + ~wif_enum_trace(); +}; + + +wif_enum_trace::wif_enum_trace(const unsigned& object_, + const std::string& name_, + const std::string& wif_name_, + const char** enum_literals_) +: wif_trace(name_, wif_name_), object(object_), old_value(object_), + literals(enum_literals_), nliterals(0), type_name(name_ + "__type__") +{ + // find number of enumeration literals - counting loop + for (nliterals = 0; enum_literals_[nliterals]; nliterals++) continue; + + bit_width = 0; + wif_type = type_name.c_str(); +} + +void wif_enum_trace::print_variable_declaration_line(FILE* f) +{ + std::fprintf(f, "type scalar \"%s\" enum ", wif_type); + + for (unsigned i = 0; i < nliterals; i++) + std::fprintf(f, "\"%s\", ", literals[i]); + std::fprintf(f, "\"SC_WIF_UNDEF\" ;\n"); + + std::fprintf(f, "declare %s \"%s\" \"%s\" ", + wif_name.c_str(), name.c_str(), wif_type); + std::fprintf(f, "variable ;\n"); + std::fprintf(f, "start_trace %s ;\n", wif_name.c_str()); +} + +bool wif_enum_trace::changed() +{ + return object != old_value; +} + +void wif_enum_trace::write(FILE* f) +{ + static bool warning_issued = false; + const char* lit; + + if (object >= nliterals) { // Note unsigned value is always greater than 0 + if (!warning_issued) { + SC_REPORT_WARNING( SC_ID_TRACING_INVALID_ENUM_VALUE_ + , name.c_str() ); + warning_issued = true; + } + lit = "SC_WIF_UNDEF"; + } + else + { + lit = literals[object]; + } + std::fprintf( f, "assign %s \"%s\" ;\n", wif_name.c_str(), lit ); + old_value = object; +} + +wif_enum_trace::~wif_enum_trace() +{ + /* Intentionally blank */ +} + + +template <class T> +class wif_T_trace +: public wif_trace +{ +public: + + wif_T_trace( const T& object_, + const std::string& name_, + const std::string& wif_name_, + wif_trace_file::wif_enum type_ ) + : wif_trace( name_, wif_name_), + object( object_ ), + old_value( object_ ) + { wif_type = wif_names[type_]; } + + void write( FILE* f ) + { + std::fprintf( f, + "assign %s \"%s\" ;\n", + wif_name.c_str(), + object.to_string().c_str() ); + old_value = object; + } + + bool changed() + { return !(object == old_value); } + + void set_width() + { bit_width = object.length(); } + +protected: + + const T& object; + T old_value; +}; + +typedef wif_T_trace<sc_dt::sc_bv_base> wif_sc_bv_trace; +typedef wif_T_trace<sc_dt::sc_lv_base> wif_sc_lv_trace; + + +//*********************************************************************** +// wif_trace_file functions +//*********************************************************************** + + +wif_trace_file::wif_trace_file(const char * name) + : sc_trace_file_base( name, "awif" ) + , wif_name_index(0) + , previous_time_units_low(0) + , previous_time_units_high(0) + , previous_time(0.0) + , traces() +{} + + +void wif_trace_file::do_initialize() +{ + char buf[2000]; + + // init + std::fprintf(fp, "init ;\n\n"); + + //timescale: + if (timescale_unit == 1e-15) std::sprintf(buf,"0"); + else if(timescale_unit == 1e-14) std::sprintf(buf,"1"); + else if(timescale_unit == 1e-13) std::sprintf(buf,"2"); + else if(timescale_unit == 1e-12) std::sprintf(buf,"3"); + else if(timescale_unit == 1e-11) std::sprintf(buf,"4"); + else if(timescale_unit == 1e-10) std::sprintf(buf,"5"); + else if(timescale_unit == 1e-9) std::sprintf(buf,"6"); + else if(timescale_unit == 1e-8) std::sprintf(buf,"7"); + else if(timescale_unit == 1e-7) std::sprintf(buf,"8"); + else if(timescale_unit == 1e-6) std::sprintf(buf,"9"); + else if(timescale_unit == 1e-5) std::sprintf(buf,"10"); + else if(timescale_unit == 1e-4) std::sprintf(buf,"11"); + else if(timescale_unit == 1e-3) std::sprintf(buf,"12"); + else if(timescale_unit == 1e-2) std::sprintf(buf,"13"); + else if(timescale_unit == 1e-1) std::sprintf(buf,"14"); + else if(timescale_unit == 1e0) std::sprintf(buf,"15"); + else if(timescale_unit == 1e1) std::sprintf(buf,"16"); + else if(timescale_unit == 1e2) std::sprintf(buf,"17"); + std::fprintf(fp,"header %s \"%s\" ;\n\n", buf, sc_version()); + + std::fprintf(fp, "comment \"ASCII WIF file produced on date: %s\" ;\n" + , localtime_string().c_str()); + + //version: + std::fprintf(fp, "comment \"Created by %s\" ;\n", sc_version()); + //conversion info + std::fprintf(fp, "comment \"Convert this file to binary WIF format using a2wif\" ;\n\n"); + + // Define the two types we need to represent bool and sc_logic + std::fprintf(fp, "type scalar \"BIT\" enum '0', '1' ;\n"); + std::fprintf(fp, "type scalar \"MVL\" enum '0', '1', 'X', 'Z', '?' ;\n"); + std::fprintf(fp, "\n"); + + //variable definitions: + int i; + for (i = 0; i < (int)traces.size(); i++) { + wif_trace* t = traces[i]; + t->set_width(); //needed for all vectors + t->print_variable_declaration_line(fp); + } + + double inittime = sc_time_stamp().to_seconds(); + previous_time = inittime/timescale_unit; + + // Dump all values at initial time + std::sprintf(buf, + "All initial values are dumped below at time " + "%g sec = %g timescale units.", + inittime, + inittime/timescale_unit + ); + write_comment(buf); + + double_to_special_int64(inittime/timescale_unit, + &previous_time_units_high, + &previous_time_units_low ); + + for (i = 0; i < (int)traces.size(); i++) { + wif_trace* t = traces[i]; + t->write(fp); + } +} + +// ---------------------------------------------------------------------------- + +#define DEFN_TRACE_METHOD(tp) \ +void \ +wif_trace_file::trace( const tp& object_, const std::string& name_ ) \ +{ \ + if( add_trace_check(name_) ) \ + traces.push_back( new wif_ ## tp ## _trace( object_, \ + name_, \ + obtain_name() ) ); \ +} + +DEFN_TRACE_METHOD(bool) +DEFN_TRACE_METHOD(float) +DEFN_TRACE_METHOD(double) + +#undef DEFN_TRACE_METHOD +#define DEFN_TRACE_METHOD(tp) \ +void \ +wif_trace_file::trace(const sc_dt::tp& object_, const std::string& name_) \ +{ \ + if( add_trace_check(name_) ) \ + traces.push_back( new wif_ ## tp ## _trace( object_, \ + name_, \ + obtain_name() ) ); \ +} + +DEFN_TRACE_METHOD(sc_bit) +DEFN_TRACE_METHOD(sc_logic) + +DEFN_TRACE_METHOD(sc_signed) +DEFN_TRACE_METHOD(sc_unsigned) +DEFN_TRACE_METHOD(sc_int_base) +DEFN_TRACE_METHOD(sc_uint_base) + +DEFN_TRACE_METHOD(sc_fxval) +DEFN_TRACE_METHOD(sc_fxval_fast) +DEFN_TRACE_METHOD(sc_fxnum) +DEFN_TRACE_METHOD(sc_fxnum_fast) + +#undef DEFN_TRACE_METHOD + + +#define DEFN_TRACE_METHOD_SIGNED(tp) \ +void \ +wif_trace_file::trace( const tp& object_, \ + const std::string& name_, \ + int width_ ) \ +{ \ + if( add_trace_check(name_) ) \ + traces.push_back( new wif_signed_ ## tp ## _trace( object_, \ + name_, \ + obtain_name(), \ + width_ ) ); \ +} + +#define DEFN_TRACE_METHOD_UNSIGNED(tp) \ +void \ +wif_trace_file::trace( const unsigned tp& object_, \ + const std::string& name_, \ + int width_ ) \ +{ \ + if( add_trace_check(name_) ) \ + traces.push_back( new wif_unsigned_ ## tp ## _trace( object_, \ + name_, \ + obtain_name(), \ + width_ ) ); \ +} + +DEFN_TRACE_METHOD_SIGNED(char) +DEFN_TRACE_METHOD_SIGNED(short) +DEFN_TRACE_METHOD_SIGNED(int) +DEFN_TRACE_METHOD_SIGNED(long) + +DEFN_TRACE_METHOD_UNSIGNED(char) +DEFN_TRACE_METHOD_UNSIGNED(short) +DEFN_TRACE_METHOD_UNSIGNED(int) +DEFN_TRACE_METHOD_UNSIGNED(long) + +#undef DEFN_TRACE_METHOD_SIGNED +#undef DEFN_TRACE_METHOD_UNSIGNED + + +#define DEFN_TRACE_METHOD_LONG_LONG(tp) \ +void \ +wif_trace_file::trace( const sc_dt::tp& object_, \ + const std::string& name_, \ + int width_ ) \ +{ \ + if( add_trace_check(name_) ) \ + traces.push_back( new wif_ ## tp ## _trace( object_, \ + name_, \ + obtain_name(), \ + width_ ) ); \ +} + +DEFN_TRACE_METHOD_LONG_LONG(int64) +DEFN_TRACE_METHOD_LONG_LONG(uint64) +#undef DEFN_TRACE_METHOD_LONG_LONG + +void +wif_trace_file::trace( const unsigned& object_, + const std::string& name_, + const char** enum_literals_ ) +{ + if( add_trace_check(name_) ) + traces.push_back( new wif_enum_trace( object_, + name_, + obtain_name(), + enum_literals_ ) ); +} + +void +wif_trace_file::trace( const sc_dt::sc_bv_base& object_, + const std::string& name_ ) +{ + traceT( object_, name_, WIF_BIT ); +} + +void +wif_trace_file::trace( const sc_dt::sc_lv_base& object_, + const std::string& name_ ) +{ + traceT( object_, name_, WIF_MVL ); +} + + +void +wif_trace_file::write_comment(const std::string& comment) +{ + if(!fp) open_fp(); + //no newline in comments allowed + std::fprintf(fp, "comment \"%s\" ;\n", comment.c_str()); +} + + +void +wif_trace_file::cycle(bool this_is_a_delta_cycle) +{ + unsigned now_units_high, now_units_low; + + // Trace delta cycles only when enabled + if (!delta_cycles() && this_is_a_delta_cycle) return; + + // Check for initialization + if( initialize() ) { + return; + }; + + // double now_units = sc_simulation_time() / timescale_unit; + double now_units = sc_time_stamp().to_seconds() / timescale_unit; + + double_to_special_int64(now_units, &now_units_high, &now_units_low ); + + // Now do the real stuff + unsigned delta_units_high, delta_units_low; + double diff_time; + diff_time = now_units - previous_time; + double_to_special_int64(diff_time, &delta_units_high, &delta_units_low); + if (this_is_a_delta_cycle && (diff_time == 0.0)) + delta_units_low++; // Increment time for delta cycle simulation + // Note that in the last statement above, we are assuming no more + // than 2^32 delta cycles - seems realistic + + bool time_printed = false; + wif_trace* const* const l_traces = &traces[0]; + for (int i = 0; i < (int)traces.size(); i++) { + wif_trace* t = l_traces[i]; + if(t->changed()){ + if(time_printed == false){ + if(delta_units_high){ + std::fprintf(fp, "delta_time %u%09u ;\n", delta_units_high, + delta_units_low); + } + else{ + std::fprintf(fp, "delta_time %u ;\n", delta_units_low); + } + time_printed = true; + } + + // Write the variable + t->write(fp); + } + } + + if(time_printed) { + std::fprintf(fp, "\n"); // Put another newline + // We update previous_time_units only when we print time because + // this field stores the previous time that was printed, not the + // previous time this function was called + previous_time_units_high = now_units_high; + previous_time_units_low = now_units_low; + previous_time = now_units; + } +} + +#if 0 +void +wif_trace_file::create_wif_name(std::string* ptr_to_str) +{ + obtain_name().swap(*ptr_to_str); +} +#endif + +// Create a WIF name for a variable +std::string +wif_trace_file::obtain_name() +{ + char buf[32]; + std::sprintf( buf, "O%d", wif_name_index ++ ); + return buf; +} + +wif_trace_file::~wif_trace_file() +{ + for( int i = 0; i < (int)traces.size(); i++ ) { + wif_trace* t = traces[i]; + delete t; + } +} + +// Map sc_logic values to values understandable by WIF +static char +map_sc_logic_state_to_wif_state(char in_char) +{ + char out_char; + + switch(in_char){ + case 'U': + case 'X': + case 'W': + case 'D': + out_char = 'X'; + break; + case '0': + case 'L': + out_char = '0'; + break; + case '1': + case 'H': + out_char = '1'; + break; + case 'Z': + out_char = 'Z'; + break; + default: + out_char = '?'; + } + return out_char; +} + +// ---------------------------------------------------------------------------- + +// Create the trace file +sc_trace_file* +sc_create_wif_trace_file(const char * name) +{ + sc_trace_file *tf = new wif_trace_file(name); + return tf; +} + + +void +sc_close_wif_trace_file( sc_trace_file* tf ) +{ + wif_trace_file* wif_tf = static_cast<wif_trace_file*>(tf); + delete wif_tf; +} + +} // namespace sc_core diff --git a/ext/systemc/src/sysc/tracing/sc_wif_trace.h b/ext/systemc/src/sysc/tracing/sc_wif_trace.h new file mode 100644 index 000000000..b4de46e1b --- /dev/null +++ b/ext/systemc/src/sysc/tracing/sc_wif_trace.h @@ -0,0 +1,222 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_wif_trace.h - Implementation of WIF tracing. + + Original Author - Abhijit Ghosh, Synopsys, Inc. + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + +/***************************************************************************** + + Acknowledgement: The tracing mechanism is based on the tracing + mechanism developed at Infineon (formerly Siemens HL). Though this + code is somewhat different, and significantly enhanced, the basics + are identical to what was originally contributed by Infineon. + The contribution of Infineon in the development of this tracing + technology is hereby acknowledged. + + *****************************************************************************/ + +/***************************************************************************** + + Instead of creating the binary WIF format, we create the ASCII + WIF format which can be converted to the binary format using + a2wif (utility that comes with VSS from Synopsys). This way, + a user who does not have Synopsys VSS can still create WIF + files, but the files can only be viewed by users who have VSS. + + *****************************************************************************/ + +#ifndef SC_WIF_TRACE_H +#define SC_WIF_TRACE_H + +#include <cstdio> +#include "sysc/datatypes/int/sc_nbdefs.h" +#include "sysc/tracing/sc_trace_file_base.h" + +namespace sc_core { + +class wif_trace; // defined in wif_trace.cc +template<class T> class wif_T_trace; + +class wif_trace_file + : public sc_trace_file_base +{ +public: + enum wif_enum {WIF_BIT=0, WIF_MVL=1, WIF_REAL=2, WIF_LAST}; + + // Create a wif trace file. + // `Name' forms the base of the name to which `.awif' is added. + explicit wif_trace_file(const char *name); + + ~wif_trace_file(); + +protected: + // These are all virtual functions in sc_trace_file and + // they need to be defined here. + + // Trace a boolean object (single bit) + void trace(const bool& object, const std::string& name); + + // Trace a sc_bit object (single bit) + void trace(const sc_dt::sc_bit& object, const std::string& name); + + // Trace a sc_logic object (single bit) + void trace(const sc_dt::sc_logic& object, const std::string& name); + + // Trace an unsigned char with the given width + void trace(const unsigned char& object, const std::string& name, + int width); + + // Trace an unsigned short with the given width + void trace(const unsigned short& object, const std::string& name, + int width); + + // Trace an unsigned int with the given width + void trace(const unsigned int& object, const std::string& name, + int width); + + // Trace an unsigned long with the given width + void trace(const unsigned long& object, const std::string& name, + int width); + + // Trace a signed char with the given width + void trace(const char& object, const std::string& name, int width); + + // Trace a signed short with the given width + void trace(const short& object, const std::string& name, int width); + + // Trace a signed int with the given width + void trace(const int& object, const std::string& name, int width); + + // Trace a signed long with the given width + void trace(const long& object, const std::string& name, int width); + + // Trace a signed long long with the given width + void trace(const sc_dt::int64& object, const std::string& name, + int width); + + // Trace an usigned long long with the given width + void trace(const sc_dt::uint64& object, const std::string& name, + int width); + + // Trace a float + void trace(const float& object, const std::string& name); + + // Trace a double + void trace(const double& object, const std::string& name); + + // Trace sc_unsigned + void trace (const sc_dt::sc_unsigned& object, + const std::string& name); + + // Trace sc_signed + void trace (const sc_dt::sc_signed& object, + const std::string& name); + + // Trace sc_uint_base + void trace (const sc_dt::sc_uint_base& object, + const std::string& name); + + // Trace sc_int_base + void trace (const sc_dt::sc_int_base& object, const std::string& name); + + // Trace sc_fxval + void trace( const sc_dt::sc_fxval& object, const std::string& name ); + + // Trace sc_fxval_fast + void trace( const sc_dt::sc_fxval_fast& object, + const std::string& name ); + + // Trace sc_fxnum + void trace( const sc_dt::sc_fxnum& object, const std::string& name ); + + // Trace sc_fxnum_fast + void trace( const sc_dt::sc_fxnum_fast& object, + const std::string& name ); + + template<class T> + void traceT(const T& object, const std::string& name, wif_enum type) + { + if( add_trace_check(name) ) + traces.push_back( new wif_T_trace<T>( object, name + , obtain_name(),type ) ); + } + + // Trace sc_bv_base (sc_bv) + virtual void trace( const sc_dt::sc_bv_base& object, + const std::string& name ); + + // Trace sc_lv_base (sc_lv) + virtual void trace( const sc_dt::sc_lv_base& object, + const std::string& name ); + + // Trace an enumerated object - where possible output the enumeration literals + // in the trace file. Enum literals is a null terminated array of null + // terminated char* literal strings. + void trace(const unsigned& object, const std::string& name, + const char** enum_literals); + + // Output a comment to the trace file + void write_comment(const std::string& comment); + + // Write trace info for cycle. + void cycle(bool delta_cycle); + +private: + +#if SC_TRACING_PHASE_CALLBACKS_ + // avoid hidden overload warnings + virtual void trace( sc_trace_file* ) const { sc_assert(false); } +#endif // SC_TRACING_PHASE_CALLBACKS_ + + // Initialize the tracing mechanism + virtual void do_initialize(); + + unsigned wif_name_index; // Number of variables traced + + unsigned previous_time_units_low; // Previous time as 64 bit integer + unsigned previous_time_units_high; + double previous_time; // Previous time as a double + +public: + // Create wif names for each variable + std::string obtain_name(); + + // Array to store the variables traced + std::vector<wif_trace*> traces; +}; + +} // namespace sc_core + +#endif // SC_WIF_TRACE_H +// Taf! diff --git a/ext/systemc/src/sysc/utils/sc_hash.cpp b/ext/systemc/src/sysc/utils/sc_hash.cpp new file mode 100644 index 000000000..fc97fe416 --- /dev/null +++ b/ext/systemc/src/sysc/utils/sc_hash.cpp @@ -0,0 +1,670 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_hash.cpp -- Implementation of a chained hash table with MTF + (move-to-front). + + Original Author: Stan Y. Liao, Synopsys, Inc. + + CHANGE LOG AT END OF FILE + *****************************************************************************/ + +#include <assert.h> +#include <stdlib.h> // duplicate (c)stdlib.h headers for Solaris +#include <cstdlib> +#include <cstddef> +#include <string.h> + +#include "sysc/kernel/sc_cmnhdr.h" +#include "sysc/utils/sc_hash.h" +#include "sysc/utils/sc_mempool.h" + +namespace sc_core { + +// we can't assume global availability of uintptr_t, +// approximate it by size_t +typedef std::size_t uintptr_t; + +const double PHASH_DEFAULT_GROW_FACTOR = 2.0; + +class sc_phash_elem { + friend class sc_phash_base; + friend class sc_phash_base_iter; + +private: + void* key; + void* contents; + sc_phash_elem* next; + + sc_phash_elem( void* k, void* c, sc_phash_elem* n ) + : key(k), contents(c), next(n) { } + sc_phash_elem() : key(0), contents(0), next(0) { } + ~sc_phash_elem() { } + + static void* operator new(std::size_t sz) + { return sc_mempool::allocate(sz); } + static void operator delete(void* p, std::size_t sz) + { sc_mempool::release(p, sz); } +}; + + +sc_phash_base::sc_phash_base( + void* def, + int size, + int density, + double grow, + bool reorder, + unsigned (*hash_fn)(const void*), + int (*cmp_fn)(const void*, const void*) +) : + default_value(def), num_bins(0), num_entries(0), max_density(density), + reorder_flag(reorder), grow_factor(grow), bins(0), hash(hash_fn), + cmpr(cmp_fn) +{ + if (size <= 0) + size = PHASH_DEFAULT_INIT_TABLE_SIZE; + else if ((size % 2) == 0) + size += 1; + num_bins = size; + bins = new sc_phash_elem*[size]; + for (int i = 0; i < size; ++i) + bins[i] = 0; +} + +void +sc_phash_base::set_cmpr_fn(cmpr_fn_t c) +{ + cmpr = c; +} + +void +sc_phash_base::set_hash_fn(hash_fn_t h) +{ + hash = h; +} + +sc_phash_base::~sc_phash_base() +{ + sc_phash_elem* ptr; + sc_phash_elem* next; + + for (int i = 0; i < num_bins; ++i) { + ptr = bins[i]; + while (ptr != 0) { + next = ptr->next; + delete ptr; + ptr = next; + } + } + delete[] bins; +} + +void +sc_phash_base::rehash() +{ + sc_phash_elem* ptr; + sc_phash_elem* next; + sc_phash_elem** old_bins = bins; + + int old_num_bins = num_bins; + unsigned hash_val; + + num_bins = (int) (grow_factor * old_num_bins); + if (num_bins % 2 == 0) + ++num_bins; + + num_entries = 0; + bins = new sc_phash_elem*[num_bins]; + memset( bins, 0, sizeof(sc_phash_elem*) * num_bins ); + + for (int i = 0; i < old_num_bins; ++i) { + ptr = old_bins[i]; + while (ptr != 0) { + next = ptr->next; + hash_val = do_hash(ptr->key); + ptr->next = bins[hash_val]; + bins[hash_val] = ptr; + ++num_entries; + ptr = next; + } + } + delete[] old_bins; +} + +sc_phash_elem* +sc_phash_base::find_entry_q( unsigned hash_val, const void* key, sc_phash_elem*** plast ) +{ + sc_phash_elem** last = &(bins[hash_val]); + sc_phash_elem* ptr = *last; + + /* The (ptr->key != key) here is meant by the "q" */ + while ((ptr != 0) && (ptr->key != key)) { + /* ^^ right here */ + last = &(ptr->next); + ptr = *last; + } + if ((ptr != 0) && reorder_flag) { + *last = ptr->next; + ptr->next = bins[hash_val]; + bins[hash_val] = ptr; + last = &(bins[hash_val]); + } + if (plast) *plast = last; + return ptr; +} + +sc_phash_elem* +sc_phash_base::find_entry_c( unsigned hash_val, const void* key, sc_phash_elem*** plast ) +{ + sc_phash_elem** last = &(bins[hash_val]); + sc_phash_elem* ptr = *last; + + while ((ptr != 0) && ((*cmpr)(ptr->key, key) != 0)) { + last = &(ptr->next); + ptr = *last; + } + /* Bring to front */ + if ((ptr != 0) && reorder_flag) { + *last = ptr->next; + ptr->next = bins[hash_val]; + bins[hash_val] = ptr; + last = &(bins[hash_val]); + } + if (plast) *plast = last; + return ptr; +} + +sc_phash_elem* +sc_phash_base::add_direct( void* key, void* contents, unsigned hash_val ) +{ + if (num_entries / num_bins >= max_density) { + rehash(); + hash_val = do_hash(key); + } + + sc_phash_elem* new_entry = new sc_phash_elem(key, contents, bins[hash_val]); + bins[hash_val] = new_entry; + ++num_entries; + return new_entry; +} + +void +sc_phash_base::erase() +{ + for (int i = 0; i < num_bins; ++i) { + sc_phash_elem* ptr = bins[i]; + while (ptr != 0) { + sc_phash_elem* next = ptr->next; + delete ptr; + ptr = next; + --num_entries; + } + bins[i] = 0; + } + assert(num_entries == 0); +} + +void +sc_phash_base::erase(void (*kfree)(void*)) +{ + for (int i = 0; i < num_bins; ++i) { + sc_phash_elem* ptr = bins[i]; + while (ptr != 0) { + sc_phash_elem* next = ptr->next; + (*kfree)(ptr->key); + delete ptr; + ptr = next; + --num_entries; + } + bins[i] = 0; + } + assert(num_entries == 0); +} + +void +sc_phash_base::copy( const sc_phash_base* b ) +{ + erase(); + iterator iter((sc_phash_base*) b); /* cast away the const */ + for ( ; ! iter.empty(); iter++) + insert( iter.key(), iter.contents() ); +} + +void +sc_phash_base::copy(const sc_phash_base& b, void* (*kdup)(const void*), void (*kfree)(void*)) +{ + erase(kfree); + iterator iter((sc_phash_base&) b); + for ( ; ! iter.empty(); iter++) + insert( (*kdup)(iter.key()), iter.contents() ); +} + +int +sc_phash_base::insert( void* k, void* c ) +{ + unsigned hash_val = do_hash(k); + sc_phash_elem* ptr = find_entry( hash_val, k ); + if (ptr == 0) { + (void) add_direct(k, c, hash_val); + return 0; + } + else { + ptr->contents = c; + return 1; + } +} + +int +sc_phash_base::insert( void* k, void* c, void* (*kdup)(const void*) ) +{ + unsigned hash_val = do_hash(k); + sc_phash_elem* ptr = find_entry( hash_val, k ); + if (ptr == 0) { + (void) add_direct((*kdup)(k), c, hash_val); + return 0; + } + else { + ptr->contents = c; + return 1; + } +} + +int +sc_phash_base::insert_if_not_exists( void* k, void* c ) +{ + unsigned hash_val = do_hash(k); + sc_phash_elem* ptr = find_entry( hash_val, k ); + if (ptr == 0) { + (void) add_direct( k, c, hash_val ); + return 0; + } + else + return 1; +} + +int +sc_phash_base::insert_if_not_exists( void* k, void* c, void* (*kdup)(const void*) ) +{ + unsigned hash_val = do_hash(k); + sc_phash_elem* ptr = find_entry( hash_val, k ); + if (ptr == 0) { + (void) add_direct( (*kdup)(k), c, hash_val ); + return 0; + } + else + return 1; +} + +int +sc_phash_base::remove( const void* k ) +{ + unsigned hash_val = do_hash(k); + sc_phash_elem** last; + sc_phash_elem* ptr = find_entry( hash_val, k, &last ); + + if (ptr == 0) + return 0; + + assert(*last == ptr); + *last = ptr->next; + delete ptr; + --num_entries; + return 1; +} + +int +sc_phash_base::remove( const void* k, void** pk, void** pc ) +{ + unsigned hash_val = do_hash(k); + sc_phash_elem** last; + sc_phash_elem* ptr = find_entry( hash_val, k, &last ); + + if (ptr == 0) { + *pk = 0; + *pc = 0; + return 0; + } + else { + *pk = ptr->key; + *pc = ptr->contents; + } + + assert(*last == ptr); + *last = ptr->next; + delete ptr; + --num_entries; + return 1; +} + +int +sc_phash_base::remove(const void* k, void (*kfree)(void*)) +{ + void* rk; + void* rc; + if (remove(k, &rk, &rc)) { + (*kfree)(rk); + return 1; + } + else + return 0; +} + +int +sc_phash_base::remove_by_contents( const void* c ) +{ + sc_phash_elem** last; + sc_phash_elem* ptr; + + int num_removed = 0; + for (int i = 0; i < num_bins; ++i) { + last = &(bins[i]); + ptr = *last; + while (ptr != 0) { + if (ptr->contents != c) { + last = &(ptr->next); + ptr = *last; + } + else { + *last = ptr->next; + delete ptr; + ptr = *last; + --num_entries; + ++num_removed; + } + } + } + return num_removed; +} + +int +sc_phash_base::remove_by_contents( bool (*predicate)(const void* c, void* arg), void* arg ) +{ + sc_phash_elem** last; + sc_phash_elem* ptr; + + int num_removed = 0; + for (int i = 0; i < num_bins; ++i) { + last = &(bins[i]); + ptr = *last; + while (ptr != 0) { + if (! (*predicate)(ptr->contents, arg)) { + last = &(ptr->next); + ptr = *last; + } + else { + *last = ptr->next; + delete ptr; + ptr = *last; + --num_entries; + ++num_removed; + } + } + } + return num_removed; +} + +int +sc_phash_base::remove_by_contents( const void* c, void (*kfree)(void*) ) +{ + sc_phash_elem** last; + sc_phash_elem* ptr; + + int num_removed = 0; + for (int i = 0; i < num_bins; ++i) { + last = &(bins[i]); + ptr = *last; + while (ptr != 0) { + if (ptr->contents != c) { + last = &(ptr->next); + ptr = *last; + } + else { + *last = ptr->next; + (*kfree)(ptr->key); + delete ptr; + ptr = *last; + --num_entries; + ++num_removed; + } + } + } + return num_removed; +} + +int +sc_phash_base::remove_by_contents( bool (*predicate)(const void*, void*), void* arg, void (*kfree)(void*)) +{ + sc_phash_elem** last; + sc_phash_elem* ptr; + + int num_removed = 0; + for (int i = 0; i < num_bins; ++i) { + last = &(bins[i]); + ptr = *last; + while (ptr != 0) { + if (! (*predicate)(ptr->contents, arg)) { + last = &(ptr->next); + ptr = *last; + } + else { + *last = ptr->next; + (*kfree)(ptr->key); + delete ptr; + ptr = *last; + --num_entries; + ++num_removed; + } + } + } + return num_removed; +} + +int +sc_phash_base::lookup( const void* k, void** c_ptr ) const +{ + unsigned hash_val = do_hash(k); + sc_phash_elem* ptr = find_entry( hash_val, k ); + if (ptr == 0) { + if (c_ptr != 0) *c_ptr = default_value; + return 0; + } + else { + if (c_ptr != 0) *c_ptr = ptr->contents; + return 1; + } +} + +void* +sc_phash_base::operator[]( const void* key ) const +{ + void* contents; + lookup( key, &contents ); + return contents; +} + +/***************************************************************************/ + +void +sc_phash_base_iter::reset( sc_phash_base* t ) +{ + table = t; + index = 0; + entry = 0; + next = 0; + + for (int i = index; i < table->num_bins; ++i) { + if (table->bins[i] != 0) { + index = i + 1; + last = &(table->bins[i]); + entry = *last; + next = entry->next; + break; + } + } +} + +bool +sc_phash_base_iter::empty() const +{ + return (entry == 0); +} + +void +sc_phash_base_iter::step() +{ + if (entry) { + last = &(entry->next); + } + entry = next; + if (! entry) { + for (int i = index; i < table->num_bins; ++i) { + if (table->bins[i] != 0) { + index = i + 1; + last = &(table->bins[i]); + entry = *last; + next = entry->next; + break; + } + } + } + else { + next = entry->next; + } +} + +void +sc_phash_base_iter::remove() +{ + delete entry; + *last = next; + entry = 0; + --table->num_entries; + step(); +} + +void +sc_phash_base_iter::remove(void (*kfree)(void*)) +{ + (*kfree)(entry->key); + delete entry; + *last = next; + entry = 0; + --table->num_entries; + step(); +} + +void* +sc_phash_base_iter::key() const +{ + return entry->key; +} + +void* +sc_phash_base_iter::contents() const +{ + return entry->contents; +} + +void* +sc_phash_base_iter::set_contents( void* c ) +{ + return entry->contents = c; +} + +/****************************************************************************/ + +unsigned +default_ptr_hash_fn(const void* p) +{ + return static_cast<unsigned>(((uintptr_t)(p) >> 2) * 2654435789U); + +} + +unsigned +default_int_hash_fn(const void* p) +{ + return static_cast<unsigned>((uintptr_t)(p) * 3141592661U); +} + + +unsigned +default_str_hash_fn(const void* p) +{ + if (!p) return 0; + + const char* x = (const char*) p; + unsigned int h = 0; + unsigned int g; + + while (*x != 0) { + h = (h << 4) + *x++; + if ((g = h & 0xf0000000) != 0) + h = (h ^ (g >> 24)) ^ g; + } + return h; +} + +int +sc_strhash_cmp( const void* a, const void* b ) +{ + return strcmp( (const char*) a, (const char*) b ); +} + +void* +sc_strhash_kdup(const void* k) +{ + char* result = (char*) malloc( strlen((const char*)k)+1 ); + strcpy(result, (const char*) k); + return result; +} + +void +sc_strhash_kfree(void* k) +{ + if (k) free((char*) k); +} + } // namespace sc_core + +// $Log: sc_hash.cpp,v $ +// Revision 1.5 2011/08/26 20:42:30 acg +// Andy Goodrich: +// (1) Replaced strdup with new and strcpy to eliminate issue with the +// Greenhills compiler. +// (2) Moved modification log to the end of the file to eliminate line +// skew when check-ins are done. +// +// Revision 1.4 2011/08/24 22:05:56 acg +// Torsten Maehne: initialization changes to remove warnings. +// +// Revision 1.3 2011/05/05 17:46:04 acg +// Philip A. Hartmann: changes in "swap" support. +// +// Revision 1.2 2011/02/18 20:38:43 acg +// Andy Goodrich: Updated Copyright notice. +// +// Revision 1.1.1.1 2006/12/15 20:20:06 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:53:10 acg +// Andy Goodrich: Added $Log command so that CVS comments are reproduced in +// the source. + +// taf diff --git a/ext/systemc/src/sysc/utils/sc_hash.h b/ext/systemc/src/sysc/utils/sc_hash.h new file mode 100644 index 000000000..14f8ee980 --- /dev/null +++ b/ext/systemc/src/sysc/utils/sc_hash.h @@ -0,0 +1,460 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_hash.cpp -- Implementation of a chained hash table with MTF + (move-to-front). + + Original Author: Stan Y. Liao, Synopsys, Inc. + + CHANGE LOG AT END OF FILE + *****************************************************************************/ + +#ifndef SC_HASH_H +#define SC_HASH_H + + +namespace sc_core { + +extern unsigned default_int_hash_fn(const void*); +extern unsigned default_ptr_hash_fn(const void*); +extern unsigned default_str_hash_fn(const void*); + +class sc_phash_elem; +class sc_phash_base_iter; +template<class K, class C> //template class +class sc_pdhash_iter; //decl. -- Amit + +const int PHASH_DEFAULT_MAX_DENSITY = 5; +const int PHASH_DEFAULT_INIT_TABLE_SIZE = 11; +extern const double PHASH_DEFAULT_GROW_FACTOR; +const bool PHASH_DEFAULT_REORDER_FLAG = true; + +class sc_phash_base { + friend class sc_phash_base_iter; + + typedef sc_phash_base_iter iterator; + +public: + typedef unsigned (*hash_fn_t)(const void*); + typedef int (*cmpr_fn_t)(const void*, const void*); + +protected: + void* default_value; + int num_bins; + int num_entries; + int max_density; + int reorder_flag; + double grow_factor; + + sc_phash_elem** bins; + + hash_fn_t hash; + cmpr_fn_t cmpr; + + void rehash(); + unsigned do_hash(const void* key) const { return (*hash)(key) % num_bins; } + + sc_phash_elem* add_direct(void* key, void* contents, unsigned hash_val); + sc_phash_elem* find_entry_c(unsigned hv, const void* k, sc_phash_elem*** plast); + sc_phash_elem* find_entry_q(unsigned hv, const void* k, sc_phash_elem*** plast); + sc_phash_elem* find_entry(unsigned hv, const void* k, sc_phash_elem*** plast=0) const + { + /* Got rid of member func. pointer and replaced with if-else */ + /* Amit (5/14/99) */ + if( cmpr == 0 ) + return ((sc_phash_base*)this)->find_entry_q( hv, k, plast ); + else + return ((sc_phash_base*)this)->find_entry_c( hv, k, plast ); + } + +public: + sc_phash_base( void* def = 0, + int size = PHASH_DEFAULT_INIT_TABLE_SIZE, + int density = PHASH_DEFAULT_MAX_DENSITY, + double grow = PHASH_DEFAULT_GROW_FACTOR, + bool reorder = PHASH_DEFAULT_REORDER_FLAG, + hash_fn_t hash_fn = default_ptr_hash_fn, + cmpr_fn_t cmpr_fn = 0 ); + ~sc_phash_base(); + + void set_cmpr_fn(cmpr_fn_t); + void set_hash_fn(hash_fn_t); + + bool empty() const { return (num_entries == 0); } + unsigned count() const { return num_entries; } + + void erase(); + void erase(void (*kfree)(void*)); + void copy( const sc_phash_base* ); + void copy( const sc_phash_base& b ) { copy(&b); } + void copy( const sc_phash_base& b, void* (*kdup)(const void*), void (*kfree)(void*)); + int insert( void* k, void* c ); + int insert( void* k ) { return insert(k, default_value); } + int insert( void* k, void* c, void* (*kdup)(const void*) ); + int insert_if_not_exists(void* k, void* c); + int insert_if_not_exists(void* k) { return insert_if_not_exists(k, default_value); } + int insert_if_not_exists(void* k, void* c, void* (*kdup)(const void*)); + int remove(const void* k); + int remove(const void* k, void** pk, void** pc); + int remove(const void* k, void (*kfree)(void*)); + int remove_by_contents(const void* c); + int remove_by_contents(bool (*predicate)(const void*, void*), void* arg); + int remove_by_contents(const void* c, void (*kfree)(void*)); + int remove_by_contents(bool (*predicate)(const void*, void*), void* arg, void (*kfree)(void*)); + int lookup(const void* k, void** pc) const; + bool contains(const void* k) const { return (lookup(k, 0) != 0); } + void* operator[](const void* key) const; +}; + +class sc_phash_base_iter { +protected: + sc_phash_base* table; + sc_phash_elem* entry; + sc_phash_elem* next; + sc_phash_elem** last; + int index; + +public: + void reset(sc_phash_base* t); + void reset(sc_phash_base& t) { reset(&t); } + + sc_phash_base_iter(sc_phash_base* t) + : table(t), entry(0), next(0), last(0), index(0) + { reset(t); } + sc_phash_base_iter(sc_phash_base& t) + : table(&t), entry(0), next(0), last(0), index(0) + { reset(t); } + ~sc_phash_base_iter() { } + + bool empty() const; + void step(); + void operator++(int) { step(); } + void remove(); + void remove(void (*kfree)(void*)); + void* key() const; + void* contents() const; + void* set_contents(void* c); +}; + +template< class K, class C > +class sc_phash_iter; + +template< class K, class C > +class sc_phash : public sc_phash_base { + friend class sc_phash_iter<K,C>; + +public: + typedef sc_phash_iter<K,C> iterator; + + sc_phash( C def = (C) 0, + int size = PHASH_DEFAULT_INIT_TABLE_SIZE, + int density = PHASH_DEFAULT_MAX_DENSITY, + double grow = PHASH_DEFAULT_GROW_FACTOR, + bool reorder = PHASH_DEFAULT_REORDER_FLAG, + hash_fn_t hash_fn = default_ptr_hash_fn, + cmpr_fn_t cmpr_fn = 0 ) + : sc_phash_base((void*) def, size, density, grow, reorder, hash_fn, cmpr_fn) { } + ~sc_phash() { } + + void copy(const sc_phash<K,C>* b) { sc_phash_base::copy(b); } + void copy(const sc_phash<K,C>& b) { sc_phash_base::copy(b); } + void copy(const sc_phash<K,C>& b, void* (*kdup)(const void*), void (*kfree)(void*)) { sc_phash_base::copy(b, kdup, kfree); } + + int insert(K k, C c) { return sc_phash_base::insert((void*) k, (void*) c); } + int insert(K k) { return sc_phash_base::insert((void*) k, default_value); } + int insert(K k, C c, void* (*kdup)(const void*)) { return sc_phash_base::insert((void*) k, (void*) c, kdup); } + int insert_if_not_exists(K k, C c) + { + return sc_phash_base::insert_if_not_exists((void*) k, (void*) c); + } + int insert_if_not_exists(K k) + { + return sc_phash_base::insert_if_not_exists((void*) k, default_value); + } + int insert_if_not_exists(K k, C c, void* (*kdup)(const void*)) + { + return sc_phash_base::insert_if_not_exists((void*) k, (void*) c, kdup); + } + int remove(K k) { return sc_phash_base::remove((const void*) k); } + int remove(K k, K* pk, C* pc) + { + return sc_phash_base::remove((const void*) k, (void**) pk, (void**) pc); + } + int remove(K k, void (*kfree)(void*)) + { + return sc_phash_base::remove((const void*) k, kfree); + } + int remove_by_contents(C c) + { + return sc_phash_base::remove_by_contents((const void*) c); + } + int remove_by_contents(bool (*predicate)(const void*, void*), void* arg) + { + return sc_phash_base::remove_by_contents(predicate, arg); + } + int remove_by_contents(const void* c, void (*kfree)(void*)) + { + return sc_phash_base::remove_by_contents(c, kfree); + } + int remove_by_contents(bool (*predicate)(const void*, void*), void* arg, void (*kfree)(void*)) + { + return sc_phash_base::remove_by_contents(predicate, arg, kfree); + } + int lookup(K k, C* pc) const + { + return sc_phash_base::lookup((const void*) k, (void**) pc); + } + bool contains(K k) const + { + return sc_phash_base::contains((const void*) k); + } + C operator[](K k) const + { + return (C) sc_phash_base::operator[]((const void*) k); + } +}; + + +template< class K, class C > +class sc_phash_iter : public sc_phash_base_iter { +public: + sc_phash_iter(sc_phash<K,C>* t) : sc_phash_base_iter(t) { } + sc_phash_iter(sc_phash<K,C>& t) : sc_phash_base_iter(t) { } + ~sc_phash_iter() { } + + void reset(sc_phash<K,C>* t) { sc_phash_base_iter::reset(t); } + void reset(sc_phash<K,C>& t) { sc_phash_base_iter::reset(t); } + + K key() const { return (K) sc_phash_base_iter::key(); } + C contents() const { return (C) sc_phash_base_iter::contents(); } + C set_contents(C c) + { + return (C) sc_phash_base_iter::set_contents((void*) c); + } +}; + + + + + +template< class K, class C > +class sc_pdhash : public sc_phash_base { + friend class sc_pdhash_iter<K,C>; + +private: + void* (*kdup)(const void*); //eliminated braces around void* -- Amit + void (*kfree)(void*); + +public: + typedef sc_pdhash_iter<K,C> iterator; + sc_pdhash( C def = (C) 0, + int size = PHASH_DEFAULT_INIT_TABLE_SIZE, + int density = PHASH_DEFAULT_MAX_DENSITY, + double grow = PHASH_DEFAULT_GROW_FACTOR, + bool reorder = PHASH_DEFAULT_REORDER_FLAG, + hash_fn_t hash_fn = (hash_fn_t) 0, // defaults added -- + cmpr_fn_t cmpr_fn = (cmpr_fn_t) 0, // Amit + void* (*kdup_fn)(const void*) = 0, + void (*kfree_fn)(void*) = 0 ) + : sc_phash_base((void*) def, size, density, grow, reorder, hash_fn, cmpr_fn) + { + kdup = kdup_fn; + kfree = kfree_fn; + } + ~sc_pdhash() + { + erase(); + } + void erase() + { + sc_phash_base::erase(kfree); + } + void copy(const sc_pdhash<K,C>& b) { sc_phash_base::copy(b, kdup, kfree); } + int insert(K k, C c) { return sc_phash_base::insert((void*) k, (void*) c, kdup); } + int insert(K k) { return sc_phash_base::insert((void*) k, default_value, kdup); } + int insert_if_not_exists(K k, C c) + { + return sc_phash_base::insert_if_not_exists((void*) k, (void*) c, kdup); + } + int insert_if_not_exists(K k) + { + return sc_phash_base::insert_if_not_exists((void*) k, default_value, kdup); + } + int remove(K k) { return sc_phash_base::remove((const void*) k, kfree); } + int remove(K k, K* pk, C* pc) + { + return sc_phash_base::remove((const void*) k, (void**) pk, (void**) pc); + } + int remove_by_contents(C c) + { + return sc_phash_base::remove_by_contents((const void*) c, kfree); + } + int remove_by_contents(bool (*predicate)(const void*, void*), void* arg) + { + return sc_phash_base::remove_by_contents(predicate, arg, kfree); + } + int lookup(K k, C* pc) const + { + return sc_phash_base::lookup((const void*) k, (void**) pc); + } + bool contains(K k) const + { + return sc_phash_base::contains((const void*) k); + } + C operator[](K k) const + { + return (C) sc_phash_base::operator[]((const void*) k); + } +}; + +template< class K, class C > +class sc_pdhash_iter : public sc_phash_base_iter { +public: + sc_pdhash_iter(sc_pdhash<K,C>* t) : sc_phash_base_iter(t) { } + sc_pdhash_iter(sc_pdhash<K,C>& t) : sc_phash_base_iter(t) { } + ~sc_pdhash_iter() { } + + void reset(sc_pdhash<K,C>* t) { sc_phash_base_iter::reset(t); } + void reset(sc_pdhash<K,C>& t) { sc_phash_base_iter::reset(t); } + + void remove() { sc_phash_base_iter::remove(((sc_pdhash<K,C>*) table)->kfree); } + K key() const { return (K) sc_phash_base_iter::key(); } + C contents() const { return (C) sc_phash_base_iter::contents(); } + C set_contents(C c) + { + return (C) sc_phash_base_iter::set_contents((void*) c); + } +}; + +extern int sc_strhash_cmp( const void*, const void* ); +extern void sc_strhash_kfree(void*); +extern void* sc_strhash_kdup(const void*); + +template< class C > // template class decl. +class sc_strhash_iter; // --Amit + +template< class C > +class sc_strhash : public sc_phash_base { + friend class sc_strhash_iter<C>; + +public: + typedef sc_strhash_iter<C> iterator; + + sc_strhash( C def = (C) 0, + int size = PHASH_DEFAULT_INIT_TABLE_SIZE, + int density = PHASH_DEFAULT_MAX_DENSITY, + double grow = PHASH_DEFAULT_GROW_FACTOR, + bool reorder = PHASH_DEFAULT_REORDER_FLAG, + unsigned (*hash_fn)(const void*) = default_str_hash_fn, + int (*cmpr_fn)(const void*, const void*) = sc_strhash_cmp ) + : sc_phash_base((void*) def, size, density, grow, reorder, hash_fn, cmpr_fn) + { + + } + ~sc_strhash() + { + erase(); + } + + void erase() { sc_phash_base::erase(sc_strhash_kfree); } + void copy(const sc_strhash<C>* b) { sc_phash_base::copy(*b, sc_strhash_kdup, sc_strhash_kfree); } + void copy(const sc_strhash<C>& b) { sc_phash_base::copy(b, sc_strhash_kdup, sc_strhash_kfree); } + + int insert(char* k, C c) { return sc_phash_base::insert((void*) k, (void*) c, sc_strhash_kdup); } + int insert(char* k) { return sc_phash_base::insert((void*) k, default_value, sc_strhash_kdup); } + int insert_if_not_exists(char* k, C c) + { + return sc_phash_base::insert_if_not_exists((void*) k, (void*) c, sc_strhash_kdup); + } + int insert_if_not_exists(char* k) + { + return sc_phash_base::insert_if_not_exists((void*) k, default_value, sc_strhash_kdup); + } + int remove(const char* k) { return sc_phash_base::remove((const void*) k, sc_strhash_kfree); } + int remove(const char* k, char** pk, C* pc) + { + return sc_phash_base::remove((const void*) k, (void**) pk, (void**) pc); + } + int remove_by_contents(C c) + { + return sc_phash_base::remove_by_contents((const void*) c, sc_strhash_kfree); + } + int remove_by_contents(bool (*predicate)(const void*, void*), void* arg) + { + return sc_phash_base::remove_by_contents(predicate, arg, sc_strhash_kfree); + } + int lookup(const char* k, C* pc) const + { + return sc_phash_base::lookup((const void*) k, (void** )pc); + } + bool contains(const char* k) const + { + return sc_phash_base::contains((const void*) k); + } + C operator[](const char* k) const + { + return (C) sc_phash_base::operator[]((const void*) k); + } +}; + +template<class C> +class sc_strhash_iter : public sc_phash_base_iter { +public: + sc_strhash_iter ( sc_strhash<C>* t ) : sc_phash_base_iter(t) { } + sc_strhash_iter ( sc_strhash<C>& t ) : sc_phash_base_iter(t) { } + ~sc_strhash_iter() { } + + void reset ( sc_strhash<C>* t ) { sc_phash_base_iter::reset(t); } + void reset ( sc_strhash<C>& t ) { sc_phash_base_iter::reset(t); } + + void remove() { sc_phash_base_iter::remove(sc_strhash_kfree); } + const char* key() { return (const char*) sc_phash_base_iter::key(); } + C contents() { return (C) sc_phash_base_iter::contents(); } + C set_contents(C c) + { + return (C) sc_phash_base_iter::set_contents((void*) c); + } +}; + +} // namespace sc_core + +// $Log: sc_hash.h,v $ +// Revision 1.5 2011/08/29 18:04:32 acg +// Philipp A. Hartmann: miscellaneous clean ups. +// +// Revision 1.4 2011/08/26 20:46:16 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +// Revision 1.3 2011/08/24 22:05:56 acg +// Torsten Maehne: initialization changes to remove warnings. +// +// Revision 1.2 2011/02/18 20:38:43 acg +// Andy Goodrich: Updated Copyright notice. +// +// Revision 1.1.1.1 2006/12/15 20:20:06 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:53:10 acg +// Andy Goodrich: Added $Log command so that CVS comments are reproduced in +// the source. + +#endif diff --git a/ext/systemc/src/sysc/utils/sc_iostream.h b/ext/systemc/src/sysc/utils/sc_iostream.h new file mode 100644 index 000000000..4f19d511e --- /dev/null +++ b/ext/systemc/src/sysc/utils/sc_iostream.h @@ -0,0 +1,91 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_iostream.h - Portable iostream header file wrapper. + + Original Author: Martin Janssen, Synopsys, Inc. + + Note: Deprecated in the meantime, since all supported + compilers are supposed to have a working C++ + standard library. + + CHANGE LOG AT END OF FILE + *****************************************************************************/ + +#ifndef SC_IOSTREAM_H +#define SC_IOSTREAM_H + +#include <ios> +#include <iostream> +#include <sstream> +#include <fstream> +#include <cstddef> +#include <cstring> + +// We use typedefs for istream and ostream here to get around some finickiness +// from aCC: + +namespace sc_dt { + +typedef ::std::istream systemc_istream; +typedef ::std::ostream systemc_ostream; + +} // namespace sc_dt + +// shortcuts that save some typing + +#ifdef CCAST +# undef CCAST +#endif +#define CCAST const_cast + +#ifdef DCAST +# undef DCAST +#endif +#define DCAST dynamic_cast + +#ifdef RCAST +# undef RCAST +#endif +#define RCAST reinterpret_cast + +#ifdef SCAST +# undef SCAST +#endif +#define SCAST static_cast + +// $Log: sc_iostream.h,v $ +// Revision 1.3 2011/08/26 20:46:18 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +// Revision 1.2 2011/02/18 20:38:43 acg +// Andy Goodrich: Updated Copyright notice. +// +// Revision 1.1.1.1 2006/12/15 20:20:06 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:53:10 acg +// Andy Goodrich: Added $Log command so that CVS comments are reproduced in +// the source. +// + +#endif // !defined(SC_IOSTREAM_H) diff --git a/ext/systemc/src/sysc/utils/sc_list.cpp b/ext/systemc/src/sysc/utils/sc_list.cpp new file mode 100644 index 000000000..88998fbe9 --- /dev/null +++ b/ext/systemc/src/sysc/utils/sc_list.cpp @@ -0,0 +1,343 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_list.cpp -- Simple implementation of a doubly linked list. + + Original Author: Stan Y. Liao, Synopsys, Inc. + + CHANGE LOG AT END OF FILE + *****************************************************************************/ + + +#include <assert.h> +#include <cstddef> + +#include "sysc/kernel/sc_cmnhdr.h" +#include "sysc/utils/sc_iostream.h" +#include "sysc/utils/sc_list.h" +#include "sysc/utils/sc_mempool.h" +#include "sysc/utils/sc_report.h" +#include "sysc/utils/sc_utils_ids.h" + +namespace sc_core { + +class sc_plist_elem { + friend class sc_plist_base_iter; + friend class sc_plist_base; + +private: + sc_plist_elem() : data(0), prev(0), next(0) + {} + sc_plist_elem( void* d, sc_plist_elem* p, sc_plist_elem* n ) : + data(d), prev(p), next(n) + {} + ~sc_plist_elem() + {} + + static void* operator new(std::size_t sz) { return sc_mempool::allocate(sz); } + static void operator delete(void* p, std::size_t sz) { sc_mempool::release(p, sz); } + + void* data; + sc_plist_elem* prev; + sc_plist_elem* next; +}; + +sc_plist_base::sc_plist_base() : head(0), tail(0) {} + +sc_plist_base::~sc_plist_base() +{ + handle_t p; + for( handle_t h = head; h != 0; h = p ) { + p = h->next; + delete h; + } +} + +void +sc_plist_base::erase_all() +{ + handle_t p; + for( handle_t h = head; h != 0; h = p ) { + p = h->next; + delete h; + } + head = 0; + tail = 0; +} + +int +sc_plist_base::size() const +{ + int n = 0; + for( handle_t h = head; h != 0; h = h->next ) { + n++; + } + return n; +} + +sc_plist_base::handle_t +sc_plist_base::push_back( void* d ) +{ + handle_t q = new sc_plist_elem( d, tail, 0 ); + if (tail) { + tail->next = q; + tail = q; + } + else { + head = tail = q; + } + return q; +} + +sc_plist_base::handle_t +sc_plist_base::push_front( void* d ) +{ + handle_t q = new sc_plist_elem( d, (sc_plist_elem*) 0, head ); + if (head) { + head->prev = q; + head = q; + } + else { + head = tail = q; + } + return q; +} + +void* +sc_plist_base::pop_back() +{ + handle_t q = tail; + void* d = q->data; + tail = tail->prev; + delete q; + if (tail != 0) { + tail->next = 0; + } + else { + head = 0; + } + return d; +} + +void* +sc_plist_base::pop_front() +{ + handle_t q = head; + void* d = q->data; + head = head->next; + delete q; + if (head != 0) { + head->prev = 0; + } + else { + tail = 0; + } + return d; +} + +sc_plist_base::handle_t +sc_plist_base::insert_before( handle_t h, void* d ) +{ + if (h == 0) { + return push_back(d); + } + else { + handle_t q = new sc_plist_elem( d, h->prev, h ); + h->prev->next = q; + h->prev = q; + return q; + } +} + +sc_plist_base::handle_t +sc_plist_base::insert_after( handle_t h, void* d ) +{ + if (h == 0) { + return push_front(d); + } + else { + handle_t q = new sc_plist_elem( d, h, h->next ); + h->next->prev = q; + h->next = q; + return q; + } +} + +void* +sc_plist_base::remove( handle_t h ) +{ + if (h == head) + return pop_front(); + else if (h == tail) + return pop_back(); + else { + void* d = h->data; + h->prev->next = h->next; + h->next->prev = h->prev; + delete h; + return d; + } +} + +void* +sc_plist_base::get( handle_t h ) const +{ + return h->data; +} + +void +sc_plist_base::set( handle_t h, void* d ) +{ + h->data = d; +} + +void +sc_plist_base::mapcar( sc_plist_map_fn f, void* arg ) +{ + for (handle_t h = head; h != 0; h = h->next) { + f( h->data, arg ); + } +} + +void* +sc_plist_base::front() const +{ + + if (head) { + return head->data; + } + else { + SC_REPORT_ERROR( SC_ID_FRONT_ON_EMPTY_LIST_ , 0 ); + // never reached + return 0; + } +} + +void* +sc_plist_base::back() const +{ + if (tail) { + return tail->data; + } + else { + SC_REPORT_ERROR( SC_ID_BACK_ON_EMPTY_LIST_, 0 ); + // never reached + return 0; + } +} + + + +sc_plist_base_iter::sc_plist_base_iter( sc_plist_base* l, bool from_tail ) : + lst(l), ptr( from_tail ? l->tail : l->head ) +{ +} + +void +sc_plist_base_iter::reset( sc_plist_base* l, bool from_tail ) +{ + lst = l; + if (from_tail) { + ptr = l->tail; + } + else { + ptr = l->head; + } +} + +sc_plist_base_iter::~sc_plist_base_iter() +{ + +} + +bool +sc_plist_base_iter::empty() const +{ + return ptr == 0; +} + +void +sc_plist_base_iter::operator++(int) +{ + ptr = ptr->next; +} + +void +sc_plist_base_iter::operator--(int) +{ + ptr = ptr->prev; +} + +void* +sc_plist_base_iter::get() const +{ + return ptr->data; +} + +void +sc_plist_base_iter::set( void* d ) +{ + ptr->data = d; +} + +void +sc_plist_base_iter::remove() +{ + sc_plist_base::handle_t nptr = ptr->next; + lst->remove(ptr); + ptr = nptr; +} + +void +sc_plist_base_iter::remove(int direction) +{ + sc_plist_base::handle_t nptr = (direction == 1) ? ptr->next : ptr->prev; + lst->remove(ptr); + ptr = nptr; +} + +void +sc_plist_base_iter::set_handle( sc_plist_elem* h ) +{ + ptr = h; +} + +} // namespace sc_core + +// $Log: sc_list.cpp,v $ +// Revision 1.4 2011/08/26 20:46:18 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +// Revision 1.3 2011/08/24 22:05:56 acg +// Torsten Maehne: initialization changes to remove warnings. +// +// Revision 1.2 2011/02/18 20:38:43 acg +// Andy Goodrich: Updated Copyright notice. +// +// Revision 1.1.1.1 2006/12/15 20:20:06 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:53:10 acg +// Andy Goodrich: Added $Log command so that CVS comments are reproduced in +// the source. + +// taf diff --git a/ext/systemc/src/sysc/utils/sc_list.h b/ext/systemc/src/sysc/utils/sc_list.h new file mode 100644 index 000000000..40f4c92af --- /dev/null +++ b/ext/systemc/src/sysc/utils/sc_list.h @@ -0,0 +1,188 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_list.h -- Simple implementation of a doubly linked list. + + Original Author: Stan Y. Liao, Synopsys, Inc. + + CHANGE LOG AT END OF FILE + *****************************************************************************/ + + +#ifndef SC_LIST_H +#define SC_LIST_H + +namespace sc_core { + +//Some forward declarations +class sc_plist_elem; +template<class T> class sc_plist_iter; + +typedef void (*sc_plist_map_fn)( void* data, void* arg ); + +class sc_plist_base { + friend class sc_plist_base_iter; + +public: + sc_plist_base(); + ~sc_plist_base(); + + typedef sc_plist_elem* handle_t; + + handle_t push_back(void* d); + handle_t push_front(void* d); + void* pop_back(); + void* pop_front(); + handle_t insert_before(handle_t h, void* d); + handle_t insert_after(handle_t h, void* d); + void* remove(handle_t h); + void* get(handle_t h) const; + void set(handle_t h, void* d); + void mapcar( sc_plist_map_fn f, void* arg ); + + void* front() const; + void* back() const; + + void erase_all(); + bool empty() const { return (head == 0); } + int size() const; + +private: + handle_t head; + handle_t tail; +}; + + +class sc_plist_base_iter { +public: + typedef sc_plist_elem* handle_t; + + sc_plist_base_iter( sc_plist_base* l, bool from_tail = false ); + ~sc_plist_base_iter(); + + void reset( sc_plist_base* l, bool from_tail = false ); + bool empty() const; + void operator++(int); + void operator--(int); + void* get() const; + void set(void* d); + void remove(); + void remove(int direction); + + void set_handle(handle_t h); + handle_t get_handle() const { return ptr; } + +private: + sc_plist_base* lst; + sc_plist_elem* ptr; +}; + +/*---------------------------------------------------------------------------*/ + +template< class T > +class sc_plist : public sc_plist_base { + friend class sc_plist_iter <T>; + +public: + typedef sc_plist_iter<T> iterator; + + sc_plist() { } + ~sc_plist() { } + + handle_t push_back(T d) { return sc_plist_base::push_back((void*)d); } + handle_t push_front(T d) { return sc_plist_base::push_front((void*)d); } + T pop_back() { return (T) sc_plist_base::pop_back(); } + T pop_front() { return (T) sc_plist_base::pop_front(); } + handle_t insert_before(handle_t h, T d) + { + return sc_plist_base::insert_before(h, (void*) d); + } + handle_t insert_after(handle_t h, T d) + { + return sc_plist_base::insert_after(h, (void*) d); + } + T remove(handle_t h) + { + return (T)sc_plist_base::remove(h); + } + T get(handle_t h) const { return (T)sc_plist_base::get(h); } + void set(handle_t h, T d) { sc_plist_base::set(h, (void*)d); } + + T front() const { return (T)sc_plist_base::front(); } + T back() const { return (T)sc_plist_base::back(); } +}; + +template< class T > +class sc_plist_iter : public sc_plist_base_iter { +public: + sc_plist_iter( sc_plist<T>* l, bool from_tail = false ) + : sc_plist_base_iter( l, from_tail ) + { + + } + sc_plist_iter( sc_plist<T>& l, bool from_tail = false ) + : sc_plist_base_iter( &l, from_tail ) + { + + } + ~sc_plist_iter() + { + + } + + void reset( sc_plist<T>* l, bool from_tail = false ) + { + sc_plist_base_iter::reset( l, from_tail ); + } + void reset( sc_plist<T>& l, bool from_tail = false ) + { + sc_plist_base_iter::reset( &l, from_tail ); + } + + T operator*() const { return (T) sc_plist_base_iter::get(); } + T get() const { return (T) sc_plist_base_iter::get(); } + void set(T d) { sc_plist_base_iter::set((void*) d); } +}; + +} // namespace sc_core + +// $Log: sc_list.h,v $ +// Revision 1.5 2011/09/01 15:16:50 acg +// Philipp A. Hartmann: revert unnecessary virtual destructors. +// +// Revision 1.4 2011/08/26 20:46:18 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +// Revision 1.3 2011/08/24 22:05:56 acg +// Torsten Maehne: initialization changes to remove warnings. +// +// Revision 1.2 2011/02/18 20:38:44 acg +// Andy Goodrich: Updated Copyright notice. +// +// Revision 1.1.1.1 2006/12/15 20:20:06 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:53:10 acg +// Andy Goodrich: Added $Log command so that CVS comments are reproduced in +// the source. + +#endif diff --git a/ext/systemc/src/sysc/utils/sc_machine.h b/ext/systemc/src/sysc/utils/sc_machine.h new file mode 100644 index 000000000..1939b0c99 --- /dev/null +++ b/ext/systemc/src/sysc/utils/sc_machine.h @@ -0,0 +1,81 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_machine.h -- Machine-dependent Environment Settings + + Original Author: Andy Goodrich, Forte Design Systems, Inc. + + CHANGE LOG AT END OF FILE + *****************************************************************************/ + + +#ifndef SC_MACHINE_H +#define SC_MACHINE_H + +#include <climits> +//#include "sysc/packages/boost/detail/endian.hpp" + +// We stripped the boost include and assume a build on x86 +#define SC_BOOST_LITTLE_ENDIAN + +// ---------------------------------------------------------------------------- +// Little or big endian machine? +// ---------------------------------------------------------------------------- + +#if defined( SC_BOOST_LITTLE_ENDIAN ) +# define SC_LITTLE_ENDIAN +#elif defined( SC_BOOST_BIG_ENDIAN ) +# define SC_BIG_ENDIAN +#else +# error "Could not detect the endianness of the CPU." +#endif + +// ---------------------------------------------------------------------------- +// Are long data types 32-bit or 64-bit? +// ---------------------------------------------------------------------------- + +#if ULONG_MAX > 0xffffffffUL +# define SC_LONG_64 +#endif + +// $Log: sc_machine.h,v $ +// Revision 1.5 2011/08/26 22:58:23 acg +// Torsten Maehne: changes for endian detection. +// +// Revision 1.4 2011/08/26 20:46:18 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +// Revision 1.3 2011/02/18 20:38:44 acg +// Andy Goodrich: Updated Copyright notice. +// +// Revision 1.2 2010/09/06 16:35:09 acg +// Andy Goodrich: changed i386 to __i386__ in ifdef. +// +// Revision 1.1.1.1 2006/12/15 20:20:06 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:53:10 acg +// Andy Goodrich: Added $Log command so that CVS comments are reproduced in +// the source. +// + +#endif // !defined(SC_MACHINE_H) diff --git a/ext/systemc/src/sysc/utils/sc_mempool.cpp b/ext/systemc/src/sysc/utils/sc_mempool.cpp new file mode 100644 index 000000000..7369c12a0 --- /dev/null +++ b/ext/systemc/src/sysc/utils/sc_mempool.cpp @@ -0,0 +1,338 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_mempool.cpp - Memory pools for small objects. + + Original Author: Stan Y. Liao, Synopsys, Inc. + + CHANGE LOG AT END OF FILE + *****************************************************************************/ + + + + +// <sc_mempool> is a class that manages the memory for small objects, +// of sizes <increment>, 2 * <increment>, ..., <num_pools> * +// <increment>. When a memory request of <k> bytes is made through +// the memory pool, the smallest pool <j> such that <j> * <increment> +// >= <k> is used. The default values of <increment> and <num_pools> +// are 8 and 8, respectively. Each pool has an allocator, that +// simply keeps a free list of cells, and allocate new blocks +// whenever necessary. We are relying on malloc() to return a +// properly aligned memory blocks. Note that the memory blocks +// allocated by the mempool are never freed. Thus, if purify is +// used, we may get MIU (memory-in-use) warnings. To disable this, +// set the environment variable SYSTEMC_MEMPOOL_DONT_USE to 1. + + +static const char* dont_use_envstring = "SYSTEMC_MEMPOOL_DONT_USE"; +static bool use_default_new = false; + + +#include <stdio.h> +#include <stdlib.h> // duplicate (c)stdlib.h headers for Solaris +#include <cstdlib> +#include "sysc/utils/sc_mempool.h" + +namespace sc_core { + +// An allocator is one that handles a particular size. It keeps a +// <free_list> from which a cell may be allocated quickly if there +// is one available. If no cell is available from <free_list>, then +// the allocator tries to find whether space is available from the +// most-recently-allocated block, as pointed to by <next_avail>. If +// so, then the cell pointed to by <next_avail> is returned, while +// <next_avail> is advanced. If <next_avail> now points beyond +// the current block, then it's reset to 0. On the other hand, +// if <next_avail> was 0 when a request to the block is made, then +// a new block is allocated by calling system malloc(), and the new +// block becomes the head of <block_list>. + + +class sc_allocator { + friend class sc_mempool; + +public: + sc_allocator( int blksz, int cellsz ); + ~sc_allocator(); + void* allocate(); + void release(void* p); + + void display_statistics(); + +private: + union link { + link* next; + double align; // alignment required. + }; + + int block_size; // size of each block in bytes, + // including the link + int cell_size; // size of each cell in bytes + + char* block_list; + link* free_list; + char* next_avail; + + int total_alloc; + int total_freed; + int free_list_alloc; +}; + +sc_allocator::sc_allocator( int blksz, int cellsz ) + : block_size(sizeof(link) + (((blksz - 1) / cellsz) + 1) * cellsz), + cell_size(cellsz), block_list(0), free_list(0), next_avail(0), + total_alloc(0), total_freed(0), free_list_alloc(0) +{} + +sc_allocator::~sc_allocator() +{ + // Shouldn't free the block_list, since global objects that use + // the memory pool may not have been destroyed yet ... + // Let it leak, let it leak, let it leak ... +} + +void* +sc_allocator::allocate() +{ + void* result = 0; + total_alloc++; + if (free_list != 0) { + free_list_alloc++; + result = free_list; + free_list = free_list->next; + return result; + } + else if (next_avail != 0) { + result = next_avail; + next_avail += cell_size; + // next_avail goes beyond the block + if (next_avail >= block_list + block_size) + next_avail = 0; + return result; + } + else { // (next_avail == 0) + link* new_block = (link*) malloc(block_size); // need alignment? + new_block->next = (link*) block_list; + block_list = (char*) new_block; + result = (block_list + sizeof(link)); + // Assume that the block will hold more than one cell ... why + // wouldn't it? + next_avail = ((char*) result) + cell_size; + return result; + } +} + +void +sc_allocator::release(void* p) +{ + total_freed++; + ((link*) p)->next = free_list; + free_list = (link*) p; +} + +void +sc_allocator::display_statistics() +{ + int nblocks = 0; + for (link* b = (link*) block_list; b != 0; b = b->next) + nblocks++; + printf("size %3d: %2d block(s), %3d requests (%3d from free list), %3d freed.\n", + cell_size, nblocks, total_alloc, free_list_alloc, total_freed); +} + + +static const int cell_sizes[] = { +/* 0 */ 0, +/* 1 */ 8, +/* 2 */ 16, +/* 3 */ 24, +/* 4 */ 32, +/* 5 */ 48, +/* 6 */ 64, +/* 7 */ 80, +/* 8 */ 96, +/* 9 */ 128 +}; + +static const int cell_size_to_allocator[] = { +/* 0 */ 0, +/* 1 */ 1, +/* 2 */ 2, +/* 3 */ 3, +/* 4 */ 4, +/* 5 */ 5, +/* 6 */ 5, +/* 7 */ 6, +/* 8 */ 6, +/* 9 */ 7, +/* 10 */ 7, +/* 11 */ 8, +/* 12 */ 8, +/* 13 */ 9, +/* 14 */ 9, +/* 15 */ 9, +/* 16 */ 9 +}; + + +class sc_mempool_int { + friend class sc_mempool; + +public: + sc_mempool_int(int blksz, int npools, int incr); + ~sc_mempool_int(); + void* do_allocate(std::size_t); + void do_release(void*, std::size_t); + + void display_statistics(); + +private: + sc_allocator** allocators; + int num_pools; + int increment; + int max_size; +}; + + +static bool +compute_use_default_new() +{ + const char* e = getenv(dont_use_envstring); + return (e != 0) && (atoi(e) != 0); +} + +sc_mempool_int::sc_mempool_int(int blksz, int npools, int incr) : + allocators(0), num_pools(0), increment(0), max_size(0) +{ + use_default_new = compute_use_default_new(); + if (! use_default_new) { + num_pools = npools; + increment = incr; + max_size = cell_sizes[sizeof(cell_sizes)/sizeof(cell_sizes[0]) - 1]; + allocators = new sc_allocator*[npools + 1]; + for (int i = 1; i <= npools; ++i) + allocators[i] = new sc_allocator(blksz, cell_sizes[i]); + allocators[0] = allocators[1]; + } +} + +sc_mempool_int::~sc_mempool_int() +{ + for (int i = 1; i <= num_pools; ++i) + delete allocators[i]; + delete[] allocators; +} + +static sc_mempool_int* the_mempool = 0; + +void* +sc_mempool_int::do_allocate(std::size_t sz) +{ + int which_allocator = cell_size_to_allocator[(sz - 1) / increment + 1]; + void* p = allocators[which_allocator]->allocate(); + return p; +} + +void +sc_mempool_int::do_release(void* p, std::size_t sz) +{ + int which_allocator = cell_size_to_allocator[(sz - 1) / increment + 1]; + allocators[which_allocator]->release(p); +} + +void +sc_mempool_int::display_statistics() +{ + printf("*** Memory Pool Statistics ***\n"); + for (int i = 1; i <= num_pools; ++i) + allocators[i]->display_statistics(); +} + +/****************************************************************************/ + +void* +sc_mempool::allocate(std::size_t sz) +{ + if (use_default_new) + return ::operator new(sz); + + if (the_mempool == 0) { + use_default_new = compute_use_default_new(); + if (use_default_new) + return ::operator new(sz); + + // Note that the_mempool is never freed. This is going to cause + // memory leaks when the program exits. + the_mempool = new sc_mempool_int( 1984, sizeof(cell_sizes)/sizeof(cell_sizes[0]) - 1, 8 ); + } + + if (sz > (unsigned) the_mempool->max_size) + return ::operator new(sz); + + return the_mempool->do_allocate(sz); +} + +void +sc_mempool::release(void* p, std::size_t sz) +{ + if (p) { + + if (use_default_new || sz > (unsigned) the_mempool->max_size) { + ::operator delete(p); + return; + } + + the_mempool->do_release(p, sz); + } +} + +void +sc_mempool::display_statistics() +{ + if (the_mempool && !use_default_new) { + the_mempool->display_statistics(); + } else { + printf("SystemC info: no memory allocation was done through the memory pool.\n"); + } +} + +} // namespace sc_core + +// $Log: sc_mempool.cpp,v $ +// Revision 1.4 2011/08/26 20:46:18 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +// Revision 1.3 2011/08/24 22:05:56 acg +// Torsten Maehne: initialization changes to remove warnings. +// +// Revision 1.2 2011/02/18 20:38:44 acg +// Andy Goodrich: Updated Copyright notice. +// +// Revision 1.1.1.1 2006/12/15 20:20:06 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:53:10 acg +// Andy Goodrich: Added $Log command so that CVS comments are reproduced in +// the source. + +// taf diff --git a/ext/systemc/src/sysc/utils/sc_mempool.h b/ext/systemc/src/sysc/utils/sc_mempool.h new file mode 100644 index 000000000..1c053ae1c --- /dev/null +++ b/ext/systemc/src/sysc/utils/sc_mempool.h @@ -0,0 +1,93 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_mempool.h - Memory pools for small objects. + + Original Author: Stan Y. Liao, Synopsys, Inc. + + CHANGE LOG AT END OF FILE + *****************************************************************************/ + +#ifndef SC_MEMPOOL_H +#define SC_MEMPOOL_H + + +#include "sysc/utils/sc_iostream.h" + +namespace sc_core { + +// ---------------------------------------------------------------------------- +// CLASS : sc_mempool +// +// ... +// ---------------------------------------------------------------------------- + +class sc_mempool +{ +public: + + static void* allocate( std::size_t sz ); + static void release( void* p, std::size_t sz ); + static void display_statistics(); +}; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_mpobject +// +// ... +// ---------------------------------------------------------------------------- + +class sc_mpobject +{ +public: + + static void* operator new( std::size_t sz ) + { return sc_mempool::allocate( sz ); } + + static void operator delete( void* p, std::size_t sz ) + { sc_mempool::release( p, sz ); } + + static void* operator new[]( std::size_t sz ) + { return sc_mempool::allocate( sz ); } + + static void operator delete[]( void* p, std::size_t sz ) + { sc_mempool::release( p, sz ); } +}; + +} // namespace sc_core + +// $Log: sc_mempool.h,v $ +// Revision 1.3 2011/08/26 20:46:18 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +// Revision 1.2 2011/02/18 20:38:44 acg +// Andy Goodrich: Updated Copyright notice. +// +// Revision 1.1.1.1 2006/12/15 20:20:06 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:53:11 acg +// Andy Goodrich: Added $Log command so that CVS comments are reproduced in +// the source. + +#endif diff --git a/ext/systemc/src/sysc/utils/sc_pq.cpp b/ext/systemc/src/sysc/utils/sc_pq.cpp new file mode 100644 index 000000000..d20580ca5 --- /dev/null +++ b/ext/systemc/src/sysc/utils/sc_pq.cpp @@ -0,0 +1,133 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_pq.cpp - Simple heap implementation of priority queue. + + Original Author: Stan Y. Liao, Synopsys, Inc. + + CHANGE LOG AT END OF FILE + *****************************************************************************/ + +// $Log: sc_pq.cpp,v $ +// Revision 1.4 2011/08/26 20:46:18 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// + +#include "sysc/utils/sc_pq.h" + +namespace sc_core { + +sc_ppq_base::sc_ppq_base( int sz, int (*cmp)( const void*, const void* ) ) + : m_heap(0), m_size_alloc( sz ), m_heap_size( 0 ), m_compar( cmp ) +{ + // m_size_alloc must be at least 2, otherwise resizing doesn't work + if( m_size_alloc < 2 ) { + m_size_alloc = 2; + } + // allocate + m_heap = new void*[m_size_alloc + 1]; + // initialize + for( int i = 0; i < m_size_alloc; ++ i ) { + m_heap[i] = 0; + } +} + +sc_ppq_base::~sc_ppq_base() +{ + delete[] m_heap; +} + +void* +sc_ppq_base::extract_top() +{ + assert( m_heap_size > 0 ); + void* topelem = m_heap[1]; + m_heap[1] = m_heap[m_heap_size]; + m_heap_size --; + heapify( 1 ); + return topelem; +} + +void +sc_ppq_base::insert( void* elem ) +{ + m_heap_size ++; + int i = m_heap_size; + + // resize the heap in case there's not enough memory + if( m_heap_size > m_size_alloc ) { + m_size_alloc += m_size_alloc / 2; + void** new_heap = new void*[m_size_alloc + 1]; + for( int j = 1; j < m_heap_size; ++ j ) { + new_heap[j] = m_heap[j]; + } + delete[] m_heap; + m_heap = new_heap; + } + + while( (i > 1) && (m_compar( m_heap[parent( i )], elem ) < 0) ) { + m_heap[i] = m_heap[parent( i )]; + i = parent( i ); + } + m_heap[i] = elem; +} + +void +sc_ppq_base::heapify( int i ) +{ + int l; + while( l = left( i ), l <= m_heap_size ) { + int largest = (m_compar( m_heap[l], m_heap[i] ) > 0) ? l : i; + + int r = right( i ); + if( (r <= m_heap_size) && + (m_compar( m_heap[r], m_heap[largest] ) > 0) ) { + largest = r; + } + + if( largest != i ) { + void* tmp = m_heap[i]; + m_heap[i] = m_heap[largest]; + m_heap[largest] = tmp; + i = largest; + } else { + break; + } + } +} + +} // namespace sc_core + +// Revision 1.3 2011/08/24 22:05:56 acg +// Torsten Maehne: initialization changes to remove warnings. +// +// Revision 1.2 2011/02/18 20:38:44 acg +// Andy Goodrich: Updated Copyright notice. +// +// Revision 1.1.1.1 2006/12/15 20:20:06 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:53:11 acg +// Andy Goodrich: Added $Log command so that CVS comments are reproduced in +// the source. + +// taf diff --git a/ext/systemc/src/sysc/utils/sc_pq.h b/ext/systemc/src/sysc/utils/sc_pq.h new file mode 100644 index 000000000..51ed54f4a --- /dev/null +++ b/ext/systemc/src/sysc/utils/sc_pq.h @@ -0,0 +1,154 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_pq.h -- A simple priority queue (which can be used to model multiple + clocks). From Cormen-Leiserson-Rivest, Ch.7. + + Original Author: Stan Y. Liao, Synopsys, Inc. + + CHANGE LOG AT END OF FILE + *****************************************************************************/ + +#ifndef SC_PQ_H +#define SC_PQ_H + + +#include <cassert> + +namespace sc_core { + +// ---------------------------------------------------------------------------- +// CLASS : sc_ppq_base +// +// Priority queue base class. +// ---------------------------------------------------------------------------- + +class sc_ppq_base +{ +public: + + typedef int (*compare_fn_t)( const void*, const void* ); + + sc_ppq_base( int sz, compare_fn_t cmp ); + + ~sc_ppq_base(); + + void* top() const + { return m_heap[1]; } + + void* extract_top(); + + void insert( void* elem ); + + int size() const + { return m_heap_size; } + + bool empty() const + { return (m_heap_size == 0); } + +protected: + + int parent( int i ) const + { return i >> 1; } + + int left( int i ) const + { return i << 1; } + + int right( int i ) const + { return (i << 1) + 1; } + + void heapify( int i ); + +private: + + void** m_heap; + int m_size_alloc; + int m_heap_size; + compare_fn_t m_compar; +}; + + +// ---------------------------------------------------------------------------- +// CLASS TEMPLATE : sc_ppq<T> +// +// This class is a simple implementation of a priority queue based on +// binary heaps. The class is templatized on its data type. A comparison +// function needs to be supplied. +// ---------------------------------------------------------------------------- + +template <class T> +class sc_ppq + : public sc_ppq_base +{ +public: + + // constructor - specify the maximum size of the queue and + // give a comparison function. + + sc_ppq( int sz, compare_fn_t cmp ) + : sc_ppq_base( sz, cmp ) + {} + + ~sc_ppq() + {} + + // returns the value of the top element in the priority queue. + T top() const + { return (T) sc_ppq_base::top(); } + + // pops the first element of the priority queue. + + T extract_top() + { return (T) sc_ppq_base::extract_top(); } + + // insert a new element to the priority queue. + + void insert( T elem ) + { sc_ppq_base::insert( (void*) elem ); } + + // size() and empty() are inherited. +}; + +} // namespace sc_core + +// $Log: sc_pq.h,v $ +// Revision 1.5 2011/08/29 18:04:32 acg +// Philipp A. Hartmann: miscellaneous clean ups. +// +// Revision 1.4 2011/08/26 20:46:18 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +// Revision 1.3 2011/08/24 22:05:56 acg +// Torsten Maehne: initialization changes to remove warnings. +// +// Revision 1.2 2011/02/18 20:38:44 acg +// Andy Goodrich: Updated Copyright notice. +// +// Revision 1.1.1.1 2006/12/15 20:20:06 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:53:11 acg +// Andy Goodrich: Added $Log command so that CVS comments are reproduced in +// the source. +// + +#endif diff --git a/ext/systemc/src/sysc/utils/sc_pvector.h b/ext/systemc/src/sysc/utils/sc_pvector.h new file mode 100644 index 000000000..3c0e127c9 --- /dev/null +++ b/ext/systemc/src/sysc/utils/sc_pvector.h @@ -0,0 +1,187 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_vector.h -- Simple implementation of a vector class. + + Original Author: Stan Y. Liao, Synopsys, Inc. + + CHANGE LOG AT END OF FILE + *****************************************************************************/ + +#ifndef SC_VECTOR_H +#define SC_VECTOR_H + +#include <vector> + +namespace sc_core { + +extern "C" { + typedef int (*CFT)( const void*, const void* ); +} + + +// #define ACCESS(I) m_vector.at(I) // index checking +#define ACCESS(I) m_vector[I] +#define ADDR_ACCESS(I) (m_vector.size() != 0 ? &m_vector[I] : 0 ) + +// ---------------------------------------------------------------------------- +// CLASS : sc_pvector<T> +// +// Simple vector class. +// ---------------------------------------------------------------------------- + +template< class T > +class sc_pvector +{ +public: + + typedef const T* const_iterator; + typedef T* iterator; + // typedef typename ::std::vector<T>::const_iterator const_iterator; + // typedef typename ::std::vector<T>::iterator iterator; + + sc_pvector( int alloc_n = 0 ) + { + } + + sc_pvector( const sc_pvector<T>& rhs ) + : m_vector( rhs.m_vector ) + {} + + ~sc_pvector() + {} + + + std::size_t size() const + { return m_vector.size(); } + + + iterator begin() + { return (iterator) ADDR_ACCESS(0); } + + const_iterator begin() const + { return (const_iterator) ADDR_ACCESS(0); } + + iterator end() + { return static_cast<iterator> (ADDR_ACCESS(m_vector.size())); } + + const_iterator end() const + { + return static_cast<const_iterator> (ADDR_ACCESS(m_vector.size())); + } + + + sc_pvector<T>& operator = ( const sc_pvector<T>& rhs ) + { m_vector = rhs.m_vector; return *this; } + + + T& operator [] ( unsigned int i ) + { + if ( i >= m_vector.size() ) m_vector.resize(i+1); + return (T&) m_vector.operator [] ( i ); + } + + const T& operator [] ( unsigned int i ) const + { + if ( i >= m_vector.size() ) m_vector.resize(i+1); + return (const T&) m_vector.operator [] ( i ); + } + + T& fetch( int i ) + { return ACCESS(i); } + + const T& fetch( int i ) const + { return (const T&) ACCESS(i); } + + + T* raw_data() + { return (T*) &ACCESS(0); } + + const T* raw_data() const + { return (const T*) &ACCESS(0); } + + + operator const ::std::vector<T>& () const + { return m_vector; } + + void push_back( T item ) + { m_vector.push_back( item ); } + + + void erase_all() + { m_vector.resize(0); } + + void sort( CFT compar ) + {qsort( (void*)&m_vector[0], m_vector.size(), sizeof(void*), compar );} + + /* These methods have been added from Ptr_Array */ + + void put( T item, int i ) + { ACCESS(i) = item; } + + void decr_count() + { m_vector.resize(m_vector.size()-1); } + + void decr_count( int k ) + { m_vector.resize(m_vector.size()-k); } + + + + protected: + mutable ::std::vector<T> m_vector; // Actual vector of pointers. +}; + +#undef ACCESS +#undef ADDR_ACCESS + +} // namespace sc_core + +// $Log: sc_pvector.h,v $ +// Revision 1.4 2011/08/26 20:46:19 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +// Revision 1.3 2011/02/18 20:38:44 acg +// Andy Goodrich: Updated Copyright notice. +// +// Revision 1.2 2011/01/20 16:52:21 acg +// Andy Goodrich: changes for IEEE 1666 2011. +// +// Revision 1.1 2010/12/07 20:11:45 acg +// Andy Goodrich: moved sc_pvector class to new header file to allow the +// use of sc_vector.h for Philipp Hartmann's new sc_vector class. +// +// Revision 1.4 2010/08/03 17:52:15 acg +// Andy Goodrich: fix signature for size() method of sc_pvector. +// +// Revision 1.3 2008/10/09 21:20:33 acg +// Andy Goodrich: fixed the way the end() methods calculate their results. +// I had incorrectly cut and pasted code from the begin() method. +// +// Revision 1.2 2007/01/17 22:44:34 acg +// Andy Goodrich: fix for Microsoft compiler. +// +// Revision 1.3 2006/01/13 18:53:11 acg +// Andy Goodrich: Added $Log command so that CVS comments are reproduced in +// the source. +// + +#endif diff --git a/ext/systemc/src/sysc/utils/sc_report.cpp b/ext/systemc/src/sysc/utils/sc_report.cpp new file mode 100644 index 000000000..378d45cde --- /dev/null +++ b/ext/systemc/src/sysc/utils/sc_report.cpp @@ -0,0 +1,330 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_report.cpp -- Run-time logging and reporting facilities + + Interface design by SystemC Verification Working Group. + Implementation by Alex Riesen, Synopsys Inc. + Original implementation by Martin Janssen, Synopsys Inc. + Reference implementation by Cadence Design Systems, Inc., 2002-09-23: + Norris Ip, Dean Shea, John Rose, Jasvinder Singh, William Paulsen, + John Pierce, Rachida Kebichi, Ted Elkind, David Bailey. + + CHANGE LOG AT END OF FILE + *****************************************************************************/ + + +#include <stdlib.h> +#include <string.h> + +#include "sysc/kernel/sc_process.h" +#include "sysc/kernel/sc_simcontext_int.h" +#include "sysc/utils/sc_stop_here.h" +#include "sysc/utils/sc_report.h" +#include "sysc/utils/sc_utils_ids.h" +#include <algorithm> // std::swap + +namespace sc_core { + + +static void sc_deprecated_report_ids(const char* method) +{ + static bool warn_report_ids_deprecated=true; + if ( warn_report_ids_deprecated ) + { + std::string message; + message = "integer report ids are deprecated, use string values: "; + message += method; + warn_report_ids_deprecated=false; + SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, message.c_str()); + } +} + +static char empty_str[] = ""; +static inline char * empty_dup(const char * p) +{ + if ( p && *p ) + { + char* result; + result = (char*)malloc(strlen(p)+1); + strcpy(result, p); + return result; + } + else + { + return empty_str; + } +} + +sc_report::sc_report() +: severity(SC_INFO), + md(0), + msg(empty_dup(0)), + file(empty_dup(0)), + line(0), + timestamp(new sc_time(sc_time_stamp())), + process(0), + m_verbosity_level(SC_MEDIUM), + m_what(empty_dup(0)) +{ +} + +sc_report::sc_report(sc_severity severity_, + const sc_msg_def* md_, + const char* msg_, + const char* file_, + int line_, + int verbosity_level) +: severity(severity_), + md(md_), + msg(empty_dup(msg_)), + file(empty_dup(file_)), + line(line_), + timestamp(new sc_time(sc_time_stamp())), + process(sc_get_current_process_b()), + m_verbosity_level(verbosity_level), + m_what( empty_dup( sc_report_compose_message(*this).c_str() ) ) +{ +} + +sc_report::sc_report(const sc_report& other) +: std::exception(other), + severity(other.severity), + md(other.md), + msg(empty_dup(other.msg)), + file(empty_dup(other.file)), + line(other.line), + timestamp(new sc_time(*other.timestamp)), + process(other.process), + m_verbosity_level(other.m_verbosity_level), + m_what(empty_dup(other.m_what)) +{ +} + +sc_report & sc_report::operator=(const sc_report& other) +{ + sc_report copy(other); + swap( copy ); + return *this; +} + +void +sc_report::swap( sc_report & that ) +{ + using std::swap; + swap( severity, that.severity ); + swap( md, that.md ); + swap( msg, that.msg ); + swap( file, that.file ); + swap( line, that.line ); + swap( timestamp, that.timestamp ); + swap( process, that.process ); + swap( m_verbosity_level, that.m_verbosity_level ); + swap( m_what, that.m_what ); +} + +sc_report::~sc_report() throw() +{ + if ( file != empty_str ) + free(file); + if ( msg != empty_str ) + free(msg); + delete timestamp; + if ( m_what != empty_str ) + free(m_what); +} + +const char * sc_report::get_msg_type() const +{ + return md->msg_type; +} + +// +// backward compatibility with 2.0+ +// + +static bool warnings_are_errors = false; +static const char unknown_id[] = "unknown id"; + +void sc_report_handler::report(sc_severity severity_, + int id_, + const char* msg_, + const char* file_, + int line_ ) +{ + sc_msg_def * md = sc_report_handler::mdlookup(id_); + + if ( !md ) + { + md = sc_report_handler::add_msg_type(unknown_id); + md->id = id_; + } + + if ( severity_ == SC_WARNING && warnings_are_errors ) + severity_ = SC_ERROR; + + sc_actions actions = execute(md, severity_); + sc_report rep(severity_, md, msg_, file_, line_); + + if ( actions & SC_CACHE_REPORT ) + cache_report(rep); + + if ( severity_ == SC_ERROR ) + actions |= SC_THROW; + else if ( severity_ == SC_FATAL ) + actions |= SC_ABORT; + + handler(rep, actions); +} + +void sc_report::register_id( int id, const char* msg ) +{ + sc_deprecated_report_ids("sc_report::register_id()"); + if( id < 0 ) { + SC_REPORT_ERROR( SC_ID_REGISTER_ID_FAILED_, + "invalid report id" ); + } + if( msg == 0 ) { + SC_REPORT_ERROR( SC_ID_REGISTER_ID_FAILED_, + "invalid report message" ); + } + sc_msg_def * md = sc_report_handler::mdlookup(id); + + if ( !md ) + md = sc_report_handler::add_msg_type(msg); + + if ( !md ) { + SC_REPORT_ERROR( SC_ID_REGISTER_ID_FAILED_, + "report_map insertion error" ); + } + + if( md->id != -1 ) { + if( strcmp( msg, md->msg_type ) != 0 ) { + SC_REPORT_ERROR( SC_ID_REGISTER_ID_FAILED_, + "report id already exists" ); + } + return; + } + md->id = id; +} + +const char* sc_report::get_message( int id ) +{ + sc_deprecated_report_ids("sc_report::get_message()"); + sc_msg_def* md = sc_report_handler::mdlookup(id); + + return md ? md->msg_type: unknown_id; +} + +bool sc_report::is_suppressed( int id ) +{ + sc_deprecated_report_ids("sc_report::is_suppressed()"); + sc_msg_def* md = sc_report_handler::mdlookup(id); + + return md ? md->actions == SC_DO_NOTHING: false; // only do-nothing set +} + +void sc_report::suppress_id(int id_, bool suppress) +{ + sc_deprecated_report_ids("sc_report::suppress_id()"); + sc_msg_def* md = sc_report_handler::mdlookup(id_); + + if ( md ) + md->actions = suppress ? SC_DO_NOTHING: SC_UNSPECIFIED; +} + +void sc_report::suppress_infos(bool suppress) +{ + sc_deprecated_report_ids("sc_report::supress_infos"); + sc_report_handler::sev_actions[SC_INFO] = + suppress ? SC_DO_NOTHING: SC_DEFAULT_INFO_ACTIONS; +} + +void sc_report::suppress_warnings(bool suppress) +{ + sc_deprecated_report_ids("sc_report::suppress_warnings"); + sc_report_handler::sev_actions[SC_WARNING] = + suppress ? SC_DO_NOTHING: SC_DEFAULT_WARNING_ACTIONS; +} + +void sc_report::make_warnings_errors(bool flag) +{ + sc_deprecated_report_ids("sc_report::make_warnings_errors"); + warnings_are_errors = flag; +} + +int sc_report::get_id() const +{ + return md->id; +} + +} // namespace sc_core + +// $Log: sc_report.cpp,v $ +// Revision 1.8 2011/08/29 18:04:32 acg +// Philipp A. Hartmann: miscellaneous clean ups. +// +// Revision 1.7 2011/08/26 20:43:01 acg +// Andy Goodrich: +// (1) Replaced strdup with new and strcpy to eliminate issue with the +// Greenhills compiler. +// (2) Moved modification log to the end of the file to eliminate line +// skew when check-ins are done. +// +// Revision 1.6 2011/08/24 22:05:56 acg +// Torsten Maehne: initialization changes to remove warnings. +// +// Revision 1.5 2011/05/05 17:46:04 acg +// Philip A. Hartmann: changes in "swap" support. +// +// Revision 1.4 2011/03/23 16:16:48 acg +// Andy Goodrich: finish message verbosity support. +// +// Revision 1.3 2011/02/18 20:38:44 acg +// Andy Goodrich: Updated Copyright notice. +// +// Revision 1.2 2011/02/01 23:02:05 acg +// Andy Goodrich: IEEE 1666 2011 changes. +// +// Revision 1.1.1.1 2006/12/15 20:20:06 acg +// SystemC 2.3 +// +// Revision 1.7 2006/03/21 00:00:37 acg +// Andy Goodrich: changed name of sc_get_current_process_base() to be +// sc_get_current_process_b() since its returning an sc_process_b instance. +// +// Revision 1.6 2006/01/25 00:31:27 acg +// Andy Goodrich: Changed over to use a standard message id of +// SC_ID_IEEE_1666_DEPRECATION for all deprecation messages. +// +// Revision 1.5 2006/01/24 22:02:30 acg +// Andy Goodrich: switch deprecated features warnings to use a single message +// id, SC_ID_IEEE_1666_DEPRECATION_. +// +// Revision 1.4 2006/01/24 20:53:41 acg +// Andy Goodrich: added warnings indicating that use of integer ids in reports +// is deprecated. Added tracing/sc_trace_ids.h to message list. +// +// Revision 1.3 2006/01/13 18:53:11 acg +// Andy Goodrich: Added $Log command so that CVS comments are reproduced in +// the source. + +// taf diff --git a/ext/systemc/src/sysc/utils/sc_report.h b/ext/systemc/src/sysc/utils/sc_report.h new file mode 100644 index 000000000..f76bef71f --- /dev/null +++ b/ext/systemc/src/sysc/utils/sc_report.h @@ -0,0 +1,299 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_report.h -- Run-time logging and reporting facilities + + Interface design by SystemC Verification Working Group. + Implementation by Alex Riesen, Synopsys Inc. + Original implementation by Martin Janssen, Synopsys Inc. + Reference implementation by Cadence Design Systems, Inc., 2002-09-23: + Norris Ip, Dean Shea, John Rose, Jasvinder Singh, William Paulsen, + John Pierce, Rachida Kebichi, Ted Elkind, David Bailey. + + CHANGE LOG AT END OF FILE + *****************************************************************************/ + +#ifndef SC_REPORT_H +#define SC_REPORT_H 1 + +#include <exception> +#include <string> + +namespace sc_core { + +// ---------------------------------------------------------------------------- +// ENUM : sc_severity +// +// Enumeration of possible exception severity levels +// ---------------------------------------------------------------------------- + +enum sc_severity { + SC_INFO = 0, // informative only + SC_WARNING, // indicates potentially incorrect condition + SC_ERROR, // indicates a definite problem + SC_FATAL, // indicates a problem from which we cannot recover + SC_MAX_SEVERITY +}; + +typedef unsigned sc_actions; + +// ---------------------------------------------------------------------------- +// ENUM : sc_verbosity +// +// Enumeration of message verbosity. +// ---------------------------------------------------------------------------- + + enum sc_verbosity { + SC_NONE = 0, + SC_LOW = 100, + SC_MEDIUM = 200, + SC_HIGH = 300, + SC_FULL = 400, + SC_DEBUG = 500 + }; + +// ---------------------------------------------------------------------------- +// ENUM : +// +// Enumeration of actions on an exception (implementation specific) +// ---------------------------------------------------------------------------- + +enum { + SC_UNSPECIFIED = 0x0000, // look for lower-priority rule + SC_DO_NOTHING = 0x0001, // take no action (ignore if other bits set) + SC_THROW = 0x0002, // throw an exception + SC_LOG = 0x0004, // add report to report log + SC_DISPLAY = 0x0008, // display report to screen + SC_CACHE_REPORT = 0x0010, // save report to cache + SC_INTERRUPT = 0x0020, // call sc_interrupt_here(...) + SC_STOP = 0x0040, // call sc_stop() + SC_ABORT = 0x0080 // call abort() +}; + +class sc_object; +class sc_time; +struct sc_msg_def; +class sc_report; +class sc_report_handler; +const std::string sc_report_compose_message( const sc_report& ); + +// ---------------------------------------------------------------------------- +// CLASS : sc_report +// +// Exception reporting +// ---------------------------------------------------------------------------- + +class sc_report : public std::exception +{ + friend class sc_report_handler; + friend sc_report* sc_handle_exception(); + + sc_report(); // used internally by sc_handle_exception + +public: + + sc_report(const sc_report&); + + sc_report & operator=(const sc_report&); + + virtual ~sc_report() throw(); + + const char * get_msg_type() const; + + const char * get_msg() const + { return msg; } + + sc_severity get_severity() const + { return severity; } + + const char * get_file_name() const + { return file; } + + int get_line_number() const + { return line; } + + const sc_time & get_time() const + { return *timestamp; } + + const char* get_process_name() const; + + int get_verbosity() const { return m_verbosity_level; } + + bool valid () const + { + return process != 0; + } + + virtual const char* what() const throw() + { + return m_what; + } + + void swap( sc_report& ); + +protected: + + sc_report(sc_severity, + const sc_msg_def*, + const char* msg, + const char* file, + int line, + int verbosity_level=SC_MEDIUM); + + sc_severity severity; + const sc_msg_def* md; + char* msg; + char* file; + int line; + sc_time* timestamp; + sc_object* process; + int m_verbosity_level; + char* m_what; + +public: // backward compatibility with 2.0+ + + static const char* get_message(int id); + static bool is_suppressed(int id); + static void make_warnings_errors(bool); + static void register_id(int id, const char* msg); + static void suppress_id(int id, bool); // only for info or warning + static void suppress_infos(bool); + static void suppress_warnings(bool); + + int get_id() const; +}; +typedef std::exception sc_exception; + +#define SC_DEFAULT_INFO_ACTIONS \ + (::sc_core::SC_LOG | ::sc_core::SC_DISPLAY) +#define SC_DEFAULT_WARNING_ACTIONS \ + (::sc_core::SC_LOG | ::sc_core::SC_DISPLAY) +#define SC_DEFAULT_ERROR_ACTIONS \ + (::sc_core::SC_LOG | ::sc_core::SC_CACHE_REPORT | ::sc_core::SC_THROW) +#define SC_DEFAULT_FATAL_ACTIONS \ + (::sc_core::SC_LOG | ::sc_core::SC_DISPLAY | \ + ::sc_core::SC_CACHE_REPORT | ::sc_core::SC_ABORT) + + +// ---------------------------------------------------------------------------- +// Report macros. +// +// Use these macros to report an info, warning, error, or fatal. +// ---------------------------------------------------------------------------- + +#define SC_REPORT_INFO( msg_type, msg ) \ + ::sc_core::sc_report_handler::report( \ + ::sc_core::SC_INFO, msg_type, msg, __FILE__, __LINE__ ) + +#define SC_REPORT_INFO_VERB( msg_type, msg, verbosity ) \ + ::sc_core::sc_report_handler::report( \ + ::sc_core::SC_INFO, msg_type, msg, verbosity, \ + __FILE__ , __LINE__ ) + +#define SC_REPORT_WARNING( msg_type, msg ) \ + ::sc_core::sc_report_handler::report( \ + ::sc_core::SC_WARNING, msg_type, msg, __FILE__, __LINE__ ) + +#define SC_REPORT_ERROR( msg_type, msg ) \ + ::sc_core::sc_report_handler::report( \ + ::sc_core::SC_ERROR, msg_type, msg, __FILE__, __LINE__ ) + +#define SC_REPORT_FATAL( msg_type, msg ) \ + ::sc_core::sc_report_handler::report( \ + ::sc_core::SC_FATAL, msg_type, msg, __FILE__, __LINE__ ) + +// ---------------------------------------------------------------------------- +// MACRO : sc_assert(expr) +// +// Like assert(), but additionally prints the current process name +// and simulation time, if the simulation is running. +// ---------------------------------------------------------------------------- + +#ifdef NDEBUG + +#define sc_assert(expr) \ + ((void) 0) + +#else + +#define sc_assert(expr) \ + ((void)((expr) ? 0 : \ + (SC_REPORT_FATAL( ::sc_core::SC_ID_ASSERTION_FAILED_, #expr ), 0))) + +#endif // NDEBUG + +extern const char SC_ID_UNKNOWN_ERROR_[]; +extern const char SC_ID_WITHOUT_MESSAGE_[]; +extern const char SC_ID_NOT_IMPLEMENTED_[]; +extern const char SC_ID_INTERNAL_ERROR_[]; +extern const char SC_ID_ASSERTION_FAILED_[]; +extern const char SC_ID_OUT_OF_BOUNDS_[]; + +// backward compatibility with 2.0+ +extern const char SC_ID_REGISTER_ID_FAILED_[]; + +} // namespace sc_core + +#include "sysc/utils/sc_report_handler.h" + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: Alex Riesen, Synopsys Inc., Jan 28, 2003 + Description of Modification: Implementation for SytemC 2.1 + + *****************************************************************************/ + +// $Log: sc_report.h,v $ +// Revision 1.8 2011/08/26 20:46:19 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +// Revision 1.7 2011/05/05 17:46:04 acg +// Philip A. Hartmann: changes in "swap" support. +// +// Revision 1.6 2011/04/19 02:39:44 acg +// Andy Goodrich: set proper name for get_verbosity(). +// +// Revision 1.5 2011/03/23 16:16:48 acg +// Andy Goodrich: finish message verbosity support. +// +// Revision 1.4 2011/02/18 20:38:44 acg +// Andy Goodrich: Updated Copyright notice. +// +// Revision 1.3 2011/02/01 23:02:05 acg +// Andy Goodrich: IEEE 1666 2011 changes. +// +// Revision 1.2 2008/05/20 20:42:50 acg +// Andy Goodrich: added sc_core namespace prefix for ID value in sc_assert() +// macro. +// +// Revision 1.1.1.1 2006/12/15 20:20:06 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:53:11 acg +// Andy Goodrich: Added $Log command so that CVS comments are reproduced in +// the source. +// + +#endif // SC_REPORT_H diff --git a/ext/systemc/src/sysc/utils/sc_report_handler.cpp b/ext/systemc/src/sysc/utils/sc_report_handler.cpp new file mode 100644 index 000000000..0de71a18b --- /dev/null +++ b/ext/systemc/src/sysc/utils/sc_report_handler.cpp @@ -0,0 +1,799 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_report_handler.cpp - + + Original Author: Alex Riesen, Synopsys, Inc. + see also sc_report.cpp + + CHANGE LOG AT END OF FILE + *****************************************************************************/ + +#include <cstdio> +#include <stdlib.h> +#include <string.h> + +#include "sysc/utils/sc_iostream.h" +#include "sysc/kernel/sc_process.h" +#include "sysc/kernel/sc_simcontext_int.h" +#include "sysc/utils/sc_stop_here.h" +#include "sysc/utils/sc_report_handler.h" +#include "sysc/utils/sc_report.h" + +namespace std {} + +namespace sc_core { + +int sc_report_handler::verbosity_level = SC_MEDIUM; + +// not documented, but available +const std::string sc_report_compose_message(const sc_report& rep) +{ + static const char * severity_names[] = { + "Info", "Warning", "Error", "Fatal" + }; + std::string str; + + str += severity_names[rep.get_severity()]; + str += ": "; + + if ( rep.get_id() >= 0 ) // backward compatibility with 2.0+ + { + char idstr[64]; + std::sprintf(idstr, "(%c%d) ", + "IWEF"[rep.get_severity()], rep.get_id()); + str += idstr; + } + str += rep.get_msg_type(); + + if( *rep.get_msg() ) + { + str += ": "; + str += rep.get_msg(); + } + if( rep.get_severity() > SC_INFO ) + { + char line_number_str[16]; + str += "\nIn file: "; + str += rep.get_file_name(); + str += ":"; + std::sprintf(line_number_str, "%d", rep.get_line_number()); + str += line_number_str; + sc_simcontext* simc = sc_get_curr_simcontext(); + + if( simc && sc_is_running() ) + { + const char* proc_name = rep.get_process_name(); + + if( proc_name ) + { + str += "\nIn process: "; + str += proc_name; + str += " @ "; + str += rep.get_time().to_string(); + } + } + } + + return str; +} +bool sc_report_close_default_log(); + +static ::std::ofstream* log_stream = 0; +static +struct auto_close_log +{ + ~auto_close_log() + { + sc_report_close_default_log(); + } +} auto_close; + +const char* sc_report::get_process_name() const +{ + return process ? process->name() : 0; +} + + +// +// The official handler of the exception reporting +// + +void sc_report_handler::default_handler(const sc_report& rep, + const sc_actions& actions) +{ + if ( actions & SC_DISPLAY ) + ::std::cout << ::std::endl << sc_report_compose_message(rep) << + ::std::endl; + + if ( (actions & SC_LOG) && get_log_file_name() ) + { + if ( !log_stream ) + log_stream = new ::std::ofstream(get_log_file_name()); // ios::trunc + + *log_stream << rep.get_time() << ": " + << sc_report_compose_message(rep) << ::std::endl; + } + if ( actions & SC_STOP ) + { + sc_stop_here(rep.get_msg_type(), rep.get_severity()); + sc_stop(); + } + if ( actions & SC_INTERRUPT ) + sc_interrupt_here(rep.get_msg_type(), rep.get_severity()); + + if ( actions & SC_ABORT ) + abort(); + + if ( actions & SC_THROW ) { + sc_process_b* proc_p = sc_get_current_process_b(); + if( proc_p && proc_p->is_unwinding() ) + proc_p->clear_unwinding(); + throw rep; + } +} + +// not documented, but available +bool sc_report_close_default_log() +{ + delete log_stream; + sc_report_handler::set_log_file_name(NULL); + + if ( !log_stream ) + return false; + + log_stream = 0; + return true; +} + +int sc_report_handler::get_count(sc_severity severity_) +{ + return sev_call_count[severity_]; +} + +int sc_report_handler::get_count(const char* msg_type_) +{ + sc_msg_def * md = mdlookup(msg_type_); + + if ( !md ) + md = add_msg_type(msg_type_); + + return md->call_count; +} + +int sc_report_handler::get_count(const char* msg_type_, sc_severity severity_) +{ + sc_msg_def * md = mdlookup(msg_type_); + + if ( !md ) + md = add_msg_type(msg_type_); + + return md->sev_call_count[severity_]; +} + + +// +// CLASS: sc_report_handler +// implementation +// + +sc_msg_def * sc_report_handler::mdlookup(const char * msg_type_) +{ + if( !msg_type_ ) // if msg_type is NULL, report unknown error + msg_type_ = SC_ID_UNKNOWN_ERROR_; + + for ( msg_def_items * item = messages; item; item = item->next ) + { + for ( int i = 0; i < item->count; ++i ) + if ( !strcmp(msg_type_, item->md[i].msg_type) ) + return item->md + i; + } + return 0; +} + +// The calculation of actions to be executed +sc_actions sc_report_handler::execute(sc_msg_def* md, sc_severity severity_) +{ + sc_actions actions = md->sev_actions[severity_]; // high prio + + if ( SC_UNSPECIFIED == actions ) // middle prio + actions = md->actions; + + if ( SC_UNSPECIFIED == actions ) // the lowest prio + actions = sev_actions[severity_]; + + actions &= ~suppress_mask; // higher than the high prio + actions |= force_mask; // higher than above, and the limit is the highest + + unsigned * limit = 0; + unsigned * call_count = 0; + + // just increment counters and check for overflow + if ( md->sev_call_count[severity_] < UINT_MAX ) + md->sev_call_count[severity_]++; + if ( md->call_count < UINT_MAX ) + md->call_count++; + if ( sev_call_count[severity_] < UINT_MAX ) + sev_call_count[severity_]++; + + if ( md->limit_mask & (1 << (severity_ + 1)) ) + { + limit = md->sev_limit + severity_; + call_count = md->sev_call_count + severity_; + } + if ( !limit && (md->limit_mask & 1) ) + { + limit = &md->limit; + call_count = &md->call_count; + } + if ( !limit ) + { + limit = sev_limit + severity_; + call_count = sev_call_count + severity_; + } + if ( *limit == 0 ) + { + // stop limit disabled + } + else if ( *limit != UINT_MAX ) + { + if ( *call_count >= *limit ) + actions |= SC_STOP; // force sc_stop() + } + return actions; +} + +void sc_report_handler::report( sc_severity severity_, + const char* msg_type_, + const char* msg_, + int verbosity_, + const char* file_, + int line_ ) +{ + sc_msg_def * md = mdlookup(msg_type_); + + // If the severity of the report is SC_INFO and the specified verbosity + // level is greater than the maximum verbosity level of the simulator then + // return without any action. + + if ( (severity_ == SC_INFO) && (verbosity_ > verbosity_level) ) return; + + // Process the report: + + if ( !md ) + md = add_msg_type(msg_type_); + + sc_actions actions = execute(md, severity_); + sc_report rep(severity_, md, msg_, file_, line_, verbosity_); + + if ( actions & SC_CACHE_REPORT ) + cache_report(rep); + + handler(rep, actions); +} + +void sc_report_handler::report(sc_severity severity_, + const char * msg_type_, + const char * msg_, + const char * file_, + int line_) +{ + sc_msg_def * md = mdlookup(msg_type_); + + // If the severity of the report is SC_INFO and the maximum verbosity + // level is less than SC_MEDIUM return without any action. + + if ( (severity_ == SC_INFO) && (SC_MEDIUM > verbosity_level) ) return; + + // Process the report: + + + if ( !md ) + md = add_msg_type(msg_type_); + + sc_actions actions = execute(md, severity_); + sc_report rep(severity_, md, msg_, file_, line_); + + if ( actions & SC_CACHE_REPORT ) + cache_report(rep); + + handler(rep, actions); +} + +// The following method is never called by the simulator. + +void sc_report_handler::initialize() +{ +#if 0 // actually, i do not know whether we have to reset these. + suppress(); + force(); + set_actions(SC_INFO, SC_DEFAULT_INFO_ACTIONS); + set_actions(SC_WARNING, SC_DEFAULT_WARNING_ACTIONS); + set_actions(SC_ERROR, SC_DEFAULT_ERROR_ACTIONS); + set_actions(SC_FATAL, SC_DEFAULT_FATAL_ACTIONS); +#endif + + sev_call_count[SC_INFO] = 0; + sev_call_count[SC_WARNING] = 0; + sev_call_count[SC_ERROR] = 0; + sev_call_count[SC_FATAL] = 0; + + msg_def_items * items = messages; + + while ( items != &msg_terminator ) + { + for ( int i = 0; i < items->count; ++i ) + { + items->md[i].call_count = 0; + items->md[i].sev_call_count[SC_INFO] = 0; + items->md[i].sev_call_count[SC_WARNING] = 0; + items->md[i].sev_call_count[SC_ERROR] = 0; + items->md[i].sev_call_count[SC_FATAL] = 0; + } + items = items->next; + } + + // PROCESS ANY ENVIRONMENTAL OVERRIDES: + + const char* deprecation_warn = std::getenv("SC_DEPRECATION_WARNINGS"); + if ( (deprecation_warn!=0) && !strcmp(deprecation_warn,"DISABLE") ) + { + set_actions("/IEEE_Std_1666/deprecated", SC_DO_NOTHING); + } +} + +// free the sc_msg_def's allocated by add_msg_type +// (or implicit msg_type registration: set_actions, abort_after) +// clear last_global_report. +void sc_report_handler::release() +{ + delete last_global_report; + last_global_report = 0; + sc_report_close_default_log(); + + msg_def_items * items = messages, * newitems = &msg_terminator; + messages = &msg_terminator; + + while ( items != &msg_terminator ) + { + for ( int i = 0; i < items->count; ++i ) + if ( items->md[i].msg_type == items->md[i].msg_type_data ) + free(items->md[i].msg_type_data); + + msg_def_items * prev = items; + items = items->next; + + if ( prev->allocated ) + { + delete [] prev->md; + delete prev; + } + else + { + prev->next = newitems; + newitems = prev; + } + } + messages = newitems; +} + +sc_msg_def * sc_report_handler::add_msg_type(const char * msg_type_) +{ + sc_msg_def * md = mdlookup(msg_type_); + int msg_type_len; + + if ( md ) + return md; + + msg_def_items * items = new msg_def_items; + + if ( !items ) + return 0; + + items->count = 1; + items->md = new sc_msg_def[items->count]; + + if ( !items->md ) + { + delete items; + return 0; + } + memset(items->md, 0, sizeof(sc_msg_def) * items->count); + msg_type_len = strlen(msg_type_); + if ( msg_type_len > 0 ) + { + items->md->msg_type_data = (char*) malloc(msg_type_len+1); + strcpy( items->md->msg_type_data, msg_type_ ); + items->md->id = -1; // backward compatibility with 2.0+ + } + else + { + delete items->md; + delete items; + return 0; + } + items->md->msg_type = items->md->msg_type_data; + add_static_msg_types(items); + items->allocated = true; + + return items->md; +} + +void sc_report_handler::add_static_msg_types(msg_def_items * items) +{ + items->allocated = false; + items->next = messages; + messages = items; +} + +sc_actions sc_report_handler::set_actions(sc_severity severity_, + sc_actions actions_) +{ + sc_actions old = sev_actions[severity_]; + sev_actions[severity_] = actions_; + return old; +} + +sc_actions sc_report_handler::set_actions(const char * msg_type_, + sc_actions actions_) +{ + sc_msg_def * md = mdlookup(msg_type_); + + if ( !md ) + md = add_msg_type(msg_type_); + + sc_actions old = md->actions; + md->actions = actions_; + + return old; +} + +sc_actions sc_report_handler::set_actions(const char * msg_type_, + sc_severity severity_, + sc_actions actions_) +{ + sc_msg_def * md = mdlookup(msg_type_); + + if ( !md ) + md = add_msg_type(msg_type_); + + sc_actions old = md->sev_actions[severity_]; + md->sev_actions[severity_] = actions_; + + return old; +} + +int sc_report_handler::stop_after(sc_severity severity_, int limit) +{ + int old = sev_limit[severity_]; + + sev_limit[severity_] = limit < 0 ? UINT_MAX: (unsigned) limit; + + return old; +} + +int sc_report_handler::stop_after(const char * msg_type_, int limit) +{ + sc_msg_def * md = mdlookup(msg_type_); + + if ( !md ) + md = add_msg_type(msg_type_); + + int old = md->limit_mask & 1 ? md->limit: UINT_MAX; + + if ( limit < 0 ) + md->limit_mask &= ~1; + else + { + md->limit_mask |= 1; + md->limit = limit; + } + return old; +} + +int sc_report_handler::stop_after(const char * msg_type_, + sc_severity severity_, + int limit) +{ + sc_msg_def * md = mdlookup(msg_type_); + + if ( !md ) + md = add_msg_type(msg_type_); + + int mask = 1 << (severity_ + 1); + int old = md->limit_mask & mask ? md->sev_limit[severity_]: UINT_MAX; + + if ( limit < 0 ) + md->limit_mask &= ~mask; + else + { + md->limit_mask |= mask; + md->sev_limit[severity_] = limit; + } + return old; +} + +sc_actions sc_report_handler::suppress(sc_actions mask) +{ + sc_actions old = suppress_mask; + suppress_mask = mask; + return old; +} + +sc_actions sc_report_handler::suppress() +{ + return suppress(0); +} + +sc_actions sc_report_handler::force(sc_actions mask) +{ + sc_actions old = force_mask; + force_mask = mask; + return old; +} + +sc_actions sc_report_handler::force() +{ + return force(0); +} + +sc_report_handler_proc +sc_report_handler::set_handler(sc_report_handler_proc handler_) +{ + sc_report_handler_proc old = handler; + handler = handler_ ? handler_: &sc_report_handler::default_handler; + return old; +} + +sc_report_handler_proc +sc_report_handler::get_handler() +{ + return handler; +} + +sc_report* sc_report_handler::get_cached_report() +{ + sc_process_b * proc = sc_get_current_process_b(); + + if ( proc ) + return proc->get_last_report(); + + return last_global_report; +} + +void sc_report_handler::clear_cached_report() +{ + sc_process_b * proc = sc_get_current_process_b(); + + if ( proc ) + proc->set_last_report(0); + else + { + delete last_global_report; + last_global_report = 0; + } +} + +sc_actions sc_report_handler::get_new_action_id() +{ + for ( sc_actions p = 1; p; p <<= 1 ) + { + if ( !(p & available_actions) ) // free + { + available_actions |= p; + return p; + } + } + return SC_UNSPECIFIED; +} + +bool sc_report_handler::set_log_file_name(const char* name_) +{ + if ( !name_ ) + { + free(log_file_name); + log_file_name = 0; + return false; + } + if ( log_file_name ) + return false; + + log_file_name = (char*)malloc(strlen(name_)+1); + strcpy(log_file_name, name_); + return true; +} + +const char * sc_report_handler::get_log_file_name() +{ + return log_file_name; +} + +void sc_report_handler::cache_report(const sc_report& rep) +{ + sc_process_b * proc = sc_get_current_process_b(); + if ( proc ) + proc->set_last_report(new sc_report(rep)); + else + { + delete last_global_report; + last_global_report = new sc_report(rep); + } +} + +// +// backward compatibility with 2.0+ +// + +sc_msg_def * sc_report_handler::mdlookup(int id) +{ + for ( msg_def_items * item = messages; item; item = item->next ) + { + for ( int i = 0; i < item->count; ++i ) + if ( id == item->md[i].id ) + return item->md + i; + } + return 0; +} + +int sc_report_handler::get_verbosity_level() { return verbosity_level; } + +int sc_report_handler::set_verbosity_level( int level ) +{ + int result = verbosity_level; + verbosity_level = level; + return result; +} + +// +// CLASS: sc_report_handler +// static variables +// + +sc_actions sc_report_handler::suppress_mask = 0; +sc_actions sc_report_handler::force_mask = 0; + +sc_actions sc_report_handler::sev_actions[SC_MAX_SEVERITY] = +{ + /* info */ SC_DEFAULT_INFO_ACTIONS, + /* warn */ SC_DEFAULT_WARNING_ACTIONS, + /* error */ SC_DEFAULT_ERROR_ACTIONS, + /* fatal */ SC_DEFAULT_FATAL_ACTIONS +}; + +// Note that SC_FATAL has a limit of 1 by default + +sc_actions sc_report_handler::sev_limit[SC_MAX_SEVERITY] = +{ + UINT_MAX, UINT_MAX, UINT_MAX, UINT_MAX +}; +sc_actions sc_report_handler::sev_call_count[SC_MAX_SEVERITY] = { 0, 0, 0, 0 }; + +sc_report* sc_report_handler::last_global_report = NULL; +sc_actions sc_report_handler::available_actions = + SC_DO_NOTHING | + SC_THROW | + SC_LOG | + SC_DISPLAY | + SC_CACHE_REPORT | + SC_INTERRUPT | + SC_STOP | + SC_ABORT; + +sc_report_handler_proc sc_report_handler::handler = + &sc_report_handler::default_handler; + +char * sc_report_handler::log_file_name = 0; + +sc_report_handler::msg_def_items * sc_report_handler::messages = + &sc_report_handler::msg_terminator; + + +// +// predefined messages +// + +const char SC_ID_REGISTER_ID_FAILED_[] = "register_id failed"; +const char SC_ID_UNKNOWN_ERROR_[] = "unknown error"; +const char SC_ID_WITHOUT_MESSAGE_[] = ""; +const char SC_ID_NOT_IMPLEMENTED_[] = "not implemented"; +const char SC_ID_INTERNAL_ERROR_[] = "internal error"; +const char SC_ID_ASSERTION_FAILED_[] = "assertion failed"; +const char SC_ID_OUT_OF_BOUNDS_[] = "out of bounds"; + +#define DEFINE_MSG(id,n) \ + { \ + (id), \ + 0u, {0u}, /* actions */ \ + 0u, {0u}, 0u, /* limits */ \ + 0u, {0u}, NULL, /* call counters */ \ + n \ + } + +static sc_msg_def default_msgs[] = { + DEFINE_MSG(SC_ID_REGISTER_ID_FAILED_, 800), + DEFINE_MSG(SC_ID_UNKNOWN_ERROR_, 0), + DEFINE_MSG(SC_ID_WITHOUT_MESSAGE_, 1), + DEFINE_MSG(SC_ID_NOT_IMPLEMENTED_, 2), + DEFINE_MSG(SC_ID_INTERNAL_ERROR_, 3), + DEFINE_MSG(SC_ID_ASSERTION_FAILED_, 4), + DEFINE_MSG(SC_ID_OUT_OF_BOUNDS_, 5) +}; + +sc_report_handler::msg_def_items sc_report_handler::msg_terminator = +{ + default_msgs, + sizeof(default_msgs)/sizeof(*default_msgs), + false, + NULL +}; + +} // namespace sc_core + +// $Log: sc_report_handler.cpp,v $ +// Revision 1.9 2011/08/29 18:04:32 acg +// Philipp A. Hartmann: miscellaneous clean ups. +// +// Revision 1.8 2011/08/26 20:46:19 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +// Revision 1.7 2011/08/07 19:08:08 acg +// Andy Goodrich: moved logs to end of file so line number synching works +// better between versions. +// +// Revision 1.6 2011/08/07 18:56:03 acg +// Philipp A. Hartmann: added cast to ? : to eliminate clang warning message. +// +// Revision 1.5 2011/03/23 16:16:49 acg +// Andy Goodrich: finish message verbosity support. +// +// Revision 1.4 2011/02/18 20:38:44 acg +// Andy Goodrich: Updated Copyright notice. +// +// Revision 1.3 2011/02/11 13:25:55 acg +// Andy Goodrich: Philipp's changes for sc_unwind_exception. +// +// Revision 1.2 2011/02/01 23:02:05 acg +// Andy Goodrich: IEEE 1666 2011 changes. +// +// Revision 1.1.1.1 2006/12/15 20:20:06 acg +// SystemC 2.3 +// +// Revision 1.7 2006/05/26 20:35:52 acg +// Andy Goodrich: removed debug message that should not have been left in. +// +// Revision 1.6 2006/03/21 00:00:37 acg +// Andy Goodrich: changed name of sc_get_current_process_base() to be +// sc_get_current_process_b() since its returning an sc_process_b instance. +// +// Revision 1.5 2006/01/31 21:42:07 acg +// Andy Goodrich: Added checks for SC_DEPRECATED_WARNINGS being defined as +// DISABLED. If so, we turn off the /IEEE_Std_1666/deprecated message group. +// +// Revision 1.4 2006/01/26 21:08:17 acg +// Andy Goodrich: conversion to use sc_is_running instead of deprecated +// sc_simcontext::is_running() +// +// Revision 1.3 2006/01/13 18:53:11 acg +// Andy Goodrich: Added $Log command so that CVS comments are reproduced in +// the source. + +// Taf! diff --git a/ext/systemc/src/sysc/utils/sc_report_handler.h b/ext/systemc/src/sysc/utils/sc_report_handler.h new file mode 100644 index 000000000..799985a1f --- /dev/null +++ b/ext/systemc/src/sysc/utils/sc_report_handler.h @@ -0,0 +1,197 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_report_handler.h - + + Original Author: Alex Riesen, Synopsys, Inc. + see also sc_report.h + + CHANGE LOG AT END OF FILE + *****************************************************************************/ + +#ifndef SC_REPORT_HANDLER_H +#define SC_REPORT_HANDLER_H + +namespace sc_core { + +// ---------------------------------------------------------------------------- +// STRUCT : sc_msg_def +// +// Exception message definition structure +// ---------------------------------------------------------------------------- + +struct sc_msg_def +{ + const char* msg_type; + sc_actions actions; + sc_actions sev_actions[SC_MAX_SEVERITY]; + unsigned limit; + unsigned sev_limit[SC_MAX_SEVERITY]; + unsigned limit_mask; // 0 - limit, 1..4 - sev_limit + unsigned call_count; + unsigned sev_call_count[SC_MAX_SEVERITY]; + char* msg_type_data; + + int id; // backward compatibility with 2.0+ +}; + +typedef void (* sc_report_handler_proc)(const sc_report&, const sc_actions &); +class sc_report; +extern bool sc_report_close_default_log(); +class sc_report_handler +{ +public: + static void report(sc_severity, + const char* msg_type, + const char* msg, + const char* file, + int line); + + static void report( sc_severity, + const char* msg_type, + const char* msg, + int verbosity, + const char* file, + int line ); + + static sc_actions set_actions(sc_severity, + sc_actions = SC_UNSPECIFIED); + + static sc_actions set_actions(const char * msg_type, + sc_actions = SC_UNSPECIFIED); + + static sc_actions set_actions(const char * msg_type, + sc_severity, + sc_actions = SC_UNSPECIFIED); + + static int stop_after(sc_severity, int limit = -1); + static int stop_after(const char* msg_type, int limit = -1); + static int stop_after(const char* msg_type, sc_severity, int limit = -1); + + static sc_actions suppress(sc_actions); + static sc_actions suppress(); + static sc_actions force(sc_actions); + static sc_actions force(); + + static int get_count(sc_severity severity_); + static int get_count(const char* msg_type_); + static int get_count(const char* msg_type_, sc_severity severity_); + + static int get_verbosity_level(); + static int set_verbosity_level( int level ); + + + static void initialize(); // just reset counters + static void release(); // initialize() needed for reports after it + + static sc_report_handler_proc set_handler(sc_report_handler_proc); + static sc_report_handler_proc get_handler(); + // use set_handler(NULL); to restore default handler + static void default_handler(const sc_report&, const sc_actions&); + + static sc_actions get_new_action_id(); + + static sc_report* get_cached_report(); + static void clear_cached_report(); + + // if filename is NULL, the previous log file name will be removed. + // The provider of a report_handler supposed to handle this. + // Return false if filename is not NULL and filename is already set. + static bool set_log_file_name(const char* filename); + static const char* get_log_file_name(); + +public: // private, actually + + struct msg_def_items + { + sc_msg_def* md; // have to point to sc_msg_def-s + int count; // set to number of items in md[] + bool allocated; // used internally, previous value ignored + msg_def_items* next; // used internally, previous value ignored + }; + + static void add_static_msg_types(msg_def_items *); + static sc_msg_def* add_msg_type(const char * msg_type); + +protected: + + static void cache_report(const sc_report&); + static sc_actions execute(sc_msg_def*, sc_severity); + + static sc_actions suppress_mask; + static sc_actions force_mask; + static sc_actions sev_actions[SC_MAX_SEVERITY]; + static unsigned sev_limit[SC_MAX_SEVERITY]; + static unsigned sev_call_count[SC_MAX_SEVERITY]; + static sc_report* last_global_report; + static sc_actions available_actions; + static char* log_file_name; + static int verbosity_level; + + static msg_def_items* messages; + static msg_def_items msg_terminator; + + static sc_report_handler_proc handler; + + static sc_msg_def* mdlookup(const char* msg_type); + +private: // backward compatibility with 2.0+ + + friend class sc_report; + static sc_msg_def* mdlookup(int id); + +public: + + static void report(sc_severity, + int id, + const char* add_msg, + const char* file, + int line); + +}; + +} // namespace sc_core + +// $Log: sc_report_handler.h,v $ +// Revision 1.5 2011/08/26 20:46:19 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +// Revision 1.4 2011/03/23 16:16:49 acg +// Andy Goodrich: finish message verbosity support. +// +// Revision 1.3 2011/02/18 20:38:44 acg +// Andy Goodrich: Updated Copyright notice. +// +// Revision 1.2 2011/02/01 23:02:05 acg +// Andy Goodrich: IEEE 1666 2011 changes. +// +// Revision 1.1.1.1 2006/12/15 20:20:06 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:53:11 acg +// Andy Goodrich: Added $Log command so that CVS comments are reproduced in +// the source. +// + +#endif + +// Taf! diff --git a/ext/systemc/src/sysc/utils/sc_stop_here.cpp b/ext/systemc/src/sysc/utils/sc_stop_here.cpp new file mode 100644 index 000000000..614b03dd0 --- /dev/null +++ b/ext/systemc/src/sysc/utils/sc_stop_here.cpp @@ -0,0 +1,124 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_stop_here.cpp -- Function provided for debugging purposes. + This file is always compiled in debug mode, such that + setting a breakpoint at this function can help locate + the cause of a SystemC error or warning. + + Original Author: Martin Janssen, Synopsys, Inc., 2001-11-14 + + CHANGE LOG AT END OF FILE + *****************************************************************************/ + +#include "sysc/utils/sc_stop_here.h" + + +namespace sc_core { + +static const char* info_id = 0; +static const char* warning_id = 0; +static const char* error_id = 0; +static const char* fatal_id = 0; + +// ---------------------------------------------------------------------------- +// FUNCTION : sc_interrupt_here +// +// Debugging aid for warning, error, and fatal reports. +// This function *cannot* be inlined. +// ---------------------------------------------------------------------------- + +void +sc_interrupt_here( const char* id, sc_severity severity ) +{ + // you can set a breakpoint at some of the lines below, either to + // interrupt with any severity, or to interrupt with a specific severity + + switch( severity ) { + case SC_INFO: + info_id = id; + break; + case SC_WARNING: + warning_id = id; + break; + case SC_ERROR: + error_id = id; + break; + default: + case SC_FATAL: + fatal_id = id; + break; + } +} + + +// ---------------------------------------------------------------------------- +// FUNCTION : sc_stop_here +// +// Debugging aid for warning, error, and fatal reports. +// This function *cannot* be inlined. +// ---------------------------------------------------------------------------- + +void +sc_stop_here( const char* id, sc_severity severity ) +{ + // you can set a breakpoint at some of the lines below, either to + // stop with any severity, or to stop with a specific severity + + switch( severity ) { + case SC_INFO: + info_id = id; + break; + case SC_WARNING: + warning_id = id; + break; + case SC_ERROR: + error_id = id; + break; + default: + case SC_FATAL: + fatal_id = id; + break; + } +} + +} // namespace sc_core + +// $Log: sc_stop_here.cpp,v $ +// Revision 1.4 2011/08/26 21:49:08 acg +// Philipp A. Hartmann: eliminate compiler warning by moving static variables +// out of functions. +// +// Revision 1.3 2011/08/26 20:46:19 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +// Revision 1.2 2011/02/18 20:38:44 acg +// Andy Goodrich: Updated Copyright notice. +// +// Revision 1.1.1.1 2006/12/15 20:20:06 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:53:11 acg +// Andy Goodrich: Added $Log command so that CVS comments are reproduced in +// the source. + +// Taf! diff --git a/ext/systemc/src/sysc/utils/sc_stop_here.h b/ext/systemc/src/sysc/utils/sc_stop_here.h new file mode 100644 index 000000000..8d8dca412 --- /dev/null +++ b/ext/systemc/src/sysc/utils/sc_stop_here.h @@ -0,0 +1,82 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_stop_here.h -- Function provided for debugging purposes. + This file is always compiled in debug mode, such that + setting a breakpoint at this function can help locate + the cause of a SystemC error or warning. + + Original Author: Martin Janssen, Synopsys, Inc., 2001-11-14 + + CHANGE LOG AT END OF FILE + *****************************************************************************/ + +// $Log: sc_stop_here.h,v $ +// Revision 1.3 2011/08/26 20:46:19 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +#ifndef SC_STOP_HERE_H +#define SC_STOP_HERE_H + + +#include "sysc/utils/sc_report.h" + + +namespace sc_core { + +// ---------------------------------------------------------------------------- +// FUNCTION : sc_interrupt_here +// +// Debugging aid for interrupt warning, error, and fatal reports. +// ---------------------------------------------------------------------------- + +extern +void +sc_interrupt_here( const char* id, sc_severity severity ); + + +// ---------------------------------------------------------------------------- +// FUNCTION : sc_stop_here +// +// Debugging aid for warning, error, and fatal reports. +// ---------------------------------------------------------------------------- + +extern +void +sc_stop_here( const char* id, sc_severity severity ); + +} // namespace sc_core + +#endif + +// Revision 1.2 2011/02/18 20:38:44 acg +// Andy Goodrich: Updated Copyright notice. +// +// Revision 1.1.1.1 2006/12/15 20:20:06 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:53:11 acg +// Andy Goodrich: Added $Log command so that CVS comments are reproduced in +// the source. +// + +// Taf! diff --git a/ext/systemc/src/sysc/utils/sc_string.cpp b/ext/systemc/src/sysc/utils/sc_string.cpp new file mode 100644 index 000000000..25c788a59 --- /dev/null +++ b/ext/systemc/src/sysc/utils/sc_string.cpp @@ -0,0 +1,612 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_string.cpp -- Implementation of a simple string class. + + Original Author: Stan Y. Liao, Synopsys, Inc. + + CHANGE LOG AT END OF FILE + *****************************************************************************/ + +#include <assert.h> +#include <ctype.h> +#include <cstdio> +#include <stdarg.h> +#include <string.h> + +#include "sysc/utils/sc_iostream.h" +#include "sysc/utils/sc_string.h" +#include "sysc/utils/sc_utils_ids.h" + +namespace sc_dt { + +inline static int +sc_roundup( int n, int m ) +{ + return ((n - 1) / m + 1) * m; +} + + +// ---------------------------------------------------------------------------- +// CLASS : sc_string_rep +// +// Reference counting string implementation class. +// ---------------------------------------------------------------------------- + +class sc_string_rep +{ + friend class sc_string_old; + friend ::std::ostream& operator<<( ::std::ostream&, const sc_string_old& ); + friend ::std::istream& operator>>( ::std::istream&, sc_string_old& ); + friend sc_string_old operator+( const char*, const sc_string_old& ); + + sc_string_rep( int size = 16 ) : + ref_count(1), alloc( sc_roundup( size, 16 ) ), str( new char[alloc] ) + { + *str = '\0'; + } + + sc_string_rep( const char* s ) : ref_count(1), alloc(0), str(0) + { + if (s) { + alloc = 1 + strlen(s); + str = strcpy( new char[alloc], s ); + } + else { + alloc = 16; + str = strcpy( new char[alloc], "" ); + } + } + + sc_string_rep( const char* s, int n); // get first n chars from the string + + ~sc_string_rep() + { + assert( ref_count == 0 ); + delete[] str; + } + + void resize( int new_size ); + void set_string( const char* s ); + + int ref_count; + int alloc; + char* str; +}; + + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + +sc_string_rep::sc_string_rep( const char* s, int n) : + ref_count(1), alloc(0), str(0) +{ + if (s && n>0) { + alloc = 1 + n; + str = strncpy( new char[alloc], s,n ); + str[n] = 00; + } + else { + alloc = 16; + str = strcpy( new char[alloc], "" ); + } +} + +void +sc_string_rep::resize( int new_size ) +{ + if (new_size <= alloc) return; + alloc = sc_roundup( new_size, 16 ); + char* new_str = strcpy( new char[alloc], str ); + delete[] str; + str = new_str; +} + +void +sc_string_rep::set_string( const char* s ) +{ + int len = strlen(s); + resize( len + 1 ); + strcpy( str, s ); +} + + +// ---------------------------------------------------------------------------- +// CLASS : sc_string_old +// +// String class (yet another). +// ---------------------------------------------------------------------------- + +// constructors + +sc_string_old::sc_string_old( int size ) : rep( new sc_string_rep(size) ) +{ +} + +sc_string_old::sc_string_old( const char* s ) : rep( new sc_string_rep(s) ) +{ +} + +sc_string_old::sc_string_old( const char* s, int n ) : + rep( new sc_string_rep( s, n ) ) +{ +} + +sc_string_old::sc_string_old( const sc_string_old& s ) : rep( s.rep ) +{ + rep->ref_count ++; +} + +sc_string_old::sc_string_old( sc_string_rep* r ) : rep(r) +{ +} + + +// destructor + +sc_string_old::~sc_string_old() +{ + if( -- (rep->ref_count) == 0 ) { + delete rep; + } +} + + +int +sc_string_old::length() const +{ + return strlen(rep->str); +} + +sc_string_old +sc_string_old::operator+( const char* s ) const +{ + int len = length(); + sc_string_rep* r = new sc_string_rep( len + strlen(s) + 1 ); + strcpy( r->str, rep->str ); + strcpy( r->str + len, s ); + return sc_string_old(r); +} + +sc_string_old sc_string_old::operator+(char c) const +{ + int len = length(); + sc_string_rep* r = new sc_string_rep( len + 2 ); + strcpy( r->str, rep->str ); + r->str[len] = c; + r->str[len+1] = 00; + return sc_string_old(r); +} + +sc_string_old +operator+( const char* s, const sc_string_old& t ) +{ + int len = strlen(s); + sc_string_rep* r = new sc_string_rep( len + t.length() + 1 ); + strcpy( r->str, s ); + strcpy( r->str + len, t ); + return sc_string_old(r); +} + +sc_string_old +sc_string_old::operator+( const sc_string_old& s ) const +{ + int len = length(); + sc_string_rep* r = new sc_string_rep( len + s.length() + 1 ); + strcpy( r->str, rep->str ); + strcpy( r->str + len, s.rep->str ); + return sc_string_old(r); +} + +sc_string_old& +sc_string_old::operator=( const char* s ) +{ + if (rep->ref_count > 1) { + --rep->ref_count; + rep = new sc_string_rep(s); + } + else { + rep->set_string(s); + } + return *this; +} + +sc_string_old& +sc_string_old::operator=( const sc_string_old& s ) +{ + if (&s == this) + return *this; + if (--(rep->ref_count) == 0) + delete rep; + rep = s.rep; + rep->ref_count++; + return *this; +} + +sc_string_old& +sc_string_old::operator+=( const char* s ) +{ + int oldlen = length(); + int slen = strlen(s); + if (rep->ref_count > 1) { + sc_string_rep* oldrep = rep; + --rep->ref_count; + rep = new sc_string_rep( oldlen + slen + 1 ); + strcpy( rep->str, oldrep->str ); + strcpy( rep->str + oldlen, s ); + } + else { + rep->resize( oldlen + slen + 1 ); + strcpy( rep->str + oldlen, s ); + } + return *this; +} + +sc_string_old& sc_string_old::operator+=(char c) +{ + int oldlen = length(); + if (rep->ref_count > 1) { + sc_string_rep* oldrep = rep; + --rep->ref_count; + rep = new sc_string_rep( oldlen + 2 ); + strcpy( rep->str, oldrep->str ); + rep->str[oldlen]=c; + rep->str[oldlen+1]=00; + } + else { + rep->resize( oldlen + 2 ); + rep->str[oldlen]=c; + rep->str[oldlen+1]=00; + } + return *this; +} + +sc_string_old& +sc_string_old::operator+=( const sc_string_old& s ) +{ + return this->operator+=( s.rep->str ); +} + +int +sc_string_old::cmp( const char* s ) const +{ + return strcmp( rep->str, s ); +} + +int +sc_string_old::cmp( const sc_string_old& s ) const +{ + return strcmp( rep->str, s.rep->str ); +} + +const char* sc_string_old::c_str() const +{ + return rep->str; +} + +// get substring +sc_string_old sc_string_old::substr(int first,int last) const +{ + if(first<0 || last<0 || first>last || first>=length() || last>=length()) + return ""; + return sc_string_old(rep->str+first, last-first+1); +} + + +sc_string_old sc_string_old::make_str(long n) // convert integer to string +{ + char buf[32]; + ::std::sprintf(buf,"%ld",n); + return sc_string_old(buf); +} + + +#define DEFINE_RELOP(op) \ +bool sc_string_old::operator op( const char* s ) const \ +{ \ + return strcmp( rep->str, s ) op 0; \ +} \ +bool sc_string_old::operator op( const sc_string_old& s ) const \ +{ \ + return strcmp( rep->str, s.rep->str ) op 0; \ +} + +DEFINE_RELOP(==) +DEFINE_RELOP(!=) +DEFINE_RELOP(<) +DEFINE_RELOP(<=) +DEFINE_RELOP(>) +DEFINE_RELOP(>=) + +sc_string_old::operator const char*() const +{ + return rep->str; +} + +char +sc_string_old::operator[]( int i ) const +{ + return rep->str[i]; +} + +char& sc_string_old::operator[]( int i ) +{ + if (rep->ref_count > 1) { + rep->ref_count--; + rep = new sc_string_rep(rep->str); + } + return rep->str[i]; +} + +void +sc_string_old::set( int i, char c ) +{ + if (rep->ref_count > 1) { + rep->ref_count--; + rep = new sc_string_rep(rep->str); + } + rep->str[i] = c; +} + +#if defined(_MSC_VER) + // Windows provides safer implementation +# define sc_vsnprintf _vsnprintf +#else +# define sc_vsnprintf vsnprintf +#endif + +sc_string_old sc_string_old::to_string(const char* format, ...) +{ + va_list argptr; + sc_string_old result; + char buffer[1024]; // static string buffer + buffer[1023]=000; + + va_start(argptr, format); + int cnt = sc_vsnprintf(buffer, 1024, format, argptr); + if(cnt>1023) // string too long + { + int buf_size = 1024; + const int max_size = 65000; + char* buf = 0; // dynamic string buffer + do + { + delete[] buf; + buf_size*=2; + buf = new char[buf_size]; + cnt = sc_vsnprintf(buf, buf_size, format, argptr); + } + while( buf_size<max_size && cnt>=buf_size); + if(cnt>=buf_size) + { + // string is longer the the maximum buffer size (max_size) + SC_REPORT_WARNING( sc_core::SC_ID_STRING_TOO_LONG_, "truncated" ); + buf[buf_size-1] = 000; + } + result = buf; + delete[] buf; + } + else + result = buffer; + + va_end(argptr); + + return result; +} + +void +sc_string_old::print( ::std::ostream& os ) const +{ + os << rep->str; +} + +void sc_string_old::test(int position)const +{ + if(position<0 || position>=length()) + SC_REPORT_ERROR( sc_core::SC_ID_OUT_OF_BOUNDS_, "sc_string_old::test" ); +} + +// TODO: conveniece formatting functions for common types +// e.g. sc_string_old("a=%d, s is %s").fmt(1).fmt("string") +// should produce a=1, s is string +// it should be safe: if less arguments specified +// it should print %specifier; extra arguments should be ignored +// if the type of the argument is incompatible with format +// specifier it should be ignored +// + +unsigned +sc_string_old::fmt_length()const +{ + unsigned result=0; + if((*this)[0]!='%') + return 0; + else + result++; + if(is_delimiter("-+0 #",result)) // flags + result++; + while(is_delimiter("0123456789*",result)) // width + result++; + if(rep->str[result]=='.') // precision + { + result++; + unsigned old_result = result; + while(is_delimiter("0123456789*",result)) result++; + if(old_result == result) //error in format + return 0; + } + if(is_delimiter("hlL",result)) result++; // I64 is not supported + if(is_delimiter("cCdiouxXeEfgGnpsS",result)) + result++; + else // error in format + return 0; + return result; +} + +sc_string_old& +sc_string_old::fmt(const sc_string_old& s) +{ + return fmt(s.c_str()); +} + +int +sc_string_old::pos( const sc_string_old& sub_string ) const +{ + int sub_len = sub_string.length(); + if( sub_len == 0 ) { + return 0; // empty string always matches + } + int ind = 0; + int len = length(); + bool found = false; + while( ind < len && ! found ) + { + found = ( sub_string == substr( ind, ind + sub_len - 1 ) ); + ++ ind; + } + if( found ) { + return -- ind; + } else { + return -1; + } +} + +sc_string_old& +sc_string_old::remove(unsigned index, unsigned length) +{ + test((int)index); + if(length!=0) + (*this) = substr(0,index-1) + substr(index+length,this->length()-1); + return *this; +} + +sc_string_old& +sc_string_old::insert(const sc_string_old& sub_string, unsigned index) +{ + if(index>(unsigned)length()) + SC_REPORT_ERROR( sc_core::SC_ID_OUT_OF_BOUNDS_, "sc_string_old::insert" ); + return (*this) = substr(0,index-1)+sub_string+substr(index,length()-1); +} + +bool +sc_string_old::is_delimiter(const sc_string_old& str, unsigned index)const +{ + test((int)index); + return str.contains(rep->str[index]); +} + +bool +sc_string_old::contains(char c)const +{ + int len = length(); + int i=0; + bool found = false; + while(!found && i<len) + found = rep->str[i++]==c; + return found; +} + +sc_string_old +sc_string_old::uppercase()const +{ + int len = length(); + sc_string_old temp(*this); + for(int i=0; i<len; i++) + { + char c = temp.rep->str[i]; + if(c>='a' && c<='z') + temp.rep->str[i] = static_cast<char>( c-32 ); + } + return temp; +} + +sc_string_old +sc_string_old::lowercase()const +{ + int len = length(); + sc_string_old temp(*this); + for(int i=0; i<len; i++) + { + char c = temp.rep->str[i]; + if(c>='A' && c<='Z') + temp.rep->str[i] = static_cast<char>( c+32 ); + } + return temp; +} + + +// ---------------------------------------------------------------------------- + +::std::istream& +operator >> ( ::std::istream& is, sc_string_old& s ) +{ + if( s.rep->ref_count > 1 ) { + -- s.rep->ref_count; + s.rep = new sc_string_rep; + } + + int i = 0; + char* p = s.rep->str; + char c; + + // skip white spaces + while( is.get( c ) && isspace( c ) ) + ; + + for( ; is.good() && ! isspace( c ); is.get( c ) ) { + if( i > s.rep->alloc - 2 ) { + s.rep->str[i] = '\0'; + s.rep->resize( (int) (s.rep->alloc * 1.5) ); + p = s.rep->str + i; + } + *p ++ = c; + i ++; + } + *p = '\0'; + + return is; +} + } // namespace sc_dt + +// $Log: sc_string.cpp,v $ +// Revision 1.6 2011/08/29 18:04:32 acg +// Philipp A. Hartmann: miscellaneous clean ups. +// +// Revision 1.5 2011/08/26 22:49:42 acg +// Torsten Maehne: remove redudant assignment. +// +// Revision 1.4 2011/08/26 20:46:19 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +// Revision 1.3 2011/08/24 22:05:56 acg +// Torsten Maehne: initialization changes to remove warnings. +// +// Revision 1.2 2011/02/18 20:38:44 acg +// Andy Goodrich: Updated Copyright notice. +// +// Revision 1.1.1.1 2006/12/15 20:20:06 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:53:11 acg +// Andy Goodrich: Added $Log command so that CVS comments are reproduced in +// the source. + +// taf diff --git a/ext/systemc/src/sysc/utils/sc_string.h b/ext/systemc/src/sysc/utils/sc_string.h new file mode 100644 index 000000000..cf225ef1e --- /dev/null +++ b/ext/systemc/src/sysc/utils/sc_string.h @@ -0,0 +1,254 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_string.h -- Implementation of a simple string class. + + Original Author: Stan Y. Liao, Synopsys, Inc. + + CHANGE LOG AT END OF FILE + *****************************************************************************/ + +// $Log: sc_string.h,v $ +// Revision 1.3 2011/08/26 20:46:19 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +#ifndef SC_STRING_H +#define SC_STRING_H + + +#include "sysc/utils/sc_iostream.h" +#include "sysc/utils/sc_report.h" + +namespace sc_dt { + class sc_string_old; +} + +#ifdef SC_USE_SC_STRING_OLD + typedef sc_dt::sc_string_old sc_string; +#endif +#ifdef SC_USE_STD_STRING + typedef ::std::string sc_string; +#endif + +namespace sc_dt { + +// forward class declarations +class sc_string_rep; + +// friend operator declarations +sc_string_old operator + ( const char* s, const sc_string_old& t ); + + +// ---------------------------------------------------------------------------- +// CLASS : sc_string +// +// String class (yet another). +// ---------------------------------------------------------------------------- + +class sc_string_old +{ + friend systemc_ostream& operator << (systemc_ostream& os, const sc_string_old& a); + friend systemc_istream& operator >> ( systemc_istream& is, sc_string_old& a ); + +public: + + // constructors + + explicit sc_string_old( int size = 16 ); + sc_string_old( const char* s ); + sc_string_old( const char* s, int n ); // get first n chars from the string + sc_string_old( const sc_string_old& s ); + + + // destructor + + ~sc_string_old(); + + + // concatenation and assignment + + sc_string_old& operator = ( const char* s ); + sc_string_old& operator = ( const sc_string_old& s ); + + sc_string_old& operator += ( const char* s ); + sc_string_old& operator += ( char c ); + sc_string_old& operator += ( const sc_string_old& s ); + + sc_string_old operator + ( const char* s ) const; + sc_string_old operator + ( char c ) const; + sc_string_old operator + ( const sc_string_old& s ) const; + + friend sc_string_old operator + ( const char* s, const sc_string_old& t ); + + + // returns substring [first,last] + + sc_string_old substr( int first, int last ) const; + + + // string comparison operators + + bool operator == ( const char* s ) const; + bool operator != ( const char* s ) const; + bool operator < ( const char* s ) const; + bool operator <= ( const char* s ) const; + bool operator > ( const char* s ) const; + bool operator >= ( const char* s ) const; + bool operator == ( const sc_string_old& s ) const; + bool operator != ( const sc_string_old& s ) const; + bool operator < ( const sc_string_old& s ) const; + bool operator <= ( const sc_string_old& s ) const; + bool operator > ( const sc_string_old& s ) const; + bool operator >= ( const sc_string_old& s ) const; + + // + // returns length of the string (excluding trailing \0) + // + int length() const; + + // + // returns c-style string + // + const char* c_str() const; + // + // returns c-style string + // + operator const char*() const; + // + // returns character at "index" position + // + char operator[](int index) const; + // + // l-value subscript + // + char& operator[](int index); + + // formatted string (see printf description) + static sc_string_old to_string(const char* format, ...); + // + // conveniece formatting functions for common types + // e.g. sc_string_old("a=%d, s is %s").fmt(1).fmt("string") + // should produce: a=1, s is string + // it should be safe: if less arguments specified + // it should print %specifier; extra arguments should be ignored + // TODO: if the type of the argument is incompatible with format + // specifier it should be ignored + // + // must have it inlined because of some compilers + template<class T> sc_string_old& fmt(const T& t) + { + // search % + int index; + int last_char = length()-1; + sc_string_old temp(*this); + do + { + index = temp.pos("%"); + if(index == last_char) + return *this; + temp = substr(index,last_char); + } while(temp[0] != '%'); + int f_len = (int)temp.fmt_length(); // length of format field + temp = to_string(substr(0,index+f_len-1).c_str(),t); + return (*this) = temp + substr(index+f_len,last_char); + } + sc_string_old& fmt(const sc_string_old& s); + // + // find position of substring in this string + // returns -1 if not found + // + int pos(const sc_string_old& sub_string)const; + // + // remove "count" characters from "index" + // + sc_string_old& remove(unsigned index, unsigned length); + // + // insert "substring" before "index" + // + sc_string_old& insert(const sc_string_old& sub_string, unsigned index); + // + // returns true if the character at byte index in this string matches + // any character in the delimiters string + // + bool is_delimiter(const sc_string_old& str, unsigned index)const; + // + // returns true if string contains the character + // + bool contains(char c)const; + // + // produce upper case string from this one + // + sc_string_old uppercase()const; + // + // produce lower case string from this one + // + sc_string_old lowercase()const; + // + // legacy methods + // + static sc_string_old make_str(long n); + void set( int index, char c ); + int cmp( const char* s ) const; + int cmp( const sc_string_old& s ) const; + + + void print( systemc_ostream& os = ::std::cout ) const; + +private: + + sc_string_old( sc_string_rep* r ); + + sc_string_rep* rep; + + void test(int position)const; + unsigned fmt_length()const; +}; + + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + +inline +systemc_ostream& +operator << ( systemc_ostream& os, const sc_string_old& a ) +{ + a.print( os ); + return os; +} + +} // namespace sc_dt + +// Revision 1.2 2011/02/18 20:38:44 acg +// Andy Goodrich: Updated Copyright notice. +// +// Revision 1.1.1.1 2006/12/15 20:20:06 acg +// SystemC 2.3 +// +// Revision 1.4 2006/05/08 17:50:51 acg +// Andy Goodrich: added David Long's forward declarations for friend +// functions, methods, and operators to keep the Microsoft compiler happy. +// +// Revision 1.3 2006/01/13 18:53:11 acg +// Andy Goodrich: Added $Log command so that CVS comments are reproduced in +// the source. +// + +#endif diff --git a/ext/systemc/src/sysc/utils/sc_temporary.h b/ext/systemc/src/sysc/utils/sc_temporary.h new file mode 100644 index 000000000..321994aad --- /dev/null +++ b/ext/systemc/src/sysc/utils/sc_temporary.h @@ -0,0 +1,228 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_temporary.h -- Temporary value pool classes. + + Original Author: Andy Goodrich, Forte Design Systems, Inc. + + CHANGE LOG AT END OF FILE + *****************************************************************************/ + +#ifndef SC_TEMPORARY_H +#define SC_TEMPORARY_H + +#include <cstddef> // std::size_t + +namespace sc_core { + +//------------------------------------------------------------------------------ +// sc_byte_heap - CLASS MANAGING A TEMPORARY HEAP OF BYTES +// +// This facility implements a heap of temporary byte allocations. Once an +// request has been allocated it is not freed. However the entire heap +// wraps and the storage is reused. This means that no allocations should +// be assumed as permanent. Allocations are double-word aligned. This is +// raw storage, so objects which contain virtual methods cannot be allocated +// with this object. See the sc_vpool object for that type of storage +// allocation. +// +// char* allocate( int size ) +// This method returns a pointer to block of size bytes. The block +// returned is the next available one in the heap. If the current heap +// cannot fullfil the request it will be rewound and storage allocated from +// its start. All allocations start on an 8-byte boundary. +// size = number of bytes to be allocated. +// +// void initialize( int heap_size=0x100000 ) +// This method allocates the storage to be managed. If there is already +// a block of storage under management it is freed. If no argument is +// provided for the heap size, a megabyte will be allocated. +// heap_size = number of bytes to allocate for the heap. +// +// unsigned int length() +// This method returns the size of this object's heap in bytes. +// +// sc_byte_heap() +// This is the non-initialized object instance constructor. It does not +// allocate the heap storage, that is done by the initialize() method. +// +// sc_byte_heap(int) +// This is the initializing object instance constructor. It does allocates +// a heap of the specified number of bytes. +// heap_size = number of bytes to allocate for the heap. +//------------------------------------------------------------------------------ +class sc_byte_heap { + public: + char* m_bgn_p; // Beginning of heap storage. + char* m_end_p; // End of heap storage. + char* m_next_p; // Next heap location to be allocated. + + inline char* allocate( std::size_t bytes_n ) + { + char* result_p; + bytes_n = (bytes_n + 7) & ((std::size_t)(-8)); + result_p = m_next_p; + m_next_p += bytes_n; + if ( m_next_p >= m_end_p ) + { + result_p = m_bgn_p; + m_next_p = m_bgn_p + bytes_n; + } + return result_p; + } + + inline void initialize( std::size_t heap_size=0x100000 ) + { + delete [] m_bgn_p; + m_bgn_p = new char[heap_size]; + m_end_p = &m_bgn_p[heap_size]; + m_next_p = m_bgn_p; + } + + inline std::size_t length() + { + return (std::size_t)(m_end_p - m_bgn_p); + } + + inline sc_byte_heap() : + m_bgn_p(0), m_end_p(0), m_next_p(0) + { + } + + inline sc_byte_heap( std::size_t heap_size ) : + m_bgn_p(0), m_end_p(0), m_next_p(0) + { + initialize( heap_size ); + } + + inline ~sc_byte_heap() + { + delete [] m_bgn_p; + } + +}; + + +//------------------------------------------------------------------------------ +// sc_vpool<T> - CLASS MANAGING A TEMPORARY VECTOR OF CLASS T INSTANCES +// +// This class implements a fixed pool of objects contained in a vector. These +// objects are allocated via the allocate() method. An index, m_pool_i, +// indicates the next object to be allocated. The vector is a power of 2 in +// size, and this fact is used to wrap the list when m_pool_i reaches the +// end of the vector. +// +// sc_vpool( int log2, T* pool_p=0 ) +// This is the object instance constructor for this class. It configures +// the object to manage a vector of 2**log2 entries. If a vector is +// not supplied one will be allocated. +// log2 = the log base two of the size of the vector. +// pool_p -> vector of 2**log2 entries to be managed or 0. +// +// ~sc_vpool() +// This is the object instance destructor for this class. It frees the +// block of storage which was being managed. +// +// T* allocate() +// This method returns the address of the next entry in the vector, m_pool_p, +// pointed to by the index, m_pool_i, and updates that index. The index +// update consists of adding 1 to m_pool_i and masking it by m_wrap. +// +// void reset() +// This method resets the allocation index, m_pool_i, to point to the start +// of the vector of objects under management. This call is not usually made +// since there are a fixed number of entries and the index wraps. However, +// for diagnostics tests it is convenient to be able to reset to the start +// of the vector. +// +// int size() +// This method returns the number of object instances contained in the +// vector being managed by this object instance. +//------------------------------------------------------------------------------ +template<class T> +class sc_vpool { + protected: + std::size_t m_pool_i; // Index of next entry to m_pool_m to provide. + T* m_pool_p; // Vector of temporaries. + std::size_t m_wrap; // Mask to wrap vector index. + + public: + inline sc_vpool( int log2, T* pool_p=0 ); + inline ~sc_vpool(); + inline T* allocate(); + inline void reset(); + inline std::size_t size(); +}; + +template<class T> sc_vpool<T>::sc_vpool( int log2, T* pool_p ) + : m_pool_i( 0 ) + , m_pool_p( pool_p ? pool_p : new T[static_cast<std::size_t>(1) << log2] ) + , m_wrap( ~(static_cast<std::size_t>(-1) << log2) ) +{ + // if ( log2 > 32 ) SC_REPORT_ERROR(SC_ID_POOL_SIZE_, ""); +} + +template<class T> sc_vpool<T>::~sc_vpool() +{ + // delete [] m_pool_p; +} + +template<class T> T* sc_vpool<T>::allocate() +{ + T* result_p; // Entry to return. + + result_p = &m_pool_p[m_pool_i]; + m_pool_i = (m_pool_i + 1) & m_wrap; + return result_p; +} + +template<class T> void sc_vpool<T>::reset() +{ + m_pool_i = 0; +} + +template<class T> std::size_t sc_vpool<T>::size() +{ + return m_wrap + 1; +} + +} // namespace sc_core + +// $Log: sc_temporary.h,v $ +// Revision 1.4 2011/08/26 20:46:19 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +// Revision 1.3 2011/08/24 22:05:56 acg +// Torsten Maehne: initialization changes to remove warnings. +// +// Revision 1.2 2011/02/18 20:38:44 acg +// Andy Goodrich: Updated Copyright notice. +// +// Revision 1.1.1.1 2006/12/15 20:20:06 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:53:11 acg +// Andy Goodrich: Added $Log command so that CVS comments are reproduced in +// the source. +// + +#endif // SC_TEMPORARY_H diff --git a/ext/systemc/src/sysc/utils/sc_utils_ids.cpp b/ext/systemc/src/sysc/utils/sc_utils_ids.cpp new file mode 100644 index 000000000..3492692b3 --- /dev/null +++ b/ext/systemc/src/sysc/utils/sc_utils_ids.cpp @@ -0,0 +1,147 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_utils_ids.cpp -- Report ids for the utils code. + + Original Author: Martin Janssen, Synopsys, Inc., 2002-01-17 + + CHANGE LOG AT END OF FILE + *****************************************************************************/ + + +#include <cstdlib> +#include <cstring> + +#include "sysc/utils/sc_report.h" + + +namespace sc_core { +#define SC_DEFINE_MESSAGE(id,unused,text) extern const char id[] = text; +#include "sysc/utils/sc_utils_ids.h" +#include "sysc/kernel/sc_kernel_ids.h" +#include "sysc/communication/sc_communication_ids.h" +#include "sysc/datatypes/bit/sc_bit_ids.h" +#include "sysc/datatypes/fx/sc_fx_ids.h" +#include "sysc/datatypes/int/sc_int_ids.h" +#include "sysc/tracing/sc_tracing_ids.h" +#undef SC_DEFINE_MESSAGE + + +static sc_msg_def texts[] = { +#define SC_DEFINE_MESSAGE(id,n,unused) \ + { (id), 0u, {0u}, 0u, {0u}, 0u, 0u, {0u}, 0, n }, + +#undef SC_UTILS_IDS_H +#include "sysc/utils/sc_utils_ids.h" + +#undef SC_KERNEL_IDS_H +#include "sysc/kernel/sc_kernel_ids.h" + +#undef SC_COMMUNICATION_IDS_H +#include "sysc/communication/sc_communication_ids.h" + +#undef SC_BIT_IDS_H +#include "sysc/datatypes/bit/sc_bit_ids.h" + +#undef SC_FX_IDS_H +#include "sysc/datatypes/fx/sc_fx_ids.h" + +#undef SC_INT_IDS_H +#include "sysc/datatypes/int/sc_int_ids.h" + +#undef SC_TRACING_IDS_H +#include "sysc/tracing/sc_tracing_ids.h" + +#undef SC_DEFINE_MESSAGE +}; +static sc_report_handler::msg_def_items items = { + texts, sizeof(texts)/sizeof(*texts), false, 0 +}; + +static +int initialize() +{ + sc_report_handler::add_static_msg_types(&items); + + // PROCESS ANY ENVIRONMENTAL OVERRIDES: + + const char* deprecation_warn = std::getenv("SC_DEPRECATION_WARNINGS"); + if ( (deprecation_warn!=0) && !std::strcmp(deprecation_warn,"DISABLE") ) + { + sc_report_handler::set_actions( SC_ID_IEEE_1666_DEPRECATION_ + , SC_DO_NOTHING); + } + return 42; +} + +static int forty_two = initialize(); + +} // namespace sc_core + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + Alex Riesen, Synopsys, Inc., 2003-02-02 + ported to SystemC 2.1 exception reporting. + + *****************************************************************************/ + + +// $Log: sc_utils_ids.cpp,v $ +// Revision 1.5 2011/08/26 20:46:19 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +// Revision 1.4 2011/02/18 20:38:44 acg +// Andy Goodrich: Updated Copyright notice. +// +// Revision 1.3 2009/02/28 00:27:57 acg +// Andy Goodrich: includes for C++ library types to keep compiler happy. +// +// Revision 1.2 2008/05/20 20:43:21 acg +// Andy Goodrich: Added includes <cstdlib> and <cstring> to pick up their +// declarations. +// +// Revision 1.1.1.1 2006/12/15 20:20:06 acg +// SystemC 2.3 +// +// Revision 1.6 2006/01/31 21:42:07 acg +// Andy Goodrich: Added checks for SC_DEPRECATED_WARNINGS being defined as +// DISABLED. If so, we turn off the /IEEE_Std_1666/deprecated message group. +// +// Revision 1.5 2006/01/24 21:59:59 acg +// Andy Goodrich: removed sc_trace_ids.h since its only message has been +// replaced by SC_ID_IEEE_1666_DEPRECATION_ message. +// +// Revision 1.4 2006/01/24 20:53:41 acg +// Andy Goodrich: added warnings indicating that use of integer ids in reports +// is deprecated. Added tracing/sc_trace_ids.h to message list. +// +// Revision 1.3 2006/01/13 18:53:11 acg +// Andy Goodrich: Added $Log command so that CVS comments are reproduced in +// the source. + +// Taf! diff --git a/ext/systemc/src/sysc/utils/sc_utils_ids.h b/ext/systemc/src/sysc/utils/sc_utils_ids.h new file mode 100644 index 000000000..811878280 --- /dev/null +++ b/ext/systemc/src/sysc/utils/sc_utils_ids.h @@ -0,0 +1,113 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_utils_ids.h -- Report ids for the utils code. + + Original Author: Martin Janssen, Synopsys, Inc., 2002-01-17 + + CHANGE LOG AT END OF FILE + *****************************************************************************/ + +#ifndef SC_UTILS_IDS_H +#define SC_UTILS_IDS_H + +// ---------------------------------------------------------------------------- +// Report ids (utils) +// +// Report ids in the range of 800-899. +// ---------------------------------------------------------------------------- + +#ifndef SC_DEFINE_MESSAGE +#define SC_DEFINE_MESSAGE(id,unused1,unused2) \ + namespace sc_core { extern const char id[]; } +namespace sc_core { + extern const char SC_ID_REGISTER_ID_FAILED_[]; // in sc_report_handler.cpp +} +#endif + +SC_DEFINE_MESSAGE(SC_ID_STRING_TOO_LONG_, + 801, "string is too long") +SC_DEFINE_MESSAGE(SC_ID_FRONT_ON_EMPTY_LIST_, + 802, "attempt to take front() on an empty list") +SC_DEFINE_MESSAGE(SC_ID_BACK_ON_EMPTY_LIST_, + 803, "attempt to take back() on an empty list") +SC_DEFINE_MESSAGE(SC_ID_IEEE_1666_DEPRECATION_, + 804, "/IEEE_Std_1666/deprecated" ) +SC_DEFINE_MESSAGE(SC_ID_VECTOR_INIT_CALLED_TWICE_, + 805, "sc_vector::init has already been called" ) +SC_DEFINE_MESSAGE(SC_ID_VECTOR_INIT_INVALID_CONTEXT_, + 806, "sc_vector::init called from invalid object context" ) +SC_DEFINE_MESSAGE(SC_ID_VECTOR_BIND_EMPTY_, + 807, "sc_vector::bind called with empty range" ) +SC_DEFINE_MESSAGE(SC_ID_VECTOR_NONOBJECT_ELEMENTS_, + 808, "sc_vector::get_elements called for element type " + "not derived from sc_object" ) + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + Alex Riesen, Synopsys, Inc., 2003-02-02 + ported to SystemC 2.1 exception reporting. + + *****************************************************************************/ + +// $Log: sc_utils_ids.h,v $ +// Revision 1.5 2011/08/26 20:46:20 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +// Revision 1.4 2011/02/18 20:38:44 acg +// Andy Goodrich: Updated Copyright notice. +// +// Revision 1.3 2011/02/14 17:54:25 acg +// Andy Goodrich: Philipp's addition of early bind checks. +// +// Revision 1.2 2010/12/07 20:10:19 acg +// Andy Goodrich: messages for new sc_vector class. +// +// Revision 1.1.1.1 2006/12/15 20:20:06 acg +// SystemC 2.3 +// +// Revision 1.6 2006/01/25 00:31:27 acg +// Andy Goodrich: Changed over to use a standard message id of +// SC_ID_IEEE_1666_DEPRECATION for all deprecation messages. +// +// Revision 1.5 2006/01/24 22:01:35 acg +// Andy Goodrich: consolidated all IEEE 1666 compliance messages to use the +// SC_ID_IEEE_1666_DEPRECATION_ message type. +// +// Revision 1.4 2006/01/24 20:53:41 acg +// Andy Goodrich: added warnings indicating that use of integer ids in reports +// is deprecated. Added tracing/sc_trace_ids.h to message list. +// +// Revision 1.3 2006/01/13 18:53:11 acg +// Andy Goodrich: Added $Log command so that CVS comments are reproduced in +// the source. +// + +#endif + +// Taf! diff --git a/ext/systemc/src/sysc/utils/sc_vector.cpp b/ext/systemc/src/sysc/utils/sc_vector.cpp new file mode 100644 index 000000000..e42fba02e --- /dev/null +++ b/ext/systemc/src/sysc/utils/sc_vector.cpp @@ -0,0 +1,178 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_vector.cpp - A vector of named (SystemC) objects (modules, ports, channels) + + Original Author: Philipp A. Hartmann, OFFIS + + CHANGE LOG AT END OF FILE + *****************************************************************************/ + + +#include "sc_vector.h" + +#include "sysc/utils/sc_hash.h" +#include "sysc/utils/sc_list.h" +#include "sysc/utils/sc_utils_ids.h" + +#include "sysc/kernel/sc_simcontext.h" +#include "sysc/kernel/sc_object_manager.h" + +#include <sstream> + +namespace sc_core { + +sc_vector_base::sc_vector_base() + : sc_object( sc_gen_unique_name("vector") ) + , vec_() + , objs_vec_() +{} + +std::vector< sc_object* > const & +sc_vector_base::get_elements() const +{ + if( !objs_vec_ ) + objs_vec_ = new std::vector< sc_object* >; + + if( objs_vec_->size() || !size() ) + return *objs_vec_; + + objs_vec_->reserve( size() ); + for( const_iterator it=begin(); it != end(); ++it ) + if( sc_object* obj = object_cast(*it) ) + objs_vec_->push_back( obj ); + + return *objs_vec_; +} + +sc_object* +sc_vector_base::implicit_cast( ... ) const +{ + SC_REPORT_ERROR( SC_ID_VECTOR_NONOBJECT_ELEMENTS_, name() ); + return NULL; +} + +void +sc_vector_base::check_index( size_type i ) const +{ + if( i>=size() ) + { + std::stringstream str; + str << name() + << "[" << i << "] >= size() = " << size(); + SC_REPORT_ERROR( SC_ID_OUT_OF_BOUNDS_, str.str().c_str() ); + } +} + +bool +sc_vector_base::check_init( size_type n ) const +{ + if ( !n ) + return false; + + if( size() ) // already filled + { + std::stringstream str; + str << name() + << ", size=" << size() + << ", requested size=" << n; + SC_REPORT_ERROR( SC_ID_VECTOR_INIT_CALLED_TWICE_ + , str.str().c_str() ); + return false; + } + + sc_simcontext* simc = simcontext(); + sc_assert( simc == sc_get_curr_simcontext() ); + + sc_object* parent_p = simc->active_object(); + if( parent_p != get_parent_object() ) + { + std::stringstream str; + str << name() << ": expected " + << ( get_parent_object() + ? get_parent_object()->name() : "<top-level>" ) + << ", got " + << ( parent_p ? parent_p->name() : "<top-level>" ); + + SC_REPORT_ERROR( SC_ID_VECTOR_INIT_INVALID_CONTEXT_ + , str.str().c_str() ); + return false; + } + + return true; +} + +void +sc_vector_base::report_empty_bind( const char* kind_, bool dst_empty_ ) const +{ + std::stringstream str; + + str << "target `" << name() << "' " + << "(" << kind_ << ") "; + + if( !size() ) { + str << "not initialised yet"; + } else if ( dst_empty_ ) { + str << "empty range given"; + } else { + str << "empty destination range given"; + } + + SC_REPORT_WARNING( SC_ID_VECTOR_BIND_EMPTY_, str.str().c_str() ); +} + +std::string +sc_vector_base::make_name( const char* prefix, size_type /* idx */ ) +{ + // TODO: How to handle name clashes due to interleaved vector + // creation and init()? + // sc_vector< foo > v1, v2; + // v1.name() == "vector", v2.name() == "vector_0" + // v1.init( 1 ); -> v1[0].name() == "vector_0" -> clash + return sc_gen_unique_name( prefix ); +} + +} // namespace sc_core + +// $Log: sc_vector.cpp,v $ +// Revision 1.6 2011/08/26 20:46:20 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +// Revision 1.5 2011/04/01 22:35:19 acg +// Andy Goodrich: spelling fix. +// +// Revision 1.4 2011/03/28 13:03:09 acg +// Andy Goodrich: Philipp's latest update. +// +// Revision 1.3 2011/03/23 16:16:28 acg +// Philipp A. Hartmann: rebase implementation on void* +// - supports virtual inheritance from sc_object again +// - build up get_elements result on demand +// - still requires element type to be derived from sc_object +// +// Revision 1.2 2011/02/14 17:54:25 acg +// Andy Goodrich: Philipp's addition of early bind checks. +// +// Revision 1.1 2011/02/13 21:54:14 acg +// Andy Goodrich: turn on embedding of cvs log records. + +// Taf! diff --git a/ext/systemc/src/sysc/utils/sc_vector.h b/ext/systemc/src/sysc/utils/sc_vector.h new file mode 100644 index 000000000..2afbaf45e --- /dev/null +++ b/ext/systemc/src/sysc/utils/sc_vector.h @@ -0,0 +1,724 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + sc_vector.h - A vector of named (SystemC) objects (modules, ports, channels) + + Original Author: Philipp A. Hartmann, OFFIS + + CHANGE LOG AT END OF FILE + *****************************************************************************/ + +#ifndef SC_VECTOR_H_INCLUDED_ +#define SC_VECTOR_H_INCLUDED_ + +#include <vector> +#include <iterator> +#include <string> +#include <algorithm> // std::swap + +#include "sysc/kernel/sc_object.h" +#include <type_traits> + +//#define SC_VECTOR_HEADER_ONLY_ + +namespace sc_core { +namespace sc_meta { + + using ::std::enable_if; + using ::std::remove_const; + using ::std::is_same; + using ::std::is_const; + + template< typename CT, typename T > + struct is_more_const { + static constexpr bool value + = ( is_same< typename remove_const<CT>::type + , typename remove_const<T>::type + >::value + && ( is_const<CT>::value >= is_const<T>::value ) ); + }; + +} // namespace sc_meta + +// forward declarations +template< typename T > class sc_vector; +template< typename T, typename MT > class sc_vector_assembly; +template< typename T, typename MT > class sc_vector_iter; + +// implementation-defined +template< typename Container, typename ArgumentIterator > +typename Container::iterator +sc_vector_do_bind( Container & cont + , ArgumentIterator first + , ArgumentIterator last + , typename Container::iterator from ); + +// implementation-defined +template< typename Container, typename ArgumentIterator > +typename Container::iterator +sc_vector_do_operator_paren( Container & cont + , ArgumentIterator first + , ArgumentIterator last + , typename Container::iterator from ); + +class sc_vector_base + : public sc_object +{ + + template<typename,typename> friend class sc_vector_assembly; + template<typename,typename> friend class sc_vector_iter; + +public: + + typedef std::vector< void* > storage_type; + typedef storage_type::size_type size_type; + typedef storage_type::difference_type difference_type; + + const char * kind() const { return "sc_vector"; } + + std::vector<sc_object*> const & get_elements() const; + + size_type size() const + { return vec_.size(); } + +protected: + + // begin implementation defined + + typedef storage_type::iterator iterator; + typedef storage_type::const_iterator const_iterator; + + sc_vector_base(); + + sc_vector_base( const char* prefix ) + : sc_object( prefix ) + , vec_() + , objs_vec_(0) + {} + + ~sc_vector_base() + { delete objs_vec_; } + + void * & at( size_type i ) + { return vec_[i]; } + + void const * at( size_type i ) const + { return vec_[i]; } + + void reserve( size_type n ) + { vec_.reserve(n); } + + void clear() + { vec_.clear(); } + + void push_back( void* item ) + { vec_.push_back(item); } + + void check_index( size_type i ) const; + bool check_init( size_type n ) const; + + static std::string make_name( const char* prefix, size_type index ); + + iterator begin() { return vec_.begin(); } + iterator end() { return vec_.end(); } + + const_iterator begin() const { return vec_.begin(); } + const_iterator end() const { return vec_.end(); } + + virtual sc_object* object_cast( void* ) const = 0; + + sc_object* implicit_cast( sc_object* p ) const { return p; } + sc_object* implicit_cast( ... /* incompatible */ ) const; + +public: + + void report_empty_bind( const char* kind_, bool dst_range_ ) const; + +private: + storage_type vec_; + mutable std::vector< sc_object* >* objs_vec_; + + // disabled + sc_vector_base( const sc_vector_base& ); + sc_vector_base& operator=( const sc_vector_base& ); + +}; // sc_vector_base + +// iterator access adapters +template< typename ElementType > +struct sc_direct_access +{ + typedef ElementType element_type; + typedef element_type type; + typedef typename sc_meta::remove_const<type>::type plain_type; + + typedef sc_direct_access< type > policy; + typedef sc_direct_access< plain_type > non_const_policy; + typedef sc_direct_access< const plain_type > const_policy; + + sc_direct_access(){} + sc_direct_access( const non_const_policy& ) {} + // convert from any policy to (const) direct policy + template <typename U> + sc_direct_access(const U&, + typename sc_meta::enable_if<sc_meta::is_more_const< + type, + typename U::policy::element_type>::value>::type* = NULL) + {} + + type* get( type* this_ ) const + { return this_; } +}; + +// iterator access adapters +template< typename ElementType + , typename AccessType > +class sc_member_access +{ + public: + template< typename, typename > friend class sc_member_access; + + typedef ElementType element_type; + typedef AccessType access_type; + typedef access_type (ElementType::*member_type); + typedef access_type type; + typedef typename sc_meta::remove_const<type>::type plain_type; + typedef typename sc_meta::remove_const<ElementType>::type plain_elem_type; + + typedef sc_member_access< element_type, access_type > policy; + typedef sc_member_access< plain_elem_type, plain_type > + non_const_policy; + typedef sc_member_access< const plain_elem_type, const plain_type > + const_policy; + + sc_member_access( member_type ptr ) + : ptr_(ptr) {} + + sc_member_access( const non_const_policy& other ) + : ptr_(other.ptr_) + {} + + access_type * get( element_type* this_ ) const + { return &(this_->*ptr_); } + + private: + member_type ptr_; +}; // sc_member_access + + +template< typename ElementType + , typename AccessPolicy = sc_direct_access<ElementType> > +class sc_vector_iter + : public std::iterator< std::random_access_iterator_tag + , typename AccessPolicy::type > + , private AccessPolicy +{ + typedef ElementType element_type; + typedef typename AccessPolicy::policy access_policy; + typedef typename AccessPolicy::non_const_policy non_const_policy; + typedef typename AccessPolicy::const_policy const_policy; + typedef typename access_policy::type access_type; + + typedef typename sc_meta::remove_const<ElementType>::type plain_type; + typedef const plain_type const_plain_type; + + friend class sc_vector< plain_type >; + template< typename, typename > friend class sc_vector_assembly; + template< typename, typename > friend class sc_vector_iter; + + typedef std::iterator< std::random_access_iterator_tag, access_type > base_type; + typedef sc_vector_iter this_type; + typedef sc_vector<plain_type> vector_type; + typedef sc_vector_base::storage_type storage_type; + + // select correct base-type iterator + template< typename U > struct select_iter + { typedef typename storage_type::iterator type; }; + template< typename U > struct select_iter< const U > + { typedef typename storage_type::const_iterator type; }; + + typedef typename select_iter<ElementType>::type raw_iterator; + typedef sc_vector_iter< const_plain_type, const_policy > const_iterator; + + // underlying vector iterator + + raw_iterator it_; + + sc_vector_iter( raw_iterator it, access_policy acc = access_policy() ) + : access_policy(acc), it_(it) {} + + access_policy const & get_policy() const { return *this; } + +public: + // interface for Random Access Iterator category, + // see ISO/IEC 14882:2003(E), 24.1 [lib.iterator.requirements] + + typedef typename base_type::difference_type difference_type; + typedef typename base_type::reference reference; + typedef typename base_type::pointer pointer; + + sc_vector_iter() : access_policy(), it_() {} + + // iterator conversions to more const, and/or direct iterators + template< typename OtherElement, typename OtherPolicy > + sc_vector_iter( const sc_vector_iter<OtherElement, OtherPolicy>& it + , typename sc_meta::enable_if<sc_meta::is_more_const< + element_type, + typename OtherPolicy::element_type>::value>::type* = NULL) + : access_policy( it.get_policy() ), it_( it.it_ ) + {} + + // step + this_type& operator++(){ ++it_; return *this; } + this_type& operator--(){ --it_; return *this; } + this_type operator++(int){ this_type old(*this); ++it_; return old; } + this_type operator--(int){ this_type old(*this); --it_; return old; } + + // advance + this_type operator+( difference_type n ) const + { return this_type( it_ + n, get_policy()); } + this_type operator-( difference_type n ) const + { return this_type( it_ - n, get_policy()); } + + this_type& operator+=( difference_type n ) { it_+=n; return *this; } + this_type& operator-=( difference_type n ) { it_-=n; return *this; } + + // relations + bool operator== ( const this_type& that ) const { return it_ == that.it_; } + bool operator!= ( const this_type& that ) const { return it_ != that.it_; } + bool operator<= ( const this_type& that ) const { return it_ <= that.it_; } + bool operator>= ( const this_type& that ) const { return it_ >= that.it_; } + bool operator< ( const this_type& that ) const { return it_ < that.it_; } + bool operator> ( const this_type& that ) const { return it_ > that.it_; } + + // dereference + reference operator*() const + { return *access_policy::get( static_cast<element_type*>(*it_) ); } + pointer operator->() const + { return access_policy::get( static_cast<element_type*>(*it_) ); } + reference operator[]( difference_type n ) const + { return *access_policy::get( static_cast<element_type*>(it_[n]) ); } + + // distance + difference_type operator-( this_type const& that ) const + { return it_-that.it_; } + +}; // sc_vector_iter + +template< typename T > +class sc_vector + : public sc_vector_base +{ + typedef sc_vector_base base_type; + typedef sc_vector<T> this_type; + +public: + typedef T element_type; + typedef sc_vector_iter< element_type > iterator; + typedef sc_vector_iter< const element_type > const_iterator; + + sc_vector(){} + + explicit sc_vector( const char* prefix ) + : base_type( prefix ) + {} + + explicit sc_vector( const char* prefix, size_type n ) + : base_type( prefix ) + { init(n); } + + template< typename Creator > + sc_vector( const char* prefix, size_type n, Creator creator ) + : base_type( prefix ) + { + init( n, creator ); + } + + virtual ~sc_vector(); + + element_type& operator[]( size_type i ) + { return *static_cast<element_type*>( base_type::at(i) ); } + + element_type& at( size_type i ) + { check_index(i); return (*this)[i]; } + + const element_type& operator[]( size_type i ) const + { return *static_cast<element_type const *>( base_type::at(i) ); } + + const element_type& at( size_type i ) const + { check_index(i); return (*this)[i]; } + + void init( size_type n ) + { init( n, &this_type::create_element ); } + + template< typename Creator > + void init( size_type n, Creator c ); + + static element_type * create_element( const char* prefix, size_type index ); + + iterator begin() { return base_type::begin(); } + iterator end() { return base_type::end(); } + + const_iterator begin() const { return base_type::begin(); } + const_iterator end() const { return base_type::end(); } + + const_iterator cbegin() const { return base_type::begin(); } + const_iterator cend() const { return base_type::end(); } + + template< typename ContainerType, typename ArgumentType > + iterator bind( sc_vector_assembly<ContainerType,ArgumentType> c ) + { return bind( c.begin(), c.end() ); } + + template< typename BindableContainer > + iterator bind( BindableContainer & c ) + { return bind( c.begin(), c.end() ); } + + template< typename BindableIterator > + iterator bind( BindableIterator first, BindableIterator last ) + { return bind( first, last, this->begin() ); } + + template< typename BindableIterator > + iterator bind( BindableIterator first, BindableIterator last + , iterator from ) + { return sc_vector_do_bind( *this, first, last, from ); } + + template< typename ContainerType, typename ArgumentType > + iterator operator()( sc_vector_assembly<ContainerType,ArgumentType> c ) + { return operator()( c.begin(), c.end() ); } + + template< typename ArgumentContainer > + iterator operator()( ArgumentContainer & c ) + { return operator()( c.begin(), c.end() ); } + + template< typename ArgumentIterator > + iterator operator()( ArgumentIterator first, ArgumentIterator last ) + { return operator()( first, last, this->begin() ); } + + template< typename ArgumentIterator > + iterator operator()( ArgumentIterator first, ArgumentIterator last + , iterator from ) + { return sc_vector_do_operator_paren( *this, first, last, from ); } + + // member-wise access + + template< typename MT > + sc_vector_assembly<T,MT> assemble( MT (T::*member_ptr) ) + { return sc_vector_assembly<T,MT>( *this, member_ptr ); } + +protected: + + void clear(); + + virtual sc_object* object_cast( void* p ) const + { return implicit_cast( static_cast<element_type*>(p) ); } + +}; + +template< typename T, typename MT > +class sc_vector_assembly +{ + template< typename U > friend class sc_vector; + +public: + + typedef sc_vector<T> base_type; + + typedef sc_vector_iter< T, sc_member_access<T, MT> > iterator; + typedef sc_vector_iter< const T + , sc_member_access<const T, const MT> > const_iterator; + + typedef T element_type; + typedef MT access_type; + + typedef typename base_type::size_type size_type; + typedef typename base_type::difference_type difference_type; + typedef typename iterator::reference reference; + typedef typename iterator::pointer pointer; + typedef typename const_iterator::reference const_reference; + typedef typename const_iterator::pointer const_pointer; + + + typedef access_type (T::*member_type); + + const char* name() const { return vec_->name(); } + const char* kind() const { return "sc_vector_assembly"; } + + iterator begin() + { return iterator( (*vec_).begin().it_, ptr_ ); } + iterator end() + { return iterator( (*vec_).end().it_, ptr_ ); } + + const_iterator cbegin() const + { return const_iterator( (*vec_).cbegin().it_, ptr_ ); } + const_iterator cend() const + { return const_iterator( (*vec_).cend().it_, ptr_ ); } + + const_iterator begin() const + { return const_iterator( (*vec_).begin().it_, ptr_ ); } + const_iterator end() const + { return const_iterator( (*vec_).end().it_, ptr_ ); } + + size_type size() const { return vec_->size(); } + const std::vector< sc_object* > & get_elements() const; + + reference operator[]( size_type idx ) + { return (*vec_)[idx].*ptr_; } + reference at( size_type idx ) + { return vec_->at(idx).*ptr_; } + const_reference operator[]( size_type idx ) const + { return (*vec_)[idx].*ptr_; } + const_reference at( size_type idx ) const + { return vec_->at(idx).*ptr_; } + + template< typename ContainerType, typename ArgumentType > + iterator bind( sc_vector_assembly<ContainerType,ArgumentType> c ) + { return bind( c.begin(), c.end() ); } + + template< typename BindableContainer > + iterator bind( BindableContainer & c ) + { return bind( c.begin(), c.end() ); } + + template< typename BindableIterator > + iterator bind( BindableIterator first, BindableIterator last ) + { return bind( first, last, this->begin() ); } + + template< typename BindableIterator > + iterator bind( BindableIterator first, BindableIterator last + , iterator from ) + { return sc_vector_do_bind( *this, first, last, from ); } + + template< typename BindableIterator > + iterator bind( BindableIterator first, BindableIterator last + , typename base_type::iterator from ) + { return bind( first, last, iterator(from.it_, ptr_) ); } + + template< typename ContainerType, typename ArgumentType > + iterator operator()( sc_vector_assembly<ContainerType,ArgumentType> c ) + { return operator()( c.begin(), c.end() ); } + + template< typename ArgumentContainer > + iterator operator()( ArgumentContainer & c ) + { return operator()( c.begin(), c.end() ); } + + template< typename ArgumentIterator > + iterator operator()( ArgumentIterator first, ArgumentIterator last ) + { return operator()( first, last, this->begin() ); } + + template< typename ArgumentIterator > + iterator operator()( ArgumentIterator first, ArgumentIterator last + , iterator from ) + { return sc_vector_do_operator_paren( *this, first, last, from ); } + + template< typename ArgumentIterator > + iterator operator()( ArgumentIterator first, ArgumentIterator last + , typename base_type::iterator from ) + { return operator()( first, last, iterator(from.it_, ptr_) ); } + + sc_vector_assembly( const sc_vector_assembly & other ) + : vec_( other.vec_ ) + , ptr_( other.ptr_ ) + , child_vec_(0) + {} + + sc_vector_assembly& operator=( sc_vector_assembly other_copy ) + { + swap( other_copy ); + return *this; + } + + void swap( sc_vector_assembly & that ) + { + using std::swap; + swap( vec_, that.vec_ ); + swap( ptr_, that.ptr_ ); + swap( child_vec_, that.child_vec_ ); + } + + void report_empty_bind( const char* kind_, bool dst_empty_ ) const + { vec_->report_empty_bind( kind_, dst_empty_ ); } + + ~sc_vector_assembly() + { delete child_vec_; } + +private: + + sc_vector_assembly( base_type & v, member_type ptr ) + : vec_(&v) + , ptr_(ptr) + , child_vec_(0) + {} + + sc_object* object_cast( pointer p ) const + { return vec_->implicit_cast( p ); } + + base_type * vec_; + member_type ptr_; + + mutable std::vector< sc_object* >* child_vec_; +}; + +template< typename T, typename MT > +sc_vector_assembly<T,MT> +sc_assemble_vector( sc_vector<T> & vec, MT (T::*ptr) ) +{ + return vec.assemble( ptr ); +} + +template< typename T > +typename sc_vector<T>::element_type * +sc_vector<T>::create_element( const char* name, size_type /* idx */ ) +{ + return new T( name ); +} + +template< typename T > +template< typename Creator > +void +sc_vector<T>::init( size_type n, Creator c ) +{ + if ( base_type::check_init(n) ) + { + base_type::reserve( n ); + try + { + for ( size_type i = 0; i<n; ++i ) + { + // this workaround is needed for SystemC 2.2/2.3 sc_bind + std::string name = make_name( basename(), i ); + const char* cname = name.c_str(); + + void* p = c( cname, i ) ; // call Creator + base_type::push_back(p); + } + } + catch ( ... ) + { + clear(); + throw; + } + } +} + +template< typename T > +void +sc_vector<T>::clear() +{ + size_type i = size(); + while ( i --> 0 ) + { + delete &( (*this)[i] ); + base_type::at(i) = 0; + } + base_type::clear(); +} + +template< typename Container, typename ArgumentIterator > +typename Container::iterator +sc_vector_do_bind( Container & cont + , ArgumentIterator first + , ArgumentIterator last + , typename Container::iterator from ) +{ + typename Container::iterator end = cont.end(); + + if( !cont.size() || from == end || first == last ) + cont.report_empty_bind( cont.kind(), from == end ); + + while( from!=end && first != last ) + (*from++).bind( *first++ ); + return from; +} + +template< typename Container, typename ArgumentIterator > +typename Container::iterator +sc_vector_do_operator_paren( Container& cont + , ArgumentIterator first + , ArgumentIterator last + , typename Container::iterator from ) +{ + typename Container::iterator end = cont.end(); + + if( !cont.size() || from == end || first == last ) + cont.report_empty_bind( cont.kind(), from == end ); + + while( from!=end && first != last ) + (*from++)( *first++ ); + return from; +} + +template< typename T > +sc_vector<T>::~sc_vector() +{ + clear(); +} + +template< typename T, typename MT > +std::vector< sc_object* > const & +sc_vector_assembly<T,MT>::get_elements() const +{ + if( !child_vec_ ) + child_vec_ = new std::vector< sc_object* >; + + if( child_vec_->size() || !size() ) + return *child_vec_; + + child_vec_->reserve( size() ); + for( const_iterator it=begin(); it != end(); ++it ) + if( sc_object * obj = object_cast( const_cast<MT*>(&*it) ) ) + child_vec_->push_back( obj ); + + return *child_vec_; +} + +} // namespace sc_core +#undef SC_RPTYPE_ +#undef SC_ENABLE_IF_ + +// $Log: sc_vector.h,v $ +// Revision 1.17 2011/08/26 20:46:20 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// +// Revision 1.16 2011/07/25 10:21:17 acg +// Andy Goodrich: check in aftermath of call to automake. +// +// Revision 1.15 2011/04/02 00:04:32 acg +// Philipp A. Hartmann: fix distance from member iterators, and +// add iterator conversions. +// +// Revision 1.14 2011/04/01 22:35:19 acg +// Andy Goodrich: spelling fix. +// +// Revision 1.13 2011/03/28 13:03:09 acg +// Andy Goodrich: Philipp's latest update. +// +// Revision 1.12 2011/03/23 16:16:28 acg +// Philipp A. Hartmann: rebase implementation on void* +// - supports virtual inheritance from sc_object again +// - build up get_elements result on demand +// - still requires element type to be derived from sc_object +// +// Revision 1.11 2011/02/19 16:46:36 acg +// Andy Goodrich: finally get the update from Philipp correct! +// + +#endif // SC_VECTOR_H_INCLUDED_ +// Taf! diff --git a/ext/systemc/src/systemc b/ext/systemc/src/systemc new file mode 100644 index 000000000..ec37d6a3c --- /dev/null +++ b/ext/systemc/src/systemc @@ -0,0 +1,128 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + systemc - Top-level namespace-based include file for the SystemC library. + + Original Author: Stan Y. Liao, Synopsys, Inc. + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: Andy Goodrich, Forte Design Systems, 31 Mar 2005 + Description of Modification: This is the old systemc.h without usings. + + *****************************************************************************/ + +// $Log: systemc,v $ +// Revision 1.6 2011/08/04 17:12:07 acg +// Andy Goodrich: moved systemc and systemc.h back to src level because +// of MSVC not doing an install. +// +// Revision 1.1 2011/07/02 13:26:48 acg +// Andy Goodrich: moved header files up one level. +// +// Revision 1.4 2011/02/18 20:28:27 acg +// Andy Goodrich: Updated Copyright. +// +// Revision 1.3 2011/01/20 16:52:09 acg +// Andy Goodrich: changes for IEEE 1666 2011. +// +// Revision 1.2 2009/11/17 19:57:51 acg +// Andy Goodrich: changes for boost. +// +// Revision 1.1.1.1 2006/12/15 20:20:04 acg +// SystemC 2.3 +// +// Revision 1.5 2006/04/11 23:11:16 acg +// Andy Goodrich: remove inclusions that exposed sc_method_process, +// sc_thread_process, and sc_cthread_process internals. +// +// Revision 1.4 2006/01/25 00:48:29 acg +// Andy Goodrich: added capture of CVS logging messages in the source. +// + +#ifndef SYSTEMC_INCLUDED +#define SYSTEMC_INCLUDED + +// include this file first +#include "sysc/kernel/sc_cmnhdr.h" + +#include "sysc/kernel/sc_externs.h" +#include "sysc/kernel/sc_except.h" +#include "sysc/kernel/sc_module.h" +#include "sysc/kernel/sc_simcontext.h" +#include "sysc/kernel/sc_process_handle.h" +#include "sysc/kernel/sc_ver.h" + +#include "sysc/communication/sc_buffer.h" +#include "sysc/communication/sc_clock.h" +#include "sysc/communication/sc_clock_ports.h" +#include "sysc/communication/sc_event_queue.h" +#include "sysc/communication/sc_export.h" +#include "sysc/communication/sc_fifo.h" +#include "sysc/communication/sc_fifo_ports.h" +#include "sysc/communication/sc_mutex.h" +#include "sysc/communication/sc_semaphore.h" +#include "sysc/communication/sc_signal.h" +#include "sysc/communication/sc_signal_ports.h" + +#include "sysc/communication/sc_signal_resolved.h" +#include "sysc/communication/sc_signal_resolved_ports.h" +#include "sysc/communication/sc_signal_rv.h" +#include "sysc/communication/sc_signal_rv_ports.h" + +#include "sysc/datatypes/bit/sc_bit.h" +#include "sysc/datatypes/bit/sc_logic.h" +#include "sysc/datatypes/bit/sc_bv.h" +#include "sysc/datatypes/bit/sc_lv.h" + +#include "sysc/datatypes/int/sc_bigint.h" +#include "sysc/datatypes/int/sc_biguint.h" +#include "sysc/datatypes/int/sc_int.h" +#include "sysc/datatypes/int/sc_uint.h" + +#include "sysc/datatypes/misc/sc_concatref.h" + +#ifdef SC_INCLUDE_FX +# include "sysc/datatypes/fx/fx.h" +#endif // SC_INCLUDE_FX + +#include "sysc/tracing/sc_trace.h" + +#include "sysc/utils/sc_iostream.h" +#include "sysc/utils/sc_utils_ids.h" + +#include "sysc/utils/sc_pvector.h" +#include "sysc/utils/sc_vector.h" + +#endif // !defined(SYSTEMC_INCLUDED) + +#ifdef SC_INCLUDE_DYNAMIC_PROCESSES +# include "sysc/kernel/sc_dynamic_processes.h" +#endif // SC_INCLUDE_DYNAMIC_PROCESSES + +#ifdef SC_USE_SC_STRING_OLD +# include "sysc/utils/sc_string.h" +#endif // SC_USE_SC_STRING_OLD diff --git a/ext/systemc/src/systemc.h b/ext/systemc/src/systemc.h new file mode 100644 index 000000000..ccc1285eb --- /dev/null +++ b/ext/systemc/src/systemc.h @@ -0,0 +1,348 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + systemc.h - Top-level include file for the SystemC library with usings. + + Original Author: Stan Y. Liao, Synopsys, Inc. + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: Andy Goodrich, Forte Design Systems, 31 Mar 2005 + Description of Modification: Changes for namespace support. + + *****************************************************************************/ + +#ifndef SYSTEMC_H +#define SYSTEMC_H + +// INCLUDE SYSTEM (std) DEFINITIONS: + +#include <cassert> +#include <climits> +#include <cmath> // math.h? +#include <cstddef> +#include <cstdio> +#include <cstdlib> +#include <cstring> +#include <exception> +#include <fstream> +#include <iostream> +#include <memory> +#include <string> +#if defined(__sun) || defined(__sun__) +# include <inttypes.h> +#elif !defined(WIN32) && !defined(_WIN32) +# include <stdint.h> +#endif +#include <typeinfo> +#include <utility> +#include <vector> + +// USINGS FOR I/O STREAM SUPPORT: + + using std::ios; + using std::streambuf; + using std::streampos; + using std::streamsize; + using std::iostream; + using std::istream; + using std::ostream; + using std::cin; + using std::cout; + using std::cerr; + using std::endl; + using std::flush; + using std::dec; + using std::hex; + using std::oct; + using std::noshowbase; + using std::showbase; + + using std::fstream; + using std::ifstream; + using std::ofstream; + +// from <cstdio>: + + using std::size_t; + using std::FILE; + using std::fpos_t; + using std::fclose; + using std::clearerr; + + using std::remove; + using std::rename; + using std::tmpfile; + using std::tmpnam; + using std::fflush; + using std::fopen; + using std::freopen; + using std::setbuf; + using std::setvbuf; + using std::fprintf; + using std::fscanf; + using std::printf; + using std::scanf; + using std::sprintf; + using std::sscanf; + using std::vfprintf; + using std::vprintf; + using std::vsprintf; + using std::fgetc; + using std::fgets; + using std::fputc; + using std::fputs; + using std::getc; + using std::getchar; + using std::gets; + using std::putc; + using std::putchar; + using std::puts; + using std::ungetc; + using std::fread; + using std::fwrite; + using std::fgetpos; + using std::fseek; + using std::fsetpos; + using std::ftell; + using std::rewind; + using std::feof; + using std::ferror; + using std::perror; + +// from <cstdlib>: + + using std::div_t; + using std::ldiv_t; + + using std::atof; + using std::atoi; + using std::atol; + using std::strtod; + using std::strtol; + using std::strtoul; + using std::rand; + using std::srand; + using std::calloc; + using std::free; + using std::malloc; + using std::realloc; + using std::abort; + using std::atexit; + using std::exit; + using std::getenv; + using std::system; + using std::bsearch; + using std::qsort; + using std::abs; + using std::div; + using std::labs; + using std::ldiv; + using std::mblen; + using std::mbtowc; + using std::mbstowcs; +#if !defined(__CYGWIN__) && !defined(__CYGWIN32) + using std::wctomb; + using std::wcstombs; +#endif + +// from <cstring>: + + using std::memcpy; + using std::memmove; + using std::strcpy; + using std::strncpy; + using std::strcat; + using std::strncat; + using std::memcmp; + using std::strcmp; + using std::strcoll; + using std::strncmp; + using std::strxfrm; + using std::memchr; + using std::strchr; + using std::strcspn; + using std::strpbrk; + using std::strrchr; + using std::strspn; + using std::strstr; + using std::strtok; + using std::memset; + using std::strerror; + using std::strlen; + +// deprecated strstream support +#if defined( SC_INCLUDE_STRSTREAM ) +#include <strstream> + + using std::strstream; + using std::strstreambuf; + using std::istrstream; + using std::ostrstream; + +#endif // SC_INCLUDE_STRSTREAM + +// INCLUDE SYSTEMC DEFINITIONS for sc_dt AND sc_core NAMESPACES: + +#include "systemc" + +// USINGS FOR THE sc_dt NAMESPACE: + +using sc_dt::SC_BIN; +using sc_dt::SC_BIN_SM; +using sc_dt::SC_BIN_US; +using sc_dt::SC_CSD; +using sc_dt::SC_DEC; +using sc_dt::SC_HEX; +using sc_dt::SC_HEX_SM; +using sc_dt::SC_HEX_US; +using sc_dt::SC_LOGIC_0; +using sc_dt::SC_LOGIC_1; +using sc_dt::SC_LOGIC_X; +using sc_dt::SC_LOGIC_Z; +using sc_dt::SC_NOBASE; +using sc_dt::SC_OCT; +using sc_dt::SC_OCT_SM; +using sc_dt::SC_OCT_US; +using sc_dt::int64; +using sc_dt::sc_abs; +using sc_dt::sc_bigint; +using sc_dt::sc_biguint; +using sc_dt::sc_bit; +using sc_dt::sc_bv; +using sc_dt::sc_bv_base; +using sc_dt::sc_digit; +using sc_dt::sc_int; +using sc_dt::sc_int_base; +using sc_dt::sc_io_show_base; +using sc_dt::sc_length_context; +using sc_dt::sc_length_param; +using sc_dt::sc_logic; +using sc_dt::sc_lv; +using sc_dt::sc_lv_base; +using sc_dt::sc_max; +using sc_dt::sc_min; +using sc_dt::sc_numrep; +using sc_dt::sc_signed; +using sc_dt::sc_uint; +using sc_dt::sc_uint_base; +using sc_dt::sc_unsigned; +using sc_dt::uint64; +// #ifdef SC_DT_DEPRECATED +using sc_dt::sc_logic_0; +using sc_dt::sc_logic_1; +using sc_dt::sc_logic_Z; +using sc_dt::sc_logic_X; +// #endif + +#ifdef SC_INCLUDE_FX + using sc_dt::sc_fxnum; + using sc_dt::sc_fxnum_bitref; + using sc_dt::sc_fxnum_fast; + using sc_dt::sc_fix; + using sc_dt::sc_fix_fast; + using sc_dt::sc_ufix; + using sc_dt::sc_ufix_fast; + using sc_dt::sc_fixed; + using sc_dt::sc_fixed_fast; + using sc_dt::sc_ufixed; + using sc_dt::sc_ufixed_fast; + using sc_dt::sc_fxval; + using sc_dt::sc_fxval_fast; + using sc_dt::sc_fxcast_switch; + using sc_dt::sc_fxcast_context; + using sc_dt::sc_fxtype_params; + using sc_dt::sc_fxtype_context; + using sc_dt::sc_q_mode; + using sc_dt::SC_RND; + using sc_dt::SC_RND_ZERO; + using sc_dt::SC_RND_MIN_INF; + using sc_dt::SC_RND_INF; + using sc_dt::SC_RND_CONV; + using sc_dt::SC_TRN; + using sc_dt::SC_TRN_ZERO; + using sc_dt::sc_o_mode; + using sc_dt::SC_SAT; + using sc_dt::SC_SAT_ZERO; + using sc_dt::SC_SAT_SYM; + using sc_dt::SC_WRAP; + using sc_dt::SC_WRAP_SM; + using sc_dt::sc_switch; + using sc_dt::SC_OFF; + using sc_dt::SC_ON; + using sc_dt::sc_fmt; + using sc_dt::SC_F; + using sc_dt::SC_E; + using sc_dt::sc_context_begin; + using sc_dt::SC_NOW; + using sc_dt::SC_LATER; +#endif // SC_INCLUDE_FX + +#if 0 // defined( _MSC_VER ) // supported versions of MSVC should support ADL + + using sc_dt::equal; + using sc_dt::not_equal; + using sc_dt::b_not; + using sc_dt::b_and; + using sc_dt::b_or; + using sc_dt::b_xor; + using sc_dt::lrotate; + using sc_dt::rrotate; + using sc_dt::reverse; + using sc_dt::concat; + using sc_dt::and_reduce; + using sc_dt::or_reduce; + using sc_dt::xor_reduce; + using sc_dt::nand_reduce; + using sc_dt::nor_reduce; + using sc_dt::xnor_reduce; + +#endif // defined( _MSC_VER ) + + +// USINGS FOR sc_core: +// +// The explicit using for ::sc_core::wait is to remove an ambiguity with +// the constructor for the system's union wait on Unix and Linux. This +// causes problems with aCC, so users of aCC should explicitly select +// the SystemC wait functions using ::sc_core::wait(...). This is actually +// a good idea for SystemC programmers in general. + +using namespace sc_core; + +#if !defined( __HP_aCC ) + using ::sc_core::wait; +#endif // !defined( __HP_aCC ) + +#ifdef SC_USE_SC_STRING_OLD + using sc_dt::sc_string_old; + typedef sc_dt::sc_string_old sc_string; +#endif +#ifdef SC_USE_STD_STRING + typedef ::std::string sc_string; +#endif + +#endif diff --git a/ext/systemc/src/tlm b/ext/systemc/src/tlm new file mode 100644 index 000000000..b4fb9fe70 --- /dev/null +++ b/ext/systemc/src/tlm @@ -0,0 +1,33 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +#ifndef __TLM_HEADER__ +#define __TLM_HEADER__ + +#include <systemc> // main SystemC header + +#include "tlm_core/tlm_2/tlm_version.h" +#include "tlm_core/tlm_1/tlm_analysis/tlm_analysis.h" +#include "tlm_core/tlm_1/tlm_req_rsp/tlm_req_rsp.h" +#include "tlm_core/tlm_2/tlm_2_interfaces/tlm_2_interfaces.h" +#include "tlm_core/tlm_2/tlm_generic_payload/tlm_generic_payload.h" +#include "tlm_core/tlm_2/tlm_sockets/tlm_sockets.h" +#include "tlm_core/tlm_2/tlm_quantum/tlm_quantum.h" + +#endif /* TLM_HEADER_INCLUDED_ */ diff --git a/ext/systemc/src/tlm.h b/ext/systemc/src/tlm.h new file mode 100644 index 000000000..36d6263ea --- /dev/null +++ b/ext/systemc/src/tlm.h @@ -0,0 +1,22 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +// kept for backwards compatibility + +#include "tlm" diff --git a/ext/systemc/src/tlm_core/tlm.pc.in b/ext/systemc/src/tlm_core/tlm.pc.in new file mode 100644 index 000000000..2d3e55c7a --- /dev/null +++ b/ext/systemc/src/tlm_core/tlm.pc.in @@ -0,0 +1,38 @@ +# Licensed to Accellera Systems Initiative Inc. (Accellera) under one or +# more contributor license agreements. See the NOTICE file distributed +# with this work for additional information regarding copyright ownership. +# Accellera licenses this file to you under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. See the License for the specific language governing +# permissions and limitations under the License. +# +# ------------------------------------------------------------------------- +# +# tlm.pc.in -- +# pkg-config definition file (template) for TLM-2.0 +# (http://www.freedesktop.org/wiki/Software/pkg-config/) +# +# Author: Philipp A. Hartmann, OFFIS, 2013-05-07 +# +# Note: The "real" definition (tlm.pc) is generated by "configure" +# during the build configuration. +# +# ------------------------------------------------------------------------- +# +prefix=@prefix@ +exec_prefix=@exec_prefix@ +includedir=@includedir@ + +Name: TLM-2.0 +Description: Accellera TLM-2.0 proof-of-concept library +Version: @TLM_PACKAGE_VERSION@ +URL: @PACKAGE_URL@ +Requires: systemc >= 2.1.v1 +Cflags: -I${includedir} diff --git a/ext/systemc/src/tlm_core/tlm_1/README.txt b/ext/systemc/src/tlm_core/tlm_1/README.txt new file mode 100644 index 000000000..c7e1c5e1f --- /dev/null +++ b/ext/systemc/src/tlm_core/tlm_1/README.txt @@ -0,0 +1,97 @@ +TLM-1.0 header files +==================== + +Dir: include/tlm_core/tlm_1/ + +SubDirs: tlm_analysis/ + tlm_req_rsp/ + +Files: README.txt + + +Comments +======== + +User code should only #include the tlm or tlm.h header file in the include/ +directory and avoid including any of the include files in this directory +directly. All objects defined in this file hierarchy are in the tlm namespace. + +The header files are organizated, by subdirectory, as follows: + + +tlm_analysis/ +-------------- + +This contains the analysis interfaces, ports, and fifos. These files were not +part of the original TLM-1.0 release, but have been grouped with TLM-1.0 in this +release of TLM-2.0 + +Files: + tlm_analysis.h (includes the other header files in this directory ) + tlm_analysis_fifo.h (defines tlm_analysis_fifo ) + tlm_analysis_if.h (defines tlm_analysis_if and tlm_delayed_analysis_if ) + tlm_analysis_port.h (defines tlm_analysis_port ) + tlm_analysis_triple.h (defines tlm_analysis_triple ) + tlm_write_if.h (defines tlm_write_if and tlm_delayed_write_if ) + + +tlm_req_rsp/ +------------ + +This provides support for TLM modeling based on a request/response pair that +are passed by value. This is the original TLM 1.0 standard, with the addition +of an overloading of the blocking transport method with pass-by-reference arguments. + +Files: + tlm_req_rsp.h (includes the key header files from the other directories) + + tlm_1_interfaces/ + tlm_core_ifs.h (defines the TLM 1.0 core interfaces: + tlm_transport_if + tlm_blocking_get_if + tlm_blocking_put_if + tlm_nonblocking_get_if + tlm_nonblocking_put_if + tlm_get_if + tlm_put_if + tlm_blocking_peek_if + tlm_nonblocking_peek_if + tlm_peek_if + tlm_blocking_get_peek_if + tlm_nonblocking_get_peek_if + tlm_get_peek_if ) + tlm_fifo_ifs.h ( defines the TLM1.0 fifo interfaces: + tlm_fifo_debug_if + tlm_fifo_put_if + tlm_fifo_get_if + tlm_fifo_config_size_if ) + tlm_master_slave_ifs.h ( defines the TLM1.0 master slave interfaces: + tlm_blocking_master_if + tlm_blocking_slave_if + tlm_nonblocking_master_if + tlm_nonblocking_slave_if + tlm_master_if + tlm_slave_if ) + tlm_tag.h ( defines tlm_tag ) + + tlm_ports/ + tlm_nonblocking_port.h (defines tlm_nonblocking_put_port, + tlm_nonblocking_get_port and + tlm_nonblocking_peek_port ) + tlm_event_finder.h (defines tlm_event_finder_t ) + + tlm_channels/ + tlm_fifo/ + tlm_fifo.h (defines tlm_fifo, includes the other files ) + tlm_fifo_peek.h (defines peek and poke interfaces for tlm_fifo ) + tlm_fifo_put_get.h (defines put and get interfaces for tlm_fifo ) + tlm_fifo_resize.h (defines expand, reduce, bound and unbound + interfaces for tlm_fifo ) + circular_buffer.h (defines circular buffer used by tlm_fifo ) + tlm_req_rsp_channels/ + tlm_req_rsp_channels.h (defines tlm_req_rsp_channel and + tlm_transport_channel ) + tlm_put_get_imp.h (contains implementatins used by the channels) + + tlm_adapters/ + tlm_adapters.h (defines transport_to_master and tlm_slave_to_transport) diff --git a/ext/systemc/src/tlm_core/tlm_1/tlm_analysis/tlm_analysis.h b/ext/systemc/src/tlm_core/tlm_1/tlm_analysis/tlm_analysis.h new file mode 100644 index 000000000..777f7141a --- /dev/null +++ b/ext/systemc/src/tlm_core/tlm_1/tlm_analysis/tlm_analysis.h @@ -0,0 +1,33 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +#ifndef __TLM_ANALYSIS_H__ +#define __TLM_ANALYSIS_H__ + + +#include "tlm_core/tlm_1/tlm_analysis/tlm_write_if.h" +#include "tlm_core/tlm_1/tlm_analysis/tlm_analysis_if.h" + +#include "tlm_core/tlm_1/tlm_analysis/tlm_analysis_triple.h" +#include "tlm_core/tlm_1/tlm_analysis/tlm_analysis_port.h" +#include "tlm_core/tlm_1/tlm_analysis/tlm_analysis_fifo.h" + +#endif + + diff --git a/ext/systemc/src/tlm_core/tlm_1/tlm_analysis/tlm_analysis_fifo.h b/ext/systemc/src/tlm_core/tlm_1/tlm_analysis/tlm_analysis_fifo.h new file mode 100644 index 000000000..1f01b2a8e --- /dev/null +++ b/ext/systemc/src/tlm_core/tlm_1/tlm_analysis/tlm_analysis_fifo.h @@ -0,0 +1,54 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +#ifndef __TLM_ANALYSIS_FIFO_H__ +#define __TLM_ANALYSIS_FIFO_H__ + +#include "tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_fifo/tlm_fifo.h" +#include "tlm_core/tlm_1/tlm_analysis/tlm_analysis_if.h" +#include "tlm_core/tlm_1/tlm_analysis/tlm_analysis_triple.h" + +namespace tlm { + +template< typename T > +class tlm_analysis_fifo : + public tlm_fifo< T > , + public virtual tlm_analysis_if< T > , + public virtual tlm_analysis_if< tlm_analysis_triple< T > > { + + public: + + // analysis fifo is an unbounded tlm_fifo + + tlm_analysis_fifo( const char *nm ) : tlm_fifo<T>( nm , -16 ) {} + tlm_analysis_fifo() : tlm_fifo<T>( -16 ) {} + + void write( const tlm_analysis_triple<T> &t ) { + nb_put( t ); + } + + void write( const T &t ) { + nb_put( t ); + } + +}; + +} // namespace tlm + +#endif diff --git a/ext/systemc/src/tlm_core/tlm_1/tlm_analysis/tlm_analysis_if.h b/ext/systemc/src/tlm_core/tlm_1/tlm_analysis/tlm_analysis_if.h new file mode 100644 index 000000000..bc24fee54 --- /dev/null +++ b/ext/systemc/src/tlm_core/tlm_1/tlm_analysis/tlm_analysis_if.h @@ -0,0 +1,39 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +#ifndef __TLM_ANALYSIS_IF_H__ +#define __TLM_ANALYSIS_IF_H__ + +#include "tlm_core/tlm_1/tlm_analysis/tlm_write_if.h" + +namespace tlm { + +template < typename T > +class tlm_analysis_if : public virtual tlm_write_if<T> +{ +}; + +template < typename T > +class tlm_delayed_analysis_if : public virtual tlm_delayed_write_if<T> +{ +}; + +} // namespace tlm + +#endif diff --git a/ext/systemc/src/tlm_core/tlm_1/tlm_analysis/tlm_analysis_port.h b/ext/systemc/src/tlm_core/tlm_1/tlm_analysis/tlm_analysis_port.h new file mode 100644 index 000000000..999092538 --- /dev/null +++ b/ext/systemc/src/tlm_core/tlm_1/tlm_analysis/tlm_analysis_port.h @@ -0,0 +1,84 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +#ifndef __TLM_ANALYSIS_PORT_H__ +#define __TLM_ANALYSIS_PORT_H__ + +#include "tlm_core/tlm_1/tlm_analysis/tlm_analysis_if.h" +#include <deque> +#include <algorithm> + +namespace tlm { + + +template < typename T> +class tlm_analysis_port : + public sc_core::sc_object , + public virtual tlm_analysis_if< T > +{ + public: + tlm_analysis_port() : sc_core::sc_object() {} + tlm_analysis_port( const char *nm ) : sc_core::sc_object( nm ) {} + + // bind and () work for both interfaces and analysis ports, since + // analysis ports implement the analysis interface + + virtual void bind( tlm_analysis_if<T> &_if ) { + m_interfaces.push_back( &_if ); + } + + void operator() ( tlm_analysis_if<T> &_if ) { bind( _if ); } + + virtual bool unbind( tlm_analysis_if<T> &_if ) { + + typename std::deque< tlm_analysis_if<T> * >::iterator i + = std::remove( m_interfaces.begin(), m_interfaces.end(), &_if ); + + if( i != m_interfaces.end() ) { + m_interfaces.erase(i, m_interfaces.end() ); + return 1; + } + + return 0; + + } + + void write( const T &t ) { + typename std::deque< tlm_analysis_if<T> * >::iterator i; + + for( i = m_interfaces.begin(); + i != m_interfaces.end(); + i++ ) { + + (*i)->write( t ); + + } + + } + + private: + std::deque< tlm_analysis_if<T> * > m_interfaces; + +}; + +} // namespace tlm + +#endif + + diff --git a/ext/systemc/src/tlm_core/tlm_1/tlm_analysis/tlm_analysis_triple.h b/ext/systemc/src/tlm_core/tlm_1/tlm_analysis/tlm_analysis_triple.h new file mode 100644 index 000000000..f65a25a2e --- /dev/null +++ b/ext/systemc/src/tlm_core/tlm_1/tlm_analysis/tlm_analysis_triple.h @@ -0,0 +1,53 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +#ifndef __TLM_ANALYSIS_TRIPLE_H__ +#define __TLM_ANALYSIS_TRIPLE_H__ + +//#include <systemc> + +namespace tlm { + +template< typename T> +struct tlm_analysis_triple { + + sc_core::sc_time start_time; + T transaction; + sc_core::sc_time end_time; + + tlm_analysis_triple() {} + + tlm_analysis_triple( const tlm_analysis_triple &triple ) { + start_time = triple.start_time; + transaction = triple.transaction; + end_time = triple.end_time; + } + + tlm_analysis_triple( const T &t ) { + transaction = t; + } + + operator T() { return transaction; } + operator const T &() const { return transaction; } + +}; + +} // namespace tlm + +#endif diff --git a/ext/systemc/src/tlm_core/tlm_1/tlm_analysis/tlm_write_if.h b/ext/systemc/src/tlm_core/tlm_1/tlm_analysis/tlm_write_if.h new file mode 100644 index 000000000..b66a591bc --- /dev/null +++ b/ext/systemc/src/tlm_core/tlm_1/tlm_analysis/tlm_write_if.h @@ -0,0 +1,42 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +#ifndef __TLM_WRITE_IF_H__ +#define __TLM_WRITE_IF_H__ + +#include <systemc> + +namespace tlm { + +template <typename T> +class tlm_write_if : public virtual sc_core::sc_interface { +public: + virtual void write(const T& t) = 0; +}; + +template <typename T> +class tlm_delayed_write_if : public virtual sc_core::sc_interface { +public: + virtual void write(const T& t, const sc_core::sc_time& time) = 0; +}; + +} // namespace tlm + + +#endif diff --git a/ext/systemc/src/tlm_core/tlm_1/tlm_req_rsp/tlm_1_interfaces/tlm_core_ifs.h b/ext/systemc/src/tlm_core/tlm_1/tlm_req_rsp/tlm_1_interfaces/tlm_core_ifs.h new file mode 100644 index 000000000..4c1340338 --- /dev/null +++ b/ext/systemc/src/tlm_core/tlm_1/tlm_req_rsp/tlm_1_interfaces/tlm_core_ifs.h @@ -0,0 +1,149 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +// +// Note to the LRM writer : This is the core of the TLM standard +// + + +#ifndef __TLM_CORE_IFS_H__ +#define __TLM_CORE_IFS_H__ + +//#include <systemc> + +#include "tlm_core/tlm_1/tlm_req_rsp/tlm_1_interfaces/tlm_tag.h" + +namespace tlm { + +// bidirectional blocking interfaces + +template < typename REQ , typename RSP > +class tlm_transport_if : public virtual sc_core::sc_interface +{ +public: + virtual RSP transport( const REQ & ) = 0; + + virtual void transport( const REQ &req , RSP &rsp ) { + rsp = transport( req ); + } + +}; + + +// uni-directional blocking interfaces + +template < typename T > +class tlm_blocking_get_if : public virtual sc_core::sc_interface +{ +public: + virtual T get( tlm_tag<T> *t = 0 ) = 0; + virtual void get( T &t ) { t = get(); } + +}; + +template < typename T > +class tlm_blocking_put_if : public virtual sc_core::sc_interface +{ +public: + virtual void put( const T &t ) = 0; +}; + +// uni-directional non blocking interfaces + +template < typename T > +class tlm_nonblocking_get_if : public virtual sc_core::sc_interface +{ +public: + virtual bool nb_get( T &t ) = 0; + virtual bool nb_can_get( tlm_tag<T> *t = 0 ) const = 0; + virtual const sc_core::sc_event &ok_to_get( tlm_tag<T> *t = 0 ) const = 0; +}; + +template < typename T > +class tlm_nonblocking_put_if : public virtual sc_core::sc_interface +{ +public: + virtual bool nb_put( const T &t ) = 0; + virtual bool nb_can_put( tlm_tag<T> *t = 0 ) const = 0; + virtual const sc_core::sc_event &ok_to_put( tlm_tag<T> *t = 0 ) const = 0; +}; + + +// combined uni-directional blocking and non blocking + +template < typename T > +class tlm_get_if : + public virtual tlm_blocking_get_if< T > , + public virtual tlm_nonblocking_get_if< T > {}; + +template < typename T > +class tlm_put_if : + public virtual tlm_blocking_put_if< T > , + public virtual tlm_nonblocking_put_if< T > {}; + + +// peek interfaces + +template < typename T > +class tlm_blocking_peek_if : public virtual sc_core::sc_interface +{ +public: + virtual T peek( tlm_tag<T> *t = 0 ) const = 0; + virtual void peek( T &t ) const { t = peek(); } + +}; + +template < typename T > +class tlm_nonblocking_peek_if : public virtual sc_core::sc_interface +{ +public: + virtual bool nb_peek( T &t ) const = 0; + virtual bool nb_can_peek( tlm_tag<T> *t = 0 ) const = 0; + virtual const sc_core::sc_event &ok_to_peek( tlm_tag<T> *t = 0 ) const = 0; +}; + +template < typename T > +class tlm_peek_if : + public virtual tlm_blocking_peek_if< T > , + public virtual tlm_nonblocking_peek_if< T > {}; + +// get_peek interfaces + +template < typename T > +class tlm_blocking_get_peek_if : + public virtual tlm_blocking_get_if<T> , + public virtual tlm_blocking_peek_if<T> {}; + +template < typename T > +class tlm_nonblocking_get_peek_if : + public virtual tlm_nonblocking_get_if<T> , + public virtual tlm_nonblocking_peek_if<T> {}; + + +template < typename T > +class tlm_get_peek_if : + public virtual tlm_get_if<T> , + public virtual tlm_peek_if<T> , + public virtual tlm_blocking_get_peek_if<T> , + public virtual tlm_nonblocking_get_peek_if<T> + {}; + +} // namespace tlm + +#endif diff --git a/ext/systemc/src/tlm_core/tlm_1/tlm_req_rsp/tlm_1_interfaces/tlm_fifo_ifs.h b/ext/systemc/src/tlm_core/tlm_1/tlm_req_rsp/tlm_1_interfaces/tlm_fifo_ifs.h new file mode 100644 index 000000000..d9b2b985b --- /dev/null +++ b/ext/systemc/src/tlm_core/tlm_1/tlm_req_rsp/tlm_1_interfaces/tlm_fifo_ifs.h @@ -0,0 +1,85 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +// +// Note to the LRM writer : These interfaces are channel specific interfaces +// useful in the context of tlm_fifo. +// + +#ifndef __TLM_FIFO_IFS_H__ +#define __TLM_FIFO_IFS_H__ + +#include "tlm_core/tlm_1/tlm_req_rsp/tlm_1_interfaces/tlm_core_ifs.h" + +namespace tlm { + +// +// Fifo specific interfaces +// + +// Fifo Debug Interface + +template< typename T > +class tlm_fifo_debug_if : public virtual sc_core::sc_interface +{ +public: + virtual int used() const = 0; + virtual int size() const = 0; + virtual void debug() const = 0; + + // + // non blocking peek and poke - no notification + // + // n is index of data : + // 0 <= n < size(), where 0 is most recently written, and size() - 1 + // is oldest ie the one about to be read. + // + + virtual bool nb_peek( T & , int n ) const = 0; + virtual bool nb_poke( const T & , int n = 0 ) = 0; + +}; + +// fifo interfaces = extended + debug + +template < typename T > +class tlm_fifo_put_if : + public virtual tlm_put_if<T> , + public virtual tlm_fifo_debug_if<T> {}; + +template < typename T > +class tlm_fifo_get_if : + public virtual tlm_get_peek_if<T> , + public virtual tlm_fifo_debug_if<T> {}; + +class tlm_fifo_config_size_if : public virtual sc_core::sc_interface +{ +public: + virtual void nb_expand( unsigned int n = 1 ) = 0; + virtual void nb_unbound( unsigned int n = 16 ) = 0; + + virtual bool nb_reduce( unsigned int n = 1 ) = 0; + virtual bool nb_bound( unsigned int n ) = 0; + +}; + +} // namespace tlm + +#endif + diff --git a/ext/systemc/src/tlm_core/tlm_1/tlm_req_rsp/tlm_1_interfaces/tlm_master_slave_ifs.h b/ext/systemc/src/tlm_core/tlm_1/tlm_req_rsp/tlm_1_interfaces/tlm_master_slave_ifs.h new file mode 100644 index 000000000..5bac3c877 --- /dev/null +++ b/ext/systemc/src/tlm_core/tlm_1/tlm_req_rsp/tlm_1_interfaces/tlm_master_slave_ifs.h @@ -0,0 +1,73 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +#ifndef __TLM_MASTER_SLAVE_IFS_H__ +#define __TLM_MASTER_SLAVE_IFS_H__ + +#include "tlm_core/tlm_1/tlm_req_rsp/tlm_1_interfaces/tlm_core_ifs.h" + +namespace tlm { + +// +// req/rsp combined interfaces +// + +// blocking + +template < typename REQ , typename RSP> +class tlm_blocking_master_if : + public virtual tlm_blocking_put_if< REQ > , + public virtual tlm_blocking_get_peek_if< RSP > {}; + +template < typename REQ , typename RSP> +class tlm_blocking_slave_if : + public virtual tlm_blocking_put_if< RSP > , + public virtual tlm_blocking_get_peek_if< REQ > {}; + +// nonblocking + +template < typename REQ , typename RSP > +class tlm_nonblocking_master_if : + public virtual tlm_nonblocking_put_if< REQ > , + public virtual tlm_nonblocking_get_peek_if< RSP > {}; + +template < typename REQ , typename RSP > +class tlm_nonblocking_slave_if : + public virtual tlm_nonblocking_put_if< RSP > , + public virtual tlm_nonblocking_get_peek_if< REQ > {}; + +// combined + +template < typename REQ , typename RSP > +class tlm_master_if : + public virtual tlm_put_if< REQ > , + public virtual tlm_get_peek_if< RSP > , + public virtual tlm_blocking_master_if< REQ , RSP > , + public virtual tlm_nonblocking_master_if< REQ , RSP > {}; + +template < typename REQ , typename RSP > +class tlm_slave_if : + public virtual tlm_put_if< RSP > , + public virtual tlm_get_peek_if< REQ > , + public virtual tlm_blocking_slave_if< REQ , RSP > , + public virtual tlm_nonblocking_slave_if< REQ , RSP > {}; + +} // namespace tlm + +#endif diff --git a/ext/systemc/src/tlm_core/tlm_1/tlm_req_rsp/tlm_1_interfaces/tlm_tag.h b/ext/systemc/src/tlm_core/tlm_1/tlm_req_rsp/tlm_1_interfaces/tlm_tag.h new file mode 100644 index 000000000..230b77d17 --- /dev/null +++ b/ext/systemc/src/tlm_core/tlm_1/tlm_req_rsp/tlm_1_interfaces/tlm_tag.h @@ -0,0 +1,31 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +// +// Note to the LRM writer : This is part of the core TLM standard +// + +#ifndef __TLM_TAG_H__ +#define __TLM_TAG_H__ + +namespace tlm { +template<class T> class tlm_tag {}; +} + +#endif diff --git a/ext/systemc/src/tlm_core/tlm_1/tlm_req_rsp/tlm_adapters/tlm_adapters.h b/ext/systemc/src/tlm_core/tlm_1/tlm_req_rsp/tlm_adapters/tlm_adapters.h new file mode 100644 index 000000000..13207187a --- /dev/null +++ b/ext/systemc/src/tlm_core/tlm_1/tlm_req_rsp/tlm_adapters/tlm_adapters.h @@ -0,0 +1,105 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +#ifndef __TLM_ADAPTERS_H__ +#define __TLM_ADAPTERS_H__ + +#include "tlm_core/tlm_1/tlm_req_rsp/tlm_1_interfaces/tlm_master_slave_ifs.h" + +namespace tlm { + +template< typename REQ , typename RSP > +class tlm_transport_to_master : + public sc_core::sc_module , + public virtual tlm_transport_if< REQ , RSP > +{ +public: + sc_core::sc_export< tlm_transport_if< REQ , RSP > > target_export; + sc_core::sc_port< tlm_master_if< REQ , RSP > > master_port; + + tlm_transport_to_master( sc_core::sc_module_name nm ) : + sc_core::sc_module( nm ) { + + target_export( *this ); + + } + + tlm_transport_to_master() : + sc_core::sc_module( sc_core::sc_module_name( sc_core::sc_gen_unique_name( "transport_to_master" ) ) ){ + + target_export( *this ); + + } + + RSP transport( const REQ &req ) { + + mutex.lock(); + + master_port->put( req ); + rsp = master_port->get(); + + mutex.unlock(); + return rsp; + + } + +private: + sc_core::sc_mutex mutex; + RSP rsp; + +}; + +template< typename REQ , typename RSP > +class tlm_slave_to_transport : public sc_core::sc_module +{ +public: + + SC_HAS_PROCESS( tlm_slave_to_transport ); + + sc_core::sc_port< tlm_slave_if< REQ , RSP > > slave_port; + sc_core::sc_port< tlm_transport_if< REQ , RSP > > initiator_port; + + tlm_slave_to_transport( sc_core::sc_module_name nm ) : sc_core::sc_module( nm ) + {} + + tlm_slave_to_transport() : + sc_core::sc_module( sc_core::sc_module_name( sc_core::sc_gen_unique_name("slave_to_transport") ) ) + {} + +private: + void run() { + + REQ req; + RSP rsp; + + while( true ) { + + slave_port->get( req ); + rsp = initiator_port->transport( req ); + slave_port->put( rsp ); + + } + + } + +}; + +} // namespace tlm + +#endif diff --git a/ext/systemc/src/tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_fifo/circular_buffer.h b/ext/systemc/src/tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_fifo/circular_buffer.h new file mode 100644 index 000000000..68c3c2c1f --- /dev/null +++ b/ext/systemc/src/tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_fifo/circular_buffer.h @@ -0,0 +1,268 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +// +// To the LRM writer : this class is purely an artifact of the implementation. +// + +#ifndef __CIRCULAR_BUFFER_H__ +#define __CIRCULAR_BUFFER_H__ + +#include <iostream> + +namespace tlm { + +template < typename T > +class circular_buffer +{ +public: + + explicit + circular_buffer( int size = 0 ); + ~circular_buffer(); + + void resize( int size ); + void clear(); + + T read(); + void write( const T & ); + + bool is_empty() const { return used() == 0; } + bool is_full() const { return free() == 0; } + + int size() const { return m_size; } + int used() const { return m_used; } + int free() const { return m_free; } + + const T& read_data() const + { return buf_read( m_buf, m_ri ); } + + const T& peek_data( int i ) const + { return buf_read( m_buf, (m_ri + i) % size() ); } + + T & poke_data( int i ) + { return buf_read( m_buf , (m_wi + i) % size() ); } + + void debug() const; + +private: + void increment_write_pos( int i = 1 ); + void increment_read_pos( int i = 1 ); + + void init(); + + circular_buffer( const circular_buffer<T> &b ); // disabled + circular_buffer<T> &operator=( const circular_buffer<T> & ); // disabled + + void* buf_alloc( int size ); + void buf_free( void*& buf ); + void buf_write( void* buf, int n, const T & t ); + T& buf_read( void* buf, int n ) const; + void buf_clear( void* buf, int n ); + +private: + int m_size; // size of the buffer + void* m_buf; // the buffer + int m_free; // number of free spaces + int m_used; // number of used spaces + int m_ri; // index of next read + int m_wi; // index of next write + +}; + +template< typename T > +void +circular_buffer<T>::debug() const +{ + + std::cout << "Buffer debug" << std::endl; + std::cout << "Size : " << size() << std::endl; + std::cout << "Free/Used " << free() << "/" << used() << std::endl; + std::cout << "Indices : r/w = " << m_ri << "/" << m_wi << std::endl; + + if( is_empty() ) { + + std::cout << "empty" << std::endl; + + } + + if( is_full() ) { + + std::cout << "full" << std::endl; + + } + + std::cout << "Data : " << std::endl; + for( int i = 0; i < used(); i++ ) { + + std::cout << peek_data( i ) << std::endl; + + } + + +} + +template < typename T > +circular_buffer<T>::circular_buffer( int size ) + : m_size(size) + , m_buf(0) +{ + init(); + +} + +template < typename T > +void +circular_buffer<T>::clear() +{ + for( int i=0; i < used(); i++ ) { + buf_clear( m_buf, i ); + } + m_free = m_size; + m_used = m_ri = m_wi = 0; +} + +template < typename T > +circular_buffer<T>::~circular_buffer() +{ + clear(); + buf_free( m_buf ); +} + +template < typename T > +void +circular_buffer<T>::resize( int size ) +{ + + int i; + void * new_buf = buf_alloc(size); + + for( i = 0; i < size && i < used(); i++ ) { + + buf_write( new_buf, i, peek_data( i ) ); + buf_clear( m_buf, (m_ri + i) % m_size ); + + } + + buf_free( m_buf ); + + m_size = size; + m_ri = 0; + m_wi = i % m_size; + m_used = i; + m_free = m_size - m_used; + + m_buf = new_buf; +} + + +template < typename T > +void +circular_buffer<T>::init() { + + if( m_size > 0 ) { + m_buf = buf_alloc( m_size ); + } + + m_free = m_size; + m_used = 0; + m_ri = 0; + m_wi = 0; + +} + +template < typename T > +T +circular_buffer<T>::read() +{ + T t = read_data(); + + buf_clear( m_buf, m_ri ); + increment_read_pos(); + + return t; +} + +template < typename T > +void +circular_buffer<T>::write( const T &t ) +{ + buf_write( m_buf, m_wi, t ); + increment_write_pos(); +} + + +template < typename T > +void +circular_buffer<T>::increment_write_pos( int i ) { + + m_wi = ( m_wi + i ) % m_size; + m_used += i; + m_free -= i; + +} + +template < typename T > +void +circular_buffer<T>::increment_read_pos( int i ) { + + m_ri = ( m_ri + i ) % m_size; + m_used -= i; + m_free += i; + +} + +template < typename T > +inline void* +circular_buffer<T>::buf_alloc( int size ) + { return new unsigned char[ size * sizeof(T) ]; } + +template < typename T > +inline void +circular_buffer<T>::buf_free( void* & buf ) + { delete [] static_cast<unsigned char*>(buf); buf = 0; } + +template < typename T > +inline void +circular_buffer<T>::buf_write( void* buf, int n, const T & t ) +{ + T* p = static_cast<T*>(buf) + n; + new (p) T(t); +} + +template < typename T > +inline T& +circular_buffer<T>::buf_read( void* buf, int n ) const +{ + T* p = static_cast<T*>(buf) + n; + return *p; +} + +template < typename T > +inline void +circular_buffer<T>::buf_clear( void* buf, int n ) +{ + T* p = static_cast<T*>(buf) + n; + p->~T(); +} + +} // namespace tlm + +#endif + diff --git a/ext/systemc/src/tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_fifo/tlm_fifo.h b/ext/systemc/src/tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_fifo/tlm_fifo.h new file mode 100644 index 000000000..7b44a32ee --- /dev/null +++ b/ext/systemc/src/tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_fifo/tlm_fifo.h @@ -0,0 +1,263 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +#ifndef __TLM_FIFO_H__ +#define __TLM_FIFO_H__ + +// +// This implements put, get and peek +// +// It also implements 0 and infinite size fifos - but the size +// zero fifos aren't rendezvous like zero length fifos, they simply are both +// full and empty at the same time. +// +// The size can be dynamically changed using the resize interface +// +// To get an infinite fifo use a -ve size in the constructor. +// The absolute value of the size is taken as the starting size of the +// actual physical buffer. +// + +//#include <systemc> + +#include "tlm_core/tlm_1/tlm_req_rsp/tlm_1_interfaces/tlm_fifo_ifs.h" +#include "tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_fifo/circular_buffer.h" + +namespace tlm { + +template <typename T> +class tlm_fifo : + public virtual tlm_fifo_get_if<T>, + public virtual tlm_fifo_put_if<T>, + public sc_core::sc_prim_channel +{ +public: + + // constructors + + explicit tlm_fifo( int size_ = 1 ) + : sc_core::sc_prim_channel( sc_core::sc_gen_unique_name( "fifo" ) ) { + + init( size_ ); + + } + + explicit tlm_fifo( const char* name_, int size_ = 1 ) + : sc_core::sc_prim_channel( name_ ) { + + init( size_ ); + + } + + // destructor + + virtual ~tlm_fifo() {} + + // tlm get interface + + T get( tlm_tag<T> * = 0 ); + + bool nb_get( T& ); + bool nb_can_get( tlm_tag<T> * = 0 ) const; + const sc_core::sc_event &ok_to_get( tlm_tag<T> * = 0 ) const { + return m_data_written_event; + } + + // tlm peek interface + + T peek( tlm_tag<T> * = 0 ) const; + + bool nb_peek( T& ) const; + bool nb_can_peek( tlm_tag<T> * = 0 ) const; + const sc_core::sc_event &ok_to_peek( tlm_tag<T> * = 0 ) const { + return m_data_written_event; + } + + // tlm put interface + + void put( const T& ); + + bool nb_put( const T& ); + bool nb_can_put( tlm_tag<T> * = 0 ) const; + + const sc_core::sc_event& ok_to_put( tlm_tag<T> * = 0 ) const { + return m_data_read_event; + } + + // resize if + + void nb_expand( unsigned int n = 1 ); + void nb_unbound( unsigned int n = 16 ); + + bool nb_reduce( unsigned int n = 1 ); + bool nb_bound( unsigned int n ); + + // debug interface + + bool nb_peek( T & , int n ) const; + bool nb_poke( const T & , int n = 0 ); + + int used() const { + return m_num_readable - m_num_read; + } + + int size() const { + return m_size; + } + + void debug() const { + + if( is_empty() ) std::cout << "empty" << std::endl; + if( is_full() ) std::cout << "full" << std::endl; + + std::cout << "size " << size() << " - " << used() << " used " + << std::endl; + std::cout << "readable " << m_num_readable + << std::endl; + std::cout << "written/read " << m_num_written << "/" << m_num_read + << std::endl; + + } + + // support functions + + static const char* const kind_string; + + const char* kind() const + { return kind_string; } + + +protected: + sc_core::sc_event &read_event( tlm_tag<T> * = 0 ) { + return m_data_read_event; + } + +protected: + + void update(); + + // support methods + + void init( int ); + +protected: + + circular_buffer<T> buffer; + + int m_size; // logical size of fifo + + int m_num_readable; // #samples readable + int m_num_read; // #samples read during this delta cycle + int m_num_written; // #samples written during this delta cycle + bool m_expand; // has an expand occurred during this delta cycle ? + int m_num_read_no_notify; // #samples read without notify during this delta cycle + + sc_core::sc_event m_data_read_event; + sc_core::sc_event m_data_written_event; + +private: + + // disabled + tlm_fifo( const tlm_fifo<T>& ); + tlm_fifo& operator = ( const tlm_fifo<T>& ); + + // + // use nb_can_get() and nb_can_put() rather than the following two + // private functions + // + + bool is_empty() const { + return used() == 0; + } + + bool is_full() const { + //return size() == m_num_readable + m_num_written; // Old buggy code + if( size() < 0 ) + return false; + else + return size() <= m_num_readable + m_num_written; + } + +}; + +template <typename T> +const char* const tlm_fifo<T>::kind_string = "tlm_fifo"; + + +/****************************************************************** +// +// init and update +// +******************************************************************/ + +template< typename T > +inline +void +tlm_fifo<T>::init( int size_ ) { + + if( size_ > 0 ) { + buffer.resize( size_ ); + } + + else if( size_ < 0 ) { + buffer.resize( -size_ ); + } + + else { + buffer.resize( 16 ); + } + + m_size = size_; + m_num_readable = 0; + m_num_read = 0; + m_num_written = 0; + m_expand = false; + m_num_read_no_notify = false; + +} + +template < typename T> +inline +void +tlm_fifo<T>::update() +{ + if( m_num_read > m_num_read_no_notify || m_expand ) { + m_data_read_event.notify( sc_core::SC_ZERO_TIME ); + } + + if( m_num_written > 0 ) { + m_data_written_event.notify( sc_core::SC_ZERO_TIME ); + } + + m_expand = false; + m_num_read = 0; + m_num_written = 0; + m_num_readable = buffer.used(); + m_num_read_no_notify = 0; + +} + +} // namespace tlm + +#include "tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_fifo/tlm_fifo_put_get.h" +#include "tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_fifo/tlm_fifo_peek.h" +#include "tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_fifo/tlm_fifo_resize.h" + +#endif + diff --git a/ext/systemc/src/tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_fifo/tlm_fifo_peek.h b/ext/systemc/src/tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_fifo/tlm_fifo_peek.h new file mode 100644 index 000000000..e856c5657 --- /dev/null +++ b/ext/systemc/src/tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_fifo/tlm_fifo_peek.h @@ -0,0 +1,98 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +#ifndef __TLM_FIFO_PEEK_H__ +#define __TLM_FIFO_PEEK_H__ + +namespace tlm { + +template < typename T> +inline +T +tlm_fifo<T>::peek( tlm_tag<T> * ) const { + + while( is_empty() ) { + + // call free-standing sc_core::wait(), + // since sc_prim_channel::wait(.) is not const + + sc_core::wait( m_data_written_event ); + } + + return buffer.read_data(); + +} + +template < typename T> +inline +bool +tlm_fifo<T>::nb_peek( T &t ) const { + + if( used() < 1 ) { + return false; + } + + t = buffer.peek_data( 0 ); + return true; + +} + +template < typename T> +inline +bool +tlm_fifo<T>::nb_peek( T &t , int n ) const { + + if( n >= used() || n < -1 ) { + return false; + } + + if( n == -1 ) { + n = used() - 1; + } + + t = buffer.peek_data( n ); + return true; + +} + +template< typename T > +inline +bool +tlm_fifo<T>::nb_can_peek( tlm_tag<T> * ) const +{ + return !is_empty(); +} + +template < typename T> +inline +bool +tlm_fifo<T>::nb_poke( const T &t , int n ) { + + if( n >= used() || n < 0 ) { + return false; + } + + buffer.poke_data( n ) = t; + return true; + +} + +} // namespace tlm + +#endif diff --git a/ext/systemc/src/tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_fifo/tlm_fifo_put_get.h b/ext/systemc/src/tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_fifo/tlm_fifo_put_get.h new file mode 100644 index 000000000..2728e0394 --- /dev/null +++ b/ext/systemc/src/tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_fifo/tlm_fifo_put_get.h @@ -0,0 +1,140 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +#ifndef __TLM_FIFO_PUT_GET_IF_H__ +#define __TLM_FIFO_PUT_GET_IF_H__ + +namespace tlm { + +/****************************************************************** +// +// get interface +// +******************************************************************/ + +template <typename T> +inline +T +tlm_fifo<T>::get( tlm_tag<T> * ) +{ + + while( is_empty() ) { + wait( m_data_written_event ); + } + + m_num_read ++; + request_update(); + + return buffer.read(); + +} + +// non-blocking read + +template <typename T> +inline +bool +tlm_fifo<T>::nb_get( T& val_ ) +{ + + if( is_empty() ) { + return false; + } + + m_num_read ++; + request_update(); + + val_ = buffer.read(); + + return true; + +} + +template <typename T> +inline +bool +tlm_fifo<T>::nb_can_get( tlm_tag<T> * ) const { + + return !is_empty(); + +} + + +/****************************************************************** +// +// put interface +// +******************************************************************/ + +template <typename T> +inline +void +tlm_fifo<T>::put( const T& val_ ) +{ + while( is_full() ) { + wait( m_data_read_event ); + } + + if( buffer.is_full() ) { + + buffer.resize( buffer.size() * 2 ); + + } + + m_num_written ++; + buffer.write( val_ ); + + request_update(); +} + +template <typename T> +inline +bool +tlm_fifo<T>::nb_put( const T& val_ ) +{ + + if( is_full() ) { + return false; + } + + if( buffer.is_full() ) { + + buffer.resize( buffer.size() * 2 ); + + } + + m_num_written ++; + buffer.write( val_ ); + request_update(); + + return true; +} + +template < typename T > +inline +bool +tlm_fifo<T>::nb_can_put( tlm_tag<T> * ) const { + + return !is_full(); + +} + +} // namespace tlm + +#endif diff --git a/ext/systemc/src/tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_fifo/tlm_fifo_resize.h b/ext/systemc/src/tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_fifo/tlm_fifo_resize.h new file mode 100644 index 000000000..39932fea1 --- /dev/null +++ b/ext/systemc/src/tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_fifo/tlm_fifo_resize.h @@ -0,0 +1,93 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +#ifndef __TLM_FIFO_RESIZE_H__ +#define __TLM_FIFO_RESIZE_H__ + +/****************************************************************** +// +// resize interface +// +******************************************************************/ + +namespace tlm { + +template < typename T> +inline +void +tlm_fifo<T>::nb_expand( unsigned int n ) { + + if( m_size >= 0 ) { + m_expand = true; + m_size += n; + request_update(); + } +} + +template < typename T> +inline +void +tlm_fifo<T>::nb_unbound( unsigned int n ) { + + m_expand = true; + m_size = -n; + + if( buffer.size() < static_cast<int>( n ) ) { + buffer.resize( n ); + } + + request_update(); + +} + +template < typename T> +inline +bool +tlm_fifo<T>::nb_reduce( unsigned int n ) { + + if( m_size < 0 ) { + return false; + } + + return nb_bound( size() - n ); + +} + +template < typename T> +inline +bool +tlm_fifo<T>::nb_bound( unsigned int new_size ) { + + bool ret = true; + + if( static_cast<int>( new_size ) < used() ) { + + new_size = used(); + ret = false; + + } + + m_size = new_size; + return ret; + +} + +} // namespace tlm + +#endif diff --git a/ext/systemc/src/tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_req_rsp_channels/tlm_put_get_imp.h b/ext/systemc/src/tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_req_rsp_channels/tlm_put_get_imp.h new file mode 100644 index 000000000..36dbd21d6 --- /dev/null +++ b/ext/systemc/src/tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_req_rsp_channels/tlm_put_get_imp.h @@ -0,0 +1,114 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +// +// To the LRM writer : these classes are purely artifacts of the implementation. +// + +#ifndef __TLM_PUT_GET_IMP_H__ +#define __TLM_PUT_GET_IMP_H__ + +#include "tlm_core/tlm_1/tlm_req_rsp/tlm_1_interfaces/tlm_master_slave_ifs.h" + +namespace tlm { + +template < typename PUT_DATA , typename GET_DATA> +class tlm_put_get_imp : + private virtual tlm_put_if< PUT_DATA > , + private virtual tlm_get_peek_if< GET_DATA > +{ +public: + tlm_put_get_imp( tlm_put_if<PUT_DATA> &p , + tlm_get_peek_if<GET_DATA> &g ) : + put_fifo( p ) , get_fifo( g ) {} + + // put interface + + void put( const PUT_DATA &t ) { put_fifo.put( t ); } + + bool nb_put( const PUT_DATA &t ) { return put_fifo.nb_put( t ); } + bool nb_can_put( tlm_tag<PUT_DATA> *t = 0 ) const { + return put_fifo.nb_can_put( t ); + } + const sc_core::sc_event &ok_to_put( tlm_tag<PUT_DATA> *t = 0 ) const { + return put_fifo.ok_to_put( t ); + } + + // get interface + + GET_DATA get( tlm_tag<GET_DATA> * = 0 ) { return get_fifo.get(); } + + bool nb_get( GET_DATA &t ) { return get_fifo.nb_get( t ); } + + bool nb_can_get( tlm_tag<GET_DATA> *t = 0 ) const { + return get_fifo.nb_can_get( t ); + } + + virtual const sc_core::sc_event &ok_to_get( tlm_tag<GET_DATA> *t = 0 ) const { + return get_fifo.ok_to_get( t ); + } + + // peek interface + + GET_DATA peek( tlm_tag<GET_DATA> * = 0 ) const { return get_fifo.peek(); } + + bool nb_peek( GET_DATA &t ) const { return get_fifo.nb_peek( t ); } + + bool nb_can_peek( tlm_tag<GET_DATA> *t = 0 ) const { + return get_fifo.nb_can_peek( t ); + } + + virtual const sc_core::sc_event &ok_to_peek( tlm_tag<GET_DATA> *t = 0 ) const { + return get_fifo.ok_to_peek( t ); + } + +private: + tlm_put_if<PUT_DATA> &put_fifo; + tlm_get_peek_if<GET_DATA> &get_fifo; +}; + +template < typename REQ , typename RSP > +class tlm_master_imp : + private tlm_put_get_imp< REQ , RSP > , + public virtual tlm_master_if< REQ , RSP > +{ +public: + + tlm_master_imp( tlm_put_if<REQ> &req , + tlm_get_peek_if<RSP> &rsp ) : + tlm_put_get_imp<REQ,RSP>( req , rsp ) {} + +}; + +template < typename REQ , typename RSP > +class tlm_slave_imp : + private tlm_put_get_imp< RSP , REQ > , + public virtual tlm_slave_if< REQ , RSP > +{ +public: + + tlm_slave_imp( tlm_get_peek_if<REQ> &req , + tlm_put_if<RSP> &rsp ) : + tlm_put_get_imp<RSP,REQ>( rsp , req ) {} + +}; + +} // namespace tlm + +#endif diff --git a/ext/systemc/src/tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_req_rsp_channels/tlm_req_rsp_channels.h b/ext/systemc/src/tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_req_rsp_channels/tlm_req_rsp_channels.h new file mode 100644 index 000000000..7bd5652f7 --- /dev/null +++ b/ext/systemc/src/tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_req_rsp_channels/tlm_req_rsp_channels.h @@ -0,0 +1,155 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +#ifndef __TLM_REQ_RSP_CHANNELS_H__ +#define __TLM_REQ_RSP_CHANNELS_H__ + +#include "tlm_core/tlm_1/tlm_req_rsp/tlm_adapters/tlm_adapters.h" +#include "tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_fifo/tlm_fifo.h" +#include "tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_req_rsp_channels/tlm_put_get_imp.h" + +namespace tlm { + +template < typename REQ , typename RSP , + typename REQ_CHANNEL = tlm_fifo<REQ> , + typename RSP_CHANNEL = tlm_fifo<RSP> > + +class tlm_req_rsp_channel : public sc_core::sc_module +{ +public: + // uni-directional slave interface + + sc_core::sc_export< tlm_fifo_get_if< REQ > > get_request_export; + sc_core::sc_export< tlm_fifo_put_if< RSP > > put_response_export; + + // uni-directional master interface + + sc_core::sc_export< tlm_fifo_put_if< REQ > > put_request_export; + sc_core::sc_export< tlm_fifo_get_if< RSP > > get_response_export; + + // master / slave interfaces + + sc_core::sc_export< tlm_master_if< REQ , RSP > > master_export; + sc_core::sc_export< tlm_slave_if< REQ , RSP > > slave_export; + + + tlm_req_rsp_channel( int req_size = 1 , int rsp_size = 1 ) : + sc_core::sc_module( sc_core::sc_module_name( sc_core::sc_gen_unique_name("tlm_req_rsp_channel") ) ) , + request_fifo( req_size ) , + response_fifo( rsp_size ) , + master( request_fifo , response_fifo ) , + slave( request_fifo , response_fifo ) + { + + bind_exports(); + + } + + tlm_req_rsp_channel( sc_core::sc_module_name module_name , + int req_size = 1 , int rsp_size = 1 ) : + sc_core::sc_module( module_name ) , + request_fifo( req_size ) , + response_fifo( rsp_size ) , + master( request_fifo , response_fifo ) , + slave( request_fifo , response_fifo ) + { + + bind_exports(); + + } + +private: + void bind_exports() { + + put_request_export( request_fifo ); + get_request_export( request_fifo ); + + put_response_export( response_fifo ); + get_response_export( response_fifo ); + + master_export( master ); + slave_export( slave ); + + } + +protected: + REQ_CHANNEL request_fifo; + RSP_CHANNEL response_fifo; + + tlm_master_imp< REQ , RSP > master; + tlm_slave_imp< REQ , RSP > slave; +}; + +template < typename REQ , typename RSP , + typename REQ_CHANNEL = tlm_fifo<REQ> , + typename RSP_CHANNEL = tlm_fifo<RSP> > +class tlm_transport_channel : public sc_core::sc_module +{ +public: + + // master transport interface + + sc_core::sc_export< tlm_transport_if< REQ , RSP > > target_export; + + // slave interfaces + + sc_core::sc_export< tlm_fifo_get_if< REQ > > get_request_export; + sc_core::sc_export< tlm_fifo_put_if< RSP > > put_response_export; + + sc_core::sc_export< tlm_slave_if< REQ , RSP > > slave_export; + + tlm_transport_channel() : + sc_core::sc_module( sc_core::sc_module_name( sc_core::sc_gen_unique_name("transport_channel" ) ) ) , + target_export("target_export") , + req_rsp( "req_rsp" , 1 , 1 ) , + t2m("ts2m") + { + do_binding(); + } + + tlm_transport_channel( sc_core::sc_module_name nm ) : + sc_core::sc_module( nm ) , + target_export("target_export") , + req_rsp( "req_rsp" , 1 , 1 ) , + t2m("tsm" ) + { + do_binding(); + } + +private: + void do_binding() { + + target_export( t2m.target_export ); + + t2m.master_port( req_rsp.master_export ); + + get_request_export( req_rsp.get_request_export ); + put_response_export( req_rsp.put_response_export ); + slave_export( req_rsp.slave_export ); + + } + + tlm_req_rsp_channel< REQ , RSP , REQ_CHANNEL , RSP_CHANNEL > req_rsp; + tlm_transport_to_master< REQ , RSP > t2m; + +}; + +} // namespace tlm + +#endif diff --git a/ext/systemc/src/tlm_core/tlm_1/tlm_req_rsp/tlm_ports/tlm_event_finder.h b/ext/systemc/src/tlm_core/tlm_1/tlm_req_rsp/tlm_ports/tlm_event_finder.h new file mode 100644 index 000000000..60874ce91 --- /dev/null +++ b/ext/systemc/src/tlm_core/tlm_1/tlm_req_rsp/tlm_ports/tlm_event_finder.h @@ -0,0 +1,94 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +#ifndef __TLM_EVENT_FINDER_H__ +#define __TLM_EVENT_FINDER_H__ + +//#include <systemc> + +#include "tlm_core/tlm_1/tlm_req_rsp/tlm_1_interfaces/tlm_tag.h" + +namespace tlm { + +template <class IF , class T> +class tlm_event_finder_t +: public sc_core::sc_event_finder +{ +public: + + // constructor + + tlm_event_finder_t( const sc_core::sc_port_base& port_, + const sc_core::sc_event& (IF::*event_method_) ( tlm_tag<T> * ) const ) + : sc_core::sc_event_finder( port_ ), m_event_method( event_method_ ) + {} + + // destructor (does nothing) + + virtual ~tlm_event_finder_t() + {} +#if !(defined SYSTEMC_VERSION & SYSTEMC_VERSION <= 20050714) + virtual const sc_core::sc_event& find_event( sc_core::sc_interface* if_p = 0 ) const; +#else + virtual const sc_core::sc_event& find_event() const; +#endif + +private: + + const sc_core::sc_event& (IF::*m_event_method) ( tlm_tag<T> * ) const; + +private: + + // disabled + tlm_event_finder_t(); + tlm_event_finder_t( const tlm_event_finder_t<IF,T>& ); + tlm_event_finder_t<IF,T>& operator = ( const tlm_event_finder_t<IF,T>& ); +}; + + +#if !(defined SYSTEMC_VERSION & SYSTEMC_VERSION <= 20050714) +template <class IF , class T> +inline +const sc_core::sc_event& +tlm_event_finder_t<IF,T>::find_event( sc_core::sc_interface* if_p ) const +{ + const IF* iface = ( if_p ) ? dynamic_cast<const IF*>( if_p ) : + dynamic_cast<const IF*>( port().get_interface() ); + if( iface == 0 ) { + report_error( sc_core::SC_ID_FIND_EVENT_, "port is not bound" ); + } + return (const_cast<IF*>( iface )->*m_event_method) ( 0 ); +} +#else +template <class IF , class T> +inline +const sc_core::sc_event& +tlm_event_finder_t<IF,T>::find_event() const +{ + const IF* iface = dynamic_cast<const IF*>( port().get_interface() ); + if( iface == 0 ) { + report_error( sc_core::SC_ID_FIND_EVENT_, "port is not bound" ); + } + return (const_cast<IF*>( iface )->*m_event_method) ( 0 ); +} +#endif + +} // namespace tlm + +#endif diff --git a/ext/systemc/src/tlm_core/tlm_1/tlm_req_rsp/tlm_ports/tlm_nonblocking_port.h b/ext/systemc/src/tlm_core/tlm_1/tlm_req_rsp/tlm_ports/tlm_nonblocking_port.h new file mode 100644 index 000000000..0af1e3487 --- /dev/null +++ b/ext/systemc/src/tlm_core/tlm_1/tlm_req_rsp/tlm_ports/tlm_nonblocking_port.h @@ -0,0 +1,91 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +#ifndef __TLM_NONBLOCKING_PORT_H__ +#define __TLM_NONBLOCKING_PORT_H__ + +#include "tlm_core/tlm_1/tlm_req_rsp/tlm_1_interfaces/tlm_core_ifs.h" +#include "tlm_core/tlm_1/tlm_req_rsp/tlm_ports/tlm_event_finder.h" + +namespace tlm { + +template < typename T > +class tlm_nonblocking_get_port : +public sc_core::sc_port< tlm_nonblocking_get_if< T > , 1 > +{ +public: + typedef tlm_nonblocking_get_if<T> get_if_type; + + tlm_nonblocking_get_port( const char *port_name ) : + sc_core::sc_port< tlm_nonblocking_get_if< T > , 1 >( port_name ) {} + + sc_core::sc_event_finder& ok_to_get() const { + + return *new tlm_event_finder_t< get_if_type , T >( + *this, + &get_if_type::ok_to_get ); + + } + +}; + +template < typename T > +class tlm_nonblocking_peek_port : +public sc_core::sc_port< tlm_nonblocking_peek_if< T > , 1 > +{ +public: + typedef tlm_nonblocking_peek_if<T> peek_if_type; + + tlm_nonblocking_peek_port( const char *port_name ) : + sc_core::sc_port< tlm_nonblocking_peek_if< T > , 1 >( port_name ) {} + + sc_core::sc_event_finder& ok_to_peek() const { + + return *new tlm_event_finder_t< peek_if_type , T >( + *this, + &peek_if_type::ok_to_peek ); + + } + +}; + + +template < typename T > +class tlm_nonblocking_put_port : +public sc_core::sc_port< tlm_nonblocking_put_if< T > , 1 > +{ +public: + typedef tlm_nonblocking_put_if<T> put_if_type; + + tlm_nonblocking_put_port( const char *port_name ) : + sc_core::sc_port< tlm_nonblocking_put_if< T > , 1 >( port_name ) {} + + sc_core::sc_event_finder& ok_to_put() const { + + return *new tlm_event_finder_t< put_if_type , T >( + *this, + &put_if_type::ok_to_put ); + + } + +}; + +} // namespace tlm + +#endif diff --git a/ext/systemc/src/tlm_core/tlm_1/tlm_req_rsp/tlm_req_rsp.h b/ext/systemc/src/tlm_core/tlm_1/tlm_req_rsp/tlm_req_rsp.h new file mode 100644 index 000000000..88f1d0e8c --- /dev/null +++ b/ext/systemc/src/tlm_core/tlm_1/tlm_req_rsp/tlm_req_rsp.h @@ -0,0 +1,37 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +#ifndef __TLM_REQ_RSP_H__ +#define __TLM_REQ_RSP_H__ + +// The unannotated TLM interfaces + +#include "tlm_core/tlm_1/tlm_req_rsp/tlm_1_interfaces/tlm_core_ifs.h" +#include "tlm_core/tlm_1/tlm_req_rsp/tlm_1_interfaces/tlm_master_slave_ifs.h" + +// The channels : tlm_fifo, tlm_transport_channel and tlm_req_rsp_channel + +#include "tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_req_rsp_channels/tlm_req_rsp_channels.h" + +// Some non blocking ports to provide static sensitivity + +#include "tlm_core/tlm_1/tlm_req_rsp/tlm_ports/tlm_nonblocking_port.h" + + +#endif /* __TLM_REQ_RSP_H__ */ diff --git a/ext/systemc/src/tlm_core/tlm_2/README.txt b/ext/systemc/src/tlm_core/tlm_2/README.txt new file mode 100644 index 000000000..cb02af2d8 --- /dev/null +++ b/ext/systemc/src/tlm_core/tlm_2/README.txt @@ -0,0 +1,111 @@ +TLM-2.0 interoperability layer header files +=========================================== + +Dir: include/tlm_core/tlm_2/ + +SubDirs: tlm_2_interfaces/ + tlm_generic_payload/ + tlm_quantum/ + tlm_sockets + +Files: README.txt + tlm_version.h + + +Comments +======== + +User code should only #include the tlm or tlm.h header file in the include/ +directory and avoid including any of the include files in this directory +directly. All objects defined in this file hierarchy are in the tlm namespace. + +tlm_version.h contains the definitions for the version string and integer values + +The header files are organizated, by subdirectory, as follows: + + +tlm_2_interfaces/ +----------------- + +Contains the TLM-2.0 core interfaces + +Files: + tlm_2_interfaces.h (includes the other header files in this directory ) + tlm_fw_bw_ifs.h (defines the TLM 2.0 interface API's: + tlm_fw_nonblocking_transport_if + tlm_bw_nonblocking_transport_if + tlm_blocking_transport_if + tlm_fw_direct_mem_if + tlm_bw_direct_mem_if + tlm_transport_dbg_if + the enumeration type + tlm_sync_enum + and the TLM 2.0 standard interfaces using the API's + tlm_fw_transport_if + tlm_bw_transport_if ) + tlm_dmi.h (defines tlm_dmi) + + +tlm_generic_payload/ +-------------------- + +Contains the TLM-2.0 generic payload and associated classes and helper functions + +Files: + tlm_generic_payload.h ( includes the other header files in this directory) + tlm_gp.h (defines the TLM 2.0 generic payload classes: + tlm_generic_payload + tlm_extension + tlm_extension_base + tlm_mm_interface + and the enumeration types + tlm_command + tlm_response_status ) + tlm_array.h (defines array class used by the extention + mechanism ) + tlm_endian_conv.h (defines the implementation for the endianness + helper functions: + tlm_to_hostendian_generic() + tlm_from_hostendian_generic() + tlm_to_hostendian_word() + tlm_from_hostendian_word() + tlm_to_hostendian_aligned() + tlm_from_hostendian_aligned() + tlm_to_hostendian_single() + tlm_from_hostendian_single() ) + + tlm_helpers.h (defines the helper functions to determine the + hostendianness: + get_host_endianness() + host_has_little_endianness() + has_host_endianness() + and defines the enumeration type: + tlm_endianness + tlm_phase.h (defines tlm_phase as an extendable enum type) + + +tlm_sockets/ +------------ + +Contains the standard TLM-2.0 initiator and target sockets (which are used as +the base classes for the convenience sockets in tlm_utils) + +Files: + tlm_sockets.h (includes the other header files in this directory) + tlm_initiator_socket.h (defines the initiator sockets: + tlm_initiator_socket_base + tlm_initiator_socket_b + tlm_initiator_socket + tlm_target_socket.h (defines the target sockets: + tlm_target_socket_base + tlm_target_socket_b + tlm_target_socket + + +tlm_quantum/ +------------ +This contains the global quantum. (The quantum keeper is in tlm_utils) + +Files: + tlm_quantum.h ( includes the other header file in this directory ) + tlm_global_quantum.h ( defines tlm_global_quantum ) diff --git a/ext/systemc/src/tlm_core/tlm_2/tlm_2_interfaces/tlm_2_interfaces.h b/ext/systemc/src/tlm_core/tlm_2/tlm_2_interfaces/tlm_2_interfaces.h new file mode 100644 index 000000000..8a0c543c8 --- /dev/null +++ b/ext/systemc/src/tlm_core/tlm_2/tlm_2_interfaces/tlm_2_interfaces.h @@ -0,0 +1,27 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +#ifndef __TLM_2_INTERFACES_H__ +#define __TLM_2_INTERFACES_H__ + +#include "tlm_core/tlm_2/tlm_2_interfaces/tlm_dmi.h" +#include "tlm_core/tlm_2/tlm_2_interfaces/tlm_fw_bw_ifs.h" + +#endif + diff --git a/ext/systemc/src/tlm_core/tlm_2/tlm_2_interfaces/tlm_dmi.h b/ext/systemc/src/tlm_core/tlm_2/tlm_2_interfaces/tlm_dmi.h new file mode 100644 index 000000000..d7c3304eb --- /dev/null +++ b/ext/systemc/src/tlm_core/tlm_2/tlm_2_interfaces/tlm_dmi.h @@ -0,0 +1,114 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +#ifndef __TLM_DMI_H__ +#define __TLM_DMI_H__ + +#include <systemc> + +namespace tlm { + +class tlm_dmi +{ + public: + + // Enum for indicating the access granted to the initiator. + // The initiator uses gp.m_command to indicate it intention (read/write) + // The target is allowed to promote DMI_ACCESS_READ or DMI_ACCESS_WRITE + // requests to dmi_access_read_write. + + enum dmi_access_e + { DMI_ACCESS_NONE = 0x00 // no access + , DMI_ACCESS_READ = 0x01 // read access + , DMI_ACCESS_WRITE = 0x02 // write access + , DMI_ACCESS_READ_WRITE = DMI_ACCESS_READ | DMI_ACCESS_WRITE // read/write access + }; + + tlm_dmi (void) + { + init(); + } + + void init (void) + { + m_dmi_ptr = 0x0; + m_dmi_start_address = 0x0; + m_dmi_end_address = (sc_dt::uint64)(-1); + m_dmi_access = DMI_ACCESS_NONE; + m_dmi_read_latency = sc_core::SC_ZERO_TIME; + m_dmi_write_latency = sc_core::SC_ZERO_TIME; + } + + unsigned char* get_dmi_ptr (void) const {return m_dmi_ptr;} + sc_dt::uint64 get_start_address (void) const {return m_dmi_start_address;} + sc_dt::uint64 get_end_address (void) const {return m_dmi_end_address;} + sc_core::sc_time get_read_latency (void) const {return m_dmi_read_latency;} + sc_core::sc_time get_write_latency (void) const {return m_dmi_write_latency;} + dmi_access_e get_granted_access (void) const {return m_dmi_access;} + bool is_none_allowed (void) const {return m_dmi_access == DMI_ACCESS_NONE;} + bool is_read_allowed (void) const {return (m_dmi_access & DMI_ACCESS_READ) == DMI_ACCESS_READ;} + bool is_write_allowed (void) const {return (m_dmi_access & DMI_ACCESS_WRITE) == DMI_ACCESS_WRITE;} + bool is_read_write_allowed (void) const {return (m_dmi_access & DMI_ACCESS_READ_WRITE) == DMI_ACCESS_READ_WRITE;} + + void set_dmi_ptr (unsigned char* p) {m_dmi_ptr = p;} + void set_start_address (sc_dt::uint64 addr) {m_dmi_start_address = addr;} + void set_end_address (sc_dt::uint64 addr) {m_dmi_end_address = addr;} + void set_read_latency (sc_core::sc_time t) {m_dmi_read_latency = t;} + void set_write_latency (sc_core::sc_time t) {m_dmi_write_latency = t;} + void set_granted_access (dmi_access_e a) {m_dmi_access = a;} + void allow_none (void) {m_dmi_access = DMI_ACCESS_NONE;} + void allow_read (void) {m_dmi_access = DMI_ACCESS_READ;} + void allow_write (void) {m_dmi_access = DMI_ACCESS_WRITE;} + void allow_read_write (void) {m_dmi_access = DMI_ACCESS_READ_WRITE;} + + private: + + // If the forward call is successful, the target returns the dmi_ptr, + // which must point to the data element corresponding to the + // dmi_start_address. The data is organized as a byte array with the + // endianness of the target (endianness member of the tlm_dmi struct). + + unsigned char* m_dmi_ptr; + + // The absolute start and end addresses of the DMI region. If the decoder + // logic in the interconnect changes the address field e.g. by masking, the + // interconnect is responsible to transform the relative address back to an + // absolute address again. + + sc_dt::uint64 m_dmi_start_address; + sc_dt::uint64 m_dmi_end_address; + + // Granted access + + dmi_access_e m_dmi_access; + + // These members define the latency of read/write transactions. The + // initiator must initialize these members to zero before requesting a + // dmi pointer, because both the interconnect as well as the target can + // add to the total transaction latency. + // Depending on the 'type' attribute only one, or both of these attributes + // will be valid. + + sc_core::sc_time m_dmi_read_latency; + sc_core::sc_time m_dmi_write_latency; +}; + +} // namespace tlm + +#endif /* TLM_DMI_HEADER */ diff --git a/ext/systemc/src/tlm_core/tlm_2/tlm_2_interfaces/tlm_fw_bw_ifs.h b/ext/systemc/src/tlm_core/tlm_2/tlm_2_interfaces/tlm_fw_bw_ifs.h new file mode 100644 index 000000000..59e81c658 --- /dev/null +++ b/ext/systemc/src/tlm_core/tlm_2/tlm_2_interfaces/tlm_fw_bw_ifs.h @@ -0,0 +1,223 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +#ifndef __TLM_FW_BW_IFS_H__ +#define __TLM_FW_BW_IFS_H__ + +#include <systemc> +#include "tlm_core/tlm_2/tlm_generic_payload/tlm_generic_payload.h" +#include "tlm_core/tlm_2/tlm_2_interfaces/tlm_dmi.h" + +namespace tlm { + +enum tlm_sync_enum { TLM_ACCEPTED, TLM_UPDATED, TLM_COMPLETED }; + +//////////////////////////////////////////////////////////////////////////// +// Basic interfaces +//////////////////////////////////////////////////////////////////////////// +template <typename TRANS = tlm_generic_payload, + typename PHASE = tlm_phase> +class tlm_fw_nonblocking_transport_if : public virtual sc_core::sc_interface { +public: + virtual tlm_sync_enum nb_transport_fw(TRANS& trans, + PHASE& phase, + sc_core::sc_time& t) = 0; +}; + +template <typename TRANS = tlm_generic_payload, + typename PHASE = tlm_phase> +class tlm_bw_nonblocking_transport_if : public virtual sc_core::sc_interface { +public: + virtual tlm_sync_enum nb_transport_bw(TRANS& trans, + PHASE& phase, + sc_core::sc_time& t) = 0; +}; + +template <typename TRANS = tlm_generic_payload> +class tlm_blocking_transport_if : public virtual sc_core::sc_interface { +public: + virtual void b_transport(TRANS& trans, + sc_core::sc_time& t) = 0; +}; + +////////////////////////////////////////////////////////////////////////// +// DMI interfaces for getting and invalidating DMI pointers: +////////////////////////////////////////////////////////////////////////// + +// The semantics of the forward interface are as follows: +// +// - An initiator that wants to get direct access to a target's memory region +// can call the get_direct_mem_ptr method with the 'trans' parameter set to +// the address that it wants to gain access to. It sets the trans.m_command +// to specify if the initiator intended use (read or write) +// to the target's DMI region. The initiator is responsible for calling the +// method with a freshly initialized tlm_dmi object either by using a newly +// constructed object, or by calling an existing object's init() method. +// - Although a reference to a complete 'TRANS' type is passed to the get_ +// direct_mem_ptr call, only the address command, and extension fields are of +// interest in most cases. +// - Read and write ranges are not necessarily identical. If they are, a target +// can specify that the range is valid for all accesses with the tlm_data +// m_type attribute in the. +// - The interconnect, if any, needs to decode the address and forward the +// call to the corresponding target. It needs to handle the address exactly +// as the target would expect on a transaction call, e.g. mask the address +// according to the target's address width. +// - If the target supports DMI access for the given address, it sets the +// data fields in the DMI struct and returns true. +// - If a target does not support DMI access it needs to return false. +// The target can either set the correct address range in the DMI struct +// to indicate the memory region where DMI is disallowed, or it can specify +// the complete address range if it doesn't know it's memory range. In this +// case the interconnect is responsible for clipping the address range to +// the correct range that the target serves. +// - The interconnect must always translate the addresses to the initiator's +// address space. This must be the inverse operation of what the +// interconnect needed to do when forwarding the call. In case the +// component wants to change any member of the tlm_dmi object, e.g. for +// its own latency to the target's latency, it must only do so *after* the +// target has been called. The target is always allowed to overwrite all +// values in the tlm_dmi object. +// - In case the slave returned with an invalid region the bus/interconnect +// must fill in the complete address region for the particular slave in the +// DMI data structure. +// +// DMI hint optimization: +// +// Initiators may use the DMI hint in the tlm_generic_payload to avoid +// unnecessary DMI attempts. The recommended sequence of interface +// method calls would be: +// +// - The initiator first tries to check if it has a valid DMI region for the +// address that it wants to access next. +// - If not, it performs a normal transaction. +// - If the DMI hint in this transaction is true, the initiator can try and +// get the DMI region. +// +// Note that the DMI hint optimization is completely optional and every +// initiator model is free to ignore the DMI hint. However, a target is +// required to set the DMI hint to true if a DMI request on the given address +// with the given transaction type (read or write) would have succeeded. + +template <typename TRANS = tlm_generic_payload> +class tlm_fw_direct_mem_if : public virtual sc_core::sc_interface +{ +public: + virtual bool get_direct_mem_ptr(TRANS& trans, + tlm_dmi& dmi_data) = 0; +}; + +// The semantics of the backwards call is as follows: +// +// - An interconnect component or a target is required to invalidate all +// affected DMI regions whenever any change in the regions take place. +// The exact rule is that a component must invalidate all those DMI regions +// that it already reported, if it would answer the same DMI request +// with any member of the tlm_dmi data structure set differently. +// - An interconnect component must forward the invalidate_direct_mem_ptr call +// to all initiators that could potentially have a DMI pointer to the region +// specified in the method arguments. A safe implementation is to call +// every attached initiator. +// - An interconnect component must transform the address region of an +// incoming invalidate_direct_mem_ptr to the corresponding address space +// for the initiators. Basically, this is the same address transformation +// that the interconnect does on the DMI ranges on the forward direction. +// - Each initiator must check if it has a pointer to the given region and +// throw this away. It is recommended that the initiator throws away all DMI +// regions that have any overlap with the given regions, but this is not a +// hard requirement. +// +// - A full DMI pointer invalidation, e.g. for a bus remap can be signaled +// by setting the range: 0x0 - 0xffffffffffffffffull = (sc_dt::uint64)-1 +// - An initiator must throw away all DMI pointers in this case. +// +// - Under no circumstances a model is allowed to call the get_direct_mem_ptr +// from within the invalidate_direct_mem_ptr method, directly or indirectly. +// +class tlm_bw_direct_mem_if : public virtual sc_core::sc_interface +{ +public: + virtual void invalidate_direct_mem_ptr(sc_dt::uint64 start_range, + sc_dt::uint64 end_range) = 0; +}; + +///////////////////////////////////////////////////////////////////// +// debug interface for memory access +///////////////////////////////////////////////////////////////////// +// +// This interface can be used to gain access to a targets memory or registers +// in a non-intrusive manner. No side effects, waits or event notifications +// must happen in the course of the method. +// +// Semantics: +// - The initiator calls the transport_dbg method with transaction 'trans' as +// argument. The commonly used parts of trans for debug are: +// . address: The start address that it wants to peek or poke. +// . length: The number of bytes that it requests to read or write. +// . command: Indicates a read or write access. +// . data: A pointer to the initiator-allocated data buffer, which must +// be at least num_bytes large. The data is always organized in +// the endianness of the machine. +// . extensions: Any extension that could affect the transaction. +// - The interconnect, if any, will decode the address and forward the call to +// the appropriate target. +// - The target must return the number of successfully transmitted bytes, where +// this number must be <= num_bytes. Thus, a target can safely return 0 if it +// does not support debug transactions. +// +template <typename TRANS = tlm_generic_payload> +class tlm_transport_dbg_if : public virtual sc_core::sc_interface +{ +public: + // The return value of defines the number of bytes successfully + // transferred. + virtual unsigned int transport_dbg(TRANS& trans) = 0; +}; + +//////////////////////////////////////////////////////////////////////////// +// Combined interfaces +//////////////////////////////////////////////////////////////////////////// + +struct tlm_base_protocol_types +{ + typedef tlm_generic_payload tlm_payload_type; + typedef tlm_phase tlm_phase_type; +}; + +// The forward interface: +template <typename TYPES = tlm_base_protocol_types> +class tlm_fw_transport_if + : public virtual tlm_fw_nonblocking_transport_if<typename TYPES::tlm_payload_type, + typename TYPES::tlm_phase_type> + , public virtual tlm_blocking_transport_if<typename TYPES::tlm_payload_type> + , public virtual tlm_fw_direct_mem_if<typename TYPES::tlm_payload_type> + , public virtual tlm_transport_dbg_if<typename TYPES::tlm_payload_type> +{}; + +// The backward interface: +template <typename TYPES = tlm_base_protocol_types> +class tlm_bw_transport_if + : public virtual tlm_bw_nonblocking_transport_if<typename TYPES::tlm_payload_type, + typename TYPES::tlm_phase_type> + , public virtual tlm_bw_direct_mem_if +{}; + +} // namespace tlm + +#endif /* __TLM_FW_BW_IFS_H__ */ diff --git a/ext/systemc/src/tlm_core/tlm_2/tlm_generic_payload/tlm_array.h b/ext/systemc/src/tlm_core/tlm_2/tlm_generic_payload/tlm_array.h new file mode 100644 index 000000000..297dd3fe4 --- /dev/null +++ b/ext/systemc/src/tlm_core/tlm_2/tlm_generic_payload/tlm_array.h @@ -0,0 +1,125 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +#ifndef __TLM_ARRAY_H__ +#define __TLM_ARRAY_H__ + +#include <systemc> +#include <exception> +// unused for the time being: #include <cassert> + +namespace tlm { + +// +// To the LRM writer: the below class is an artifact of the tlm_generic_payload +// implementation and not part of the core TLM standard +// + + +// This implements a lean and fast array class that supports array expansion on +// request. The class is primarily used in the tlm_generic_payload class for +// storing the pointers to the extensions. +// +// Individual array elements can be accessed through the [] operators, and the +// array length is returned by the size() method. +// +// The size can be dynamically expanded using the expand(uint) method. There +// is no shrinking mechanism implemented, because the extension mechanism +// does not require this feature. Bear in mind that calling the expand method +// may invalidate all direct pointers into the array. + + +//the tlm_array shall always be used with T=tlm_extension_base* +template <typename T> +class tlm_array + : private std::vector<T> +{ + typedef std::vector<T> base_type; + typedef typename base_type::size_type size_type; +public: + + // constructor: + tlm_array(size_type size = 0, T const & default_value = T() ) + : base_type(size,default_value) + , m_entries() + , m_default(default_value) + { + //m_entries.reserve(size); // optional + } + + // copy constructor: + // tlm_array(const tlm_array& orig) = default; + + // destructor: + // ~tlm_array() = default; + + // operators for dereferencing: + using base_type::operator[]; + + // array size: + using base_type::size; + + // expand the array if needed: + void expand(size_type new_size) + { + if (new_size > size()) + { + base_type::resize(new_size); + //m_entries.reserve(new_size); // optional + } + } + + static const char* const kind_string; + const char* kind() const { return kind_string; } + + //this function shall get a pointer to a array slot + // it stores this slot in a cache of active slots + void insert_in_cache(T* p) + { + //assert( (p-&(*this)[0]) < size() ); + m_entries.push_back( p-&(*this)[0] ); + } + + //this functions clears all active slots of the array + void free_entire_cache() + { + while(m_entries.size()) + { + if ((*this)[m_entries.back()]) //we make sure no one cleared the slot manually + (*this)[m_entries.back()]->free();//...and then we call free on the content of the slot + (*this)[m_entries.back()]=0; //afterwards we set the slot to NULL + m_entries.pop_back(); + } + } + +protected: + std::vector<size_type> m_entries; + T m_default; + + // disabled: + tlm_array& operator=(const tlm_array<T>&); +}; + + +template <typename T> +const char* const tlm_array<T>::kind_string = "tlm_array"; + +} // namespace tlm + +#endif /* __TLM_ARRAY_H__ */ diff --git a/ext/systemc/src/tlm_core/tlm_2/tlm_generic_payload/tlm_endian_conv.h b/ext/systemc/src/tlm_core/tlm_2/tlm_generic_payload/tlm_endian_conv.h new file mode 100644 index 000000000..648115554 --- /dev/null +++ b/ext/systemc/src/tlm_core/tlm_2/tlm_generic_payload/tlm_endian_conv.h @@ -0,0 +1,792 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + + +#ifndef __TLM_ENDIAN_CONV_H__ +#define __TLM_ENDIAN_CONV_H__ + +#include <systemc> +#include "tlm_core/tlm_2/tlm_generic_payload/tlm_gp.h" + + +namespace tlm { + + +/* +Tranaction-Level Modelling +Endianness Helper Functions + +DESCRIPTION +A set of functions for helping users to get the endianness +right in their TLM models of system initiators. These functions are +for use within an initiator. They can not be used as-is outside +an initiator because the extension used to store context will not work +if cascaded, and they do not respect the generic payload mutability +rules. However this code may be easily copied and adapted for use +in bridges, etc.. + +These functions are not compulsory. There are other legitimate ways to +achieve the same functionality. If extra information is available at +compile time about the nature of an initiator's transactions, this can +be exploited to accelerate simulations by creating further functions +similar to those in this file. In general a functional transaction can be +described in more than one way by a TLM-2 GP object. + +The functions convert the endianness of a GP object, either on request or +response. They should only be used when the initiator's endianness +does not match the host's endianness. They assume 'arithmetic mode' +meaning that within a data word the byte order is always host-endian. +For non-arithmetic mode initiators they can be used with a data word +size of 1 byte. + +All the functions are templates, for example: + +template<class DATAWORD> inline void + to_hostendian_generic(tlm_generic_payload *txn, int sizeof_databus) + +The template parameter provides the data word width. Having this as a class +makes it easy to use it for copy and swap operations within the functions. +If the assignment operator for this class is overloaded, the endianness +conversion function may not have the desired effect. + +All the functions have the same signature except for different names. + +The principle is that a function to_hostendian_convtype() is called when the +initiator-endian transaction is created, and the matching function +from_hostendian_convtype() is called when the transaction is completed, for +example before read data can be used. In some cases the from_ function is +redundant but an empty function is provided anyway. It is strongly +recommended that the from_ function is called, in case it ceases to be +redundant in future versions of this code. + +No context needs to be managed outside the two functions, except that they +must be called with the same template parameter and the same bus width. + +For initiator models that can not easily manage this context information, +a single entry point for the from_ function is provided, which will be +a little slower than calling the correct from_ function directly, as +it can not be inlined. + +All functions assume power-of-2 bus and data word widths. + +Functions offered: + +0) A pair of functions that work for almost all TLM2 GP transactions. The +only limitations are that data and bus widths should be powers of 2, and that +the data length should be an integer number of streaming widths and that the +streaming width should be an integer number of data words. +These functions always allocate new data and byte enable buffers and copy +data one byte at a time. + tlm_to_hostendian_generic(tlm_generic_payload *txn, int sizeof_databus) + tlm_from_hostendian_generic(tlm_generic_payload *txn, int sizeof_databus) + +1) A pair of functions that work for all transactions regardless of data and +bus data sizes and address alignment except for the the following +limitations: +- byte-enables are supported only when byte-enable granularity is no finer +than the data word (every data word is wholly enabled or wholly disabled) +- byte-enable-length is not supported (if byte enables are present, the byte +enable length must be equal to the data length). +- streaming width is not supported +- data word wider than bus word is not supported +A new data buffer and a new byte enable buffer are always allocated. Byte +enables are assumed to be needed even if not required for the original +(unconverted) transaction. Data is copied to the new buffer on request +(for writes) or on response (for reads). Copies are done word-by-word +where possible. + tlm_to_hostendian_word(tlm_generic_payload *txn, int sizeof_databus) + tlm_from_hostendian_word(tlm_generic_payload *txn, int sizeof_databus) + +2) If the original transaction is both word and bus-aligned then this pair of +functions can be used. It will complete faster than the generic function +because the data reordering function is much simpler and no address +conversion is required. +The following limitations apply: +- byte-enables are supported only when byte-enable granularity is no finer +than the data word (every data word is wholly enabled or wholly disabled) +- byte-enable-length is not supported (if byte enables are present, the byte +enable length must be equal to the data length). +- streaming width is not supported +- data word wider than bus word is not supported +- the transaction must be an integer number of bus words +- the address must be aligned to the bus width + tlm_to_hostendian_aligned(tlm_generic_payload *txn, int sizeof_databus) + tlm_from_hostendian_aligned(tlm_generic_payload *txn, int sizeof_databus) + +3) For single word transactions that don't cross a bus word boundary it +is always safe to work in-place and the conversion is very simple. Again, +streaming width and byte-enable length are not supported, and byte-enables +may not changes within a data word. + tlm_to_hostendian_single(tlm_generic_payload *txn, int sizeof_databus) + tlm_from_hostendian_single(tlm_generic_payload *txn, int sizeof_databus) + +4) A single entry point for accessing the correct from_ function without +needing to store context. + tlm_from_hostendian(tlm_generic_payload *txn) +*/ + + + +#ifndef uchar +#define uchar unsigned char +#else +#define TLM_END_CONV_DONT_UNDEF_UCHAR +#endif + + +/////////////////////////////////////////////////////////////////////////////// +// Generic Utilities + +class tlm_endian_context; +class tlm_endian_context_pool { + public: + tlm_endian_context *first; + inline tlm_endian_context_pool(); + inline ~tlm_endian_context_pool(); + inline tlm_endian_context *pop(); + inline void push(tlm_endian_context *c); +}; +static tlm_endian_context_pool global_tlm_endian_context_pool; + +// an extension to keep the information needed for reconversion of response +class tlm_endian_context : public tlm_extension<tlm_endian_context> { + public: + tlm_endian_context() : dbuf_size(0), bebuf_size(0) {} + ~tlm_endian_context() { + if(dbuf_size > 0) delete [] new_dbuf; + if(bebuf_size > 0) delete [] new_bebuf; + } + + sc_dt::uint64 address; // used by generic, word + sc_dt::uint64 new_address; // used by generic + uchar *data_ptr; // used by generic, word, aligned + uchar *byte_enable; // used by word + int length; // used by generic, word + int stream_width; // used by generic + + // used by common entry point on response + void (*from_f)(tlm_generic_payload *txn, unsigned int sizeof_databus); + int sizeof_databus; + + // reordering buffers for data and byte-enables + uchar *new_dbuf, *new_bebuf; + int dbuf_size, bebuf_size; + void establish_dbuf(int len) { + if(len <= dbuf_size) return; + if(dbuf_size > 0) delete [] new_dbuf; + new_dbuf = new uchar[len]; + dbuf_size = len; + } + void establish_bebuf(int len) { + if(len <= bebuf_size) return; + if(bebuf_size > 0) delete [] new_bebuf; + new_bebuf = new uchar[len]; + bebuf_size = len; + } + + // required for extension management + void free() { + global_tlm_endian_context_pool.push(this); + } + tlm_extension_base* clone() const {return 0;} + void copy_from(tlm_extension_base const &) {return;} + + // for pooling + tlm_endian_context *next; +}; +// Assumptions about transaction contexts: +// 1) only the address attribute of a transaction +// is mutable. all other attributes are unchanged from the request to +// response side conversion. +// 2) the conversion functions in this file do not respect the mutability +// rules and do not put the transaction back into its original state after +// completion. so if the initiator has any cleaning up to do (eg of byte +// enable buffers), it needs to store its own context. the transaction +// returned to the initiator may contain pointers to data and byte enable +// that can/must not be deleted. +// 3) the conversion functions in this file use an extension to store +// context information. they do not remove this extension. the initiator +// should not remove it unless it deletes the generic payload +// object. + +inline tlm_endian_context *establish_context(tlm_generic_payload *txn) { + tlm_endian_context *tc = txn->get_extension<tlm_endian_context>(); + if(tc == 0) { + tc = global_tlm_endian_context_pool.pop(); + txn->set_extension(tc); + } + return tc; +} + +inline tlm_endian_context_pool::tlm_endian_context_pool() : first(0) {} + +inline tlm_endian_context_pool::~tlm_endian_context_pool() { + while(first != 0) { + tlm_endian_context *next = first->next; + delete first; + first = next; + } +} + +tlm_endian_context *tlm_endian_context_pool::pop() { + if(first == 0) return new tlm_endian_context; + tlm_endian_context *r = first; + first = first->next; + return r; +} + +void tlm_endian_context_pool::push(tlm_endian_context *c) { + c->next = first; + first = c; +} + + +// a set of constants for efficient filling of byte enables +template<class D> class tlm_bool { + public: + static D TLM_TRUE; + static D TLM_FALSE; + static D make_uchar_array(uchar c) { + D d; + uchar *tmp = (uchar *)(&d); + for(ptrdiff_t i=0; i!=sizeof(D); i++) tmp[i] = c; // 64BITFIX negligable risk but easy fix // + return d; + } + // also provides an syntax-efficient tester, using a + // copy constuctor and an implicit cast to boolean + tlm_bool(D &d) : b(*((uchar*)&d) != TLM_BYTE_DISABLED) {} + operator bool() const {return b;} + private: + bool b; +}; + +template<class D> D tlm_bool<D>::TLM_TRUE + = tlm_bool<D>::make_uchar_array(TLM_BYTE_ENABLED); +template<class D> D tlm_bool<D>::TLM_FALSE + = tlm_bool<D>::make_uchar_array(TLM_BYTE_DISABLED); + + + +/////////////////////////////////////////////////////////////////////////////// +// function set (0): Utilities +inline void copy_db0(uchar *src1, uchar *src2, uchar *dest1, uchar *dest2) { + *dest1 = *src1; + *dest2 = *src2; +} + +inline void copy_dbtrue0(uchar *src1, uchar *src2, uchar *dest1, uchar *dest2) { + *dest1 = *src1; + *dest2 = TLM_BYTE_ENABLED; +} + +inline void copy_btrue0(uchar *src1, uchar *src2, uchar *dest1, uchar *dest2) { + *dest2 = TLM_BYTE_ENABLED; +} + +inline void copy_b0(uchar *src1, uchar *src2, uchar *dest1, uchar *dest2) { + *dest2 = *src2; +} + +inline void copy_dbyb0(uchar *src1, uchar *src2, uchar *dest1, uchar *dest2) { + if(*dest2 == TLM_BYTE_ENABLED) *src1 = *dest1; +} + + +template<class D, + void COPY(uchar *he_d, uchar *he_b, uchar *ie_d, uchar *ie_b)> +inline void loop_generic0(int new_len, int new_stream_width, + int orig_stream_width, int sizeof_databus, + sc_dt::uint64 orig_start_address, sc_dt::uint64 new_start_address, int be_length, + uchar *ie_data, uchar *ie_be, uchar *he_data, uchar *he_be) { + + for(int orig_sword = 0, new_sword = 0; new_sword < new_len; + new_sword += new_stream_width, orig_sword += orig_stream_width) { + + sc_dt::uint64 ie_addr = orig_start_address; + for(int orig_dword = orig_sword; + orig_dword < orig_sword + orig_stream_width; orig_dword += sizeof(D)) { + + for(int curr_byte = orig_dword + sizeof(D) - 1; + curr_byte >= orig_dword; curr_byte--) { + + ptrdiff_t he_index = ((ie_addr++) ^ (sizeof_databus - 1)) + - new_start_address + new_sword; // 64BITFIX // + COPY(ie_data+curr_byte, + ie_be+(curr_byte % be_length), // 64BITRISK no risk of overflow, always positive // + he_data+he_index, he_be+he_index); + } + } + } +} + + +/////////////////////////////////////////////////////////////////////////////// +// function set (0): Response +template<class DATAWORD> inline void +tlm_from_hostendian_generic(tlm_generic_payload *txn, unsigned int sizeof_databus) { + if(txn->is_read()) { + tlm_endian_context *tc = txn->template get_extension<tlm_endian_context>(); + loop_generic0<DATAWORD, ©_dbyb0>(txn->get_data_length(), + txn->get_streaming_width(), tc->stream_width, sizeof_databus, tc->address, + tc->new_address, txn->get_data_length(), tc->data_ptr, 0, txn->get_data_ptr(), + txn->get_byte_enable_ptr()); + } +} + + +/////////////////////////////////////////////////////////////////////////////// +// function set (0): Request +template<class DATAWORD> inline void +tlm_to_hostendian_generic(tlm_generic_payload *txn, unsigned int sizeof_databus) { + tlm_endian_context *tc = establish_context(txn); + tc->from_f = &(tlm_from_hostendian_generic<DATAWORD>); + tc->sizeof_databus = sizeof_databus; + + // calculate new size: nr stream words multiplied by big enough stream width + int s_width = txn->get_streaming_width(); + int length = txn->get_data_length(); + if(s_width >= length) s_width = length; + int nr_stream_words = length/s_width; + + // find out in which bus word the stream word starts and ends + sc_dt::uint64 new_address = (txn->get_address() & ~(sizeof_databus - 1)); + sc_dt::uint64 end_address = ((txn->get_address() + s_width - 1) + & ~(sizeof_databus - 1)); + + int new_stream_width = end_address - new_address + sizeof_databus; + int new_length = new_stream_width * nr_stream_words; + + // store context + tc->data_ptr = txn->get_data_ptr(); + tc->address = txn->get_address(); + tc->new_address = new_address; + tc->stream_width = s_width; + uchar *orig_be = txn->get_byte_enable_ptr(); + int orig_be_length = txn->get_byte_enable_length(); + + // create data and byte-enable buffers + txn->set_address(new_address); + tc->establish_dbuf(new_length); + txn->set_data_ptr(tc->new_dbuf); + tc->establish_bebuf(new_length); + txn->set_byte_enable_ptr(tc->new_bebuf); + memset(txn->get_byte_enable_ptr(), TLM_BYTE_DISABLED, new_length); + txn->set_streaming_width(new_stream_width); + txn->set_data_length(new_length); + txn->set_byte_enable_length(new_length); + + // copy data and/or byte enables + if(txn->is_write()) { + if(orig_be == 0) { + loop_generic0<DATAWORD, ©_dbtrue0>(new_length, + new_stream_width, s_width, sizeof_databus, tc->address, + new_address, new_length, tc->data_ptr, 0, txn->get_data_ptr(), + txn->get_byte_enable_ptr()); + } else { + loop_generic0<DATAWORD, ©_db0>(new_length, + new_stream_width, s_width, sizeof_databus, tc->address, + new_address, orig_be_length, tc->data_ptr, orig_be, txn->get_data_ptr(), + txn->get_byte_enable_ptr()); + } + } else { // read transaction + if(orig_be == 0) { + loop_generic0<DATAWORD, ©_btrue0>(new_length, + new_stream_width, s_width, sizeof_databus, tc->address, + new_address, new_length, tc->data_ptr, 0, txn->get_data_ptr(), + txn->get_byte_enable_ptr()); + } else { + loop_generic0<DATAWORD, ©_b0>(new_length, + new_stream_width, s_width, sizeof_databus, tc->address, + new_address, orig_be_length, tc->data_ptr, orig_be, txn->get_data_ptr(), + txn->get_byte_enable_ptr()); + } + } +} + + + +/////////////////////////////////////////////////////////////////////////////// +// function set (1): Utilities +template<class D> +inline void copy_d1(uchar *src1, uchar *src2, uchar *dest1, uchar *dest2) { + *((D *)dest1) = *((D *)src1); + *((D *)dest2) = tlm_bool<D>::TLM_TRUE; +} + +template<class D> +inline void copy_db1(uchar *src1, uchar *src2, uchar *dest1, uchar *dest2) { + *((D *)dest1) = *((D *)src1); + *((D *)dest2) = *((D *)src2); +} + +template<class D> +inline void true_b1(uchar *src1, uchar *src2, uchar *dest1, uchar *dest2) { + *((D *)dest2) = tlm_bool<D>::TLM_TRUE; +} + +template<class D> +inline void copy_b1(uchar *src1, uchar *src2, uchar *dest1, uchar *dest2) { + *((D *)dest2) = *((D *)src2); +} + +template<class D> +inline void copy_dbyb1(uchar *src1, uchar *src2, uchar *dest1, uchar *dest2) { + if(*src2 != TLM_BYTE_DISABLED) *((D *)src1) = *((D *)dest1); +} + +template<class D> +inline void copy_dbytrue1(uchar *src1, uchar *src2, uchar *dest1, uchar *dest2) { + *((D *)src1) = *((D *)dest1); +} + +template<class D> inline void false_b1(uchar *dest1) { + *((D *)dest1) = tlm_bool<D>::TLM_FALSE; +} + +template<class D> inline void no_b1(uchar *dest1) { +} + +template<class D, + void COPY(uchar *src1, uchar *src2, uchar *dest1, uchar *dest2), + void COPYuchar(uchar *src1, uchar *src2, uchar *dest1, uchar *dest2), + void FILLFALSE(uchar *dest1), void FILLFALSEuchar(uchar *dest1)> +inline int loop_word1( + int bytes_left, int len0, int lenN, int sizeof_databus, + uchar *start, uchar *end, uchar *src, uchar *bsrc, uchar *dest, uchar *bdest) { + ptrdiff_t d2b_src = bsrc - src; // 64BITFIX was int // + ptrdiff_t d2b_dest = bdest - dest; // 64BITFIX was int // + uchar *original_dest = dest; + + while(true) { + // len0 bytes at start of a bus word + if((src >= start) && (src < end)) { + for(int i=0; i<len0; i++) { + COPYuchar(src, src+d2b_src, dest, dest+d2b_dest); + src++; + dest++; + } + bytes_left -= len0; + if(bytes_left <= 0) return int(dest - original_dest); + } else { + for(int i=0; i<len0; i++) { + FILLFALSEuchar(dest+d2b_dest); + src++; + dest++; + } + } + src -= 2 * sizeof(D); + + // sequence of full data word fragments + for(unsigned int i=1; i<sizeof_databus/sizeof(D); i++) { + if((src >= start) && (src < end)) { + COPY(src, src+d2b_src, dest, dest+d2b_dest); + bytes_left -= sizeof(D); + } else { + FILLFALSE(dest+d2b_dest); + } + dest += sizeof(D); + if(bytes_left <= 0) return int(dest - original_dest); + src -= sizeof(D); + } + + // lenN bytes at end of bus word + if((src >= start) && (src < end)) { + for(int i=0; i<lenN; i++) { + COPYuchar(src, src+d2b_src, dest, dest+d2b_dest); + src++; + dest++; + } + bytes_left -= lenN; + if(bytes_left <= 0) return int(dest - original_dest); + } else { + for(int i=0; i<lenN; i++) { + FILLFALSEuchar(dest+d2b_dest); + src++; + dest++; + } + } + src += 2 * sizeof_databus; + } +} + + +/////////////////////////////////////////////////////////////////////////////// +// function set (1): Response +template<class DATAWORD> inline void +tlm_from_hostendian_word(tlm_generic_payload *txn, unsigned int sizeof_databus) { + if(txn->is_read()) { + tlm_endian_context *tc = txn->template get_extension<tlm_endian_context>(); + sc_dt::uint64 b_mask = sizeof_databus - 1; + int d_mask = sizeof(DATAWORD) - 1; + int a_offset = static_cast<int>(tc->address & b_mask); + int len0 = (sizeof_databus - a_offset) & d_mask; + int lenN = sizeof(DATAWORD) - len0; + uchar *d_start = tc->data_ptr; + uchar *d_end = ptrdiff_t(tc->length) + d_start; // 64BITFIX probably redundant // + uchar *d = ptrdiff_t(((sizeof_databus - a_offset) & ~d_mask) + lenN) + d_start; // 64BITFIX probably redundant // + + // iterate over transaction copying data qualified by byte-enables + if(tc->byte_enable == 0) { + loop_word1<DATAWORD, ©_dbytrue1<DATAWORD>, + ©_dbytrue1<uchar>, &no_b1<DATAWORD>, &no_b1<uchar> >( + tc->length, len0, lenN, sizeof_databus, d_start, d_end, d, + 0, txn->get_data_ptr(), 0); + } else { + loop_word1<DATAWORD, ©_dbyb1<DATAWORD>, + ©_dbyb1<uchar>, &no_b1<DATAWORD>, &no_b1<uchar> >( + tc->length, len0, lenN, sizeof_databus, d_start, d_end, d, + tc->byte_enable - d_start + d, txn->get_data_ptr(), 0); + } + } +} + + +/////////////////////////////////////////////////////////////////////////////// +// function set (1): Request +template<class DATAWORD> inline void +tlm_to_hostendian_word(tlm_generic_payload *txn, unsigned int sizeof_databus) { + tlm_endian_context *tc = establish_context(txn); + tc->from_f = &(tlm_from_hostendian_word<DATAWORD>); + tc->sizeof_databus = sizeof_databus; + + sc_dt::uint64 b_mask = sizeof_databus - 1; + int d_mask = sizeof(DATAWORD) - 1; + sc_dt::uint64 a_aligned = txn->get_address() & ~b_mask; + int a_offset = static_cast<int>(txn->get_address() & b_mask); + int len0 = (sizeof_databus - a_offset) & d_mask; + int lenN = sizeof(DATAWORD) - len0; + uchar *d_start = txn->get_data_ptr(); + uchar *d_end = ptrdiff_t(txn->get_data_length()) + d_start; // 64BITFIX probably redundant // + uchar *d = ptrdiff_t(((sizeof_databus - a_offset) & ~d_mask) + lenN) + d_start; // 64BITFIX probably redundant // + + // create new data and byte enable buffers + int long_enough = txn->get_data_length() + 2 * sizeof_databus; + tc->establish_dbuf(long_enough); + uchar *new_data = tc->new_dbuf; + tc->establish_bebuf(long_enough); + uchar *new_be = tc->new_bebuf; + + if(txn->is_read()) { + tc->data_ptr = d_start; + tc->address = txn->get_address(); + tc->byte_enable = txn->get_byte_enable_ptr(); + tc->length = txn->get_data_length(); + if(txn->get_byte_enable_ptr() == 0) { + // iterate over transaction creating new byte enables from all-true + txn->set_data_length(loop_word1<DATAWORD, &true_b1<DATAWORD>, + &true_b1<uchar>, &false_b1<DATAWORD>, &false_b1<uchar> >( + txn->get_data_length(), len0, lenN, sizeof_databus, + d_start, d_end, d, 0, new_data, new_be)); + } else { + // iterate over transaction copying byte enables + txn->set_data_length(loop_word1<DATAWORD, ©_b1<DATAWORD>, + ©_b1<uchar>, &false_b1<DATAWORD>, &false_b1<uchar> >( + txn->get_data_length(), len0, lenN, sizeof_databus, d_start, d_end, + d, txn->get_byte_enable_ptr() - d_start + d, new_data, new_be)); + } + } else { + // WRITE + if(txn->get_byte_enable_ptr() == 0) { + // iterate over transaction copying data and creating new byte-enables + txn->set_data_length(loop_word1<DATAWORD, ©_d1<DATAWORD>, + ©_d1<uchar>, &false_b1<DATAWORD>, &false_b1<uchar> >( + txn->get_data_length(), len0, lenN, sizeof_databus, + d_start, d_end, d, 0, new_data, new_be)); + } else { + // iterate over transaction copying data and byte-enables + txn->set_data_length(loop_word1<DATAWORD, ©_db1<DATAWORD>, + ©_db1<uchar>, &false_b1<DATAWORD>, &false_b1<uchar> >( + txn->get_data_length(), len0, lenN, sizeof_databus, d_start, d_end, + d, txn->get_byte_enable_ptr() - d_start + d, new_data, new_be)); + } + } + txn->set_byte_enable_length(txn->get_data_length()); + txn->set_streaming_width(txn->get_data_length()); + txn->set_data_ptr(new_data); + txn->set_byte_enable_ptr(new_be); + txn->set_address(a_aligned); +} + + + +/////////////////////////////////////////////////////////////////////////////// +// function set (2): Utilities +template<class D> inline void copy_d2(D *src1, D *src2, D *dest1, D *dest2) { + *dest1 = *src1; +} + +template<class D> inline void copy_db2(D *src1, D *src2, D *dest1, D *dest2) { + *dest1 = *src1; + *dest2 = *src2; +} + +template<class D> +inline void copy_dbyb2(D *src1, D *src2, D *dest1, D *dest2) { + if(tlm_bool<D>(*src2)) *dest1 = *src1; +} + +template<class D, void COPY(D *src1, D *src2, D *dest1, D *dest2)> +inline void loop_aligned2(D *src1, D *src2, D *dest1, D *dest2, + int words, int words_per_bus) { + ptrdiff_t src1to2 = (char *)src2 - (char *)src1; // 64BITFIX was int and operands were cast to int // + ptrdiff_t dest1to2 = (char *)dest2 - (char *)dest1; // 64BITFIX was int and operands were cast to int // + + D *done = src1 + ptrdiff_t(words); // 64BITFIX // + D *bus_start = src1; + src1 += ptrdiff_t(words_per_bus - 1); // 64BITFIX // + + while(true) { + COPY(src1, (D *)(src1to2+(char *)src1), dest1, (D *)(dest1to2+(char *)dest1)); // 64BITFIX // + dest1++; + if((--src1) < bus_start) { + bus_start += ptrdiff_t(words_per_bus); // 64BITFIX // + if(bus_start == done) break; + src1 = bus_start + ptrdiff_t(words_per_bus - 1); // 64BITFIX // + } + } +} + + +/////////////////////////////////////////////////////////////////////////////// +// function set (2): Response +template<class DATAWORD> inline void +tlm_from_hostendian_aligned(tlm_generic_payload *txn, unsigned int sizeof_databus) { + int words_per_bus = sizeof_databus/sizeof(DATAWORD); + if(words_per_bus == 1) return; + int words = (txn->get_data_length())/sizeof(DATAWORD); + tlm_endian_context *tc = txn->template get_extension<tlm_endian_context>(); + + if(txn->get_byte_enable_ptr() == 0) { + // no byte enables + if(txn->is_read()) { + // RD without byte enables. Copy data to original buffer + loop_aligned2<DATAWORD, ©_d2<DATAWORD> >( + (DATAWORD *)(txn->get_data_ptr()), + 0, (DATAWORD *)(tc->data_ptr), 0, words, words_per_bus); + } + } else { + // byte enables present + if(txn->is_read()) { + // RD with byte enables. Copy data qualified by byte-enables + loop_aligned2<DATAWORD, ©_dbyb2<DATAWORD> >( + (DATAWORD *)(txn->get_data_ptr()), + (DATAWORD *)(txn->get_byte_enable_ptr()), + (DATAWORD *)(tc->data_ptr), 0, words, words_per_bus); + } + } +} + + +/////////////////////////////////////////////////////////////////////////////// +// function set (2): Request +template<class DATAWORD> inline void +tlm_to_hostendian_aligned(tlm_generic_payload *txn, unsigned int sizeof_databus) { + tlm_endian_context *tc = establish_context(txn); + tc->from_f = &(tlm_from_hostendian_aligned<DATAWORD>); + tc->sizeof_databus = sizeof_databus; + + int words_per_bus = sizeof_databus/sizeof(DATAWORD); + if(words_per_bus == 1) return; + int words = (txn->get_data_length())/sizeof(DATAWORD); + + DATAWORD *original_be = (DATAWORD *)(txn->get_byte_enable_ptr()); + DATAWORD *original_data = (DATAWORD *)(txn->get_data_ptr()); + + // always allocate a new data buffer + tc->establish_dbuf(txn->get_data_length()); + txn->set_data_ptr(tc->new_dbuf); + + if(original_be == 0) { + // no byte enables + if(txn->is_write()) { + // WR no byte enables. Copy data + loop_aligned2<DATAWORD, ©_d2<DATAWORD> >(original_data, 0, + (DATAWORD *)(txn->get_data_ptr()), 0, + words, words_per_bus); + } else { + // RD no byte enables. Save original data pointer + tc->data_ptr = (uchar *)original_data; + } + } else { + // byte enables present + // allocate a new buffer for them + tc->establish_bebuf(txn->get_data_length()); + txn->set_byte_enable_ptr(tc->new_bebuf); + txn->set_byte_enable_length(txn->get_data_length()); + + if(txn->is_write()) { + // WR with byte enables. Copy data and BEs + loop_aligned2<DATAWORD, ©_db2<DATAWORD> >(original_data, original_be, + (DATAWORD *)(txn->get_data_ptr()), + (DATAWORD *)(txn->get_byte_enable_ptr()), words, words_per_bus); + } else { + // RD with byte enables. Save original data pointer + tc->data_ptr = (uchar *)original_data; + // Copy byte enables to new buffer + loop_aligned2<DATAWORD, ©_d2<DATAWORD> >(original_be, 0, + (DATAWORD *)(txn->get_byte_enable_ptr()), 0, + words, words_per_bus); + } + } +} + + + +/////////////////////////////////////////////////////////////////////////////// +// function set (3): Response +template<class DATAWORD> inline void +tlm_from_hostendian_single(tlm_generic_payload *txn, unsigned int sizeof_databus) { + // nothing needs to be done here +} + + +/////////////////////////////////////////////////////////////////////////////// +// function set (3): Request +template<class DATAWORD> inline void +tlm_to_hostendian_single(tlm_generic_payload *txn, unsigned int sizeof_databus) { + tlm_endian_context *tc = establish_context(txn); + tc->from_f = &(tlm_from_hostendian_single<DATAWORD>); + tc->sizeof_databus = sizeof_databus; + + // only need to change the address, always safe to work in-place + sc_dt::uint64 mask = sizeof_databus-1; + sc_dt::uint64 a = txn->get_address(); + txn->set_address((a & ~mask) | + (sizeof_databus - (a & mask) - sizeof(DATAWORD))); +} + + + +/////////////////////////////////////////////////////////////////////////////// +// helper function which works for all responses +inline void tlm_from_hostendian(tlm_generic_payload *txn) { + tlm_endian_context *tc = txn->get_extension<tlm_endian_context>(); + (*(tc->from_f))(txn, tc->sizeof_databus); +} + + +#ifndef TLM_END_CONV_DONT_UNDEF_UCHAR +#undef uchar +#endif + +} // namespace tlm + + +#endif // multiple-inclusion protection + diff --git a/ext/systemc/src/tlm_core/tlm_2/tlm_generic_payload/tlm_generic_payload.h b/ext/systemc/src/tlm_core/tlm_2/tlm_generic_payload/tlm_generic_payload.h new file mode 100644 index 000000000..3e25e56f2 --- /dev/null +++ b/ext/systemc/src/tlm_core/tlm_2/tlm_generic_payload/tlm_generic_payload.h @@ -0,0 +1,29 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +#ifndef __TLM_GENERIC_PAYLOAD_H__ +#define __TLM_GENERIC_PAYLOAD_H__ + +#include "tlm_core/tlm_2/tlm_generic_payload/tlm_helpers.h" +#include "tlm_core/tlm_2/tlm_generic_payload/tlm_phase.h" +#include "tlm_core/tlm_2/tlm_generic_payload/tlm_gp.h" +#include "tlm_core/tlm_2/tlm_generic_payload/tlm_endian_conv.h" + +#endif + diff --git a/ext/systemc/src/tlm_core/tlm_2/tlm_generic_payload/tlm_gp.h b/ext/systemc/src/tlm_core/tlm_2/tlm_generic_payload/tlm_gp.h new file mode 100644 index 000000000..965e059ab --- /dev/null +++ b/ext/systemc/src/tlm_core/tlm_2/tlm_generic_payload/tlm_gp.h @@ -0,0 +1,642 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +// 12-Jan-2009 John Aynsley Bug fix. has_mm() and get_ref_count() should both be const +// 23-Mar-2009 John Aynsley Add method update_original_from() +// 20-Apr-2009 John Aynsley Bug fix for 64-bit machines: unsigned long int -> unsigned int +// 5-May-2011 JA and Philipp Hartmann Add tlm_gp_option, set_gp_option, get_gp_option +// 11-May-2011 John Aynsley Add run-time check to release() + + +#ifndef __TLM_GP_H__ +#define __TLM_GP_H__ + +#include <systemc> +#include "tlm_core/tlm_2/tlm_generic_payload/tlm_array.h" + +namespace tlm { + +class +tlm_generic_payload; + +class tlm_mm_interface { +public: + virtual void free(tlm_generic_payload*) = 0; + virtual ~tlm_mm_interface() {} +}; + +//--------------------------------------------------------------------------- +// Classes and helper functions for the extension mechanism +//--------------------------------------------------------------------------- +// Helper function: +inline unsigned int max_num_extensions(bool increment=false) +{ + static unsigned int max_num = 0; + if (increment) ++max_num; + return max_num; +} + +// This class can be used for storing pointers to the extension classes, used +// in tlm_generic_payload: +class tlm_extension_base +{ +public: + virtual tlm_extension_base* clone() const = 0; + virtual void free() { delete this; } + virtual void copy_from(tlm_extension_base const &) = 0; +protected: + virtual ~tlm_extension_base() {} + static unsigned int register_extension() + { + return (max_num_extensions(true) - 1); + }; +}; + +// Base class for all extension classes, derive your extension class in +// the following way: +// class my_extension : public tlm_extension<my_extension> { ... +// This triggers proper extension registration during C++ static +// contruction time. my_extension::ID will hold the unique index in the +// tlm_generic_payload::m_extensions array. +template <typename T> +class tlm_extension : public tlm_extension_base +{ +public: + virtual tlm_extension_base* clone() const = 0; + virtual void copy_from(tlm_extension_base const &ext) = 0; //{assert(typeid(this)==typeid(ext)); assert(ID === ext.ID); assert(0);} + virtual ~tlm_extension() {} + const static unsigned int ID; +}; + +template <typename T> +const +unsigned int tlm_extension<T>::ID = tlm_extension_base::register_extension(); + +//--------------------------------------------------------------------------- +// enumeration types +//--------------------------------------------------------------------------- +enum tlm_command { + TLM_READ_COMMAND, + TLM_WRITE_COMMAND, + TLM_IGNORE_COMMAND +}; + +enum tlm_response_status { + TLM_OK_RESPONSE = 1, + TLM_INCOMPLETE_RESPONSE = 0, + TLM_GENERIC_ERROR_RESPONSE = -1, + TLM_ADDRESS_ERROR_RESPONSE = -2, + TLM_COMMAND_ERROR_RESPONSE = -3, + TLM_BURST_ERROR_RESPONSE = -4, + TLM_BYTE_ENABLE_ERROR_RESPONSE = -5 +}; + +enum tlm_gp_option { + TLM_MIN_PAYLOAD, + TLM_FULL_PAYLOAD, + TLM_FULL_PAYLOAD_ACCEPTED +}; + +#define TLM_BYTE_DISABLED 0x0 +#define TLM_BYTE_ENABLED 0xff + +//--------------------------------------------------------------------------- +// The generic payload class: +//--------------------------------------------------------------------------- +class tlm_generic_payload { + +public: + //--------------- + // Constructors + //--------------- + + // Default constructor + tlm_generic_payload() + : m_address(0) + , m_command(TLM_IGNORE_COMMAND) + , m_data(0) + , m_length(0) + , m_response_status(TLM_INCOMPLETE_RESPONSE) + , m_dmi(false) + , m_byte_enable(0) + , m_byte_enable_length(0) + , m_streaming_width(0) + , m_gp_option(TLM_MIN_PAYLOAD) + , m_extensions(max_num_extensions()) + , m_mm(0) + , m_ref_count(0) + { + } + + explicit tlm_generic_payload(tlm_mm_interface* mm) + : m_address(0) + , m_command(TLM_IGNORE_COMMAND) + , m_data(0) + , m_length(0) + , m_response_status(TLM_INCOMPLETE_RESPONSE) + , m_dmi(false) + , m_byte_enable(0) + , m_byte_enable_length(0) + , m_streaming_width(0) + , m_gp_option(TLM_MIN_PAYLOAD) + , m_extensions(max_num_extensions()) + , m_mm(mm) + , m_ref_count(0) + { + } + + void acquire(){assert(m_mm != 0); m_ref_count++;} + void release(){assert(m_mm != 0 && m_ref_count > 0); if (--m_ref_count==0) m_mm->free(this);} + int get_ref_count() const {return m_ref_count;} + void set_mm(tlm_mm_interface* mm) { m_mm = mm; } + bool has_mm() const { return m_mm != 0; } + + void reset(){ + //should the other members be reset too? + m_gp_option = TLM_MIN_PAYLOAD; + m_extensions.free_entire_cache(); + }; + + +private: + //disabled copy ctor and assignment operator. + // Copy constructor + tlm_generic_payload(const tlm_generic_payload& x) + : m_address(x.get_address()) + , m_command(x.get_command()) + , m_data(x.get_data_ptr()) + , m_length(x.get_data_length()) + , m_response_status(x.get_response_status()) + , m_dmi(x.is_dmi_allowed()) + , m_byte_enable(x.get_byte_enable_ptr()) + , m_byte_enable_length(x.get_byte_enable_length()) + , m_streaming_width(x.get_streaming_width()) + , m_gp_option(x.m_gp_option) + , m_extensions(max_num_extensions()) + { + // copy all extensions + for(unsigned int i=0; i<m_extensions.size(); i++) + { + m_extensions[i] = x.get_extension(i); + } + } + + // Assignment operator + tlm_generic_payload& operator= (const tlm_generic_payload& x) + { + m_command = x.get_command(); + m_address = x.get_address(); + m_data = x.get_data_ptr(); + m_length = x.get_data_length(); + m_response_status = x.get_response_status(); + m_byte_enable = x.get_byte_enable_ptr(); + m_byte_enable_length = x.get_byte_enable_length(); + m_streaming_width = x.get_streaming_width(); + m_gp_option = x.get_gp_option(); + m_dmi = x.is_dmi_allowed(); + + // extension copy: all extension arrays must be of equal size by + // construction (i.e. it must either be constructed after C++ + // static construction time, or the resize_extensions() method must + // have been called prior to using the object) + for(unsigned int i=0; i<m_extensions.size(); i++) + { + m_extensions[i] = x.get_extension(i); + } + return (*this); + } +public: + // non-virtual deep-copying of the object + void deep_copy_from(const tlm_generic_payload & other) + { + m_command = other.get_command(); + m_address = other.get_address(); + m_length = other.get_data_length(); + m_response_status = other.get_response_status(); + m_byte_enable_length = other.get_byte_enable_length(); + m_streaming_width = other.get_streaming_width(); + m_gp_option = other.get_gp_option(); + m_dmi = other.is_dmi_allowed(); + + // deep copy data + // there must be enough space in the target transaction! + if(m_data && other.m_data) + { + memcpy(m_data, other.m_data, m_length); + } + // deep copy byte enables + // there must be enough space in the target transaction! + if(m_byte_enable && other.m_byte_enable) + { + memcpy(m_byte_enable, other.m_byte_enable, m_byte_enable_length); + } + // deep copy extensions (sticky and non-sticky) + for(unsigned int i=0; i<other.m_extensions.size(); i++) + { + if(other.m_extensions[i]) + { //original has extension i + if(!m_extensions[i]) + { //We don't: clone. + tlm_extension_base *ext = other.m_extensions[i]->clone(); + if(ext) //extension may not be clonable. + { + if(has_mm()) + { //mm can take care of removing cloned extensions + set_auto_extension(i, ext); + } + else + { // no mm, user will call free_all_extensions(). + set_extension(i, ext); + } + } + } + else + { //We already have such extension. Copy original over it. + m_extensions[i]->copy_from(*other.m_extensions[i]); + } + } + } + } + + // To update the state of the original generic payload from a deep copy + // Assumes that "other" was created from the original by calling deep_copy_from + // Argument use_byte_enable_on_read determines whether to use or ignores byte enables + // when copying back the data array on a read command + + void update_original_from(const tlm_generic_payload & other, + bool use_byte_enable_on_read = true) + { + // Copy back extensions that are present on the original + update_extensions_from(other); + + // Copy back the response status and DMI hint attributes + m_response_status = other.get_response_status(); + m_dmi = other.is_dmi_allowed(); + + // Copy back the data array for a read command only + // deep_copy_from allowed null pointers, and so will we + // We assume the arrays are the same size + // We test for equal pointers in case the original and the copy share the same array + + if(is_read() && m_data && other.m_data && m_data != other.m_data) + { + if (m_byte_enable && use_byte_enable_on_read) + { + if (m_byte_enable_length == 8 && m_length % 8 == 0 ) + { + // Optimized implementation copies 64-bit words by masking + for (unsigned int i = 0; i < m_length; i += 8) + { + typedef sc_dt::uint64* u; + *reinterpret_cast<u>(&m_data[i]) &= ~*reinterpret_cast<u>(m_byte_enable); + *reinterpret_cast<u>(&m_data[i]) |= *reinterpret_cast<u>(&other.m_data[i]) & + *reinterpret_cast<u>(m_byte_enable); + } + } + else if (m_byte_enable_length == 4 && m_length % 4 == 0 ) + { + // Optimized implementation copies 32-bit words by masking + for (unsigned int i = 0; i < m_length; i += 4) + { + typedef unsigned int* u; + *reinterpret_cast<u>(&m_data[i]) &= ~*reinterpret_cast<u>(m_byte_enable); + *reinterpret_cast<u>(&m_data[i]) |= *reinterpret_cast<u>(&other.m_data[i]) & + *reinterpret_cast<u>(m_byte_enable); + } + } + else + // Unoptimized implementation + for (unsigned int i = 0; i < m_length; i++) + if ( m_byte_enable[i % m_byte_enable_length] ) + m_data[i] = other.m_data[i]; + } + else + memcpy(m_data, other.m_data, m_length); + } + } + + void update_extensions_from(const tlm_generic_payload & other) + { + // deep copy extensions that are already present + for(unsigned int i=0; i<other.m_extensions.size(); i++) + { + if(other.m_extensions[i]) + { //original has extension i + if(m_extensions[i]) + { //We have it too. copy. + m_extensions[i]->copy_from(*other.m_extensions[i]); + } + } + } + } + + // Free all extensions. Useful when reusing a cloned transaction that doesn't have memory manager. + // normal and sticky extensions are freed and extension array cleared. + void free_all_extensions() + { + m_extensions.free_entire_cache(); + for(unsigned int i=0; i<m_extensions.size(); i++) + { + if(m_extensions[i]) + { + m_extensions[i]->free(); + m_extensions[i] = 0; + } + } + } + //-------------- + // Destructor + //-------------- + virtual ~tlm_generic_payload() { + for(unsigned int i=0; i<m_extensions.size(); i++) + if(m_extensions[i]) m_extensions[i]->free(); + } + + //---------------- + // API (including setters & getters) + //--------------- + + // Command related method + bool is_read() const {return (m_command == TLM_READ_COMMAND);} + void set_read() {m_command = TLM_READ_COMMAND;} + bool is_write() const {return (m_command == TLM_WRITE_COMMAND);} + void set_write() {m_command = TLM_WRITE_COMMAND;} + tlm_command get_command() const {return m_command;} + void set_command(const tlm_command command) {m_command = command;} + + // Address related methods + sc_dt::uint64 get_address() const {return m_address;} + void set_address(const sc_dt::uint64 address) {m_address = address;} + + // Data related methods + unsigned char* get_data_ptr() const {return m_data;} + void set_data_ptr(unsigned char* data) {m_data = data;} + + // Transaction length (in bytes) related methods + unsigned int get_data_length() const {return m_length;} + void set_data_length(const unsigned int length) {m_length = length;} + + // Response status related methods + bool is_response_ok() const {return (m_response_status > 0);} + bool is_response_error() const {return (m_response_status <= 0);} + tlm_response_status get_response_status() const {return m_response_status;} + void set_response_status(const tlm_response_status response_status) + {m_response_status = response_status;} + std::string get_response_string() const + { + switch(m_response_status) + { + case TLM_OK_RESPONSE: return "TLM_OK_RESPONSE"; + case TLM_INCOMPLETE_RESPONSE: return "TLM_INCOMPLETE_RESPONSE"; + case TLM_GENERIC_ERROR_RESPONSE: return "TLM_GENERIC_ERROR_RESPONSE"; + case TLM_ADDRESS_ERROR_RESPONSE: return "TLM_ADDRESS_ERROR_RESPONSE"; + case TLM_COMMAND_ERROR_RESPONSE: return "TLM_COMMAND_ERROR_RESPONSE"; + case TLM_BURST_ERROR_RESPONSE: return "TLM_BURST_ERROR_RESPONSE"; + case TLM_BYTE_ENABLE_ERROR_RESPONSE: return "TLM_BYTE_ENABLE_ERROR_RESPONSE"; + } + return "TLM_UNKNOWN_RESPONSE"; + } + + // Streaming related methods + unsigned int get_streaming_width() const {return m_streaming_width;} + void set_streaming_width(const unsigned int streaming_width) {m_streaming_width = streaming_width; } + + // Byte enable related methods + unsigned char* get_byte_enable_ptr() const {return m_byte_enable;} + void set_byte_enable_ptr(unsigned char* byte_enable){m_byte_enable = byte_enable;} + unsigned int get_byte_enable_length() const {return m_byte_enable_length;} + void set_byte_enable_length(const unsigned int byte_enable_length){m_byte_enable_length = byte_enable_length;} + + // This is the "DMI-hint" a slave can set this to true if it + // wants to indicate that a DMI request would be supported: + void set_dmi_allowed(bool dmi_allowed) { m_dmi = dmi_allowed; } + bool is_dmi_allowed() const { return m_dmi; } + + // Use full set of attributes in DMI/debug? + tlm_gp_option get_gp_option() const { return m_gp_option; } + void set_gp_option( const tlm_gp_option gp_opt ) { m_gp_option = gp_opt; } + +private: + + /* --------------------------------------------------------------------- */ + /* Generic Payload attributes: */ + /* --------------------------------------------------------------------- */ + /* - m_command : Type of transaction. Three values supported: */ + /* - TLM_WRITE_COMMAND */ + /* - TLM_READ_COMMAND */ + /* - TLM_IGNORE_COMMAND */ + /* - m_address : Transaction base address (byte-addressing). */ + /* - m_data : When m_command = TLM_WRITE_COMMAND contains a */ + /* pointer to the data to be written in the target.*/ + /* When m_command = TLM_READ_COMMAND contains a */ + /* pointer where to copy the data read from the */ + /* target. */ + /* - m_length : Total number of bytes of the transaction. */ + /* - m_response_status : This attribute indicates whether an error has */ + /* occurred during the transaction. */ + /* Values supported are: */ + /* - TLM_OK_RESP */ + /* - TLM_INCOMPLETE_RESP */ + /* - TLM_GENERIC_ERROR_RESP */ + /* - TLM_ADDRESS_ERROR_RESP */ + /* - TLM_COMMAND_ERROR_RESP */ + /* - TLM_BURST_ERROR_RESP */ + /* - TLM_BYTE_ENABLE_ERROR_RESP */ + /* */ + /* - m_byte_enable : It can be used to create burst transfers where */ + /* the address increment between each beat is greater */ + /* than the word length of each beat, or to place */ + /* words in selected byte lanes of a bus. */ + /* - m_byte_enable_length : For a read or a write command, the target */ + /* interpret the byte enable length attribute as the */ + /* number of elements in the bytes enable array. */ + /* - m_streaming_width : */ + /* --------------------------------------------------------------------- */ + + sc_dt::uint64 m_address; + tlm_command m_command; + unsigned char* m_data; + unsigned int m_length; + tlm_response_status m_response_status; + bool m_dmi; + unsigned char* m_byte_enable; + unsigned int m_byte_enable_length; + unsigned int m_streaming_width; + tlm_gp_option m_gp_option; + +public: + + /* --------------------------------------------------------------------- */ + /* Dynamic extension mechanism: */ + /* --------------------------------------------------------------------- */ + /* The extension mechanism is intended to enable initiator modules to */ + /* optionally and transparently add data fields to the */ + /* tlm_generic_payload. Target modules are free to check for extensions */ + /* and may or may not react to the data in the extension fields. The */ + /* definition of the extensions' semantics is solely in the */ + /* responsibility of the user. */ + /* */ + /* The following rules apply: */ + /* */ + /* - Every extension class must be derived from tlm_extension, e.g.: */ + /* class my_extension : public tlm_extension<my_extension> { ... } */ + /* */ + /* - A tlm_generic_payload object should be constructed after C++ */ + /* static initialization time. This way it is guaranteed that the */ + /* extension array is of sufficient size to hold all possible */ + /* extensions. Alternatively, the initiator module can enforce a valid */ + /* extension array size by calling the resize_extensions() method */ + /* once before the first transaction with the payload object is */ + /* initiated. */ + /* */ + /* - Initiators should use the the set_extension(e) or clear_extension(e)*/ + /* methods for manipulating the extension array. The type of the */ + /* argument must be a pointer to the specific registered extension */ + /* type (my_extension in the above example) and is used to */ + /* automatically locate the appropriate index in the array. */ + /* */ + /* - Targets can check for a specific extension by calling */ + /* get_extension(e). e will point to zero if the extension is not */ + /* present. */ + /* */ + /* --------------------------------------------------------------------- */ + + // Stick the pointer to an extension into the vector, return the + // previous value: + template <typename T> T* set_extension(T* ext) + { + return static_cast<T*>(set_extension(T::ID, ext)); + } + + // non-templatized version with manual index: + tlm_extension_base* set_extension(unsigned int index, + tlm_extension_base* ext) + { + tlm_extension_base* tmp = m_extensions[index]; + m_extensions[index] = ext; + return tmp; + } + + // Stick the pointer to an extension into the vector, return the + // previous value and schedule its release + template <typename T> T* set_auto_extension(T* ext) + { + return static_cast<T*>(set_auto_extension(T::ID, ext)); + } + + // non-templatized version with manual index: + tlm_extension_base* set_auto_extension(unsigned int index, + tlm_extension_base* ext) + { + tlm_extension_base* tmp = m_extensions[index]; + m_extensions[index] = ext; + if (!tmp) m_extensions.insert_in_cache(&m_extensions[index]); + assert(m_mm != 0); + return tmp; + } + + // Check for an extension, ext will point to 0 if not present + template <typename T> void get_extension(T*& ext) const + { + ext = get_extension<T>(); + } + template <typename T> T* get_extension() const + { + return static_cast<T*>(get_extension(T::ID)); + } + // Non-templatized version with manual index: + tlm_extension_base* get_extension(unsigned int index) const + { + return m_extensions[index]; + } + + //this call just removes the extension from the txn but does not + // call free() or tells the MM to do so + // it return false if there was active MM so you are now in an unsafe situation + // recommended use: when 100% sure there is no MM + template <typename T> void clear_extension(const T* ext) + { + clear_extension<T>(); + } + + //this call just removes the extension from the txn but does not + // call free() or tells the MM to do so + // it return false if there was active MM so you are now in an unsafe situation + // recommended use: when 100% sure there is no MM + template <typename T> void clear_extension() + { + clear_extension(T::ID); + } + + //this call removes the extension from the txn and does + // call free() or tells the MM to do so when the txn is finally done + // recommended use: when not sure there is no MM + template <typename T> void release_extension(T* ext) + { + release_extension<T>(); + } + + //this call removes the extension from the txn and does + // call free() or tells the MM to do so when the txn is finally done + // recommended use: when not sure there is no MM + template <typename T> void release_extension() + { + release_extension(T::ID); + } + +private: + // Non-templatized version with manual index + void clear_extension(unsigned int index) + { + m_extensions[index] = static_cast<tlm_extension_base*>(0); + } + // Non-templatized version with manual index + void release_extension(unsigned int index) + { + if (m_mm) + { + m_extensions.insert_in_cache(&m_extensions[index]); + } + else + { + m_extensions[index]->free(); + m_extensions[index] = static_cast<tlm_extension_base*>(0); + } + } + +public: + // Make sure the extension array is large enough. Can be called once by + // an initiator module (before issuing the first transaction) to make + // sure that the extension array is of correct size. This is only needed + // if the initiator cannot guarantee that the generic payload object is + // allocated after C++ static construction time. + void resize_extensions() + { + m_extensions.expand(max_num_extensions()); + } + +private: + tlm_array<tlm_extension_base*> m_extensions; + tlm_mm_interface* m_mm; + unsigned int m_ref_count; +}; + +} // namespace tlm + +#endif /* __TLM_GP_H__ */ diff --git a/ext/systemc/src/tlm_core/tlm_2/tlm_generic_payload/tlm_helpers.h b/ext/systemc/src/tlm_core/tlm_2/tlm_generic_payload/tlm_helpers.h new file mode 100644 index 000000000..da3abb4f9 --- /dev/null +++ b/ext/systemc/src/tlm_core/tlm_2/tlm_generic_payload/tlm_helpers.h @@ -0,0 +1,80 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/* --------------------------------------------------------------------------------------- + @file tlm_helpers.h + + @brief + + Original Authors: + Charles Wilson, ESLX + +--------------------------------------------------------------------------------------- */ + +#ifndef __TLM_HELPERS_H__ +#define __TLM_HELPERS_H__ + +//#include <sys/param.h> +//#include <cstring> + +namespace tlm { + +enum tlm_endianness { TLM_UNKNOWN_ENDIAN, TLM_LITTLE_ENDIAN, TLM_BIG_ENDIAN }; + +inline tlm_endianness get_host_endianness(void) +{ + static tlm_endianness host_endianness = TLM_UNKNOWN_ENDIAN; + + if (host_endianness == TLM_UNKNOWN_ENDIAN) { + unsigned int number = 1; + unsigned char *p_msb_or_lsb = (unsigned char*)&number; + + host_endianness = (p_msb_or_lsb[0] == 0) ? TLM_BIG_ENDIAN : TLM_LITTLE_ENDIAN; + } + return host_endianness; +} + +inline bool host_has_little_endianness(void) +{ + static tlm_endianness host_endianness = TLM_UNKNOWN_ENDIAN; + static bool host_little_endian = false; + + if (host_endianness == TLM_UNKNOWN_ENDIAN) { + unsigned int number = 1; + unsigned char *p_msb_or_lsb = (unsigned char*)&number; + + host_little_endian = (p_msb_or_lsb[0] == 0) ? false : true; + } + + return host_little_endian; +} + +inline bool has_host_endianness(tlm_endianness endianness) +{ + if (host_has_little_endianness()) { + return endianness == TLM_LITTLE_ENDIAN; + + } else { + return endianness == TLM_BIG_ENDIAN; + } +} + +} // namespace tlm + +#endif /* __TLM_HELPERS_H__ */ diff --git a/ext/systemc/src/tlm_core/tlm_2/tlm_generic_payload/tlm_phase.h b/ext/systemc/src/tlm_core/tlm_2/tlm_generic_payload/tlm_phase.h new file mode 100644 index 000000000..af0a278c9 --- /dev/null +++ b/ext/systemc/src/tlm_core/tlm_2/tlm_generic_payload/tlm_phase.h @@ -0,0 +1,87 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +#ifndef __TLM_PHASE_H__ +#define __TLM_PHASE_H__ + +#include <string> +#include <iostream> +#include <vector> + +namespace tlm { + +//enum tlm_phase { BEGIN_REQ, END_REQ, BEGIN_RESP, END_RESP }; + +enum tlm_phase_enum { UNINITIALIZED_PHASE=0, BEGIN_REQ=1, END_REQ, BEGIN_RESP, END_RESP }; + +inline unsigned int create_phase_number(){ + static unsigned int number=END_RESP+1; + return number++; +} + +inline std::vector<const char*>& get_phase_name_vec(){ + static std::vector<const char*> phase_name_vec(END_RESP+1, (const char*)NULL); + return phase_name_vec; +} + +class tlm_phase{ +public: + tlm_phase(): m_id(0) {} + tlm_phase(unsigned int id): m_id(id){} + tlm_phase(const tlm_phase_enum& standard): m_id((unsigned int) standard){} + tlm_phase& operator=(const tlm_phase_enum& standard){m_id=(unsigned int)standard; return *this;} + operator unsigned int() const{return m_id;} + +private: + unsigned int m_id; +}; + +inline +std::ostream& operator<<(std::ostream& s, const tlm_phase& p){ + switch ((unsigned int)p){ + case UNINITIALIZED_PHASE: s<<"UNINITIALIZED_PHASE"; break; + case BEGIN_REQ: s<<"BEGIN_REQ"; break; + case END_REQ: s<<"END_REQ"; break; + case BEGIN_RESP: s<<"BEGIN_RESP"; break; + case END_RESP: s<<"END_RESP"; break; + default: + s<<get_phase_name_vec()[(unsigned int)p]; return s; + } + return s; +} + +#define TLM_DECLARE_EXTENDED_PHASE(name_arg) \ +class tlm_phase_##name_arg:public tlm::tlm_phase{ \ +public:\ +static const tlm_phase_##name_arg& get_phase(){static tlm_phase_##name_arg tmp; return tmp;}\ +private:\ +tlm_phase_##name_arg():tlm::tlm_phase(tlm::create_phase_number()){tlm::get_phase_name_vec().push_back(get_char_##name_arg());};\ +tlm_phase_##name_arg(const tlm_phase_##name_arg&); \ +tlm_phase_##name_arg& operator=(const tlm_phase_##name_arg&); \ +static inline const char* get_char_##name_arg(){static const char* tmp=#name_arg; return tmp;} \ +}; \ +static const tlm_phase_##name_arg& name_arg=tlm_phase_##name_arg::get_phase() + +// for backwards-compatibility +#define DECLARE_EXTENDED_PHASE(NameArg) \ + TLM_DECLARE_EXTENDED_PHASE( NameArg ) + +} // namespace tlm + +#endif /* TLM_PHASE_HEADER */ diff --git a/ext/systemc/src/tlm_core/tlm_2/tlm_quantum/tlm_global_quantum.h b/ext/systemc/src/tlm_core/tlm_2/tlm_quantum/tlm_global_quantum.h new file mode 100644 index 000000000..eb36a898e --- /dev/null +++ b/ext/systemc/src/tlm_core/tlm_2/tlm_quantum/tlm_global_quantum.h @@ -0,0 +1,97 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +#ifndef __TLM_GLOBAL_QUANTUM_H__ +#define __TLM_GLOBAL_QUANTUM_H__ + +#include <systemc> + +namespace tlm { + +// +// tlm_global_quantum class +// +// The global quantum is the maximum time an initiator can run ahead of +// systemC time. All initiators should synchronize on timingpoints that +// are multiples of the global quantum value. +// +// sc_set_time_resolution can only be called before the first +// sc_time object is created. This means that after setting the +// global quantum it will not be possible to call sc_set_time_resolution. +// If sc_set_time_resolution must be called this must be done before +// the global quantum is set. +// + +class tlm_global_quantum +{ +public: + // + // Returns a reference to the tlm_global_quantum singleton + // + static tlm_global_quantum& instance() + { + static tlm_global_quantum instance_; + return instance_; + } + +public: + + // + // Setter/getter for the global quantum + // + void set(const sc_core::sc_time& t) + { + m_global_quantum = t; + } + + const sc_core::sc_time& get() const + { + return m_global_quantum; + } + + // + // This function will calculate the maximum value for the next local + // quantum for an initiator. All initiators should synchronize on + // integer multiples of the global quantum value. The value for the + // local quantum of an initiator can be smaller, but should never be + // greater than the value returned by this method. + // + sc_core::sc_time compute_local_quantum() + { + if (m_global_quantum != sc_core::SC_ZERO_TIME) { + const sc_core::sc_time current = sc_core::sc_time_stamp(); + const sc_core::sc_time g_quant = m_global_quantum; + return g_quant - (current % g_quant); + } else { + return sc_core::SC_ZERO_TIME; + } + } + +protected: + tlm_global_quantum() : m_global_quantum(sc_core::SC_ZERO_TIME) + { + } + +protected: + sc_core::sc_time m_global_quantum; +}; + +} // namespace tlm + +#endif diff --git a/ext/systemc/src/tlm_core/tlm_2/tlm_quantum/tlm_quantum.h b/ext/systemc/src/tlm_core/tlm_2/tlm_quantum/tlm_quantum.h new file mode 100644 index 000000000..c5138ab06 --- /dev/null +++ b/ext/systemc/src/tlm_core/tlm_2/tlm_quantum/tlm_quantum.h @@ -0,0 +1,25 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +#ifndef __TLM_QUANTUM_H__ +#define __TLM_QUANTUM_H__ + +#include "tlm_core/tlm_2/tlm_quantum/tlm_global_quantum.h" + +#endif diff --git a/ext/systemc/src/tlm_core/tlm_2/tlm_sockets/tlm_initiator_socket.h b/ext/systemc/src/tlm_core/tlm_2/tlm_sockets/tlm_initiator_socket.h new file mode 100644 index 000000000..3dd42e806 --- /dev/null +++ b/ext/systemc/src/tlm_core/tlm_2/tlm_sockets/tlm_initiator_socket.h @@ -0,0 +1,252 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +#ifndef __TLM_INITIATOR_SOCKET_H__ +#define __TLM_INITIATOR_SOCKET_H__ + +//#include <systemc> +#include "tlm_core/tlm_2/tlm_2_interfaces/tlm_fw_bw_ifs.h" + +namespace tlm { + + +template <unsigned int BUSWIDTH = 32, + typename FW_IF = tlm_fw_transport_if<>, + typename BW_IF = tlm_bw_transport_if<> > +class tlm_base_initiator_socket_b +{ +public: + virtual ~tlm_base_initiator_socket_b() {} + + virtual sc_core::sc_port_b<FW_IF> & get_base_port() = 0; + virtual sc_core::sc_port_b<FW_IF> const & get_base_port() const = 0; + virtual BW_IF & get_base_interface() = 0; + virtual BW_IF const & get_base_interface() const = 0; + virtual sc_core::sc_export<BW_IF> & get_base_export() = 0; + virtual sc_core::sc_export<BW_IF> const & get_base_export() const = 0; +}; + + +template <unsigned int BUSWIDTH, + typename FW_IF, + typename BW_IF> class tlm_base_target_socket_b; + +template <unsigned int BUSWIDTH, + typename FW_IF, + typename BW_IF, + int N +#if !(defined SYSTEMC_VERSION & SYSTEMC_VERSION <= 20050714) + ,sc_core::sc_port_policy POL +#endif + > class tlm_base_target_socket; + +template <unsigned int BUSWIDTH = 32, + typename FW_IF = tlm_fw_transport_if<>, + typename BW_IF = tlm_bw_transport_if<>, + int N = 1 +#if !(defined SYSTEMC_VERSION & SYSTEMC_VERSION <= 20050714) + ,sc_core::sc_port_policy POL = sc_core::SC_ONE_OR_MORE_BOUND +#endif + > +class tlm_base_initiator_socket : public tlm_base_initiator_socket_b<BUSWIDTH, FW_IF, BW_IF>, + public sc_core::sc_port<FW_IF, N +#if !(defined SYSTEMC_VERSION & SYSTEMC_VERSION <= 20050714) + , POL +#endif + > + +{ +public: + typedef FW_IF fw_interface_type; + typedef BW_IF bw_interface_type; + typedef sc_core::sc_port<fw_interface_type, N +#if !(defined SYSTEMC_VERSION & SYSTEMC_VERSION <= 20050714) + , POL +#endif + > port_type; + + typedef sc_core::sc_export<bw_interface_type> export_type; + + typedef tlm_base_target_socket_b<BUSWIDTH, + fw_interface_type, + bw_interface_type> base_target_socket_type; + typedef tlm_base_initiator_socket_b<BUSWIDTH, + fw_interface_type, + bw_interface_type> base_type; + + template <unsigned int, typename, typename, int +#if !(defined SYSTEMC_VERSION & SYSTEMC_VERSION <= 20050714) + ,sc_core::sc_port_policy +#endif + > + friend class tlm_base_target_socket; + +public: + tlm_base_initiator_socket() + : port_type(sc_core::sc_gen_unique_name("tlm_base_initiator_socket")) + , m_export(sc_core::sc_gen_unique_name("tlm_base_initiator_socket_export")) + { + } + + explicit tlm_base_initiator_socket(const char* name) + : port_type(name) + , m_export(sc_core::sc_gen_unique_name((std::string(name) + "_export").c_str())) + { + } + + virtual const char* kind() const + { + return "tlm_base_initiator_socket"; + } + + unsigned int get_bus_width() const + { + return BUSWIDTH; + } + + // + // Bind initiator socket to target socket + // - Binds the port of the initiator socket to the export of the target + // socket + // - Binds the port of the target socket to the export of the initiator + // socket + // + virtual void bind(base_target_socket_type& s) + { + // initiator.port -> target.export + (get_base_port())(s.get_base_interface()); + // target.port -> initiator.export + (s.get_base_port())(get_base_interface()); + } + + void operator() (base_target_socket_type& s) + { + bind(s); + } + + // + // Bind initiator socket to initiator socket (hierarchical bind) + // - Binds both the export and the port + // + virtual void bind(base_type& s) + { + // port + (get_base_port())(s.get_base_port()); + // export + (s.get_base_export())(get_base_export()); + } + + void operator() (base_type& s) + { + bind(s); + } + + // + // Bind interface to socket + // - Binds the interface to the export of this socket + // + virtual void bind(bw_interface_type& ifs) + { + (get_base_export())(ifs); + } + + void operator() (bw_interface_type& s) + { + bind(s); + } + + // Implementation of pure virtual functions of base class + virtual sc_core::sc_port_b<FW_IF> & get_base_port() + { return *this; } + virtual sc_core::sc_port_b<FW_IF> const & get_base_port() const + { return *this; } + + virtual BW_IF & get_base_interface() + { return m_export; } + virtual BW_IF const & get_base_interface() const +#if !( defined(IEEE_1666_SYSTEMC) && IEEE_1666_SYSTEMC >= 201101L ) + { return const_cast<export_type &>(m_export); } +#else + { return m_export; } +#endif + + virtual sc_core::sc_export<BW_IF> & get_base_export() + { return m_export; } + virtual sc_core::sc_export<BW_IF> const & get_base_export() const + { return m_export; } + +protected: + export_type m_export; +}; + +// +// Convenience socket classes +// + +template <unsigned int BUSWIDTH = 32, + typename TYPES = tlm_base_protocol_types, + int N = 1 +#if !(defined SYSTEMC_VERSION & SYSTEMC_VERSION <= 20050714) + ,sc_core::sc_port_policy POL = sc_core::SC_ONE_OR_MORE_BOUND +#endif + > +class tlm_initiator_socket : + public tlm_base_initiator_socket <BUSWIDTH, + tlm_fw_transport_if<TYPES>, + tlm_bw_transport_if<TYPES>, + N +#if !(defined SYSTEMC_VERSION & SYSTEMC_VERSION <= 20050714) + ,POL +#endif + > +{ +public: + tlm_initiator_socket() : + tlm_base_initiator_socket<BUSWIDTH, + tlm_fw_transport_if<TYPES>, + tlm_bw_transport_if<TYPES>, + N +#if !(defined SYSTEMC_VERSION & SYSTEMC_VERSION <= 20050714) + ,POL +#endif + >() + { + } + + explicit tlm_initiator_socket(const char* name) : + tlm_base_initiator_socket<BUSWIDTH, + tlm_fw_transport_if<TYPES>, + tlm_bw_transport_if<TYPES>, + N +#if !(defined SYSTEMC_VERSION & SYSTEMC_VERSION <= 20050714) + ,POL +#endif + >(name) + { + } + + virtual const char* kind() const + { + return "tlm_initiator_socket"; + } +}; + +} // namespace tlm + +#endif diff --git a/ext/systemc/src/tlm_core/tlm_2/tlm_sockets/tlm_sockets.h b/ext/systemc/src/tlm_core/tlm_2/tlm_sockets/tlm_sockets.h new file mode 100644 index 000000000..013e29286 --- /dev/null +++ b/ext/systemc/src/tlm_core/tlm_2/tlm_sockets/tlm_sockets.h @@ -0,0 +1,26 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +#ifndef __TLM_SOCKETS_H__ +#define __TLM_SOCKETS_H__ + +#include "tlm_core/tlm_2/tlm_sockets/tlm_initiator_socket.h" +#include "tlm_core/tlm_2/tlm_sockets/tlm_target_socket.h" + +#endif /* __TLM_SOCKETS_H__ */ diff --git a/ext/systemc/src/tlm_core/tlm_2/tlm_sockets/tlm_target_socket.h b/ext/systemc/src/tlm_core/tlm_2/tlm_sockets/tlm_target_socket.h new file mode 100644 index 000000000..4ed29f62a --- /dev/null +++ b/ext/systemc/src/tlm_core/tlm_2/tlm_sockets/tlm_target_socket.h @@ -0,0 +1,275 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +#ifndef __TLM_TARGET_SOCKET_H__ +#define __TLM_TARGET_SOCKET_H__ + +//#include <systemc> +#include "tlm_core/tlm_2/tlm_2_interfaces/tlm_fw_bw_ifs.h" + + +namespace tlm { + +template <unsigned int BUSWIDTH = 32, + typename FW_IF = tlm_fw_transport_if<>, + typename BW_IF = tlm_bw_transport_if<> > +class tlm_base_target_socket_b +{ +public: + virtual ~tlm_base_target_socket_b() {} + + virtual sc_core::sc_port_b<BW_IF> & get_base_port() = 0; + virtual sc_core::sc_export<FW_IF> & get_base_export() = 0; + virtual FW_IF & get_base_interface() = 0; +}; + +template <unsigned int BUSWIDTH, + typename FW_IF, + typename BW_IF> class tlm_base_initiator_socket_b; + +template <unsigned int BUSWIDTH, + typename FW_IF, + typename BW_IF, + int N +#if !(defined SYSTEMC_VERSION & SYSTEMC_VERSION <= 20050714) + ,sc_core::sc_port_policy POL +#endif + > class tlm_base_initiator_socket; + +template <unsigned int BUSWIDTH = 32, + typename FW_IF = tlm_fw_transport_if<>, + typename BW_IF = tlm_bw_transport_if<>, + int N = 1 +#if !(defined SYSTEMC_VERSION & SYSTEMC_VERSION <= 20050714) + ,sc_core::sc_port_policy POL = sc_core::SC_ONE_OR_MORE_BOUND +#endif + > +class tlm_base_target_socket : public tlm_base_target_socket_b<BUSWIDTH, FW_IF, BW_IF>, + public sc_core::sc_export<FW_IF> +{ +public: + typedef FW_IF fw_interface_type; + typedef BW_IF bw_interface_type; + typedef sc_core::sc_port<bw_interface_type, N +#if !(defined SYSTEMC_VERSION & SYSTEMC_VERSION <= 20050714) + , POL +#endif + > port_type; + + typedef sc_core::sc_export<fw_interface_type> export_type; + typedef tlm_base_initiator_socket_b<BUSWIDTH, + fw_interface_type, + bw_interface_type> base_initiator_socket_type; + + typedef tlm_base_target_socket_b<BUSWIDTH, + fw_interface_type, + bw_interface_type> base_type; + + template <unsigned int, typename, typename, int +#if !(defined SYSTEMC_VERSION & SYSTEMC_VERSION <= 20050714) + ,sc_core::sc_port_policy +#endif + + > + friend class tlm_base_initiator_socket; + +public: + tlm_base_target_socket() + : export_type(sc_core::sc_gen_unique_name("tlm_base_target_socket")) + , m_port(sc_core::sc_gen_unique_name("tlm_base_target_socket_port")) + { + } + + explicit tlm_base_target_socket(const char* name) + : export_type(name) + , m_port(sc_core::sc_gen_unique_name((std::string(name) + "_port").c_str())) + { + } + + virtual const char* kind() const + { + return "tlm_base_target_socket"; + } + + unsigned int get_bus_width() const + { + return BUSWIDTH; + } + + // + // Bind target socket to initiator socket + // - Binds the port of the initiator socket to the export of the target + // socket + // - Binds the port of the target socket to the export of the initiator + // socket + // + virtual void bind(base_initiator_socket_type& s) + { + // initiator.port -> target.export + (s.get_base_port())(get_base_interface()); + // target.port -> initiator.export + get_base_port()(s.get_base_interface()); + } + + void operator() (base_initiator_socket_type& s) + { + bind(s); + } + + // + // Bind target socket to target socket (hierarchical bind) + // - Binds both the export and the port + // + virtual void bind(base_type& s) + { + // export + (get_base_export())(s.get_base_export()); + // port + (s.get_base_port())(get_base_port()); + } + + void operator() (base_type& s) + { + bind(s); + } + + // + // Bind interface to socket + // - Binds the interface to the export + // + virtual void bind(fw_interface_type& ifs) + { + export_type* exp = &get_base_export(); + if( this == exp ) { + export_type::bind( ifs ); // non-virtual function call + } else { + exp->bind( ifs ); + } + } + + void operator() (fw_interface_type& s) + { + bind(s); + } + + // + // Forward to 'size()' of port class + // + int size() const + { + return m_port.size(); + } + + // + // Forward to 'operator->()' of port class + // + bw_interface_type* operator->() + { + return m_port.operator->(); + } + + // + // Forward to 'operator[]()' of port class + // + bw_interface_type* operator[](int i) + { + return m_port.operator[](i); + } + + // Implementation of pure virtual functions of base class + + virtual sc_core::sc_port_b<BW_IF> & get_base_port() + { return m_port; } + virtual sc_core::sc_port_b<BW_IF> const & get_base_port() const + { return m_port; } + + virtual FW_IF & get_base_interface() + { return *this; } + virtual FW_IF const & get_base_interface() const +#if !( defined(IEEE_1666_SYSTEMC) && IEEE_1666_SYSTEMC >= 201101L ) + { return *const_cast<export_type*>(static_cast<export_type const*>(this)); } +#else + { return *this; } +#endif + + virtual sc_core::sc_export<FW_IF> & get_base_export() + { return *this; } + virtual sc_core::sc_export<FW_IF> const & get_base_export() const + { return *this; } + +protected: + port_type m_port; +}; + + +// +// Convenience blocking and non-blocking socket classes +// + +template <unsigned int BUSWIDTH = 32, + typename TYPES = tlm_base_protocol_types, + int N = 1 +#if !(defined SYSTEMC_VERSION & SYSTEMC_VERSION <= 20050714) + ,sc_core::sc_port_policy POL = sc_core::SC_ONE_OR_MORE_BOUND +#endif + > +class tlm_target_socket : + public tlm_base_target_socket <BUSWIDTH, + tlm_fw_transport_if<TYPES>, + tlm_bw_transport_if<TYPES>, + N +#if !(defined SYSTEMC_VERSION & SYSTEMC_VERSION <= 20050714) + ,POL +#endif + > +{ +public: + tlm_target_socket() : + tlm_base_target_socket<BUSWIDTH, + tlm_fw_transport_if<TYPES>, + tlm_bw_transport_if<TYPES>, + N +#if !(defined SYSTEMC_VERSION & SYSTEMC_VERSION <= 20050714) + ,POL +#endif + >() + { + } + + explicit tlm_target_socket(const char* name) : + tlm_base_target_socket<BUSWIDTH, + tlm_fw_transport_if<TYPES>, + tlm_bw_transport_if<TYPES>, + N +#if !(defined SYSTEMC_VERSION & SYSTEMC_VERSION <= 20050714) + ,POL +#endif + >(name) + { + } + + virtual const char* kind() const + { + return "tlm_target_socket"; + } +}; + +} // namespace tlm + +#endif diff --git a/ext/systemc/src/tlm_core/tlm_2/tlm_version.h b/ext/systemc/src/tlm_core/tlm_2/tlm_version.h new file mode 100644 index 000000000..e9b7a6569 --- /dev/null +++ b/ext/systemc/src/tlm_core/tlm_2/tlm_version.h @@ -0,0 +1,180 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/* --------------------------------------------------------------------------------------- + @file tlm_version.h + + @brief TLM version header + + Original Author: + Charles Wilson, XtremeEDA Corporation + + @description + This header contains preprocessor and compiler symbols to allow for the determination + of the TLM version information. This conforms to IEEE 1666-2005 section 8.5.5 - 8.5.7 + . + The following are provided: + . + preprocessor: TLM_VERSION_MAJOR numeric + TLM_VERSION_MINOR numeric + TLM_VERSION_PATCH numeric + TLM_VERSION_ORIGINATOR string ([A-Z][a-z][0-9]_) + TLM_VERSION_RELEASE_DATE ISO8601 date (YYYYMMDD) + TLM_VERSION_PRERELEASE string ([A-Z][a-z][0-9]_) + TLM_IS_PRERELEASE bool (1,0) + TLM_VERSION string {2.0.0_DR3-TLMWG} + TLM_COPYRIGHT string + . + compiler: tlm_version_major const unsigned int + tlm_version_minor const unsigned int + tlm_version_patch const unsigned int + tlm_version_originator const std::string + tlm_version_release_date const std::string + tlm_version_prerelease const std::string + tlm_is_prerelease const bool + tlm_version const string + tlm_copyright const string + . + accessors: inline const char* tlm_release (void) + inline const char* tlm_version (void) + inline const char* tlm_copyright (void) + +--------------------------------------------------------------------------------------- */ + +#ifndef __TLM_VERSION_H__ +#define __TLM_VERSION_H__ + +namespace tlm +{ + +#define TLM_VERSION_MAJOR 2 ///< version major level ( numeric ) +#define TLM_VERSION_MINOR 0 ///< version minor level ( numeric ) +#define TLM_VERSION_PATCH 3 ///< version patch level ( numeric ) +#define TLM_VERSION_ORIGINATOR "Accellera" ///< TLM creator string +#define TLM_VERSION_SEPARATOR "." ///< version string separator + +#define TLM_IS_PRERELEASE 0 ///< pre-release flag ( 1 / 0 ) + +#if TLM_IS_PRERELEASE +# define TLM_VERSION_PRERELEASE "pub_rev" ///< pre-release version string +#else +# define TLM_VERSION_PRERELEASE "" ///< pre-release version string +#endif + +#define TLM_VERSION_RELEASE_YEAR "2013" ///< release year ( YYYY ) +#define TLM_VERSION_RELEASE_MONTH "12" ///< release month ( MM ) +#define TLM_VERSION_RELEASE_DAY "15" ///< release day ( DD ) + +#define TLM_COPYRIGHT \ + "Copyright (c) 1996-" TLM_VERSION_RELEASE_YEAR " by all Contributors\n" \ + "ALL RIGHTS RESERVED" + +/************************** do not modify below this line *******************************/ + +/******************************* preprocessor symbols ***********************************/ + +#define TLM_VERSION_RELEASE_DATE TLM_VERSION_RELEASE_YEAR \ + TLM_VERSION_RELEASE_MONTH \ + TLM_VERSION_RELEASE_DAY + +#define TLM_VERSION_STR(x) TLM_VERSION_STR_HELPER(x) +#define TLM_VERSION_STR_HELPER(x) #x + +#define TLM_VERSION_STRING_MAJOR TLM_VERSION_STR(TLM_VERSION_MAJOR) +#define TLM_VERSION_STRING_MINOR TLM_VERSION_STR(TLM_VERSION_MINOR) +#define TLM_VERSION_STRING_PATCH TLM_VERSION_STR(TLM_VERSION_PATCH) + +#define TLM_VERSION_STRING_MMP TLM_VERSION_STRING_MAJOR TLM_VERSION_SEPARATOR \ + TLM_VERSION_STRING_MINOR TLM_VERSION_SEPARATOR \ + TLM_VERSION_STRING_PATCH + +#define TLM_VERSION_STRING_PRE_START "_" +#define TLM_VERSION_STRING_PRE_END "-" + +#if ( TLM_IS_PRERELEASE == 1 ) + +#define TLM_VERSION_STRING_PRERELEASE TLM_VERSION_PRERELEASE +#define TLM_VERSION_STRING_RELEASE_DATE "" + +#else /* TLM_IS_PRERELEASE == 1 */ + +#define TLM_VERSION_STRING_PRERELEASE "" +#define TLM_VERSION_STRING_RELEASE_DATE TLM_VERSION_RELEASE_DATE + +#endif /* TLM_IS_PRERELEASE == 1 */ + +#define TLM_VERSION_STRING TLM_VERSION_STRING_MMP \ + TLM_VERSION_STRING_PRE_START \ + TLM_VERSION_STRING_PRERELEASE \ + TLM_VERSION_STRING_PRE_END \ + TLM_VERSION_ORIGINATOR + +#define TLM_VERSION_STRING_2 "TLM " \ + TLM_VERSION_STRING_MMP \ + " --- " \ + TLM_VERSION_RELEASE_YEAR \ + "-" \ + TLM_VERSION_RELEASE_MONTH \ + "-" \ + TLM_VERSION_RELEASE_DAY + +#define TLM_VERSION TLM_VERSION_STRING + +/********************************* compiler symbols **************************************/ + +const unsigned int tlm_version_major ( TLM_VERSION_MAJOR ); +const unsigned int tlm_version_minor ( TLM_VERSION_MINOR ); +const unsigned int tlm_version_patch ( TLM_VERSION_PATCH ); + +const bool tlm_is_prerelease ( TLM_IS_PRERELEASE ); + +const std::string tlm_version_string ( TLM_VERSION_STRING ); +const std::string tlm_version_originator ( TLM_VERSION_ORIGINATOR ); +const std::string tlm_version_prerelease ( TLM_VERSION_PRERELEASE ); +const std::string tlm_version_release_date ( TLM_VERSION_STRING_RELEASE_DATE ); +const std::string tlm_copyright_string ( TLM_COPYRIGHT ); +const std::string tlm_version_string_2 ( TLM_VERSION_STRING_2 ); + +inline const char* +tlm_release +( void +) +{ + return tlm_version_string.c_str (); +} + +inline const char* +tlm_version +( void +) +{ + return tlm_version_string_2.c_str (); +} + +inline const char* +tlm_copyright +( void +) +{ + return tlm_copyright_string.c_str (); +} + +} // namespace tlm + +#endif /* __TLM_VERSION_H__ */ diff --git a/ext/systemc/src/tlm_utils/README.txt b/ext/systemc/src/tlm_utils/README.txt new file mode 100644 index 000000000..8be587bdf --- /dev/null +++ b/ext/systemc/src/tlm_utils/README.txt @@ -0,0 +1,85 @@ + +TLM-2.0 standard utilities +========================== + +Dir: include/tlm_utils + +SubDirs: + +Files: README.txt + instance_specific_extensions.h + multi_passthrough_initiator_socket.h + multi_passthrough_target_socket.h + multi_socket_bases.h + peq_with_get.h + simple_initiator_socket.h + simple_target_socket.h + peq_with_cb_and_phase.h + passthrough_target_socket.h + tlm_quantumkeeper.h + + +Comments +======== + +This directory contains a number of ease-of-use and convenience implementations +for the interoperability standard. All objects defined in the header files of +this directory are contained in the tlm_util namespace. +There is no tlm_utils.h header files containing all includes in order to avoid +additional dependencies for TLM 2.0 + +Files: + simple_initiator_socket.h + version of an initiator socket that has a default implementation of all + interfaces and allows to register an implementation for any of the + interfaces to the socket, either unique interfaces or tagged interfaces + (carrying an additional id) + + simple_target_socket.h + version of a target socket that has a default implementation of all + interfaces and allows to register an implementation for any of the + interfaces to the socket, either unique interfaces or tagged interfaces + (carrying an additional id) + This socket allows to register only 1 of the transport interfaces + (blocking or non-blocking) and implements a conversion in case the + socket is used on the other interface + + passthrough_target_socket.h + version of a target socket that has a default implementation of all + interfaces and allows to register an implementation for any of the + interfaces to the socket. + + multi_passthrough_initiator_socket.h + an implementation of a socket that allows to bind multiple targets to the + same initiator socket. Implements a mechanism to allow to identify in the + backward path through which index of the socket the call passed through + + multi_passthrough_target_socket.h + an implementation of a socket that allows to bind multiple initiators to + the same target socket. Implements a mechanism to allow to identify in the + forward path through which index of the socket the call passed through + + multi_socket_bases.h + contains base class definitions used by the multi_passthrough sockets + + peq_with_get.h + payload event queue (PEQ) implementation using a pull interface. + Has a get_next_transaction API that returns the transaction that is + scheduled in the event queue + + peq_with_cb_and_phase.h + another payload event queue, this one with a push interface (callback + mechanism ). Allows to register a callback that will be called whenever + the event in the event queue is triggered, the callback gets transaction + and phase as arguments + + instance_specific_extensions.h + is an implementation for adding extentions in the generic payload that + are specific to an instance along the path of a transaction, to allow that + extentions of the same type can be used by the different blocks along + the path of the transaction + + tlm_quantumkeeper.h + is an convenience object used to keep track of the local time in + an initiator (how much it has run ahead of the SystemC time), to + synchronize with SystemC time etc. diff --git a/ext/systemc/src/tlm_utils/instance_specific_extensions.h b/ext/systemc/src/tlm_utils/instance_specific_extensions.h new file mode 100644 index 000000000..b17b86219 --- /dev/null +++ b/ext/systemc/src/tlm_utils/instance_specific_extensions.h @@ -0,0 +1,306 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/* +Instance specific extensions, are extension that only a single instance of a module +may access. They are invisible to all other modules; they are private to this +instance so to speak. + +As they are only of value to a certain instance, this instance knows very well +when it needs them and when it does not need them any longer (usually when +a transaction passes through a module for the last time). +It does not have to care if anyone else in the system may still have a +reference to the transaction as this one is not able to access the extension +anyway. +Therefore the instance is obliged to call set_extension when it wants to add a +private extension and clear_extension when it does not need it any more. + +To get access to an instance specifc extension the module must own a so called +instance_specific_extension_accessor that provides the exclusive access rights. +Assuming the instance_specific_extension_accessor of a given module is called m_accessor +and the transaction of which the private extension is about to be accessed +is called txn, then the calls have to be + +m_accessor(txn).set_extension(...); +or +m_accessor(txn).clear_extension(...); + +The owner of the private extension is responsible to allocate/deallocate +the extension before/after setting/clearing the extension. +*/ + +#ifndef __INSTANCE_SPECIFIC_EXTENSIONS_H__ +#define __INSTANCE_SPECIFIC_EXTENSIONS_H__ + +#include <tlm> + +namespace tlm_utils { + +//Helper to do the numbering of private extension accessors +inline unsigned int max_num_ispex_accessors(bool increment=false) +{ + static unsigned int max_num = 0; + if (increment) ++max_num; + return max_num; +} + +//Helper to do the index generation for private extensions +inline unsigned int max_num_ispex(bool increment=false) +{ + static unsigned int max_num = 0; + if (increment) ++max_num; + return max_num; +} + +//The private extension base. Similar to normal extension base, but without clone and free +class ispex_base +{ +public: + virtual ~ispex_base() {} +protected: + static unsigned int register_private_extension() + { + return (max_num_ispex(true) - 1); + }; +}; + +//The templated private extension. Similar to normal extension +template <typename T> +class +instance_specific_extension : public ispex_base{ +public: + virtual ~instance_specific_extension() {} + const static unsigned int priv_id; +}; + +template <typename T> +const +unsigned int instance_specific_extension<T>::priv_id = ispex_base::register_private_extension(); + + +//this thing is basically a snippet of the generic_payload +// it contains all the extension specific code (the extension API so to speak) +// the differences are: +// - it calls back to its owner whenever a real (==non-NULL) extension gets set for the first time +// - it calls back to its owner whenever a living (==non-NULL) extension gets cleared +template<typename U> +class instance_specific_extensions_per_accessor{ +public: + + typedef void (U::*cb)(); + + instance_specific_extensions_per_accessor(U* container, cb inc, cb dec): m_container(container), m_inc(inc), m_dec(dec){ + } + + template <typename T> T* set_extension(T* ext) + { + resize_extensions(); + T* tmp = static_cast<T*>(m_extensions[T::priv_id]); + m_extensions[T::priv_id] = static_cast<ispex_base*>(ext); + if (!tmp && ext) (m_container->*m_inc)(); + return tmp; + } + // non-templatized version with manual index: + ispex_base* set_extension(unsigned int index, + ispex_base* ext) + { + resize_extensions(); + ispex_base* tmp = m_extensions[index]; + m_extensions[index] = ext; + if (!tmp && ext) (m_container->*m_inc)(); + return tmp; + } + + // Check for an extension, ext will point to 0 if not present + template <typename T> void get_extension(T*& ext) const + { + ext = static_cast<T*>(m_extensions[T::priv_id]); + } + // Non-templatized version: + ispex_base* get_extension(unsigned int index) const + { + return m_extensions[index]; + } + + // Clear extension, the argument is needed to find the right index: + template <typename T> void clear_extension(const T* ext) + { + resize_extensions(); + if (m_extensions[T::priv_id]) (m_container->*m_dec)(); + m_extensions[T::priv_id] = static_cast<ispex_base*>(0); + } + // Non-templatized version with manual index + void clear_extension(unsigned int index) + { + if (index < m_extensions.size()) + { + if (m_extensions[index]) (m_container->*m_dec)(); + m_extensions[index] = static_cast<ispex_base*>(0); + } + } + + // Make sure the extension array is large enough. Can be called once by + // an initiator module (before issuing the first transaction) to make + // sure that the extension array is of correct size. This is only needed + // if the initiator cannot guarantee that the generic payload object is + // allocated after C++ static construction time. + void resize_extensions() + { + m_extensions.expand(max_num_ispex()); + } + +private: + tlm::tlm_array<ispex_base*> m_extensions; + U* m_container; + cb m_inc, m_dec; + +}; + +class instance_specific_extension_container; + + +//the pool for the container, plain as can be +class instance_specific_extension_container_pool{ + friend class instance_specific_extension_carrier; + friend class instance_specific_extension_container; + instance_specific_extension_container_pool() : unused(NULL){} + inline ~instance_specific_extension_container_pool(); + inline static instance_specific_extension_container_pool& get_ispexcont_pool(){ static instance_specific_extension_container_pool tmp; return tmp;} + inline instance_specific_extension_container* create(); + inline void free(instance_specific_extension_container*); + + instance_specific_extension_container* unused; +}; + +class instance_specific_extension_carrier; + +//this thing contains the vector of extensions per accessor +//which can be really large so this one should be pool allocated +// therefore it keeps a use_count of itself to automatically free itself +// - to this end it provides callbacks to the extensions per accessor +// to increment and decrement the use_count +class instance_specific_extension_container{ + friend class instance_specific_extension_container_pool; + friend class instance_specific_extension_accessor; + friend class instance_specific_extension_carrier; + + instance_specific_extension_container(): use_count(0), next(NULL){resize();} + + void resize(){ + m_ispex_per_accessor.resize(max_num_ispex_accessors()); + for (unsigned int i=0; i<m_ispex_per_accessor.size(); i++) { + m_ispex_per_accessor[i]=new instance_specific_extensions_per_accessor<instance_specific_extension_container>(this, + &instance_specific_extension_container::inc_use_count, + &instance_specific_extension_container::dec_use_count + ); + m_ispex_per_accessor[i]->resize_extensions(); + } + } + + ~instance_specific_extension_container(){ + for (unsigned int i=0; i<m_ispex_per_accessor.size(); i++) delete m_ispex_per_accessor[i]; + } + + void inc_use_count(){use_count++;} + inline void dec_use_count(); + + std::vector<instance_specific_extensions_per_accessor<instance_specific_extension_container>* > m_ispex_per_accessor; + unsigned int use_count; + tlm::tlm_generic_payload* my_txn; + instance_specific_extension_carrier* my_carrier; + instance_specific_extension_container* next; //for pooling +}; + + +inline instance_specific_extension_container_pool::~instance_specific_extension_container_pool(){ + while(unused) { instance_specific_extension_container* tmp=unused; unused=unused->next; delete tmp;} +} + +instance_specific_extension_container* instance_specific_extension_container_pool::create(){ + if (!unused) {unused=new instance_specific_extension_container();} + instance_specific_extension_container* tmp=unused; + unused=unused->next; + return tmp; +} + +void instance_specific_extension_container_pool::free(instance_specific_extension_container* cont){ + cont->next=unused; + unused=cont; +} + +//This is the class that actually sits in the extension array +//we keep this small since that one gets allocated and deallocated all the times +class instance_specific_extension_carrier: public tlm::tlm_extension<instance_specific_extension_carrier>{ + friend class instance_specific_extension_accessor; + +public: + instance_specific_extension_carrier(){ + m_container=instance_specific_extension_container_pool::get_ispexcont_pool().create(); + m_container->my_carrier=this; + } + + virtual tlm::tlm_extension_base* clone() const { + //we don't clone since private info is instance specific and associated to a given txn (the original) + //so the deep copied txn will be virgin in terms of private info + return NULL; + } + void copy_from(tlm::tlm_extension_base const &){return;} + void free(){return;} +private: + instance_specific_extension_container* m_container; +}; + +inline void instance_specific_extension_container::dec_use_count(){ + if ((--use_count)==0) { //if this container isn't used any more + instance_specific_extension_container_pool::get_ispexcont_pool().free(this); //we send it back to our pool + //we have to do that manually, as we cannot rely on the fact that there is MM in the txn + my_txn->clear_extension(my_carrier); //and remove it from the transaction's extension array + delete my_carrier; + } +} + + +//This class 'hides' all the instance specific extension stuff from the user +// he instantiates one of those (e.g. instance_specific_extension_accessor extAcc;) and can then access +// the private extensions +// extAcc(txn).extensionAPIFnCall() +// where extensionAPIFnCall is set_extension, get_extension, clear_extension,... +class instance_specific_extension_accessor{ +public: + instance_specific_extension_accessor(): m_index(max_num_ispex_accessors(true)-1){} + + template<typename T> + inline instance_specific_extensions_per_accessor<instance_specific_extension_container>& operator()(T& txn){ + instance_specific_extension_carrier* carrier; + txn.get_extension(carrier); + if (!carrier){ + carrier=new instance_specific_extension_carrier(); + carrier->m_container->my_txn=&txn; + txn.set_extension(carrier); + } + return *(carrier->m_container->m_ispex_per_accessor[m_index]); + } + +protected: + unsigned int m_index; +}; + +} + +#endif diff --git a/ext/systemc/src/tlm_utils/multi_passthrough_initiator_socket.h b/ext/systemc/src/tlm_utils/multi_passthrough_initiator_socket.h new file mode 100644 index 000000000..6404d84bb --- /dev/null +++ b/ext/systemc/src/tlm_utils/multi_passthrough_initiator_socket.h @@ -0,0 +1,299 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ +#ifndef __MULTI_PASSTHROUGH_INITIATOR_SOCKET_H__ +#define __MULTI_PASSTHROUGH_INITIATOR_SOCKET_H__ + +#include "multi_socket_bases.h" + +namespace tlm_utils { + +/* +This class implements a trivial multi initiator socket. +The triviality refers to the fact that the socket does not +do blocking to non-blocking or non-blocking to blocking conversions. + +It allows to connect multiple targets to this socket. +The user has to register callbacks for the bw interface methods +he likes to use. The callbacks are basically equal to the bw interface +methods but carry an additional integer that indicates to which +index of this socket the calling target is connected. +*/ +template <typename MODULE, + unsigned int BUSWIDTH = 32, + typename TYPES = tlm::tlm_base_protocol_types, + unsigned int N=0 +#if !(defined SYSTEMC_VERSION & SYSTEMC_VERSION <= 20050714) + ,sc_core::sc_port_policy POL = sc_core::SC_ONE_OR_MORE_BOUND +#endif + > +class multi_passthrough_initiator_socket: public multi_init_base< BUSWIDTH, + TYPES, + N +#if !(defined SYSTEMC_VERSION & SYSTEMC_VERSION <= 20050714) + ,POL +#endif + > +{ + +public: + + //typedefs + // tlm 2.0 types for nb_transport + typedef typename TYPES::tlm_payload_type transaction_type; + typedef typename TYPES::tlm_phase_type phase_type; + typedef tlm::tlm_sync_enum sync_enum_type; + + // typedefs to keep the fn ptr notations short + typedef sync_enum_type (MODULE::*nb_cb)(int, + transaction_type&, + phase_type&, + sc_core::sc_time&); + typedef void (MODULE::*dmi_cb)(int, sc_dt::uint64, sc_dt::uint64); + + typedef multi_init_base<BUSWIDTH, + TYPES, + N +#if !(defined SYSTEMC_VERSION & SYSTEMC_VERSION <= 20050714) + ,POL +#endif + > base_type; + + typedef typename base_type::base_target_socket_type base_target_socket_type; + + //CTOR + multi_passthrough_initiator_socket() + : base_type(sc_core::sc_gen_unique_name("multi_passthrough_initiator_socket")) + , m_hierarch_bind(0) + , m_beoe_disabled(false) + , m_dummy(42) + { + } + + //CTOR + multi_passthrough_initiator_socket(const char* name) + : base_type(name) + , m_hierarch_bind(0) + , m_beoe_disabled(false) + , m_dummy(42) + { + } + + ~multi_passthrough_initiator_socket(){ + //clean up everything allocated by 'new' + for (unsigned int i=0; i<m_binders.size(); i++) delete m_binders[i]; + } + + //simple helpers for warnings an errors to shorten in code notation + void display_warning(const std::string& text) const { + std::stringstream s; + s<<"WARNING in instance "<<base_type::name()<<": "<<text; + SC_REPORT_WARNING("/OSCI_TLM-2/multi_socket", s.str().c_str()); + } + + void display_error(const std::string& text) const { + std::stringstream s; + s<<"ERROR in instance "<<base_type::name()<<": "<<text; + SC_REPORT_ERROR("/OSCI_TLM-2/multi_socket", s.str().c_str()); + } + + + //register callback for nb transport of bw interface + void register_nb_transport_bw(MODULE* mod, + sync_enum_type (MODULE::*cb)(int, + transaction_type&, + phase_type&, + sc_core::sc_time&)) + { + //warn if there already is a callback + if (!m_nb_f.empty()){ + display_warning("NBTransport_bw callback already registered."); + return; + } + + //set the functor + m_nb_f.set_function(mod, cb); + } + + //register callback for dmi function of bw interface + void register_invalidate_direct_mem_ptr(MODULE* mod, + void (MODULE::*cb)(int, sc_dt::uint64, sc_dt::uint64)) + { + //warn if there already is a callback + if (!m_dmi_f.empty()){ + display_warning("InvalidateDMI callback already registered."); + return; + } + + //set the functor + m_dmi_f.set_function(mod, cb); + } + + //Override virtual functions of the tlm_initiator_socket: + // this function is called whenever an sc_port (as part of a target socket) + // wants to bind to the export of the underlying tlm_initiator_socket + //At this time a callback binder is created an returned to the sc_port + // of the target socket, so that it binds to the callback binder + virtual tlm::tlm_bw_transport_if<TYPES>& get_base_interface() + { + m_binders.push_back(new callback_binder_bw<TYPES>(m_binders.size())); + return *m_binders[m_binders.size()-1]; + } + + // const overload not allowed for multi-sockets + virtual const tlm::tlm_bw_transport_if<TYPES>& get_base_interface() const + { + display_error("'get_base_interface()' const not allowed for multi-sockets."); + return base_type::get_base_interface(); + } + + //Override virtual functions of the tlm_initiator_socket: + // this function is called whenever an sc_export (as part of a initiator socket) + // wants to bind to the export of the underlying tlm_initiator_socket + // i.e. a hierarchical bind takes place + virtual sc_core::sc_export<tlm::tlm_bw_transport_if<TYPES> >& get_base_export() + { + if (!m_beoe_disabled) //we are not bound hierarchically + base_type::m_export.bind(m_dummy); //so we bind the dummy to avoid a SystemC error + return base_type::get_base_export(); //and then return our own export so that the hierarchical binding is set up properly + } + + virtual const sc_core::sc_export<tlm::tlm_bw_transport_if<TYPES> >& get_base_export() const + { + return base_type::get_base_export(); + } + + //bind against a target socket + virtual void bind(base_target_socket_type& s) + { + //error if this socket is already bound hierarchically + if (m_hierarch_bind) + display_error("Already hierarchically bound."); + + base_type::bind(s); //satisfy systemC, leads to a call to get_base_interface() + + //try to cast the target socket into a fw interface + sc_core::sc_export<tlm::tlm_fw_transport_if<TYPES> >* p_ex_s=dynamic_cast<sc_core::sc_export<tlm::tlm_fw_transport_if<TYPES> >*>(&s); + if (!p_ex_s) display_error("Multi socket not bound to tlm_socket."); + + //try a cast into a multi sockets + multi_to_multi_bind_base<TYPES>* test=dynamic_cast<multi_to_multi_bind_base<TYPES>*> (p_ex_s); + if (test) //did we just do a multi-multi bind?? + //if that is the case the multi target socket must have just created a callback binder + // which we want to get from it. + //Moreover, we also just created one, which we will pass to it. + m_sockets.push_back(test->get_last_binder(m_binders[m_binders.size()-1])); + else{ // if not just bind normally + sc_core::sc_export<tlm::tlm_fw_transport_if<TYPES> >& ex_s=*p_ex_s; + m_sockets.push_back(&((tlm::tlm_fw_transport_if<TYPES>&)ex_s)); //store the interface we are bound against + } + } + + //operator notation for direct bind + void operator() (base_target_socket_type& s) + { + bind(s); + } + + //SystemC standard callback before end of elaboration + void before_end_of_elaboration(){ + //if our export hasn't been bound yet (due to a hierarch binding) + // we bind it now to avoid a SystemC error. + //We must do that, because it is legal not to register a callback on this socket + // as the user might only use b_transport + if (!base_type::m_export.get_interface()){ + base_type::m_export.bind(m_dummy); + } + + //'break' here if the socket was told not to do callback binding + if (m_beoe_disabled) return; + + //get the callback binders of the top of the hierachical bind chain + // NOTE: this could be the same socket if there is no hierachical bind + std::vector<callback_binder_bw<TYPES>* >& binders=get_hierarch_bind()->get_binders(); + + //get the interfaces bound to the top of the hierachical bind chain + // NOTE: this could be the same socket if there is no hierachical bind + m_used_sockets=get_hierarch_bind()->get_sockets(); + + //register the callbacks of this socket with the callback binders + // we just got from the top of the hierachical bind chain + for (unsigned int i=0; i<binders.size(); i++) { + binders[i]->set_callbacks(m_nb_f, m_dmi_f); + } + } + + // + // Bind multi initiator socket to multi initiator socket (hierarchical bind) + // + virtual void bind(base_type& s) + { + if (m_binders.size()) //a multi socket is either bound hierarchically or directly + display_error("Socket already directly bound."); + if (m_hierarch_bind){ + display_warning("Socket already bound hierarchically. Bind attempt ignored."); + return; + } + + //remember to which socket we are hierarchically bound and disable it, + // so that it won't try to register callbacks itself + s.disable_cb_bind(); + m_hierarch_bind=&s; + base_type::bind(s); //satisfy SystemC + } + + //operator notation for hierarchical bind + void operator() (base_type& s) + { + bind(s); + } + + //get access to sub port + tlm::tlm_fw_transport_if<TYPES>* operator[](int i){return m_used_sockets[i];} + + //get the number of bound targets + // NOTE: this is only valid at end of elaboration! + unsigned int size() {return get_hierarch_bind()->get_sockets().size();} + +protected: + //implementation of base class interface + base_type* get_hierarch_bind(){if (m_hierarch_bind) return m_hierarch_bind->get_hierarch_bind(); else return this;} + void disable_cb_bind(){ m_beoe_disabled=true;} + std::vector<callback_binder_bw<TYPES>* >& get_binders(){return m_binders;} + std::vector<tlm::tlm_fw_transport_if<TYPES>*>& get_sockets(){return m_sockets;} + //vector of connected sockets + std::vector<tlm::tlm_fw_transport_if<TYPES>*> m_sockets; + std::vector<tlm::tlm_fw_transport_if<TYPES>*> m_used_sockets; + //vector of binders that convert untagged interface into tagged interface + std::vector<callback_binder_bw<TYPES>*> m_binders; + + base_type* m_hierarch_bind; //pointer to hierarchical bound multi port + bool m_beoe_disabled; // bool that remembers whether this socket shall bind callbacks or not + callback_binder_bw<TYPES> m_dummy; //a callback binder that is bound to the underlying export + // in case there was no real bind + + //callbacks as functors + // (allows to pass the callback to another socket that does not know the type of the module that owns + // the callbacks) + typename callback_binder_bw<TYPES>::nb_func_type m_nb_f; + typename callback_binder_bw<TYPES>::dmi_func_type m_dmi_f; +}; + +} + +#endif diff --git a/ext/systemc/src/tlm_utils/multi_passthrough_target_socket.h b/ext/systemc/src/tlm_utils/multi_passthrough_target_socket.h new file mode 100644 index 000000000..03270f7a1 --- /dev/null +++ b/ext/systemc/src/tlm_utils/multi_passthrough_target_socket.h @@ -0,0 +1,340 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ +#ifndef __MULTI_PASSTHROUGH_TARGET_SOCKET_H__ +#define __MULTI_PASSTHROUGH_TARGET_SOCKET_H__ + +#include "tlm_utils/multi_socket_bases.h" +#include <sstream> + +namespace tlm_utils { + +/* +This class implements a trivial multi target socket. +The triviality refers to the fact that the socket does not +do blocking to non-blocking or non-blocking to blocking conversions. + +It allows to connect multiple initiators to this socket. +The user has to register callbacks for the fw interface methods +he likes to use. The callbacks are basically equal to the fw interface +methods but carry an additional integer that indicates to which +index of this socket the calling initiator is connected. +*/ +template <typename MODULE, + unsigned int BUSWIDTH = 32, + typename TYPES = tlm::tlm_base_protocol_types, + unsigned int N=0 +#if !(defined SYSTEMC_VERSION & SYSTEMC_VERSION <= 20050714) + ,sc_core::sc_port_policy POL = sc_core::SC_ONE_OR_MORE_BOUND +#endif + > +class multi_passthrough_target_socket: public multi_target_base< BUSWIDTH, + TYPES, + N +#if !(defined SYSTEMC_VERSION & SYSTEMC_VERSION <= 20050714) + ,POL +#endif + > + , public multi_to_multi_bind_base<TYPES> +{ + +public: + + //typedefs + // tlm 2.0 types for nb_transport + typedef typename TYPES::tlm_payload_type transaction_type; + typedef typename TYPES::tlm_phase_type phase_type; + typedef tlm::tlm_sync_enum sync_enum_type; + + // typedefs to keep the fn ptr notations short + typedef sync_enum_type (MODULE::*nb_cb)(int, transaction_type&, phase_type&, sc_core::sc_time&); + typedef void (MODULE::*b_cb)(int, transaction_type&, sc_core::sc_time&); + typedef unsigned int (MODULE::*dbg_cb)(int, transaction_type& txn); + typedef bool (MODULE::*dmi_cb)(int, transaction_type& txn, tlm::tlm_dmi& dmi); + + typedef multi_target_base<BUSWIDTH, + TYPES, + N +#if !(defined SYSTEMC_VERSION & SYSTEMC_VERSION <= 20050714) + ,POL +#endif + > base_type; + + typedef typename base_type::base_initiator_socket_type base_initiator_socket_type; + + //CTOR + multi_passthrough_target_socket() + : base_type(sc_core::sc_gen_unique_name("multi_passthrough_target_socket")) + , m_hierarch_bind(0) + , m_eoe_disabled(false) + , m_export_callback_created(false) + { + } + + //CTOR + multi_passthrough_target_socket(const char* name) + : base_type(name) + , m_hierarch_bind(0) + , m_eoe_disabled(false) + , m_export_callback_created(false) + { + } + + ~multi_passthrough_target_socket(){ + //clean up everything allocated by 'new' + for (unsigned int i=0; i<m_binders.size(); i++) delete m_binders[i]; + } + + //simple helpers for warnings an errors to shorten in code notation + void display_warning(const std::string& text) const { + std::stringstream s; + s<<"WARNING in instance "<<base_type::name()<<": "<<text; + SC_REPORT_WARNING("/OSCI_TLM-2/multi_socket", s.str().c_str()); + } + + void display_error(const std::string& text) const { + std::stringstream s; + s<<"ERROR in instance "<<base_type::name()<<": "<<text; + SC_REPORT_ERROR("/OSCI_TLM-2/multi_socket", s.str().c_str()); + } + + void check_export_binding() + { + //if our export hasn't been bound yet (due to a hierarch binding) + // we bind it now. + //We do that here as the user of the target port HAS to bind at least on callback, + //otherwise the socket was useless. Nevertheless, the target socket may still + // stay unbound afterwards. + if (!sc_core::sc_export<tlm::tlm_fw_transport_if<TYPES> >::get_interface()) + { + // We bind to a callback_binder that will be used as the first interface + // i.e. calls to the sc_export will have the same ID as calls from the first initator + // socket bound + callback_binder_fw<TYPES> * binder; + + if (m_binders.size() == 0) + { + binder = new callback_binder_fw<TYPES>(m_binders.size()); + m_binders.push_back(binder); + m_export_callback_created = true; + } + else + { + binder = m_binders[0]; + } + + sc_core::sc_export<tlm::tlm_fw_transport_if<TYPES> >::bind(*binder); + } + } + + //register callback for nb transport of fw interface + void register_nb_transport_fw(MODULE* mod, + nb_cb cb) + { + check_export_binding(); + + //warn if there already is a callback + if (!m_nb_f.empty()){ + display_warning("NBTransport_bw callback already registered."); + return; + } + + //set the functor + m_nb_f.set_function(mod, cb); + } + + //register callback for b transport of fw interface + void register_b_transport(MODULE* mod, + b_cb cb) + { + check_export_binding(); + + //warn if there already is a callback + if (!m_b_f.empty()){ + display_warning("BTransport callback already registered."); + return; + } + + //set the functor + m_b_f.set_function(mod, cb); + } + + //register callback for debug transport of fw interface + void register_transport_dbg(MODULE* mod, + dbg_cb cb) + { + check_export_binding(); + + //warn if there already is a callback + if (!m_dbg_f.empty()){ + display_warning("DebugTransport callback already registered."); + return; + } + + //set the functor + m_dbg_f.set_function(mod, cb); + } + + //register callback for DMI of fw interface + void register_get_direct_mem_ptr(MODULE* mod, + dmi_cb cb) + { + check_export_binding(); + + //warn if there already is a callback + if (!m_dmi_f.empty()){ + display_warning("DMI callback already registered."); + return; + } + + //set the functor + m_dmi_f.set_function(mod, cb); + } + + + //Override virtual functions of the tlm_target_socket: + // this function is called whenever an sc_port (as part of a init socket) + // wants to bind to the export of the underlying tlm_target_socket + //At this time a callback binder is created an returned to the sc_port + // of the init socket, so that it binds to the callback binder + virtual tlm::tlm_fw_transport_if<TYPES>& get_base_interface() + { + //error if this socket is already bound hierarchically + if (m_hierarch_bind) display_error("Socket already bound hierarchically."); + + if (!m_export_callback_created) + m_binders.push_back(new callback_binder_fw<TYPES>(m_binders.size())); + else + m_export_callback_created = false; + + return *m_binders[m_binders.size()-1]; + } + + // const overload not allowed for multi-sockets + virtual const tlm::tlm_fw_transport_if<TYPES>& get_base_interface() const + { + display_error("'get_base_interface()' const not allowed for multi-sockets."); + return base_type::get_base_interface(); + } + + //just return the export of the underlying tlm_target_socket in case of a hierarchical bind + virtual sc_core::sc_export<tlm::tlm_fw_transport_if<TYPES> >& get_base_export() + { + return *this; + } + + //just return the export of the underlying tlm_target_socket in case of a hierarchical bind + virtual const sc_core::sc_export<tlm::tlm_fw_transport_if<TYPES> >& get_base_export() const + { + return base_type::get_base_export(); + } + + //the standard end of elaboration callback + void end_of_elaboration(){ + //'break' here if the socket was told not to do callback binding + if (m_eoe_disabled) return; + + //get the callback binders and the multi binds of the top of the hierachical bind chain + // NOTE: this could be the same socket if there is no hierachical bind + std::vector<callback_binder_fw<TYPES>* >& binders=get_hierarch_bind()->get_binders(); + std::map<unsigned int, tlm::tlm_bw_transport_if<TYPES>*>& multi_binds=get_hierarch_bind()->get_multi_binds(); + + //iterate over all binders + for (unsigned int i=0; i<binders.size(); i++) { + binders[i]->set_callbacks(m_nb_f, m_b_f, m_dmi_f, m_dbg_f); //set the callbacks for the binder + if (multi_binds.find(i)!=multi_binds.end()) //check if this connection is multi-multi + //if so remember the interface + m_sockets.push_back(multi_binds[i]); + else{ //if we are bound to a normal socket + //get the calling port and try to cast it into a tlm socket base + base_initiator_socket_type* test=dynamic_cast<base_initiator_socket_type*>(binders[i]->get_other_side()); + if (!test){display_error("Not bound to tlm_socket.");} + m_sockets.push_back(&test->get_base_interface()); //remember the interface + } + } + } + + // + // Bind multi target socket to multi target socket (hierarchical bind) + // + virtual void bind(base_type& s) + { + //warn if already bound hierarchically + if (m_eoe_disabled){ + display_warning("Socket already bound hierarchically. Bind attempt ignored."); + return; + } + + //disable our own end of elaboration call + disable_cb_bind(); + + //inform the bound target socket that it is bound hierarchically now + s.set_hierarch_bind((base_type*)this); + base_type::bind(s); //satisfy SystemC + } + + //operator notation for hierarchical bind + void operator() (base_type& s) + { + bind(s); + } + + //get access to sub port + tlm::tlm_bw_transport_if<TYPES>* operator[](int i){return m_sockets[i];} + + //get number of bound initiators + // NOTE: this is only valid at end of elaboration! + unsigned int size(){return get_hierarch_bind()->get_binders().size();} + +protected: + //implementation of base class interface + base_type* get_hierarch_bind(){if (m_hierarch_bind) return m_hierarch_bind->get_hierarch_bind(); else return this;} + std::map<unsigned int, tlm::tlm_bw_transport_if<TYPES>*>& get_multi_binds(){return m_multi_binds;} + void set_hierarch_bind(base_type* h){m_hierarch_bind=h;} + tlm::tlm_fw_transport_if<TYPES>* get_last_binder(tlm::tlm_bw_transport_if<TYPES>* other){ + m_multi_binds[m_binders.size()-1]=other; + return m_binders[m_binders.size()-1]; + } + + //map that stores to which index a multi init socket is connected + // and the interface of the multi init socket + std::map<unsigned int, tlm::tlm_bw_transport_if<TYPES>*> m_multi_binds; + + void disable_cb_bind(){ m_eoe_disabled=true;} + std::vector<callback_binder_fw<TYPES>* >& get_binders(){return m_binders;} + //vector of connected sockets + std::vector<tlm::tlm_bw_transport_if<TYPES>*> m_sockets; + //vector of binders that convert untagged interface into tagged interface + std::vector<callback_binder_fw<TYPES>*> m_binders; + + base_type* m_hierarch_bind; //pointer to hierarchical bound multi port + bool m_eoe_disabled; //bool that diables callback bindings at end of elaboration + bool m_export_callback_created; // bool to indicate that a callback has already been created for export binding + + //callbacks as functors + // (allows to pass the callback to another socket that does not know the type of the module that owns + // the callbacks) + typename callback_binder_fw<TYPES>::nb_func_type m_nb_f; + typename callback_binder_fw<TYPES>::b_func_type m_b_f; + typename callback_binder_fw<TYPES>::debug_func_type m_dbg_f; + typename callback_binder_fw<TYPES>::dmi_func_type m_dmi_f; +}; + +} + +#endif diff --git a/ext/systemc/src/tlm_utils/multi_socket_bases.h b/ext/systemc/src/tlm_utils/multi_socket_bases.h new file mode 100644 index 000000000..457398495 --- /dev/null +++ b/ext/systemc/src/tlm_utils/multi_socket_bases.h @@ -0,0 +1,418 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +#ifndef __MULTI_SOCKET_BASES_H__ +#define __MULTI_SOCKET_BASES_H__ + +#include <systemc> +#include <tlm> + +#include <map> +#include <sstream> + +namespace tlm_utils { + +template <typename signature> +struct fn_container{ + signature function; +}; + +#define TLM_DEFINE_FUNCTOR(name) \ +template <typename MODULE, typename TRAITS> \ +inline TLM_RET_VAL static_##name( void* mod \ + , void* fn \ + , int index \ + , TLM_FULL_ARG_LIST) \ +{ \ + typedef fn_container<TLM_RET_VAL (MODULE::*)(int, TLM_FULL_ARG_LIST)> fn_container_type; \ + MODULE* tmp_mod=static_cast<MODULE*>(mod); \ + fn_container_type* tmp_cb =static_cast<fn_container_type*> (fn); \ + return (tmp_mod->*(tmp_cb->function))(index, TLM_ARG_LIST_WITHOUT_TYPES); \ +}\ +\ +template <typename MODULE, typename TRAITS> \ +inline void delete_fn_container_of_##name(void* fn) \ +{ \ + typedef fn_container<TLM_RET_VAL (MODULE::*)(int, TLM_FULL_ARG_LIST)> fn_container_type; \ + fn_container_type* tmp_cb =static_cast<fn_container_type*> (fn); \ + if (tmp_cb) delete tmp_cb;\ +} \ +\ +template <typename TRAITS> \ +class name##_functor{ \ +public: \ + typedef typename TRAITS::tlm_payload_type payload_type; \ + typedef typename TRAITS::tlm_phase_type phase_type; \ + typedef TLM_RET_VAL (*call_fn)(void*,void*, int, TLM_FULL_ARG_LIST); \ + typedef void (*del_fn)(void*); \ +\ + name##_functor(): m_fn(0), m_del_fn(0), m_mod(0), m_mem_fn(0){} \ + ~name##_functor(){if (m_del_fn) (*m_del_fn)(m_mem_fn);} \ +\ + template <typename MODULE> \ + void set_function(MODULE* mod, TLM_RET_VAL (MODULE::*cb)(int, TLM_FULL_ARG_LIST)){ \ + typedef fn_container<TLM_RET_VAL (MODULE::*)(int, TLM_FULL_ARG_LIST)> fn_container_type; \ + m_fn=&static_##name<MODULE,TRAITS>;\ + m_del_fn=&delete_fn_container_of_##name<MODULE,TRAITS>;\ + m_del_fn(m_mem_fn); \ + fn_container_type* tmp= new fn_container_type(); \ + tmp->function=cb; \ + m_mod=static_cast<void*>(mod); \ + m_mem_fn=static_cast<void*>(tmp); \ + } \ + \ + TLM_RET_VAL operator()(int index, TLM_FULL_ARG_LIST){ \ + return m_fn(m_mod,m_mem_fn, index, TLM_ARG_LIST_WITHOUT_TYPES); \ + } \ +\ + bool empty(){return (m_mod==0 || m_mem_fn==0 || m_fn==0);}\ +\ +protected: \ + call_fn m_fn;\ + del_fn m_del_fn; \ + void* m_mod; \ + void* m_mem_fn; \ +private: \ + name##_functor& operator=(const name##_functor&); \ +} + + +#define TLM_RET_VAL tlm::tlm_sync_enum +#define TLM_FULL_ARG_LIST typename TRAITS::tlm_payload_type& txn, typename TRAITS::tlm_phase_type& ph, sc_core::sc_time& t +#define TLM_ARG_LIST_WITHOUT_TYPES txn,ph,t +TLM_DEFINE_FUNCTOR(nb_transport); +#undef TLM_RET_VAL +#undef TLM_FULL_ARG_LIST +#undef TLM_ARG_LIST_WITHOUT_TYPES + +#define TLM_RET_VAL void +#define TLM_FULL_ARG_LIST typename TRAITS::tlm_payload_type& txn, sc_core::sc_time& t +#define TLM_ARG_LIST_WITHOUT_TYPES txn,t +TLM_DEFINE_FUNCTOR(b_transport); +#undef TLM_RET_VAL +#undef TLM_FULL_ARG_LIST +#undef TLM_ARG_LIST_WITHOUT_TYPES + +#define TLM_RET_VAL unsigned int +#define TLM_FULL_ARG_LIST typename TRAITS::tlm_payload_type& txn +#define TLM_ARG_LIST_WITHOUT_TYPES txn +TLM_DEFINE_FUNCTOR(debug_transport); +#undef TLM_RET_VAL +#undef TLM_FULL_ARG_LIST +#undef TLM_ARG_LIST_WITHOUT_TYPES + +#define TLM_RET_VAL bool +#define TLM_FULL_ARG_LIST typename TRAITS::tlm_payload_type& txn, tlm::tlm_dmi& dmi +#define TLM_ARG_LIST_WITHOUT_TYPES txn,dmi +TLM_DEFINE_FUNCTOR(get_dmi_ptr); +#undef TLM_RET_VAL +#undef TLM_FULL_ARG_LIST +#undef TLM_ARG_LIST_WITHOUT_TYPES + +#define TLM_RET_VAL void +#define TLM_FULL_ARG_LIST sc_dt::uint64 l, sc_dt::uint64 u +#define TLM_ARG_LIST_WITHOUT_TYPES l,u +TLM_DEFINE_FUNCTOR(invalidate_dmi); +#undef TLM_RET_VAL +#undef TLM_FULL_ARG_LIST +#undef TLM_ARG_LIST_WITHOUT_TYPES + +#undef TLM_DEFINE_FUNCTOR + +/* +This class implements the fw interface. +It allows to register a callback for each of the fw interface methods. +The callbacks simply forward the fw interface call, but add the id (an int) +of the callback binder to the signature of the call. +*/ +template <typename TYPES> +class callback_binder_fw: public tlm::tlm_fw_transport_if<TYPES>{ + public: + //typedefs according to the used TYPES class + typedef typename TYPES::tlm_payload_type transaction_type; + typedef typename TYPES::tlm_phase_type phase_type; + typedef tlm::tlm_sync_enum sync_enum_type; + + //typedefs for the callbacks + typedef nb_transport_functor<TYPES> nb_func_type; + typedef b_transport_functor<TYPES> b_func_type; + typedef debug_transport_functor<TYPES> debug_func_type; + typedef get_dmi_ptr_functor<TYPES> dmi_func_type; + + //ctor: an ID is needed to create a callback binder + callback_binder_fw(int id): m_id(id), m_nb_f(0), m_b_f(0), m_dbg_f(0), m_dmi_f(0), m_caller_port(0) { + } + + //the nb_transport method of the fw interface + sync_enum_type nb_transport_fw(transaction_type& txn, + phase_type& p, + sc_core::sc_time& t){ + //check if a callback is registered + if ((m_nb_f == 0) || (m_nb_f && m_nb_f->empty())) { + //std::cerr<<"No function registered"<<std::endl; + SC_REPORT_ERROR("/OSCI_TLM-2/multi_socket","Call to nb_transport_fw without a registered callback for nb_transport_fw."); + } + else + return (*m_nb_f)(m_id, txn, p, t); //do the callback + return tlm::TLM_ACCEPTED; //unreachable + } + + //the b_transport method of the fw interface + void b_transport(transaction_type& trans,sc_core::sc_time& t){ + //check if a callback is registered + if ((m_b_f == 0) || (m_b_f && m_b_f->empty())) { + SC_REPORT_ERROR("/OSCI_TLM-2/multi_socket","Call to b_transport without a registered callback for b_transport."); + } + else + (*m_b_f)(m_id, trans,t); //do the callback + } + + //the DMI method of the fw interface + bool get_direct_mem_ptr(transaction_type& trans, tlm::tlm_dmi& dmi_data){ + //check if a callback is registered + if ((m_dmi_f == 0) && (m_dmi_f && m_dmi_f->empty())) { + dmi_data.allow_none(); + dmi_data.set_start_address(0x0); + dmi_data.set_end_address((sc_dt::uint64)-1); + return false; + } + else + return (*m_dmi_f)(m_id, trans,dmi_data); //do the callback + } + + //the debug method of the fw interface + unsigned int transport_dbg(transaction_type& trans){ + //check if a callback is registered + if ((m_dbg_f == 0) || (m_dbg_f && m_dbg_f->empty())) { + return 0; + } + else + return (*m_dbg_f)(m_id, trans); //do the callback + } + + //the SystemC standard callback register_port: + // - called when a port if bound to the interface + // - allowd to find out who is bound to that callback binder + void register_port(sc_core::sc_port_base& b, const char* name){ + m_caller_port=&b; + } + + //register callbacks for all fw interface methods at once + void set_callbacks(nb_func_type& cb1, b_func_type& cb2, dmi_func_type& cb3, debug_func_type& cb4){ + m_nb_f=&cb1; + m_b_f=&cb2; + m_dmi_f=&cb3; + m_dbg_f=&cb4; + } + + //getter method to get the port that is bound to that callback binder + // NOTE: this will only return a valid value at end of elaboration + // (but not before end of elaboration!) + sc_core::sc_port_base* get_other_side(){return m_caller_port;} + + private: + //the ID of the callback binder + int m_id; + + //the callbacks + nb_func_type* m_nb_f; + b_func_type* m_b_f; + debug_func_type* m_dbg_f; + dmi_func_type* m_dmi_f; + + //the port bound to that callback binder + sc_core::sc_port_base* m_caller_port; +}; + +/* +This class implements the bw interface. +It allows to register a callback for each of the bw interface methods. +The callbacks simply forward the bw interface call, but add the id (an int) +of the callback binder to the signature of the call. +*/ +template <typename TYPES> +class callback_binder_bw: public tlm::tlm_bw_transport_if<TYPES>{ + public: + //typedefs according to the used TYPES class + typedef typename TYPES::tlm_payload_type transaction_type; + typedef typename TYPES::tlm_phase_type phase_type; + typedef tlm::tlm_sync_enum sync_enum_type; + + //typedefs for the callbacks + typedef nb_transport_functor<TYPES> nb_func_type; + typedef invalidate_dmi_functor<TYPES> dmi_func_type; + + //ctor: an ID is needed to create a callback binder + callback_binder_bw(int id): m_id(id), m_nb_f(0), m_dmi_f(0) { + } + + //the nb_transport method of the bw interface + sync_enum_type nb_transport_bw(transaction_type& txn, + phase_type& p, + sc_core::sc_time& t){ + //check if a callback is registered + if ((m_nb_f == 0) || (m_nb_f && m_nb_f->empty())) { + SC_REPORT_ERROR("/OSCI_TLM-2/multi_socket","Call to nb_transport_bw without a registered callback for nb_transport_bw"); + } + else + return (*m_nb_f)(m_id, txn, p, t); //do the callback + return tlm::TLM_ACCEPTED; //unreachable + } + + //the DMI method of the bw interface + void invalidate_direct_mem_ptr(sc_dt::uint64 l, sc_dt::uint64 u){ + //check if a callback is registered + if ((m_dmi_f == 0) || (m_dmi_f && m_dmi_f->empty())) { + return; + } + else + (*m_dmi_f)(m_id,l,u); //do the callback + } + + //register callbacks for all bw interface methods at once + void set_callbacks(nb_func_type& cb1, dmi_func_type& cb2){ + m_nb_f=&cb1; + m_dmi_f=&cb2; + } + + private: + //the ID of the callback binder + int m_id; + //the callbacks + nb_func_type* m_nb_f; + dmi_func_type* m_dmi_f; +}; + + +/* +This class forms the base for multi initiator sockets. +It enforces a multi initiator socket to implement all functions +needed to do hierarchical bindings. +*/ +template <unsigned int BUSWIDTH = 32, + typename TYPES = tlm::tlm_base_protocol_types, + unsigned int N=0 +#if !(defined SYSTEMC_VERSION & SYSTEMC_VERSION <= 20050714) + ,sc_core::sc_port_policy POL = sc_core::SC_ONE_OR_MORE_BOUND +#endif + > +class multi_init_base: public tlm::tlm_initiator_socket<BUSWIDTH, + TYPES, + N +#if !(defined SYSTEMC_VERSION & SYSTEMC_VERSION <= 20050714) + ,POL +#endif + >{ +public: + //typedef for the base type: the standard tlm initiator socket + typedef tlm::tlm_initiator_socket<BUSWIDTH, + TYPES, + N +#if !(defined SYSTEMC_VERSION & SYSTEMC_VERSION <= 20050714) + ,POL +#endif + > base_type; + + //this method shall disable the code that does the callback binding + // that registers callbacks to binders + virtual void disable_cb_bind()=0; + + //this method shall return the multi_init_base to which the + // multi_init_base is bound hierarchically + // If the base is not bound hierarchically it shall return a pointer to itself + virtual multi_init_base* get_hierarch_bind()=0; + + //this method shall return a vector of the callback binders of multi initiator socket + virtual std::vector<callback_binder_bw<TYPES>* >& get_binders()=0; + + //this method shall return a vector of all target interfaces bound to this multi init socket + virtual std::vector<tlm::tlm_fw_transport_if<TYPES>*>& get_sockets()=0; + + //ctor and dtor + virtual ~multi_init_base(){} + multi_init_base():base_type(sc_core::sc_gen_unique_name("multi_init_base")){} + multi_init_base(const char* name):base_type(name){} +}; + +/* +This class forms the base for multi target sockets. +It enforces a multi target socket to implement all functions +needed to do hierarchical bindings. +*/ +template <unsigned int BUSWIDTH = 32, + typename TYPES = tlm::tlm_base_protocol_types, + unsigned int N=0 +#if !(defined SYSTEMC_VERSION & SYSTEMC_VERSION <= 20050714) + ,sc_core::sc_port_policy POL = sc_core::SC_ONE_OR_MORE_BOUND +#endif + > +class multi_target_base: public tlm::tlm_target_socket<BUSWIDTH, + TYPES, + N +#if !(defined SYSTEMC_VERSION & SYSTEMC_VERSION <= 20050714) + ,POL +#endif + >{ +public: + //typedef for the base type: the standard tlm target socket + typedef tlm::tlm_target_socket<BUSWIDTH, + TYPES, + N +#if !(defined SYSTEMC_VERSION & SYSTEMC_VERSION <= 20050714) + ,POL +#endif + > base_type; + + //this method shall return the multi_init_base to which the + // multi_init_base is bound hierarchically + // If the base is not bound hierarchically it shall return a pointer to itself + virtual multi_target_base* get_hierarch_bind()=0; + + //this method shall inform the multi target socket that it is bound + // hierarchically and to which other multi target socket it is bound hierarchically + virtual void set_hierarch_bind(multi_target_base*)=0; + + //this method shall return a vector of the callback binders of multi initiator socket + virtual std::vector<callback_binder_fw<TYPES>* >& get_binders()=0; + + //this method shall return a map of all multi initiator sockets that are bound to this multi target + // the key of the map is the index at which the multi initiator i bound, while the value + // is the interface of the multi initiator socket that is bound at that index + virtual std::map<unsigned int, tlm::tlm_bw_transport_if<TYPES>*>& get_multi_binds()=0; + + //ctor and dtor + virtual ~multi_target_base(){} + multi_target_base():base_type(sc_core::sc_gen_unique_name("multi_target_base")){} + multi_target_base(const char* name):base_type(name){} +}; + +/* +All multi sockets must additionally derive from this class. +It enforces a multi socket to implement a function +needed to do multi init to multi target bindings. +*/ +template <typename TYPES> +class multi_to_multi_bind_base{ +public: + virtual ~multi_to_multi_bind_base(){} + virtual tlm::tlm_fw_transport_if<TYPES>* get_last_binder(tlm::tlm_bw_transport_if<TYPES>*)=0; +}; + +} +#endif diff --git a/ext/systemc/src/tlm_utils/passthrough_target_socket.h b/ext/systemc/src/tlm_utils/passthrough_target_socket.h new file mode 100644 index 000000000..1a3b14df7 --- /dev/null +++ b/ext/systemc/src/tlm_utils/passthrough_target_socket.h @@ -0,0 +1,479 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +#ifndef __PASSTHROUGH_TARGET_SOCKET_H__ +#define __PASSTHROUGH_TARGET_SOCKET_H__ + +#include <tlm> +#include <sstream> + +namespace tlm_utils { + +template <typename MODULE, + unsigned int BUSWIDTH = 32, + typename TYPES = tlm::tlm_base_protocol_types> +class passthrough_target_socket : + public tlm::tlm_target_socket<BUSWIDTH, TYPES> +{ +public: + typedef typename TYPES::tlm_payload_type transaction_type; + typedef typename TYPES::tlm_phase_type phase_type; + typedef tlm::tlm_sync_enum sync_enum_type; + typedef tlm::tlm_fw_transport_if<TYPES> fw_interface_type; + typedef tlm::tlm_bw_transport_if<TYPES> bw_interface_type; + typedef tlm::tlm_target_socket<BUSWIDTH, TYPES> base_type; + +public: + passthrough_target_socket() : + base_type(sc_core::sc_gen_unique_name("passthrough_target_socket")), + m_process(this->name()) + { + bind(m_process); + } + + explicit passthrough_target_socket(const char* n) : + base_type(n), + m_process(this->name()) + { + bind(m_process); + } + + using tlm::tlm_target_socket<BUSWIDTH, TYPES>::bind; + + // REGISTER_XXX + void register_nb_transport_fw(MODULE* mod, + sync_enum_type (MODULE::*cb)(transaction_type&, + phase_type&, + sc_core::sc_time&)) + { + m_process.set_nb_transport_ptr(mod, cb); + } + + void register_b_transport(MODULE* mod, + void (MODULE::*cb)(transaction_type&, + sc_core::sc_time&)) + { + m_process.set_b_transport_ptr(mod, cb); + } + + void register_transport_dbg(MODULE* mod, + unsigned int (MODULE::*cb)(transaction_type&)) + { + m_process.set_transport_dbg_ptr(mod, cb); + } + + void register_get_direct_mem_ptr(MODULE* mod, + bool (MODULE::*cb)(transaction_type&, + tlm::tlm_dmi&)) + { + m_process.set_get_direct_mem_ptr(mod, cb); + } + +private: + class process : public tlm::tlm_fw_transport_if<TYPES> + { + public: + typedef sync_enum_type (MODULE::*NBTransportPtr)(transaction_type&, + phase_type&, + sc_core::sc_time&); + typedef void (MODULE::*BTransportPtr)(transaction_type&, + sc_core::sc_time&); + typedef unsigned int (MODULE::*TransportDbgPtr)(transaction_type&); + typedef bool (MODULE::*GetDirectMem_ptr)(transaction_type&, + tlm::tlm_dmi&); + + process(const std::string& name) : + m_name(name), + m_mod(0), + m_nb_transport_ptr(0), + m_b_transport_ptr(0), + m_transport_dbg_ptr(0), + m_get_direct_mem_ptr(0) + { + } + + void set_nb_transport_ptr(MODULE* mod, NBTransportPtr p) + { + if (m_nb_transport_ptr) { + std::stringstream s; + s << m_name << ": non-blocking callback allready registered"; + SC_REPORT_WARNING("/OSCI_TLM-2/passthrough_socket",s.str().c_str()); + + } else { + assert(!m_mod || m_mod == mod); + m_mod = mod; + m_nb_transport_ptr = p; + } + } + + void set_b_transport_ptr(MODULE* mod, BTransportPtr p) + { + if (m_b_transport_ptr) { + std::stringstream s; + s << m_name << ": blocking callback allready registered"; + SC_REPORT_WARNING("/OSCI_TLM-2/passthrough_socket",s.str().c_str()); + } else { + assert(!m_mod || m_mod == mod); + m_mod = mod; + m_b_transport_ptr = p; + } + } + + void set_transport_dbg_ptr(MODULE* mod, TransportDbgPtr p) + { + if (m_transport_dbg_ptr) { + std::stringstream s; + s << m_name << ": debug callback allready registered"; + SC_REPORT_WARNING("/OSCI_TLM-2/passthrough_socket",s.str().c_str()); + } else { + assert(!m_mod || m_mod == mod); + m_mod = mod; + m_transport_dbg_ptr = p; + } + } + + void set_get_direct_mem_ptr(MODULE* mod, GetDirectMem_ptr p) + { + if (m_get_direct_mem_ptr) { + std::stringstream s; + s << m_name << ": get DMI pointer callback allready registered"; + SC_REPORT_WARNING("/OSCI_TLM-2/passthrough_socket",s.str().c_str()); + } else { + assert(!m_mod || m_mod == mod); + m_mod = mod; + m_get_direct_mem_ptr = p; + } + } + + sync_enum_type nb_transport_fw(transaction_type& trans, + phase_type& phase, + sc_core::sc_time& t) + { + if (m_nb_transport_ptr) { + // forward call + assert(m_mod); + return (m_mod->*m_nb_transport_ptr)(trans, phase, t); + + } else { + std::stringstream s; + s << m_name << ": no non-blocking callback registered"; + SC_REPORT_ERROR("/OSCI_TLM-2/passthrough_socket",s.str().c_str()); + } + return tlm::TLM_ACCEPTED; ///< unreachable code + } + + void b_transport(transaction_type& trans, sc_core::sc_time& t) + { + if (m_b_transport_ptr) { + // forward call + assert(m_mod); + return (m_mod->*m_b_transport_ptr)(trans, t); + + } else { + std::stringstream s; + s << m_name << ": no blocking callback registered"; + SC_REPORT_ERROR("/OSCI_TLM-2/passthrough_socket",s.str().c_str()); + } + } + + unsigned int transport_dbg(transaction_type& trans) + { + if (m_transport_dbg_ptr) { + // forward call + assert(m_mod); + return (m_mod->*m_transport_dbg_ptr)(trans); + + } else { + // No debug support + return 0; + } + } + + bool get_direct_mem_ptr(transaction_type& trans, + tlm::tlm_dmi& dmi_data) + { + if (m_get_direct_mem_ptr) { + // forward call + assert(m_mod); + return (m_mod->*m_get_direct_mem_ptr)(trans, dmi_data); + + } else { + // No DMI support + dmi_data.allow_read_write(); + dmi_data.set_start_address(0x0); + dmi_data.set_end_address((sc_dt::uint64)-1); + return false; + } + } + + private: + const std::string m_name; + MODULE* m_mod; + NBTransportPtr m_nb_transport_ptr; + BTransportPtr m_b_transport_ptr; + TransportDbgPtr m_transport_dbg_ptr; + GetDirectMem_ptr m_get_direct_mem_ptr; + }; + +private: + process m_process; +}; + +//ID Tagged version +template <typename MODULE, + unsigned int BUSWIDTH = 32, + typename TYPES = tlm::tlm_base_protocol_types> +class passthrough_target_socket_tagged : + public tlm::tlm_target_socket<BUSWIDTH, TYPES> +{ +public: + typedef typename TYPES::tlm_payload_type transaction_type; + typedef typename TYPES::tlm_phase_type phase_type; + typedef tlm::tlm_sync_enum sync_enum_type; + typedef tlm::tlm_fw_transport_if<TYPES> fw_interface_type; + typedef tlm::tlm_bw_transport_if<TYPES> bw_interface_type; + typedef tlm::tlm_target_socket<BUSWIDTH, TYPES> base_type; + +public: + passthrough_target_socket_tagged() : + base_type(sc_core::sc_gen_unique_name("passthrough_target_socket_tagged")), + m_process(this->name()) + { + bind(m_process); + } + + explicit passthrough_target_socket_tagged(const char* n) : + base_type(n), + m_process(this->name()) + { + bind(m_process); + } + + using tlm::tlm_target_socket<BUSWIDTH, TYPES>::bind; + + // REGISTER_XXX + void register_nb_transport_fw(MODULE* mod, + sync_enum_type (MODULE::*cb)(int id, + transaction_type&, + phase_type&, + sc_core::sc_time&), + int id) + { + m_process.set_nb_transport_ptr(mod, cb); + m_process.set_nb_transport_user_id(id); + } + + void register_b_transport(MODULE* mod, + void (MODULE::*cb)(int id, + transaction_type&, + sc_core::sc_time&), + int id) + { + m_process.set_b_transport_ptr(mod, cb); + m_process.set_b_transport_user_id(id); + } + + void register_transport_dbg(MODULE* mod, + unsigned int (MODULE::*cb)(int id, + transaction_type&), + int id) + { + m_process.set_transport_dbg_ptr(mod, cb); + m_process.set_transport_dbg_user_id(id); + } + + void register_get_direct_mem_ptr(MODULE* mod, + bool (MODULE::*cb)(int id, + transaction_type&, + tlm::tlm_dmi&), + int id) + { + m_process.set_get_direct_mem_ptr(mod, cb); + m_process.set_get_dmi_user_id(id); + } + +private: + class process : public tlm::tlm_fw_transport_if<TYPES> + { + public: + typedef sync_enum_type (MODULE::*NBTransportPtr)(int id, + transaction_type&, + phase_type&, + sc_core::sc_time&); + typedef void (MODULE::*BTransportPtr)(int id, + transaction_type&, + sc_core::sc_time&); + typedef unsigned int (MODULE::*TransportDbgPtr)(int id, + transaction_type&); + typedef bool (MODULE::*GetDirectMem_ptr)(int id, + transaction_type&, + tlm::tlm_dmi&); + + process(const std::string& name) : + m_name(name), + m_mod(0), + m_nb_transport_ptr(0), + m_b_transport_ptr(0), + m_transport_dbg_ptr(0), + m_get_direct_mem_ptr(0), + m_nb_transport_user_id(0), + m_b_transport_user_id(0), + m_transport_dbg_user_id(0), + m_get_dmi_user_id(0) + { + } + + void set_nb_transport_user_id(int id) { m_nb_transport_user_id = id; } + void set_b_transport_user_id(int id) { m_b_transport_user_id = id; } + void set_transport_dbg_user_id(int id) { m_transport_dbg_user_id = id; } + void set_get_dmi_user_id(int id) { m_get_dmi_user_id = id; } + + void set_nb_transport_ptr(MODULE* mod, NBTransportPtr p) + { + if (m_nb_transport_ptr) { + std::stringstream s; + s << m_name << ": non-blocking callback allready registered"; + SC_REPORT_WARNING("/OSCI_TLM-2/passthrough_socket",s.str().c_str()); + } else { + assert(!m_mod || m_mod == mod); + m_mod = mod; + m_nb_transport_ptr = p; + } + } + + void set_b_transport_ptr(MODULE* mod, BTransportPtr p) + { + if (m_b_transport_ptr) { + std::stringstream s; + s << m_name << ": blocking callback allready registered"; + SC_REPORT_WARNING("/OSCI_TLM-2/passthrough_socket",s.str().c_str()); + } else { + assert(!m_mod || m_mod == mod); + m_mod = mod; + m_b_transport_ptr = p; + } + } + + void set_transport_dbg_ptr(MODULE* mod, TransportDbgPtr p) + { + if (m_transport_dbg_ptr) { + std::stringstream s; + s << m_name << ": debug callback allready registered"; + SC_REPORT_WARNING("/OSCI_TLM-2/passthrough_socket",s.str().c_str()); + } else { + assert(!m_mod || m_mod == mod); + m_mod = mod; + m_transport_dbg_ptr = p; + } + } + + void set_get_direct_mem_ptr(MODULE* mod, GetDirectMem_ptr p) + { + if (m_get_direct_mem_ptr) { + std::stringstream s; + s << m_name << ": get DMI pointer callback allready registered"; + SC_REPORT_WARNING("/OSCI_TLM-2/passthrough_socket",s.str().c_str()); + } else { + assert(!m_mod || m_mod == mod); + m_mod = mod; + m_get_direct_mem_ptr = p; + } + } + + sync_enum_type nb_transport_fw(transaction_type& trans, + phase_type& phase, + sc_core::sc_time& t) + { + if (m_nb_transport_ptr) { + // forward call + assert(m_mod); + return (m_mod->*m_nb_transport_ptr)(m_nb_transport_user_id, trans, phase, t); + + } else { + std::stringstream s; + s << m_name << ": no non-blocking callback registered"; + SC_REPORT_ERROR("/OSCI_TLM-2/passthrough_socket",s.str().c_str()); + } + return tlm::TLM_ACCEPTED; ///< unreachable code + } + + void b_transport(transaction_type& trans, sc_core::sc_time& t) + { + if (m_b_transport_ptr) { + // forward call + assert(m_mod); + return (m_mod->*m_b_transport_ptr)(m_b_transport_user_id, trans, t); + + } else { + std::stringstream s; + s << m_name << ": no blocking callback registered"; + SC_REPORT_ERROR("/OSCI_TLM-2/passthrough_socket",s.str().c_str()); + } + } + + unsigned int transport_dbg(transaction_type& trans) + { + if (m_transport_dbg_ptr) { + // forward call + assert(m_mod); + return (m_mod->*m_transport_dbg_ptr)(m_transport_dbg_user_id, trans); + + } else { + // No debug support + return 0; + } + } + + bool get_direct_mem_ptr(transaction_type& trans, + tlm::tlm_dmi& dmi_data) + { + if (m_get_direct_mem_ptr) { + // forward call + assert(m_mod); + return (m_mod->*m_get_direct_mem_ptr)(m_get_dmi_user_id, trans, dmi_data); + + } else { + // No DMI support + dmi_data.allow_read_write(); + dmi_data.set_start_address(0x0); + dmi_data.set_end_address((sc_dt::uint64)-1); + return false; + } + } + + private: + const std::string m_name; + MODULE* m_mod; + NBTransportPtr m_nb_transport_ptr; + BTransportPtr m_b_transport_ptr; + TransportDbgPtr m_transport_dbg_ptr; + GetDirectMem_ptr m_get_direct_mem_ptr; + int m_nb_transport_user_id; + int m_b_transport_user_id; + int m_transport_dbg_user_id; + int m_get_dmi_user_id; + }; + +private: + process m_process; +}; + +} + +#endif diff --git a/ext/systemc/src/tlm_utils/peq_with_cb_and_phase.h b/ext/systemc/src/tlm_utils/peq_with_cb_and_phase.h new file mode 100644 index 000000000..60f96e6bd --- /dev/null +++ b/ext/systemc/src/tlm_utils/peq_with_cb_and_phase.h @@ -0,0 +1,301 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +// 12-Jan-2009 John Aynsley Bug fix. Phase argument to notify should be const +// 20-Mar-2009 John Aynsley Add cancel_all() method + + +#ifndef __PEQ_WITH_CB_AND_PHASE_H__ +#define __PEQ_WITH_CB_AND_PHASE_H__ + +#ifndef SC_INCLUDE_DYNAMIC_PROCESSES // needed for sc_spawn +# define SC_INCLUDE_DYNAMIC_PROCESSES +#endif + +#include <vector> +#include <systemc> +#include <tlm> + +namespace tlm_utils { + +template <typename PAYLOAD> +class time_ordered_list +{ +public: + struct element + { + struct element *next; + PAYLOAD p; + sc_core::sc_time t; + sc_dt::uint64 d; + element(PAYLOAD& p, sc_core::sc_time t, sc_dt::uint64 d): p(p),t(t),d(d) {} + element(){} + }; + + element *nill; + element *empties; + element *list; + unsigned int size; + + time_ordered_list() + : nill(new element()), + empties(NULL), + list(nill), + size(0) + { + } + + ~time_ordered_list() { + reset(); + while(empties){ + struct element *e=empties->next; + delete empties; + empties=e; + } + delete nill; + } + + void reset() { + while(size) { + delete_top(); + } + } + + void insert(const PAYLOAD& p, sc_core::sc_time t) { + if (!empties) { + empties=new struct element(); + empties->next=NULL; + } + + struct element *e=empties; + empties=empties->next; + e->p=p; + e->t=t; + e->d=sc_core::sc_delta_count(); + + struct element * ancestor=nill; + struct element * iterator=list; + while (iterator!=nill && iterator->t<=t){ + ancestor=iterator; + iterator=iterator->next; + } + if (ancestor==nill){ + e->next=list; + list=e; + } + else { + e->next=iterator; + ancestor->next=e; + } + size++; + } + + void delete_top(){ + if (list != nill) { + struct element *e=list; + list=list->next; + e->next=empties; + empties=e; + size--; + } + } + + unsigned int get_size() + { + return size; + } + + PAYLOAD &top() + { + return list->p; + } + sc_core::sc_time top_time() + { + return list->t; + } + + sc_dt::uint64& top_delta() + { + return list->d; + } + + sc_core::sc_time next_time() + { + return list->next->t; + } +}; + +//--------------------------------------------------------------------------- +/** + * An event queue that can contain any number of pending + * notifications. Each notification have an associate payload. + */ +//--------------------------------------------------------------------------- +template<typename OWNER,typename TYPES=tlm::tlm_base_protocol_types> +class peq_with_cb_and_phase: + public sc_core::sc_object +{ + + typedef typename TYPES::tlm_payload_type tlm_payload_type; + typedef typename TYPES::tlm_phase_type tlm_phase_type; + typedef std::pair<tlm_payload_type*, tlm_phase_type> PAYLOAD; + typedef void (OWNER::*cb)(tlm_payload_type&, const tlm_phase_type&); + + class delta_list{ + public: + delta_list(){ + reset(); + entries.resize(100); + } + + inline void insert(const PAYLOAD& p){ + if (size==entries.size()){ + entries.resize(entries.size()*2); + } + entries[size++]=p; + } + + inline PAYLOAD& get(){ + return entries[out++]; + } + + inline bool next(){ + return out<size; + } + + inline void reset(){ + size=0; + out=0; + } + public: + unsigned int size; + private: + std::vector<PAYLOAD> entries; + unsigned int out; + }; + +public: + + peq_with_cb_and_phase(OWNER* _owner, cb _cb) + :sc_core::sc_object( sc_core::sc_gen_unique_name( "peq_with_cb_and_phase" ) ) + ,m_owner(_owner) + ,m_cb(_cb) + { + sc_core::sc_spawn_options opts; + opts.spawn_method(); + opts.set_sensitivity(&m_e); + opts.dont_initialize(); + sc_core::sc_spawn(sc_bind(&peq_with_cb_and_phase::fec, this), + sc_core::sc_gen_unique_name("fec"), &opts); + } + + peq_with_cb_and_phase(const char* _name, OWNER* _owner,cb _cb) + : sc_core::sc_object( _name ) + ,m_owner(_owner) + ,m_cb(_cb) + { + sc_core::sc_spawn_options opts; + opts.spawn_method(); + opts.set_sensitivity(&m_e); + opts.dont_initialize(); + sc_core::sc_spawn(sc_bind(&peq_with_cb_and_phase::fec, this), + sc_core::sc_gen_unique_name("fec"), &opts); + } + + ~peq_with_cb_and_phase(){} + + void notify (tlm_payload_type& t, const tlm_phase_type& p, const sc_core::sc_time& when){ + //t.aquire(); + if (when==sc_core::SC_ZERO_TIME) { + if (sc_core::sc_delta_count() & (sc_dt::uint64)0x1) //uneven delta cycle so delta delay is for even cylce + m_even_delta.insert(PAYLOAD(&t,p)); + else + m_uneven_delta.insert(PAYLOAD(&t,p)); //even delta cycle so delta delay is for uneven delta + m_e.notify(sc_core::SC_ZERO_TIME); + } + else { + m_ppq.insert(PAYLOAD(&t,p), when + sc_core::sc_time_stamp() ); + m_e.notify(when); // note, this will only over-right the "newest" event. + } + } + + void notify (tlm_payload_type& t, const tlm_phase_type& p){ + m_immediate_yield.insert(PAYLOAD(&t,p)); + m_e.notify(); // immediate notification + } + + // Cancel all events from the event queue + void cancel_all() { + m_ppq.reset(); + m_uneven_delta.reset(); + m_even_delta.reset(); + m_immediate_yield.reset(); + m_e.cancel(); + } + +private: + + void fec(){ + //immediate yield notifications + while(m_immediate_yield.next()) {PAYLOAD& tmp=m_immediate_yield.get(); (m_owner->*m_cb)(*tmp.first, tmp.second);} //tmp.first->release();} + m_immediate_yield.reset(); + + //delta notifications + if (sc_core::sc_delta_count() & (sc_dt::uint64) 0x1) {//uneven delta so put out all payloads for uneven delta + while (m_uneven_delta.next()) {PAYLOAD& tmp=m_uneven_delta.get(); (m_owner->*m_cb)(*tmp.first, tmp.second);} //tmp.first->release();} + m_uneven_delta.reset(); + if (m_even_delta.size) m_e.notify(sc_core::SC_ZERO_TIME); + } + else { + while (m_even_delta.next()) {PAYLOAD& tmp=m_even_delta.get(); (m_owner->*m_cb)(*tmp.first, tmp.second);} //tmp.first->release();} + m_even_delta.reset(); + if (m_uneven_delta.size) m_e.notify(sc_core::SC_ZERO_TIME); + } + if (!m_ppq.get_size()) return; //there were only delta notification + + //timed notifications + const sc_core::sc_time now=sc_core::sc_time_stamp(); + sc_core::sc_time top=m_ppq.top_time(); + + while(m_ppq.get_size() && top==now) { // push all active ones into target + PAYLOAD& tmp=m_ppq.top(); + (m_owner->*m_cb)(*tmp.first, tmp.second); //tmp.first->release();} + m_ppq.delete_top(); + top=m_ppq.top_time(); + } + if ( m_ppq.get_size()) { + m_e.notify( top - now) ; + } + + } + + OWNER* m_owner; + cb m_cb; + + time_ordered_list<PAYLOAD> m_ppq; + delta_list m_uneven_delta; + delta_list m_even_delta; + delta_list m_immediate_yield; + + sc_core::sc_event m_e; // default event +}; + +} + +#endif // __PEQ_WITH_CB_AND_PHASE_H__ diff --git a/ext/systemc/src/tlm_utils/peq_with_get.h b/ext/systemc/src/tlm_utils/peq_with_get.h new file mode 100644 index 000000000..5c85f25d5 --- /dev/null +++ b/ext/systemc/src/tlm_utils/peq_with_get.h @@ -0,0 +1,94 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +// 12-Jan-2009 John Aynsley Bug fix. sc_time argument to notify should be const +// 20-Mar-2009 John Aynsley Add cancel_all() method + + +#ifndef __PEQ_WITH_GET_H__ +#define __PEQ_WITH_GET_H__ + +#include <systemc> +//#include <tlm> +#include <map> + +namespace tlm_utils { + +template <class PAYLOAD> +class peq_with_get : public sc_core::sc_object +{ +public: + typedef PAYLOAD transaction_type; + typedef std::pair<const sc_core::sc_time, transaction_type*> pair_type; + +public: + peq_with_get(const char* name) : sc_core::sc_object(name) + { + } + + void notify(transaction_type& trans, const sc_core::sc_time& t) + { + m_scheduled_events.insert(pair_type(t + sc_core::sc_time_stamp(), &trans)); + m_event.notify(t); + } + + void notify(transaction_type& trans) + { + m_scheduled_events.insert(pair_type(sc_core::sc_time_stamp(), &trans)); + m_event.notify(); // immediate notification + } + + // needs to be called until it returns 0 + transaction_type* get_next_transaction() + { + if (m_scheduled_events.empty()) { + return 0; + } + + sc_core::sc_time now = sc_core::sc_time_stamp(); + if (m_scheduled_events.begin()->first <= now) { + transaction_type* trans = m_scheduled_events.begin()->second; + m_scheduled_events.erase(m_scheduled_events.begin()); + return trans; + } + + m_event.notify(m_scheduled_events.begin()->first - now); + + return 0; + } + + sc_core::sc_event& get_event() + { + return m_event; + } + + // Cancel all events from the event queue + void cancel_all() { + m_scheduled_events.clear(); + m_event.cancel(); + } + +private: + std::multimap<const sc_core::sc_time, transaction_type*> m_scheduled_events; + sc_core::sc_event m_event; +}; + +} + +#endif diff --git a/ext/systemc/src/tlm_utils/simple_initiator_socket.h b/ext/systemc/src/tlm_utils/simple_initiator_socket.h new file mode 100644 index 000000000..4609fd885 --- /dev/null +++ b/ext/systemc/src/tlm_utils/simple_initiator_socket.h @@ -0,0 +1,292 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +#ifndef __SIMPLE_INITIATOR_SOCKET_H__ +#define __SIMPLE_INITIATOR_SOCKET_H__ + +#include <tlm> +#include <sstream> + +namespace tlm_utils { + +template <typename MODULE, + unsigned int BUSWIDTH = 32, + typename TYPES = tlm::tlm_base_protocol_types> +class simple_initiator_socket : + public tlm::tlm_initiator_socket<BUSWIDTH, TYPES> +{ +public: + typedef typename TYPES::tlm_payload_type transaction_type; + typedef typename TYPES::tlm_phase_type phase_type; + typedef tlm::tlm_sync_enum sync_enum_type; + typedef tlm::tlm_fw_transport_if<TYPES> fw_interface_type; + typedef tlm::tlm_bw_transport_if<TYPES> bw_interface_type; + typedef tlm::tlm_initiator_socket<BUSWIDTH, TYPES> base_type; + +public: + simple_initiator_socket() : + base_type(sc_core::sc_gen_unique_name("simple_initiator_socket")), + m_process(this->name()) + { + this->m_export.bind(m_process); + } + + explicit simple_initiator_socket(const char* n) : + base_type(n), + m_process(this->name()) + { + this->m_export.bind(m_process); + } + + void register_nb_transport_bw(MODULE* mod, + sync_enum_type (MODULE::*cb)(transaction_type&, + phase_type&, + sc_core::sc_time&)) + { + m_process.set_transport_ptr(mod, cb); + } + + void register_invalidate_direct_mem_ptr(MODULE* mod, + void (MODULE::*cb)(sc_dt::uint64, sc_dt::uint64)) + { + m_process.set_invalidate_direct_mem_ptr(mod, cb); + } + +private: + class process : public tlm::tlm_bw_transport_if<TYPES> + { + public: + typedef sync_enum_type (MODULE::*TransportPtr)(transaction_type&, + phase_type&, + sc_core::sc_time&); + typedef void (MODULE::*InvalidateDirectMemPtr)(sc_dt::uint64, + sc_dt::uint64); + + process(const std::string& name) : + m_name(name), + m_mod(0), + m_transport_ptr(0), + m_invalidate_direct_mem_ptr(0) + { + } + + void set_transport_ptr(MODULE* mod, TransportPtr p) + { + if (m_transport_ptr) { + std::stringstream s; + s << m_name << ": non-blocking callback allready registered"; + SC_REPORT_WARNING("/OSCI_TLM-2/simple_socket",s.str().c_str()); + } else { + assert(!m_mod || m_mod == mod); + m_mod = mod; + m_transport_ptr = p; + } + } + + void set_invalidate_direct_mem_ptr(MODULE* mod, InvalidateDirectMemPtr p) + { + if (m_invalidate_direct_mem_ptr) { + std::stringstream s; + s << m_name << ": invalidate DMI callback allready registered"; + SC_REPORT_WARNING("/OSCI_TLM-2/simple_socket",s.str().c_str()); + } else { + assert(!m_mod || m_mod == mod); + m_mod = mod; + m_invalidate_direct_mem_ptr = p; + } + } + + sync_enum_type nb_transport_bw(transaction_type& trans, phase_type& phase, sc_core::sc_time& t) + { + if (m_transport_ptr) { + // forward call + assert(m_mod); + return (m_mod->*m_transport_ptr)(trans, phase, t); + + } else { + std::stringstream s; + s << m_name << ": no transport callback registered"; + SC_REPORT_ERROR("/OSCI_TLM-2/simple_socket",s.str().c_str()); + } + return tlm::TLM_ACCEPTED; ///< unreachable code + } + + void invalidate_direct_mem_ptr(sc_dt::uint64 start_range, + sc_dt::uint64 end_range) + { + if (m_invalidate_direct_mem_ptr) { + // forward call + assert(m_mod); + (m_mod->*m_invalidate_direct_mem_ptr)(start_range, end_range); + } + } + + private: + const std::string m_name; + MODULE* m_mod; + TransportPtr m_transport_ptr; + InvalidateDirectMemPtr m_invalidate_direct_mem_ptr; + }; + +private: + process m_process; +}; + +// Tagged version + +template <typename MODULE, + unsigned int BUSWIDTH = 32, + typename TYPES = tlm::tlm_base_protocol_types> +class simple_initiator_socket_tagged : + public tlm::tlm_initiator_socket<BUSWIDTH, TYPES> +{ +public: + typedef typename TYPES::tlm_payload_type transaction_type; + typedef typename TYPES::tlm_phase_type phase_type; + typedef tlm::tlm_sync_enum sync_enum_type; + typedef tlm::tlm_fw_transport_if<TYPES> fw_interface_type; + typedef tlm::tlm_bw_transport_if<TYPES> bw_interface_type; + typedef tlm::tlm_initiator_socket<BUSWIDTH, TYPES> base_type; + +public: + simple_initiator_socket_tagged() : + base_type(sc_core::sc_gen_unique_name("simple_initiator_socket_tagged")), + m_process(this->name()) + { + this->m_export.bind(m_process); + } + + explicit simple_initiator_socket_tagged(const char* n) : + base_type(n), + m_process(this->name()) + { + this->m_export.bind(m_process); + } + + void register_nb_transport_bw(MODULE* mod, + sync_enum_type (MODULE::*cb)(int, + transaction_type&, + phase_type&, + sc_core::sc_time&), + int id) + { + m_process.set_transport_ptr(mod, cb); + m_process.set_transport_user_id(id); + } + + void register_invalidate_direct_mem_ptr(MODULE* mod, + void (MODULE::*cb)(int, sc_dt::uint64, sc_dt::uint64), + int id) + { + m_process.set_invalidate_direct_mem_ptr(mod, cb); + m_process.set_invalidate_dmi_user_id(id); + } + +private: + class process : public tlm::tlm_bw_transport_if<TYPES> + { + public: + typedef sync_enum_type (MODULE::*TransportPtr)(int, + transaction_type&, + phase_type&, + sc_core::sc_time&); + typedef void (MODULE::*InvalidateDirectMemPtr)(int, + sc_dt::uint64, + sc_dt::uint64); + + process(const std::string& name) : + m_name(name), + m_mod(0), + m_transport_ptr(0), + m_invalidate_direct_mem_ptr(0), + m_transport_user_id(0), + m_invalidate_direct_mem_user_id(0) + { + } + + void set_transport_user_id(int id) { m_transport_user_id = id; } + void set_invalidate_dmi_user_id(int id) { m_invalidate_direct_mem_user_id = id; } + + void set_transport_ptr(MODULE* mod, TransportPtr p) + { + if (m_transport_ptr) { + std::stringstream s; + s << m_name << ": non-blocking callback allready registered"; + SC_REPORT_WARNING("/OSCI_TLM-2/simple_socket",s.str().c_str()); + } else { + assert(!m_mod || m_mod == mod); + m_mod = mod; + m_transport_ptr = p; + } + } + + void set_invalidate_direct_mem_ptr(MODULE* mod, InvalidateDirectMemPtr p) + { + if (m_invalidate_direct_mem_ptr) { + std::stringstream s; + s << m_name << ": invalidate DMI callback allready registered"; + SC_REPORT_WARNING("/OSCI_TLM-2/simple_socket",s.str().c_str()); + } else { + assert(!m_mod || m_mod == mod); + m_mod = mod; + m_invalidate_direct_mem_ptr = p; + } + } + + sync_enum_type nb_transport_bw(transaction_type& trans, phase_type& phase, sc_core::sc_time& t) + { + if (m_transport_ptr) { + // forward call + assert(m_mod); + return (m_mod->*m_transport_ptr)(m_transport_user_id, trans, phase, t); + + } else { + std::stringstream s; + s << m_name << ": no transport callback registered"; + SC_REPORT_ERROR("/OSCI_TLM-2/simple_socket",s.str().c_str()); + } + return tlm::TLM_ACCEPTED; ///< unreachable code + } + + void invalidate_direct_mem_ptr(sc_dt::uint64 start_range, + sc_dt::uint64 end_range) + { + if (m_invalidate_direct_mem_ptr) { + // forward call + assert(m_mod); + (m_mod->*m_invalidate_direct_mem_ptr)(m_invalidate_direct_mem_user_id, start_range, end_range); + } + } + + private: + const std::string m_name; + MODULE* m_mod; + TransportPtr m_transport_ptr; + InvalidateDirectMemPtr m_invalidate_direct_mem_ptr; + int m_transport_user_id; + int m_invalidate_direct_mem_user_id; + }; + +private: + process m_process; +}; + +} + +#endif diff --git a/ext/systemc/src/tlm_utils/simple_target_socket.h b/ext/systemc/src/tlm_utils/simple_target_socket.h new file mode 100644 index 000000000..34ed1a7f4 --- /dev/null +++ b/ext/systemc/src/tlm_utils/simple_target_socket.h @@ -0,0 +1,1114 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +// ***************************************************************************** +// Modified by John Aynsley, Doulos, Feb 2009, +// Fix a bug in simple_target_socket and simple_target_socket_tagged +// with the addition of one new line of code in each: wait(*e); +// ***************************************************************************** + +// ***************************************************************************** +// Modified by John Aynsley on behalf of Robert Guenzel, May 2011, +// Fix a bug in simple_target_socket and simple_target_socket_tagged +// with the addition of one new line of code in each: wait(t); +// ***************************************************************************** + + +#ifndef __SIMPLE_TARGET_SOCKET_H__ +#define __SIMPLE_TARGET_SOCKET_H__ + +#ifndef SC_INCLUDE_DYNAMIC_PROCESSES // needed for sc_spawn +# define SC_INCLUDE_DYNAMIC_PROCESSES +#endif + +#include <systemc> +#include <tlm> +#include "tlm_utils/peq_with_get.h" +#include <sstream> + +namespace tlm_utils { + +template <typename MODULE, + unsigned int BUSWIDTH = 32, + typename TYPES = tlm::tlm_base_protocol_types> +class simple_target_socket : + public tlm::tlm_target_socket<BUSWIDTH, TYPES> +{ + friend class fw_process; + friend class bw_process; +public: + typedef typename TYPES::tlm_payload_type transaction_type; + typedef typename TYPES::tlm_phase_type phase_type; + typedef tlm::tlm_sync_enum sync_enum_type; + typedef tlm::tlm_fw_transport_if<TYPES> fw_interface_type; + typedef tlm::tlm_bw_transport_if<TYPES> bw_interface_type; + typedef tlm::tlm_target_socket<BUSWIDTH, TYPES> base_type; + +public: + simple_target_socket() : + base_type(sc_core::sc_gen_unique_name("simple_target_socket")), + m_fw_process(this), + m_bw_process(this) + { + bind(m_fw_process); + } + + explicit simple_target_socket(const char* n) : + base_type(n), + m_fw_process(this), + m_bw_process(this) + { + bind(m_fw_process); + } + + using tlm::tlm_target_socket<BUSWIDTH, TYPES>::bind; + + // bw transport must come thru us. + tlm::tlm_bw_transport_if<TYPES> * operator ->() {return &m_bw_process;} + + // REGISTER_XXX + void register_nb_transport_fw(MODULE* mod, + sync_enum_type (MODULE::*cb)(transaction_type&, + phase_type&, + sc_core::sc_time&)) + { + assert(!sc_core::sc_get_curr_simcontext()->elaboration_done()); + m_fw_process.set_nb_transport_ptr(mod, cb); + } + + void register_b_transport(MODULE* mod, + void (MODULE::*cb)(transaction_type&, + sc_core::sc_time&)) + { + assert(!sc_core::sc_get_curr_simcontext()->elaboration_done()); + m_fw_process.set_b_transport_ptr(mod, cb); + } + + void register_transport_dbg(MODULE* mod, + unsigned int (MODULE::*cb)(transaction_type&)) + { + assert(!sc_core::sc_get_curr_simcontext()->elaboration_done()); + m_fw_process.set_transport_dbg_ptr(mod, cb); + } + + void register_get_direct_mem_ptr(MODULE* mod, + bool (MODULE::*cb)(transaction_type&, + tlm::tlm_dmi&)) + { + assert(!sc_core::sc_get_curr_simcontext()->elaboration_done()); + m_fw_process.set_get_direct_mem_ptr(mod, cb); + } + +private: + //make call on bw path. + sync_enum_type bw_nb_transport(transaction_type &trans, phase_type &phase, sc_core::sc_time &t) + { + return base_type::operator ->()->nb_transport_bw(trans, phase, t); + } + + void bw_invalidate_direct_mem_ptr(sc_dt::uint64 s,sc_dt::uint64 e) + { + base_type::operator ->()->invalidate_direct_mem_ptr(s, e); + } + + //Helper class to handle bw path calls + // Needed to detect transaction end when called from b_transport. + class bw_process : public tlm::tlm_bw_transport_if<TYPES> + { + public: + bw_process(simple_target_socket *p_own) : m_owner(p_own) + { + } + + sync_enum_type nb_transport_bw(transaction_type &trans, phase_type &phase, sc_core::sc_time &t) + { + typename std::map<transaction_type*, sc_core::sc_event *>::iterator it; + + it = m_owner->m_pending_trans.find(&trans); + if(it == m_owner->m_pending_trans.end()) { + // Not a blocking call, forward. + return m_owner->bw_nb_transport(trans, phase, t); + + } else { + if (phase == tlm::END_REQ) { + m_owner->m_end_request.notify(sc_core::SC_ZERO_TIME); + return tlm::TLM_ACCEPTED; + + } else if (phase == tlm::BEGIN_RESP) { + if (m_owner->m_current_transaction == &trans) { + m_owner->m_end_request.notify(sc_core::SC_ZERO_TIME); + } + //TODO: add response-accept delay? + it->second->notify(t); + m_owner->m_pending_trans.erase(it); + return tlm::TLM_COMPLETED; + + } else { + assert(0); exit(1); + } + +// return tlm::TLM_COMPLETED; //Should not reach here + } + } + + void invalidate_direct_mem_ptr(sc_dt::uint64 s,sc_dt::uint64 e) + { + return m_owner->bw_invalidate_direct_mem_ptr(s, e); + } + + private: + simple_target_socket *m_owner; + }; + + class fw_process : public tlm::tlm_fw_transport_if<TYPES>, + public tlm::tlm_mm_interface + { + public: + typedef sync_enum_type (MODULE::*NBTransportPtr)(transaction_type&, + phase_type&, + sc_core::sc_time&); + typedef void (MODULE::*BTransportPtr)(transaction_type&, + sc_core::sc_time&); + typedef unsigned int (MODULE::*TransportDbgPtr)(transaction_type&); + typedef bool (MODULE::*GetDirectMemPtr)(transaction_type&, + tlm::tlm_dmi&); + + fw_process(simple_target_socket *p_own) : + m_name(p_own->name()), + m_owner(p_own), + m_mod(0), + m_nb_transport_ptr(0), + m_b_transport_ptr(0), + m_transport_dbg_ptr(0), + m_get_direct_mem_ptr(0), + m_peq(sc_core::sc_gen_unique_name("m_peq")), + m_response_in_progress(false) + { + sc_core::sc_spawn_options opts; + opts.set_sensitivity(&m_peq.get_event()); + sc_core::sc_spawn(sc_bind(&fw_process::b2nb_thread, this), + sc_core::sc_gen_unique_name("b2nb_thread"), &opts); + } + + void set_nb_transport_ptr(MODULE* mod, NBTransportPtr p) + { + if (m_nb_transport_ptr) { + std::stringstream s; + s << m_name << ": non-blocking callback allready registered"; + SC_REPORT_WARNING("/OSCI_TLM-2/simple_socket",s.str().c_str()); + } else { + assert(!m_mod || m_mod == mod); + m_mod = mod; + m_nb_transport_ptr = p; + } + } + + void set_b_transport_ptr(MODULE* mod, BTransportPtr p) + { + if (m_b_transport_ptr) { + std::stringstream s; + s << m_name << ": blocking callback allready registered"; + SC_REPORT_WARNING("/OSCI_TLM-2/simple_socket",s.str().c_str()); + } else { + assert(!m_mod || m_mod == mod); + m_mod = mod; + m_b_transport_ptr = p; + } + } + + void set_transport_dbg_ptr(MODULE* mod, TransportDbgPtr p) + { + if (m_transport_dbg_ptr) { + std::stringstream s; + s << m_name << ": debug callback allready registered"; + SC_REPORT_WARNING("/OSCI_TLM-2/simple_socket",s.str().c_str()); + } else { + assert(!m_mod || m_mod == mod); + m_mod = mod; + m_transport_dbg_ptr = p; + } + } + + void set_get_direct_mem_ptr(MODULE* mod, GetDirectMemPtr p) + { + if (m_get_direct_mem_ptr) { + std::stringstream s; + s << m_name << ": get DMI pointer callback allready registered"; + SC_REPORT_WARNING("/OSCI_TLM-2/simple_socket",s.str().c_str()); + } else { + assert(!m_mod || m_mod == mod); + m_mod = mod; + m_get_direct_mem_ptr = p; + } + } +// Interface implementation + sync_enum_type nb_transport_fw(transaction_type& trans, + phase_type& phase, + sc_core::sc_time& t) + { + if (m_nb_transport_ptr) { + // forward call + assert(m_mod); + return (m_mod->*m_nb_transport_ptr)(trans, phase, t); + + } else if (m_b_transport_ptr) { + if (phase == tlm::BEGIN_REQ) { + // prepare thread to do blocking call + process_handle_class * ph = m_process_handle.get_handle(&trans); + + if (!ph) { // create new dynamic process + ph = new process_handle_class(&trans); + m_process_handle.put_handle(ph); + + sc_core::sc_spawn_options opts; + opts.dont_initialize(); + opts.set_sensitivity(&ph->m_e); + + sc_core::sc_spawn(sc_bind(&fw_process::nb2b_thread,this, ph), + sc_core::sc_gen_unique_name("nb2b_thread"), &opts); + } + + ph->m_e.notify(t); + return tlm::TLM_ACCEPTED; + + } else if (phase == tlm::END_RESP) { + m_response_in_progress = false; + m_end_response.notify(t); + return tlm::TLM_COMPLETED; + + } else { + assert(0); exit(1); +// return tlm::TLM_COMPLETED; ///< unreachable code + } + + } else { + std::stringstream s; + s << m_name << ": no non-blocking transport callback registered"; + SC_REPORT_ERROR("/OSCI_TLM-2/simple_socket",s.str().c_str()); + } + return tlm::TLM_ACCEPTED; ///< unreachable code + } + + void b_transport(transaction_type& trans, sc_core::sc_time& t) + { + if (m_b_transport_ptr) { + // forward call + assert(m_mod); + (m_mod->*m_b_transport_ptr)(trans, t); + return; + + } else if (m_nb_transport_ptr) { + m_peq.notify(trans, t); + t = sc_core::SC_ZERO_TIME; + + mm_end_event_ext mm_ext; + const bool mm_added = !trans.has_mm(); + + if (mm_added) { + trans.set_mm(this); + trans.set_auto_extension(&mm_ext); + trans.acquire(); + } + + // wait until transaction is finished + sc_core::sc_event end_event; + m_owner->m_pending_trans[&trans] = &end_event; + sc_core::wait(end_event); + + if (mm_added) { + // release will not delete the transaction, it will notify mm_ext.done + trans.release(); + if (trans.get_ref_count()) { + sc_core::wait(mm_ext.done); + } + trans.set_mm(0); + } + + } else { + std::stringstream s; + s << m_name << ": no blocking transport callback registered"; + SC_REPORT_ERROR("/OSCI_TLM-2/simple_socket",s.str().c_str()); + } + } + + unsigned int transport_dbg(transaction_type& trans) + { + if (m_transport_dbg_ptr) { + // forward call + assert(m_mod); + return (m_mod->*m_transport_dbg_ptr)(trans); + + } else { + // No debug support + return 0; + } + } + + bool get_direct_mem_ptr(transaction_type& trans, + tlm::tlm_dmi& dmi_data) + { + if (m_get_direct_mem_ptr) { + // forward call + assert(m_mod); + return (m_mod->*m_get_direct_mem_ptr)(trans, dmi_data); + + } else { + // No DMI support + dmi_data.allow_read_write(); + dmi_data.set_start_address(0x0); + dmi_data.set_end_address((sc_dt::uint64)-1); + return false; + } + } + + private: + +// dynamic process handler for nb2b conversion + + class process_handle_class { + public: + explicit process_handle_class(transaction_type * trans) + : m_trans(trans),m_suspend(false) {} + + transaction_type* m_trans; + sc_core::sc_event m_e; + bool m_suspend; + }; + + class process_handle_list { + public: + process_handle_list() {} + + ~process_handle_list() { + for( typename std::vector<process_handle_class*>::iterator + it=v.begin(), end = v.end(); it != end; ++it ) + delete *it; + } + + process_handle_class* get_handle(transaction_type *trans) + { + typename std::vector<process_handle_class*>::iterator it; + + for(it = v.begin(); it != v.end(); it++) { + if ((*it)->m_suspend) { // found suspended dynamic process, re-use it + (*it)->m_trans = trans; // replace to new one + (*it)->m_suspend = false; + return *it; + } + } + return NULL; // no suspended process + } + + void put_handle(process_handle_class* ph) + { + v.push_back(ph); + } + + private: + std::vector<process_handle_class*> v; + }; + + process_handle_list m_process_handle; + + + void nb2b_thread(process_handle_class* h) + { + + while(1) { + transaction_type *trans = h->m_trans; + sc_core::sc_time t = sc_core::SC_ZERO_TIME; + + // forward call + assert(m_mod); + (m_mod->*m_b_transport_ptr)(*trans, t); + + sc_core::wait(t); + + // return path + while (m_response_in_progress) { + sc_core::wait(m_end_response); + } + t = sc_core::SC_ZERO_TIME; + phase_type phase = tlm::BEGIN_RESP; + sync_enum_type sync = m_owner->bw_nb_transport(*trans, phase, t); + if ( !(sync == tlm::TLM_COMPLETED || + (sync == tlm::TLM_UPDATED && phase == tlm::END_RESP)) ) { + m_response_in_progress = true; + } + + // suspend until next transaction + h->m_suspend = true; + sc_core::wait(); + } + } + + void b2nb_thread() + { + while (true) { + sc_core::wait(m_peq.get_event()); + + transaction_type* trans; + while ((trans = m_peq.get_next_transaction())!=0) { + assert(m_mod); + assert(m_nb_transport_ptr); + phase_type phase = tlm::BEGIN_REQ; + sc_core::sc_time t = sc_core::SC_ZERO_TIME; + + switch ((m_mod->*m_nb_transport_ptr)(*trans, phase, t)) { + case tlm::TLM_COMPLETED: + { + // notify transaction is finished + typename std::map<transaction_type*, sc_core::sc_event *>::iterator it = + m_owner->m_pending_trans.find(trans); + assert(it != m_owner->m_pending_trans.end()); + it->second->notify(t); + m_owner->m_pending_trans.erase(it); + break; + } + + case tlm::TLM_ACCEPTED: + case tlm::TLM_UPDATED: + switch (phase) { + case tlm::BEGIN_REQ: + m_owner->m_current_transaction = trans; + sc_core::wait(m_owner->m_end_request); + m_owner->m_current_transaction = 0; + break; + + case tlm::END_REQ: + sc_core::wait(t); + break; + + case tlm::BEGIN_RESP: + { + phase = tlm::END_RESP; + sc_core::wait(t); // This line is a bug fix added in TLM-2.0.2 + t = sc_core::SC_ZERO_TIME; + (m_mod->*m_nb_transport_ptr)(*trans, phase, t); + + // notify transaction is finished + typename std::map<transaction_type*, sc_core::sc_event *>::iterator it = + m_owner->m_pending_trans.find(trans); + assert(it != m_owner->m_pending_trans.end()); + it->second->notify(t); + m_owner->m_pending_trans.erase(it); + break; + } + + default: + assert(0); exit(1); + }; + break; + + default: + assert(0); exit(1); + }; + } + } + } + + void free(tlm::tlm_generic_payload* trans) + { + mm_end_event_ext* ext = trans->template get_extension<mm_end_event_ext>(); + assert(ext); + // notif event first before freeing extensions (reset) + ext->done.notify(); + trans->reset(); + } + + private: + struct mm_end_event_ext : public tlm::tlm_extension<mm_end_event_ext> + { + tlm::tlm_extension_base* clone() const { return NULL; } + void free() {} + void copy_from(tlm::tlm_extension_base const &) {} + sc_core::sc_event done; + }; + + private: + const std::string m_name; + simple_target_socket *m_owner; + MODULE* m_mod; + NBTransportPtr m_nb_transport_ptr; + BTransportPtr m_b_transport_ptr; + TransportDbgPtr m_transport_dbg_ptr; + GetDirectMemPtr m_get_direct_mem_ptr; + peq_with_get<transaction_type> m_peq; + bool m_response_in_progress; + sc_core::sc_event m_end_response; + }; + +private: + fw_process m_fw_process; + bw_process m_bw_process; + std::map<transaction_type*, sc_core::sc_event *> m_pending_trans; + sc_core::sc_event m_end_request; + transaction_type* m_current_transaction; +}; + +//ID Tagged version +template <typename MODULE, + unsigned int BUSWIDTH = 32, + typename TYPES = tlm::tlm_base_protocol_types> +class simple_target_socket_tagged : + public tlm::tlm_target_socket<BUSWIDTH, TYPES> +{ + friend class fw_process; + friend class bw_process; +public: + typedef typename TYPES::tlm_payload_type transaction_type; + typedef typename TYPES::tlm_phase_type phase_type; + typedef tlm::tlm_sync_enum sync_enum_type; + typedef tlm::tlm_fw_transport_if<TYPES> fw_interface_type; + typedef tlm::tlm_bw_transport_if<TYPES> bw_interface_type; + typedef tlm::tlm_target_socket<BUSWIDTH, TYPES> base_type; + +public: + simple_target_socket_tagged() : + base_type(sc_core::sc_gen_unique_name("simple_target_socket_tagged")), + m_fw_process(this), + m_bw_process(this) + { + bind(m_fw_process); + } + + explicit simple_target_socket_tagged(const char* n) : + base_type(n), + m_fw_process(this), + m_bw_process(this) + { + bind(m_fw_process); + } + + using tlm::tlm_target_socket<BUSWIDTH, TYPES>::bind; + + // bw transport must come thru us. + tlm::tlm_bw_transport_if<TYPES> * operator ->() {return &m_bw_process;} + + // REGISTER_XXX + void register_nb_transport_fw(MODULE* mod, + sync_enum_type (MODULE::*cb)(int id, + transaction_type&, + phase_type&, + sc_core::sc_time&), + int id) + { + assert(!sc_core::sc_get_curr_simcontext()->elaboration_done()); + m_fw_process.set_nb_transport_ptr(mod, cb); + m_fw_process.set_nb_transport_user_id(id); + } + + void register_b_transport(MODULE* mod, + void (MODULE::*cb)(int id, + transaction_type&, + sc_core::sc_time&), + int id) + { + assert(!sc_core::sc_get_curr_simcontext()->elaboration_done()); + m_fw_process.set_b_transport_ptr(mod, cb); + m_fw_process.set_b_transport_user_id(id); + } + + void register_transport_dbg(MODULE* mod, + unsigned int (MODULE::*cb)(int id, + transaction_type&), + int id) + { + assert(!sc_core::sc_get_curr_simcontext()->elaboration_done()); + m_fw_process.set_transport_dbg_ptr(mod, cb); + m_fw_process.set_transport_dbg_user_id(id); + } + + void register_get_direct_mem_ptr(MODULE* mod, + bool (MODULE::*cb)(int id, + transaction_type&, + tlm::tlm_dmi&), + int id) + { + assert(!sc_core::sc_get_curr_simcontext()->elaboration_done()); + m_fw_process.set_get_direct_mem_ptr(mod, cb); + m_fw_process.set_get_dmi_user_id(id); + } + +private: + //make call on bw path. + sync_enum_type bw_nb_transport(transaction_type &trans, phase_type &phase, sc_core::sc_time &t) + { + return base_type::operator ->()->nb_transport_bw(trans, phase, t); + } + + void bw_invalidate_direct_mem_ptr(sc_dt::uint64 s,sc_dt::uint64 e) + { + base_type::operator ->()->invalidate_direct_mem_ptr(s, e); + } + + //Helper class to handle bw path calls + // Needed to detect transaction end when called from b_transport. + class bw_process : public tlm::tlm_bw_transport_if<TYPES> + { + public: + bw_process(simple_target_socket_tagged *p_own) : m_owner(p_own) + { + } + + sync_enum_type nb_transport_bw(transaction_type &trans, phase_type &phase, sc_core::sc_time &t) + { + typename std::map<transaction_type*, sc_core::sc_event *>::iterator it; + + it = m_owner->m_pending_trans.find(&trans); + if(it == m_owner->m_pending_trans.end()) { + // Not a blocking call, forward. + return m_owner->bw_nb_transport(trans, phase, t); + + } else { + if (phase == tlm::END_REQ) { + m_owner->m_end_request.notify(sc_core::SC_ZERO_TIME); + return tlm::TLM_ACCEPTED; + + } else if (phase == tlm::BEGIN_RESP) { + if (m_owner->m_current_transaction == &trans) { + m_owner->m_end_request.notify(sc_core::SC_ZERO_TIME); + } + //TODO: add response-accept delay? + it->second->notify(t); + m_owner->m_pending_trans.erase(it); + return tlm::TLM_COMPLETED; + + } else { + assert(0); exit(1); + } + +// return tlm::TLM_COMPLETED; //Should not reach here + } + } + + void invalidate_direct_mem_ptr(sc_dt::uint64 s,sc_dt::uint64 e) + { + return m_owner->bw_invalidate_direct_mem_ptr(s, e); + } + + private: + simple_target_socket_tagged *m_owner; + }; + + class fw_process : public tlm::tlm_fw_transport_if<TYPES>, + public tlm::tlm_mm_interface + { + public: + typedef sync_enum_type (MODULE::*NBTransportPtr)(int id, + transaction_type&, + phase_type&, + sc_core::sc_time&); + typedef void (MODULE::*BTransportPtr)(int id, + transaction_type&, + sc_core::sc_time&); + typedef unsigned int (MODULE::*TransportDbgPtr)(int id, + transaction_type&); + typedef bool (MODULE::*GetDirectMemPtr)(int id, + transaction_type&, + tlm::tlm_dmi&); + + fw_process(simple_target_socket_tagged *p_own) : + m_name(p_own->name()), + m_owner(p_own), + m_mod(0), + m_nb_transport_ptr(0), + m_b_transport_ptr(0), + m_transport_dbg_ptr(0), + m_get_direct_mem_ptr(0), + m_nb_transport_user_id(0), + m_b_transport_user_id(0), + m_transport_dbg_user_id(0), + m_get_dmi_user_id(0), + m_peq(sc_core::sc_gen_unique_name("m_peq")), + m_response_in_progress(false) + { + sc_core::sc_spawn_options opts; + opts.set_sensitivity(&m_peq.get_event()); + sc_core::sc_spawn(sc_bind(&fw_process::b2nb_thread, this), + sc_core::sc_gen_unique_name("b2nb_thread"), &opts); + } + + void set_nb_transport_user_id(int id) { m_nb_transport_user_id = id; } + void set_b_transport_user_id(int id) { m_b_transport_user_id = id; } + void set_transport_dbg_user_id(int id) { m_transport_dbg_user_id = id; } + void set_get_dmi_user_id(int id) { m_get_dmi_user_id = id; } + + void set_nb_transport_ptr(MODULE* mod, NBTransportPtr p) + { + if (m_nb_transport_ptr) { + std::stringstream s; + s << m_name << ": non-blocking callback allready registered"; + SC_REPORT_WARNING("/OSCI_TLM-2/simple_socket",s.str().c_str()); + } else { + assert(!m_mod || m_mod == mod); + m_mod = mod; + m_nb_transport_ptr = p; + } + } + + void set_b_transport_ptr(MODULE* mod, BTransportPtr p) + { + if (m_b_transport_ptr) { + std::stringstream s; + s << m_name << ": blocking callback allready registered"; + SC_REPORT_WARNING("/OSCI_TLM-2/simple_socket",s.str().c_str()); + } else { + assert(!m_mod || m_mod == mod); + m_mod = mod; + m_b_transport_ptr = p; + } + } + + void set_transport_dbg_ptr(MODULE* mod, TransportDbgPtr p) + { + if (m_transport_dbg_ptr) { + std::stringstream s; + s << m_name << ": debug callback allready registered"; + SC_REPORT_WARNING("/OSCI_TLM-2/simple_socket",s.str().c_str()); + } else { + assert(!m_mod || m_mod == mod); + m_mod = mod; + m_transport_dbg_ptr = p; + } + } + + void set_get_direct_mem_ptr(MODULE* mod, GetDirectMemPtr p) + { + if (m_get_direct_mem_ptr) { + std::stringstream s; + s << m_name << ": get DMI pointer callback allready registered"; + SC_REPORT_WARNING("/OSCI_TLM-2/simple_socket",s.str().c_str()); + } else { + assert(!m_mod || m_mod == mod); + m_mod = mod; + m_get_direct_mem_ptr = p; + } + } +// Interface implementation + sync_enum_type nb_transport_fw(transaction_type& trans, + phase_type& phase, + sc_core::sc_time& t) + { + if (m_nb_transport_ptr) { + // forward call + assert(m_mod); + return (m_mod->*m_nb_transport_ptr)(m_nb_transport_user_id, trans, phase, t); + + } else if (m_b_transport_ptr) { + if (phase == tlm::BEGIN_REQ) { + + // prepare thread to do blocking call + process_handle_class * ph = m_process_handle.get_handle(&trans); + + if (!ph) { // create new dynamic process + ph = new process_handle_class(&trans); + m_process_handle.put_handle(ph); + + sc_core::sc_spawn_options opts; + opts.dont_initialize(); + opts.set_sensitivity(&ph->m_e); + + sc_core::sc_spawn(sc_bind(&fw_process::nb2b_thread, this, ph), + sc_core::sc_gen_unique_name("nb2b_thread"), &opts); + } + + ph->m_e.notify(t); + return tlm::TLM_ACCEPTED; + + } else if (phase == tlm::END_RESP) { + m_response_in_progress = false; + m_end_response.notify(t); + return tlm::TLM_COMPLETED; + + } else { + assert(0); exit(1); +// return tlm::TLM_COMPLETED; ///< unreachable code + } + + } else { + std::stringstream s; + s << m_name << ": no non-blocking transport callback registered"; + SC_REPORT_ERROR("/OSCI_TLM-2/simple_socket",s.str().c_str()); + } + return tlm::TLM_ACCEPTED; ///< unreachable code + } + + void b_transport(transaction_type& trans, sc_core::sc_time& t) + { + if (m_b_transport_ptr) { + // forward call + assert(m_mod); + (m_mod->*m_b_transport_ptr)(m_b_transport_user_id, trans, t); + return; + + } else if (m_nb_transport_ptr) { + m_peq.notify(trans, t); + t = sc_core::SC_ZERO_TIME; + + mm_end_event_ext mm_ext; + const bool mm_added = !trans.has_mm(); + + if (mm_added){ + trans.set_mm(this); + trans.set_auto_extension(&mm_ext); + trans.acquire(); + } + + // wait until transaction is finished + sc_core::sc_event end_event; + m_owner->m_pending_trans[&trans] = &end_event; + sc_core::wait(end_event); + + if (mm_added) { + // release will not delete the transaction, it will notify mm_ext.done + trans.release(); + if (trans.get_ref_count()) { + sc_core::wait(mm_ext.done); + } + trans.set_mm(0); + } + + } else { + std::stringstream s; + s << m_name << ": no transport callback registered"; + SC_REPORT_ERROR("/OSCI_TLM-2/simple_socket",s.str().c_str()); + } + } + + unsigned int transport_dbg(transaction_type& trans) + { + if (m_transport_dbg_ptr) { + // forward call + assert(m_mod); + return (m_mod->*m_transport_dbg_ptr)(m_transport_dbg_user_id, trans); + + } else { + // No debug support + return 0; + } + } + + bool get_direct_mem_ptr(transaction_type& trans, + tlm::tlm_dmi& dmi_data) + { + if (m_get_direct_mem_ptr) { + // forward call + assert(m_mod); + return (m_mod->*m_get_direct_mem_ptr)(m_get_dmi_user_id, trans, dmi_data); + + } else { + // No DMI support + dmi_data.allow_read_write(); + dmi_data.set_start_address(0x0); + dmi_data.set_end_address((sc_dt::uint64)-1); + return false; + } + } + + private: +// dynamic process handler for nb2b conversion + + class process_handle_class { + public: + explicit process_handle_class(transaction_type * trans) + : m_trans(trans),m_suspend(false){} + + transaction_type* m_trans; + sc_core::sc_event m_e; + bool m_suspend; + }; + + class process_handle_list { + public: + process_handle_list() {} + + ~process_handle_list() { + for( typename std::vector<process_handle_class*>::iterator + it=v.begin(), end = v.end(); it != end; ++it ) + delete *it; + } + + process_handle_class* get_handle(transaction_type *trans) + { + typename std::vector<process_handle_class*>::iterator it; + + for(it = v.begin(); it != v.end(); it++) { + if ((*it)->m_suspend) { // found suspended dynamic process, re-use it + (*it)->m_trans = trans; // replace to new one + (*it)->m_suspend = false; + return *it; + } + } + return NULL; // no suspended process + } + + void put_handle(process_handle_class* ph) + { + v.push_back(ph); + } + + private: + std::vector<process_handle_class*> v; + }; + + process_handle_list m_process_handle; + + void nb2b_thread(process_handle_class* h) + { + + while(1) { + transaction_type * trans = h->m_trans; + sc_core::sc_time t = sc_core::SC_ZERO_TIME; + + // forward call + assert(m_mod); + (m_mod->*m_b_transport_ptr)(m_b_transport_user_id, *trans, t); + + sc_core::wait(t); + + // return path + while (m_response_in_progress) { + sc_core::wait(m_end_response); + } + t = sc_core::SC_ZERO_TIME; + phase_type phase = tlm::BEGIN_RESP; + sync_enum_type sync = m_owner->bw_nb_transport(*trans, phase, t); + if ( !(sync == tlm::TLM_COMPLETED || + (sync == tlm::TLM_UPDATED && phase == tlm::END_RESP)) ) { + m_response_in_progress = true; + } + + // suspend until next transaction + h->m_suspend = true; + sc_core::wait(); + } + } + + void b2nb_thread() + { + while (true) { + sc_core::wait(m_peq.get_event()); + + transaction_type* trans; + while ((trans = m_peq.get_next_transaction())!=0) { + assert(m_mod); + assert(m_nb_transport_ptr); + phase_type phase = tlm::BEGIN_REQ; + sc_core::sc_time t = sc_core::SC_ZERO_TIME; + + switch ((m_mod->*m_nb_transport_ptr)(m_nb_transport_user_id, *trans, phase, t)) { + case tlm::TLM_COMPLETED: + { + // notify transaction is finished + typename std::map<transaction_type*, sc_core::sc_event *>::iterator it = + m_owner->m_pending_trans.find(trans); + assert(it != m_owner->m_pending_trans.end()); + it->second->notify(t); + m_owner->m_pending_trans.erase(it); + break; + } + + case tlm::TLM_ACCEPTED: + case tlm::TLM_UPDATED: + switch (phase) { + case tlm::BEGIN_REQ: + m_owner->m_current_transaction = trans; + sc_core::wait(m_owner->m_end_request); + m_owner->m_current_transaction = 0; + break; + + case tlm::END_REQ: + sc_core::wait(t); + break; + + case tlm::BEGIN_RESP: + { + phase = tlm::END_RESP; + sc_core::wait(t); // This line is a bug fix added in TLM-2.0.2 + t = sc_core::SC_ZERO_TIME; + (m_mod->*m_nb_transport_ptr)(m_nb_transport_user_id, *trans, phase, t); + + // notify transaction is finished + typename std::map<transaction_type*, sc_core::sc_event *>::iterator it = + m_owner->m_pending_trans.find(trans); + assert(it != m_owner->m_pending_trans.end()); + it->second->notify(t); + m_owner->m_pending_trans.erase(it); + break; + } + + default: + assert(0); exit(1); + }; + break; + + default: + assert(0); exit(1); + }; + } + } + } + + void free(tlm::tlm_generic_payload* trans) + { + mm_end_event_ext* ext = trans->template get_extension<mm_end_event_ext>(); + assert(ext); + // notif event first before freeing extensions (reset) + ext->done.notify(); + trans->reset(); + } + + private: + struct mm_end_event_ext : public tlm::tlm_extension<mm_end_event_ext> + { + tlm::tlm_extension_base* clone() const { return NULL; } + void free() {} + void copy_from(tlm::tlm_extension_base const &) {} + sc_core::sc_event done; + }; + + private: + const std::string m_name; + simple_target_socket_tagged *m_owner; + MODULE* m_mod; + NBTransportPtr m_nb_transport_ptr; + BTransportPtr m_b_transport_ptr; + TransportDbgPtr m_transport_dbg_ptr; + GetDirectMemPtr m_get_direct_mem_ptr; + int m_nb_transport_user_id; + int m_b_transport_user_id; + int m_transport_dbg_user_id; + int m_get_dmi_user_id; + peq_with_get<transaction_type> m_peq; + bool m_response_in_progress; + sc_core::sc_event m_end_response; + }; + +private: + fw_process m_fw_process; + bw_process m_bw_process; + std::map<transaction_type*, sc_core::sc_event *> m_pending_trans; + sc_core::sc_event m_end_request; + transaction_type* m_current_transaction; +}; + +} + +#endif diff --git a/ext/systemc/src/tlm_utils/tlm2_base_protocol_checker.h b/ext/systemc/src/tlm_utils/tlm2_base_protocol_checker.h new file mode 100755 index 000000000..3dbca9e49 --- /dev/null +++ b/ext/systemc/src/tlm_utils/tlm2_base_protocol_checker.h @@ -0,0 +1,1055 @@ + +// Filename: tlm2_base_protocol_checker.h + +//---------------------------------------------------------------------- +// Copyright (c) 2008-2013 by Doulos Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +//---------------------------------------------------------------------- + +// Author: John Aynsley, Doulos + +// Version 1, 11 July 2008 +// Version 2, 16 July 2008 Only generate ref_count > 1 warning from 1st checker of path +// Version 3, 17 July 2008 Support compilation under SystemC 2.1.v1 +// Version 4, 12 Aug 2008 Add header #include <map> +// Version 5, 08 Sep 2008 Fix bugs in message text +// Version 6, 01 Aug 2010 Update messages to refer to OSCI TLM-2.0 LRM of July 2009 +// Version 7, 25 Oct 2011 Minor bug fix for certain compilers: replace u_char with uchar_t +// Version 8, 02 Nov 2011 Support the endianness conversion functions by excluding the +// tlm_endian_context extension from the protocol checks +// Version 9, 17 Aug 2012 Fix LRM reference on line 805 (should be 8.2.11 a) [NOT YET RELEASED] +// Version 10, 3 Jan 2013 Updated messages to refer to IEEE Std 1666-2011, the combined SystemC + TLM-2.0 LRM +// Added checks related to the generic payload option attribute +// Version 11, 14 Mar 2016 Fix minor bug - start_phase should be a copy, not a reference + +// TLM-2.0 Base Protocol Compliance Checker + +/* +Instantiate this checker module in-line between initiator and target, initiator and interconnect, +or interconnect and target by binding the target_socket and initiator_socket +Binding two checkers either side of an interconnect component, or interleaving a series of +checkers with interconnect components, will enable some deeper checks as against having just +a single checker + +For example + + Initiator *initiator; + Bus *bus; + Memory *memory; + ... + initiator->socket.bind(bus->target_socket); + bus->initiator_socket.bind(memory->socket); + +might become + + tlm_utils::tlm2_base_protocol_checker<32> *checker1; + tlm_utils::tlm2_base_protocol_checker<32> *checker2; + ... + initiator->socket.bind(checker1->target_socket); + checker1->initiator_socket.bind(bus->target_socket); + bus->initiator_socket.bind(checker2->target_socket); + checker2->initiator_socket.bind(memory->socket); + + +GENERAL FEATURES OF THE BASE PROTOCOL CHECKER + +The checks are relatively expensive, hence by default the number of checks is limited. +A maximum number can be set explicitly by calling set_num_checks(max) +Checking can be deactivated at any time by calling set_num_checks(0) +All checkers decrement a single global count, because having some checkers running and +others not can cause bogus violation reports +It is not permitted to turn checks on by calling set_num_checks() once checking has been +deactivated, because this could cause bogus violation reports + +The DMI and debug checks are unaffected by the num_checks count (because they are cheap) + +The error messages contain User Manual references + +The checker is designed to be used with a transaction pool: otherwise it could consume +a lot of memory. The checker keeps a local copy of each transaction object +Failures are reported with a severity of SC_ERROR. The actions may be overridden by calling: + sc_report_handler::set_actions("tlm2_protocol_checker", ...); + +SPECIFIC CHECKS + +nb_transport: phase sequence BEGIN_REQ -> END_REQ -> BEGIN_RESP -> END_RESP +Must not have two outstanding requests or responses (exclusion rules) +Must not have decreasing timing annotations on calls to or returns from nb_transport_fw/bw +Phase extensions permitted and ignored +Must not call b_transport during nb_transport phase sequence and vice-versa + +nb_transport: memory manager must be set +nb_transport: reference count must be non-zero +First checker in BEGIN_REQ path should see ref_count == 1 (warning only) +An interconnect component that sets a memory manager should also clear it +An interconnect component that sets extensions with no memory manager should also clear them +(Does not bother with these memory manager checks for DMI and debug) + +Transaction object must be properly initialized +Many generic payload attributes must not be modified during the transaction lifetime +Transaction object must not be re-allocated for a new transaction while still in use +DMI descriptor must be properly initialized +Debug transaction must be properly initialized +Debug byte count must be less than data_length + +Checks that require multiple checkers to be instantiated along a transaction path: +The BEGIN_RESP path must be the reverse of the BEGIN_REQ path +Transaction object must not be sent with BEGIN_REQ while participating in a previous response +Interconnect component must not set response status attribute to TLM_OK_RESPONSE +Interconnect component must not modify data array on the response path + +Generic payload option attribute (IEEE Std 1666-2011, SystemC 2.3.x) +gp_option must be properly initialized and only used for DMI and debug transport +When gp_option is used, other gp attributes must be initalized and used as per the transport interfaces +*/ + + +// ******************** PREAMBLE ******************** + + +#ifndef __tlm2_base_protocol_checker__ +#define __tlm2_base_protocol_checker__ + +#include "systemc" +using std::cout; +using std::endl; +using std::dec; +using std::hex; + +#include "tlm.h" +#include <sstream> +#include <map> + + +namespace tlm_utils { + + +// Number of checks remaining +const sc_dt::uint64 default_num_checks = 100000; +static sc_dt::uint64 num_checks = default_num_checks; + + +// Types used when building a trace of the transaction path +typedef unsigned char uchar_t; +typedef std::deque<sc_core::sc_module*> deque_t; + +struct path_t { + path_t () { response_in_progress = false; ok_response = false; resp_data_ptr = 0; } + + bool response_in_progress; + bool ok_response; + deque_t path; + uchar_t* resp_data_ptr; // Copy of data on response path +}; + +// Global variable used for checks involving multiple checkers along a transaction path +static std::map<tlm::tlm_generic_payload*, path_t> shared_map; + + +// ******************** CLASS DEFINITION ******************** + + +template <unsigned int BUSWIDTH = 32> +class tlm2_base_protocol_checker + +: public sc_core::sc_module +, public tlm::tlm_fw_transport_if<tlm::tlm_base_protocol_types> +, public tlm::tlm_bw_transport_if<tlm::tlm_base_protocol_types> +{ +public: + + // Instantiate and bind checker inline between an existing pair of initiator and target sockets + + tlm::tlm_target_socket <BUSWIDTH, tlm::tlm_base_protocol_types, 1> target_socket; + tlm::tlm_initiator_socket<BUSWIDTH, tlm::tlm_base_protocol_types, 1> initiator_socket; + + SC_CTOR(tlm2_base_protocol_checker) + : m_request_in_progress(0), m_response_in_progress(0) + { + target_socket .bind( *this ); + initiator_socket.bind( *this ); + } + + + // Access methods for num_checks count + + static void set_num_checks(sc_dt::uint64 n) { + if (num_checks == 0) + SC_REPORT_FATAL("tlm2_protocol_checker", "Method set_num_checks called after checking has stopped due to maximum number of checks being reached"); + num_checks = n; + } + + static sc_dt::uint64 get_num_checks() { return num_checks; } + + + // TLM-2.0 interface methods for initiator and target sockets, instrumented with checks + + virtual tlm::tlm_sync_enum nb_transport_fw( + tlm::tlm_generic_payload& trans, tlm::tlm_phase& phase, sc_core::sc_time& delay) + { + tlm::tlm_phase start_phase = phase; + + if (num_checks) + nb_transport_fw_pre_checks( trans, phase, delay ); + + tlm::tlm_sync_enum status; + status = initiator_socket->nb_transport_fw( trans, phase, delay ); + + if (num_checks) + nb_transport_fw_post_checks( trans, start_phase, phase, delay, status ); + + return status; + } + + virtual tlm::tlm_sync_enum nb_transport_bw( + tlm::tlm_generic_payload& trans, tlm::tlm_phase& phase, sc_core::sc_time& delay) + { + if (num_checks) + nb_transport_bw_pre_checks( trans, phase, delay ); + + tlm::tlm_sync_enum status; + status = target_socket->nb_transport_bw( trans, phase, delay ); + + if (num_checks) + nb_transport_bw_post_checks( trans, phase, delay, status ); + + return status; + } + + virtual void b_transport( tlm::tlm_generic_payload& trans, sc_core::sc_time& delay ) + { + if (num_checks) + b_transport_pre_checks( trans, delay ); + + initiator_socket->b_transport( trans, delay ); + + if (num_checks) + b_transport_post_checks( trans, delay ); + } + + virtual bool get_direct_mem_ptr(tlm::tlm_generic_payload& trans, + tlm::tlm_dmi& dmi_data) + { + get_direct_mem_ptr_pre_checks( trans, dmi_data ); + + bool status; + status = initiator_socket->get_direct_mem_ptr( trans, dmi_data ); + + get_direct_mem_ptr_post_checks( trans, dmi_data ); + return status; + } + + virtual void invalidate_direct_mem_ptr(sc_dt::uint64 start_range, + sc_dt::uint64 end_range) + { + target_socket->invalidate_direct_mem_ptr(start_range, end_range); + } + + virtual unsigned int transport_dbg(tlm::tlm_generic_payload& trans) + { + transport_dbg_pre_checks( trans ); + + unsigned int count; + count = initiator_socket->transport_dbg( trans ); + + transport_dbg_post_checks( trans, count ); + return count; + } + + +private: + void b_transport_pre_checks( tlm::tlm_generic_payload& trans, sc_core::sc_time& delay); + + void b_transport_post_checks( tlm::tlm_generic_payload& trans, sc_core::sc_time& delay); + + void nb_transport_fw_pre_checks( + tlm::tlm_generic_payload& trans, tlm::tlm_phase& phase, sc_core::sc_time& delay); + + void nb_transport_fw_post_checks( + tlm::tlm_generic_payload& trans, tlm::tlm_phase& start_phase, tlm::tlm_phase& phase, + sc_core::sc_time& delay, tlm::tlm_sync_enum status); + + void nb_transport_bw_pre_checks( + tlm::tlm_generic_payload& trans, tlm::tlm_phase& phase, sc_core::sc_time& delay); + + void nb_transport_bw_post_checks( + tlm::tlm_generic_payload& trans, tlm::tlm_phase& phase, sc_core::sc_time& delay, + tlm::tlm_sync_enum status); + + void nb_transport_response_checks( + tlm::tlm_generic_payload& trans, tlm::tlm_phase& phase, sc_core::sc_time& delay, + const char* txt2, const char* txt3, const char* txt4); + + void check_initial_state( tlm::tlm_generic_payload& trans, const char* txt2 ); + void check_trans_not_modified( tlm::tlm_generic_payload& trans, const char* txt2 ); + void check_response_path( tlm::tlm_generic_payload& trans, const char* txt2 ); + void remember_gp_option( tlm::tlm_generic_payload& trans ); + + void get_direct_mem_ptr_pre_checks( tlm::tlm_generic_payload& trans, tlm::tlm_dmi& dmi_data ); + + void get_direct_mem_ptr_post_checks( tlm::tlm_generic_payload& trans, tlm::tlm_dmi& dmi_data ); + + void transport_dbg_pre_checks( tlm::tlm_generic_payload& trans ); + + void transport_dbg_post_checks( tlm::tlm_generic_payload& trans, unsigned int count ); + + void tlm2error( tlm::tlm_generic_payload& trans, const char* ref, bool warning = false ); + +private: + + struct state_t { + state_t() { b_call = 0; ph = tlm::UNINITIALIZED_PHASE; gp = 0; } + + bool has_mm; + unsigned int b_call; // Number of b_transport calls in progress + tlm::tlm_phase ph; + sc_core::sc_time time; // Current time + annotated delay + tlm::tlm_generic_payload* gp; // Points to new data and byte enable buffers + uchar_t* data_ptr; // Stores original pointers + uchar_t* byte_enable_ptr; + }; + + // Transaction state for the specific hop where this checker is inlined + std::map<tlm::tlm_generic_payload*, state_t> m_map; + + // Flags for exclusion rules + tlm::tlm_generic_payload* m_request_in_progress; + tlm::tlm_generic_payload* m_response_in_progress; + + std::ostringstream txt; + +}; + + + +// ******************** MEMBER FUNCTION DEFINITIONS ******************** + + +#define BOILERPLATE \ +template <unsigned int BUSWIDTH> \ +void tlm2_base_protocol_checker<BUSWIDTH>:: + + +BOILERPLATE +b_transport_pre_checks( + tlm::tlm_generic_payload& trans, sc_core::sc_time& delay) +{ + ++ m_map[&trans].b_call; + + if ( trans.has_mm() && trans.get_ref_count() == 0) + { + txt << "Transaction passed to b_transport with memory manager and reference count of 0"; + tlm2error(trans, "14.5 t)"); + } + check_initial_state(trans, "b_transport"); + +#if !(defined SYSTEMC_VERSION & SYSTEMC_VERSION <= 20050714) + if (sc_core::sc_get_current_process_handle().proc_kind() == sc_core::SC_METHOD_PROC_) + { + txt << "b_transport called from method process"; + tlm2error(trans, "11.1.1.4 b)"); + } +#endif + + if (m_map[&trans].ph > 0 && m_map[&trans].ph < 4) + { + txt << "b_transport called during a sequence of nb_transport calls"; + tlm2error(trans, "15.2.10 c)"); + } +} + + +BOILERPLATE +b_transport_post_checks( + tlm::tlm_generic_payload& trans, sc_core::sc_time& delay) +{ + check_response_path(trans, "b_transport"); + check_trans_not_modified(trans, "b_transport"); + -- m_map[&trans].b_call; +} + + +BOILERPLATE +nb_transport_fw_pre_checks( + tlm::tlm_generic_payload& trans, tlm::tlm_phase& phase, sc_core::sc_time& delay) +{ + if ( !trans.has_mm() ) + { + txt << "Transaction passed to nb_transport_fw with no memory manager set"; + tlm2error(trans, "14.5 i)"); + } + if ( trans.get_ref_count() == 0) + { + txt << "Transaction passed to nb_transport_fw with reference count of 0"; + tlm2error(trans, "14.5 t)"); + } + + switch (phase) + { + case tlm::BEGIN_REQ: + check_initial_state(trans, "nb_transport_fw"); + + if (m_map[&trans].ph > 0 && m_map[&trans].ph < 4) // END_RESP -> BEGIN_REQ is legal + { + txt << "Phase " << phase << " sent out-of-sequence on forward path, detected in nb_transport_fw"; + tlm2error(trans, "15.2.4"); + } + + if (m_request_in_progress) + { + txt << "Transaction violates BEGIN_REQ exclusion rule, detected in nb_transport_fw"; + tlm2error(trans, "15.2.6 e)"); + } + m_request_in_progress = &trans; + + if (m_map[&trans].b_call) + { + txt << "nb_transport_fw called during a b_transport call"; + tlm2error(trans, "15.2.10 c)"); + } + break; + + case tlm::END_REQ: + case tlm::BEGIN_RESP: + case tlm::UNINITIALIZED_PHASE: + txt << "Phase " << phase << " sent on forward path, detected in nb_transport_fw"; + tlm2error(trans, " 15.2.3 c)"); + break; + + case tlm::END_RESP: + if (m_map[&trans].ph != tlm::BEGIN_RESP) + { + txt << "Phase " << phase << " sent out-of-sequence on forward path, detected in nb_transport_fw"; + tlm2error(trans, "15.2.4"); + } + m_response_in_progress = 0; + break; + } + + if (phase < 5) // Ignore extended phases + m_map[&trans].ph = phase; + + if (sc_core::sc_time_stamp() + delay < m_map[&trans].time) + { + txt << "nb_transport_fw called with decreasing timing annotation:" + << " delay = " << delay + << ", sc_time_stamp() + delay from previous call = " << m_map[&trans].time; + tlm2error(trans, "15.2.7 c)"); + } + m_map[&trans].time = sc_core::sc_time_stamp() + delay; +} + + +BOILERPLATE +nb_transport_fw_post_checks( + tlm::tlm_generic_payload& trans, tlm::tlm_phase& start_phase, tlm::tlm_phase& phase, + sc_core::sc_time& delay, tlm::tlm_sync_enum status) +{ + if (status == tlm::TLM_UPDATED) + { + nb_transport_response_checks( + trans, phase, delay, "(forward) return", "Return from nb_transport_fw", "nb_transport_fw"); + } + else if (status == tlm::TLM_COMPLETED) + { + if (start_phase == tlm::BEGIN_REQ) + check_response_path(trans, "nb_transport_fw"); + m_request_in_progress = 0; + m_map[&trans].ph = tlm::UNINITIALIZED_PHASE; + } + + // Transaction object should not be re-allocated, even during the END_RESP phase + //if (phase != tlm::END_RESP) + { + std::ostringstream txt; + txt << "nb_transport_fw, phase = " << phase; + check_trans_not_modified(trans, txt.str().c_str()); + } +} + + +BOILERPLATE +nb_transport_bw_pre_checks( + tlm::tlm_generic_payload& trans, tlm::tlm_phase& phase, sc_core::sc_time& delay) +{ + if ( !trans.has_mm() ) + { + txt << "Transaction passed to nb_transport_bw with no memory manager set"; + tlm2error(trans, "14.5 i)"); + } + if ( trans.get_ref_count() == 0) + { + txt << "Transaction passed to nb_transport_bw with reference count of 0"; + tlm2error(trans, "14.5 t)"); + } + nb_transport_response_checks( + trans, phase, delay, "backward", "nb_transport_bw called", "nb_transport_bw"); +} + + +BOILERPLATE +nb_transport_bw_post_checks( + tlm::tlm_generic_payload& trans, tlm::tlm_phase& phase, sc_core::sc_time& delay, + tlm::tlm_sync_enum status) +{ + if (status == tlm::TLM_UPDATED) + { + switch (phase) + { + case tlm::BEGIN_REQ: + txt << "Phase " << phase << " sent out-of-sequence on (backward) return path, detected in nb_transport_bw"; + tlm2error(trans, "15.2.4"); + break; + + case tlm::END_REQ: + case tlm::BEGIN_RESP: + case tlm::UNINITIALIZED_PHASE: + txt << "Phase " << phase << " sent on (backward) return path, detected in nb_transport_bw"; + tlm2error(trans, "15.2.3 c)"); + break; + + case tlm::END_RESP: + if (m_map[&trans].ph != tlm::BEGIN_RESP) + { + txt << "Phase " << phase << " sent out-of-sequence on (backward) return path, detected in nb_transport_bw"; + tlm2error(trans, "15.2.4"); + } + + m_response_in_progress = 0; + break; + } + + if (phase < 5) // Ignore extended phases + m_map[&trans].ph = phase; + + if (sc_core::sc_time_stamp() + delay < m_map[&trans].time) + { + txt << "Return from nb_transport_bw with decreasing timing annotation:" + << " delay = " << delay + << ", sc_time_stamp() + delay from previous call = " << m_map[&trans].time; + tlm2error(trans, "15.2.7 c)"); + } + m_map[&trans].time = sc_core::sc_time_stamp() + delay; + } + else if (status == tlm::TLM_COMPLETED) + { + m_response_in_progress = 0; + m_map[&trans].ph = tlm::UNINITIALIZED_PHASE; + } + + // Transaction object should not be re-allocated, even during the END_RESP phase + //if (phase != tlm::END_RESP) + { + std::ostringstream txt; + txt << "nb_transport_bw, phase = " << phase; + check_trans_not_modified(trans, txt.str().c_str()); + } +} + + +BOILERPLATE +nb_transport_response_checks( + tlm::tlm_generic_payload& trans, tlm::tlm_phase& phase, sc_core::sc_time& delay, + const char* txt2, const char* txt3, const char* txt4) +{ + if (trans.is_response_ok()) + if (shared_map[&trans].response_in_progress && !shared_map[&trans].ok_response) + { + txt << "Interconnect component sets response status attribute to TLM_OK_RESPONSE" + << ", detected in " << txt4; + tlm2error(trans, "14.7"); + + } + + switch (phase) + { + case tlm::BEGIN_REQ: + case tlm::END_RESP: + case tlm::UNINITIALIZED_PHASE: + txt << "Phase " << phase << " sent on " << txt2 << " path" + << ", detected in " << txt4; + tlm2error(trans, "15.2.3 c)"); + break; + + case tlm::END_REQ: + if (m_map[&trans].ph != tlm::BEGIN_REQ) + { + txt << "Phase " << phase << " sent out-of-sequence on " << txt2 << " path" + << ", detected in " << txt4; + tlm2error(trans, "15.2.4"); + } + + m_request_in_progress = 0; + break; + + case tlm::BEGIN_RESP: + if (m_map[&trans].ph != tlm::BEGIN_REQ && m_map[&trans].ph != tlm::END_REQ) + { + txt << "Phase " << phase << " sent out-of-sequence on " << txt2 << " path" + << ", detected in " << txt4; + tlm2error(trans, "15.2.4"); + } + + if (&trans == m_request_in_progress) + m_request_in_progress = 0; + + if (m_response_in_progress) + { + txt << "Transaction violates BEGIN_RESP exclusion rule" + << ", detected in " << txt4; + tlm2error(trans, "15.2.6 f)"); + } + m_response_in_progress = &trans; + + check_response_path(trans, txt4); + break; + } + + if (phase < 5) // Ignore extended phases + m_map[&trans].ph = phase; + + if (sc_core::sc_time_stamp() + delay < m_map[&trans].time) + { + txt << txt3 << " with decreasing timing annotation:" + << " delay = " << delay + << ", sc_time_stamp() + delay from previous call = " << m_map[&trans].time; + tlm2error(trans, "15.2.7 c)"); + } + m_map[&trans].time = sc_core::sc_time_stamp() + delay; +} + + +BOILERPLATE +check_initial_state( + tlm::tlm_generic_payload& trans, const char* txt2 ) +{ + if (num_checks > 0) + { + --num_checks; + if (num_checks == 0) + SC_REPORT_INFO("tlm2_protocol_checker", "Checkers deactivated after executing the set number of checks"); + } + + if ( trans.has_mm() && trans.get_ref_count() > 1 && shared_map[&trans].path.empty() ) + { + txt << "New transaction passed to " << txt2 << " with reference count = " + << trans.get_ref_count(); + tlm2error(trans, "14.5 t)", true); + } + if (trans.get_data_ptr() == 0 && trans.get_command() != tlm::TLM_IGNORE_COMMAND) + { + txt << "Transaction not properly initialized: data_ptr == 0, detected in " << txt2; + tlm2error(trans, "14.11 e)"); + } + if (trans.get_data_length() == 0 && trans.get_command() != tlm::TLM_IGNORE_COMMAND) + { + txt << "Transaction not properly initialized: data_langth == 0, detected in " << txt2; + tlm2error(trans, "14.12 d)"); + } + if (trans.get_byte_enable_ptr() != 0 && trans.get_byte_enable_length() == 0) + { + txt << "Transaction not properly initialized: " + << "byte_enable_ptr != 0 and byte_enable_length == 0, detected in " << txt2; + tlm2error(trans, "14.14 f)"); + } + if (trans.get_streaming_width() == 0) + { + txt << "Transaction not properly initialized: streaming_width == 0, detected in " << txt2; + tlm2error(trans, "14.15 f)"); + } + if (trans.is_dmi_allowed()) + { + txt << "Transaction not properly initialized: dmi_allowed == true, detected in " << txt2; + tlm2error(trans, "14.16"); + } + if (trans.get_response_status() != tlm::TLM_INCOMPLETE_RESPONSE) + { + txt << "Transaction not properly initialized: response_status != TLM_INCOMPLETE_RESPONSE, detected in " << txt2; + tlm2error(trans, "14.17 e)"); + } + if (trans.get_gp_option() != tlm::TLM_MIN_PAYLOAD) + { + txt << "Transaction not properly initialized: gp_option != TLM_MIN_PAYLOAD, detected in " << txt2; + tlm2error(trans, "14.8 g)"); + } + + // Setup clones of transaction and buffers in map + tlm::tlm_generic_payload* gp = m_map[&trans].gp; + if (gp == 0) + gp = new tlm::tlm_generic_payload; // Memory leak: transactions are never cleared from map + else + { + delete [] gp->get_data_ptr(); + gp->free_all_extensions(); + } + gp->set_data_ptr( new uchar_t[trans.get_data_length()] ); + m_map[&trans].data_ptr = trans.get_data_ptr(); + + if (gp->get_byte_enable_ptr()) + delete [] gp->get_byte_enable_ptr(); + if (trans.get_byte_enable_ptr()) + gp->set_byte_enable_ptr( new uchar_t[trans.get_byte_enable_length()] ); + else + gp->set_byte_enable_ptr(0); + m_map[&trans].byte_enable_ptr = trans.get_byte_enable_ptr(); + + gp->deep_copy_from(trans); + m_map[&trans].gp = gp; + m_map[&trans].time = sc_core::SC_ZERO_TIME; + m_map[&trans].has_mm = trans.has_mm(); + + // Store request path checker sequence + if (shared_map[&trans].resp_data_ptr) + { + delete [] shared_map[&trans].resp_data_ptr; + shared_map[&trans].resp_data_ptr = 0; + } + if (shared_map[&trans].response_in_progress) + { + txt << "Transaction object sent with BEGIN_REQ while still being used on a previous response path, detected in " << txt2; + tlm2error(trans, "14.5 x)"); + } + shared_map[&trans].ok_response = false; + shared_map[&trans].path.push_back(this); +} + + +BOILERPLATE +remember_gp_option( + tlm::tlm_generic_payload& trans) +{ + // Setup clone of transaction in map in order to check gp_option only + tlm::tlm_generic_payload* gp = m_map[&trans].gp; + if (gp == 0) + gp = new tlm::tlm_generic_payload; // Memory leak: transactions are never cleared from map + gp->set_gp_option( trans.get_gp_option() ); + m_map[&trans].gp = gp; +} + + +BOILERPLATE +check_trans_not_modified( + tlm::tlm_generic_payload& trans, const char* txt2 ) +{ + tlm::tlm_generic_payload* init = m_map[&trans].gp; + + if (trans.get_command() != init->get_command()) + { + txt << "Command attribute modified during transaction lifetime, detected in " << txt2; + tlm2error(trans, "14.7"); + } + if (trans.get_data_ptr() != m_map[&trans].data_ptr) + { + txt << "Data pointer attribute modified during transaction lifetime, detected in " << txt2; + tlm2error(trans, "14.7"); + } + if (trans.get_data_length() != init->get_data_length()) + { + txt << "Data length attribute modified during transaction lifetime, detected in " << txt2; + tlm2error(trans, "14.7"); + } + if (trans.get_command() == tlm::TLM_WRITE_COMMAND) + for (unsigned int i = 0; i < init->get_data_length(); i++) + if (trans.get_data_ptr()[i] != init->get_data_ptr()[i]) + { + txt << "Data array modified during transaction lifetime, detected in " << txt2; + tlm2error(trans, "14.7"); + } + if (trans.get_byte_enable_ptr() != m_map[&trans].byte_enable_ptr) + { + txt << "Byte enable pointer attribute modified during transaction lifetime, detected in " << txt2; + tlm2error(trans, "14.7"); + } + if (trans.get_byte_enable_length() != init->get_byte_enable_length()) + { + txt << "Byte enable length attribute modified during transaction lifetime, detected in " << txt2; + tlm2error(trans, "14.7"); + } + if (trans.get_byte_enable_ptr()) + for (unsigned int i = 0; i < init->get_byte_enable_length(); i++) + if (trans.get_byte_enable_ptr()[i] != init->get_byte_enable_ptr()[i]) + { + txt << "Byte enable array modified during transaction lifetime, detected in " << txt2; + tlm2error(trans, "14.7"); + } + if (trans.get_streaming_width() != init->get_streaming_width()) + { + txt << "Streaming width attribute modified during transaction lifetime, detected in " << txt2; + tlm2error(trans, "14.7"); + } + if (init->get_gp_option() == tlm::TLM_MIN_PAYLOAD && trans.get_gp_option() != tlm::TLM_MIN_PAYLOAD) + { + txt << "Generic payload option attribute modified during transaction lifetime, detected in " << txt2; + tlm2error(trans, "14.8 g)"); + } + if ( !m_map[&trans].has_mm ) + { + if (trans.has_mm()) + { + txt << "Interconnect component sets a memory manager, but does not clear it on return, detected in " << txt2; + tlm2error(trans, "14.5 aa)"); + } + + for (unsigned int i = 0; i < tlm::max_num_extensions(); i++) + // Exclude tlm_endian_context extension from the check because it is not cloned in m_map + if (i != tlm::tlm_endian_context::ID) + if (trans.get_extension(i)) + if ( !m_map[&trans].gp->get_extension(i) ) + { + txt << "Extension set (index = " << i << ") without also being deleted in the absence of a memory manager, detected in " << txt2; + tlm2error(trans, "14.5 aa)"); + } + } + + uchar_t* resp_data_ptr = shared_map[&trans].resp_data_ptr; + if (resp_data_ptr) + for (unsigned int i = 0; i < trans.get_data_length(); i++) + if (trans.get_data_ptr()[i] != resp_data_ptr[i]) + { + txt << "Transaction data array modified in interconnect component on response path, detected in " << txt2; + tlm2error(trans, "14.7"); + } +} + + +BOILERPLATE +check_response_path( + tlm::tlm_generic_payload& trans, const char* txt2 ) +{ + if ( !shared_map[&trans].path.empty() ) + { + if ( this != shared_map[&trans].path.back() ) + { + txt << "BEGIN_RESP path is not the reverse of the BEGIN_REQ path."; + txt << "\nBEGIN_REQ path includes these checkers: -> "; + deque_t path = shared_map[&trans].path; + for (deque_t::iterator i = path.begin(); i < path.end(); i++) + txt << (*i)->name() << " -> "; + txt << "\nDetected in " << txt2; + tlm2error(trans, "15.2.11 a)"); + } + shared_map[&trans].path.pop_back(); + shared_map[&trans].response_in_progress = !shared_map[&trans].path.empty(); + shared_map[&trans].ok_response = trans.is_response_ok(); + + // Create a copy of the data array for comparison on the response path + if ( !shared_map[&trans].resp_data_ptr ) + { + shared_map[&trans].resp_data_ptr = new uchar_t[trans.get_data_length()]; + memcpy(shared_map[&trans].resp_data_ptr, trans.get_data_ptr(), trans.get_data_length()); + } + } +} + + +BOILERPLATE +get_direct_mem_ptr_pre_checks( + tlm::tlm_generic_payload& trans, tlm::tlm_dmi& dmi_data ) +{ + remember_gp_option(trans); + + if (dmi_data.get_dmi_ptr() != 0) + { + txt << "DMI descriptor not properly initialized: dmi_ptr != 0"; + tlm2error(trans, "11.2.5 f)"); + } + if (!dmi_data.is_none_allowed()) + { + txt << "DMI descriptor not properly initialized: granted_access != DMI_ACCESS_NONE"; + tlm2error(trans, "11.2.5 a)"); + } + if (dmi_data.get_start_address() != 0) + { + txt << "DMI descriptor not properly initialized: start_address != 0"; + tlm2error(trans, "11.2.5 u)"); + } + if (dmi_data.get_end_address() != (sc_dt::uint64)(-1)) + { + txt << "DMI descriptor not properly initialized: end_address != 0"; + tlm2error(trans, "11.2.5 u)"); + } + if (dmi_data.get_read_latency() != sc_core::SC_ZERO_TIME) + { + txt << "DMI descriptor not properly initialized: read_latency != SC_ZERO_TIME"; + tlm2error(trans, "11.2.5 ac)"); + } + if (dmi_data.get_write_latency() != sc_core::SC_ZERO_TIME) + { + txt << "DMI descriptor not properly initialized: write_latency != SC_ZERO_TIME"; + tlm2error(trans, "11.2.5 ac)"); + } + + if (trans.get_gp_option() == tlm::TLM_FULL_PAYLOAD) + { + /* + if (trans.is_dmi_allowed()) // Would be rather brutal to flag dmi_allowed as an arror for a DMI transaction! + { + txt << "DMI transaction not properly initialized: dmi_allowed == true"; + tlm2error(trans, "14.8 e) & 14.16"); + } + */ + if (trans.get_response_status() != tlm::TLM_INCOMPLETE_RESPONSE) + { + txt << "DMI transaction not properly initialized: response_status != TLM_INCOMPLETE_RESPONSE"; + tlm2error(trans, "14.8 e) & 14.17 e)"); + } + } + else if (trans.get_gp_option() == tlm::TLM_FULL_PAYLOAD_ACCEPTED) + { + txt << "DMI transaction not properly initialized: gp_option == TLM_FULL_PAYLOAD_ACCEPTED"; + tlm2error(trans, "14.8 c) & e) & j)"); + } +} + + +BOILERPLATE +get_direct_mem_ptr_post_checks( tlm::tlm_generic_payload& trans, tlm::tlm_dmi& dmi_data ) +{ + tlm::tlm_generic_payload* init = m_map[&trans].gp; + + if (init->get_gp_option() == tlm::TLM_MIN_PAYLOAD && trans.get_gp_option() != tlm::TLM_MIN_PAYLOAD) + { + txt << "DMI transaction gp_option attribute value TLM_MIN_PAYLOAD modified during transaction lifetime"; + tlm2error(trans, "14.8 h)"); + } + else if (init->get_gp_option() == tlm::TLM_FULL_PAYLOAD && trans.get_gp_option() == tlm::TLM_MIN_PAYLOAD) + { + txt << "DMI transaction gp_option attribute value changed from TLM_FULL_PAYLOAD to TLM_MIN_PAYLOAD"; + tlm2error(trans, "14.8 j)"); + } +} + + +BOILERPLATE +transport_dbg_pre_checks( tlm::tlm_generic_payload& trans ) +{ + remember_gp_option(trans); + + if (trans.get_data_length() > 0 && trans.get_data_ptr() == 0) + { + txt << "Debug transaction has data_ptr == 0"; + tlm2error(trans, "11.3.4 l)"); + } + + if (trans.get_gp_option() == tlm::TLM_FULL_PAYLOAD) + { + if (trans.get_byte_enable_ptr() != 0 && trans.get_byte_enable_length() == 0) + { + txt << "Debug transaction not properly initialized: " + << "byte_enable_ptr != 0 and byte_enable_length == 0"; + tlm2error(trans, "14.8 f) & 14.14 f)"); + } + if (trans.get_streaming_width() == 0) + { + txt << "Debug transaction not properly initialized: streaming_width == 0"; + tlm2error(trans, "14.8 f) & 14.15 f)"); + } + if (trans.is_dmi_allowed()) + { + txt << "Debug transaction not properly initialized: dmi_allowed == true"; + tlm2error(trans, "14.8 f) & 14.16"); + } + if (trans.get_response_status() != tlm::TLM_INCOMPLETE_RESPONSE) + { + txt << "Debug transaction not properly initialized: response_status != TLM_INCOMPLETE_RESPONSE"; + tlm2error(trans, "14.8 f) & 14.17 e)"); + } + } + else if (trans.get_gp_option() == tlm::TLM_FULL_PAYLOAD_ACCEPTED) + { + txt << "Debug transaction not properly initialized: gp_option == TLM_FULL_PAYLOAD_ACCEPTED"; + tlm2error(trans, "14.8 c) & f) & l)"); + }} + + +BOILERPLATE +transport_dbg_post_checks( tlm::tlm_generic_payload& trans, unsigned int count ) +{ + tlm::tlm_generic_payload* init = m_map[&trans].gp; + + if (trans.get_data_length() > 0 && trans.get_data_ptr() == 0) + { + txt << "Debug transaction has data_ptr == 0"; + tlm2error(trans, "11.3.4 l)"); + } + if (count > trans.get_data_length()) + { + txt << "Count returned from transport_dbg is greater than data_length"; + tlm2error(trans, "11.3.4 s)"); + } + + if (init->get_gp_option() == tlm::TLM_MIN_PAYLOAD && trans.get_gp_option() != tlm::TLM_MIN_PAYLOAD) + { + txt << "Debug transaction gp_option attribute value TLM_MIN_PAYLOAD modified during transaction lifetime"; + tlm2error(trans, "14.8 h)"); + } + else if (init->get_gp_option() == tlm::TLM_FULL_PAYLOAD && trans.get_gp_option() == tlm::TLM_MIN_PAYLOAD) + { + txt << "Debug transaction gp_option attribute value changed from TLM_FULL_PAYLOAD to TLM_MIN_PAYLOAD"; + tlm2error(trans, "14.8 l)"); + }} + + +BOILERPLATE +tlm2error( tlm::tlm_generic_payload& trans, const char* ref, bool warning ) +{ + txt << "\n\nRefer to IEEE Std 1666-2011, clause " << ref; + txt << "\n\nChecker instance: " << this->name(); + txt << "\n\nTransaction details:"; + txt << "\n has_mm = " << dec << trans.has_mm() << " (bool)"; + txt << "\n ref_count = " << dec << trans.get_ref_count() << " (int)"; + txt << "\n\n gp_option = " << + (trans.get_gp_option() == tlm::TLM_MIN_PAYLOAD ? "TLM_MIN_PAYLOAD" + :trans.get_gp_option() == tlm::TLM_FULL_PAYLOAD ? "TLM_FULL_PAYLOAD" + : "TLM_FULL_PAYLOAD_ACCEPTED"); + txt << "\n command = " << + (trans.get_command() == tlm::TLM_READ_COMMAND ? "TLM_READ_COMMAND" + :trans.get_command() == tlm::TLM_WRITE_COMMAND ? "TLM_WRITE_COMMAND" + : "TLM_IGNORE_COMMAND"); + txt << "\n address = " << hex << trans.get_address() << " (hex)"; + txt << "\n data_ptr = " << hex + << reinterpret_cast<int*>(trans.get_data_ptr()) << " (hex)"; + txt << "\n data_length = " << hex << trans.get_data_length() << " (hex)"; + txt << "\n streaming_width = " << hex << trans.get_streaming_width() << " (hex)"; + txt << "\n byte_enable_ptr = " << hex + << reinterpret_cast<int*>(trans.get_byte_enable_ptr()) << " (hex)"; + txt << "\n byte_enable_length = " << hex << trans.get_byte_enable_length() << " (hex)"; + txt << "\n dmi_allowed = " << dec << trans.is_dmi_allowed() << " (bool)"; + txt << "\n response_status = " << trans.get_response_string(); + + bool extensions_present = false; + for (unsigned int i = 0; i < tlm::max_num_extensions(); i++) + { + tlm::tlm_extension_base* ext = trans.get_extension(i); + if (ext) + { + if (!extensions_present) + txt << "\n\n extensions:"; + txt << "\n index = " << i << " type = " << typeid(*ext).name(); + extensions_present = true; + } + } + + txt << "\n\n"; + if (warning) + SC_REPORT_WARNING("tlm2_protocol_checker", txt.str().c_str()); + else + SC_REPORT_ERROR("tlm2_protocol_checker", txt.str().c_str()); +} + + + +} // namespace tlm_utils + +#endif // __tlm2_base_protocol_checker__ diff --git a/ext/systemc/src/tlm_utils/tlm_quantumkeeper.h b/ext/systemc/src/tlm_utils/tlm_quantumkeeper.h new file mode 100644 index 000000000..ed211665f --- /dev/null +++ b/ext/systemc/src/tlm_utils/tlm_quantumkeeper.h @@ -0,0 +1,172 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +// 20-Mar-2009 John Aynsley Add set_and_sync() method + + +#ifndef __TLM_QUANTUMKEEPER_H__ +#define __TLM_QUANTUMKEEPER_H__ + +#include "tlm_core/tlm_2/tlm_quantum/tlm_global_quantum.h" + +namespace tlm_utils { + + // + // tlm_quantumkeeper class + // + // The tlm_quantumkeeper class is used to keep track of the local time in + // an initiator (how much it has run ahead of the SystemC time), to + // synchronize with SystemC time etc. + // + class tlm_quantumkeeper + { + public: + // + // Static setters/getters for the global quantum value. + // + // The global quantum is the maximum time an initiator can run ahead of + // systemC time. All initiators will synchronize on timingpoints that are + // multiples of the global quantum value. + // + static void set_global_quantum(const sc_core::sc_time& t) + { + tlm::tlm_global_quantum::instance().set(t); + } + + static const sc_core::sc_time& get_global_quantum() + { + return tlm::tlm_global_quantum::instance().get(); + } + + public: + tlm_quantumkeeper() : + m_next_sync_point(sc_core::SC_ZERO_TIME), + m_local_time(sc_core::SC_ZERO_TIME) + { + } + + virtual ~tlm_quantumkeeper() {} + + // + // Increment the local time (the time the initiator is ahead of the + // systemC time) After incrementing the local time an initiator should + // check (with the need_sync method) if a sync is required. + // + virtual void inc(const sc_core::sc_time& t) + { + m_local_time += t; + } + + // + // Sets the local time (the time the initiator is ahead of the + // systemC time) After changing the local time an initiator should + // check (with the need_sync method) if a sync is required. + // + virtual void set(const sc_core::sc_time& t) + { + m_local_time = t; + } + + // + // Checks if a sync to systemC is required for this initiator. This will + // be the case if the local time becomes greater than the local (current) + // quantum value for this initiator. + // + virtual bool need_sync() const + { + return sc_core::sc_time_stamp() + m_local_time >= m_next_sync_point; + } + + // + // Synchronize to systemC. This call will do a wait for the time the + // initiator was running ahead of systemC time and reset the + // tlm_quantumkeeper. + // + virtual void sync() + { + sc_core::wait(m_local_time); + reset(); + } + + // + // Non-virtual convenience method to set the local time and sync only if needed + // + void set_and_sync(const sc_core::sc_time& t) + { + set(t); + if (need_sync()) + sync(); + } + + // + // Resets the local time to SC_ZERO_TIME and computes the value of the + // next local quantum. This method should be called by an initiator after + // a wait because of a synchronization request by a target (TLM_ACCEPTED, + // or TLM_UPDATED). + // + virtual void reset() + { + m_local_time = sc_core::SC_ZERO_TIME; + m_next_sync_point = sc_core::sc_time_stamp() + compute_local_quantum(); + } + + // + // Helper function to get the current systemC time, taken the local time + // into account. The current systemC time is calculated as the time + // returned by sc_time_stamp incremeneted with the time the initiator is + // running ahead. + // + virtual sc_core::sc_time get_current_time() const + { + return sc_core::sc_time_stamp() + m_local_time; + } + + // + // Helper functions to get the time the initiator is running ahead of + // systenC (local time). This time should be passed to a target in the + // nb_transport call + // + virtual sc_core::sc_time get_local_time() const + { + return m_local_time; + } + + protected: + // + // Calculate the next local quantum for this initiator. + // + // The method can be overloaded in a derived object if an initiator wants + // to use another local quantum. This derived object should also take the + // global quantum into account. It's local quantum should not be set to a + // value that is larger than the quantum returned by the + // compute_local_quantum of the tlm_global_quantum singleton. + // + virtual sc_core::sc_time compute_local_quantum() + { + return tlm::tlm_global_quantum::instance().compute_local_quantum(); + } + + protected: + sc_core::sc_time m_next_sync_point; + sc_core::sc_time m_local_time; + }; + +} // namespace tlm + +#endif |