From: Matthias Jung Date: Wed, 1 Mar 2017 17:39:56 +0000 (+0100) Subject: ext: Include SystemC 2.3.1 into gem5 X-Git-Tag: v19.0.0.0~2792 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=aa651c7f8321bf96fc88f9a17285225000a753ec;p=gem5.git ext: Include SystemC 2.3.1 into 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, but I was able to exchange the boost calls by c++11 alternatives. The recent SystemC version is placed into /ext and is integrated into gem5's build system. The goal is to integrate some SystemC tests for the CI in some following patches. Change-Id: I4b66ec806b5e3cffc1d7c85d3735ff4fa5b31fd0 Reviewed-on: https://gem5-review.googlesource.com/2240 Reviewed-by: Andreas Sandberg Maintainer: Andreas Sandberg --- 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 + + * Combined SystemC 2.3.1 / TLM 2.0.3 officially released. + +2012-07-01 Andy Goodrich + + * Combined SystemC 2.3.0 / TLM-2.0.2 officially released. + +2007-03-14 Andy Goodrich + + * SystemC 2.2 released. + +2006-06-05 Andy Goodrich + + * SystemC 2.2 Beta released to the public. + +2005-07-14 Andy Goodrich + + * SystemC 2.1v1 released. + +2003-12-02 Andy Goodrich + + * SystemC 2.1 Beta-7 released. + +2003-06-13 Andy Goodrich + + * SystemC 2.1 Beta-1 released. + +2002-04-05 Martin Janssen + + * SystemC 2.0.1 released. + +2001-10-05 Martin Janssen + + * SystemC 2.0 released. + +2001-09-05 Martin Janssen + + * SystemC 2.0 Beta-2 released. + +2001-07-13 Martin Janssen + + * 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="" + + 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-, + 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=-] + + 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 .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= - + 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) header from + + 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 + 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 header from header + + Previous versions of SystemC always included the full + header on all Windows platforms. This adds unnecessary bloat to + many SystemC applications, reducing compilation times. + + If you rely on the inclusion of the 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= - + 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('/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' and 'sc_buffer' 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 instead of + + + - 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 on Windows + platforms, removing the automatic inclusion from + (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::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 , + instead of + + + - 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 primitive channel class. + Like sc_signal, 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 +// +// The sc_buffer primitive channel class. +// ---------------------------------------------------------------------------- + +template< typename T, sc_writer_policy POL = SC_DEFAULT_WRITER_POLICY > +class sc_buffer +: public sc_signal +{ +public: + + // typedefs + + typedef sc_buffer this_type; + typedef sc_signal 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& 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::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::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(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 ).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 only + instead of sc_signal_in_if 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 +{ + typedef sc_signal 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& signal() + { return *this; } + + const sc_signal_in_if& 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 only + instead of sc_signal_in_if 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 sc_in_clk; +typedef sc_inout sc_inout_clk; +typedef sc_out 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 cannot have more than one reader" ) +SC_DEFINE_MESSAGE( SC_ID_MORE_THAN_ONE_FIFO_WRITER_, 105, + "sc_fifo cannot have more than one writer" ) +SC_DEFINE_MESSAGE( SC_ID_INVALID_FIFO_SIZE_, 106, + "sc_fifo 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 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 +// +// Interface specific event finder class. +// ---------------------------------------------------------------------------- + +template +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& ); + sc_event_finder_t& operator = ( const sc_event_finder_t& ); +}; + + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + +template +inline +const sc_event& +sc_event_finder_t::find_event( sc_interface* if_p ) const +{ + const IF* iface = ( if_p ) ? DCAST( if_p ) : + DCAST( port().get_interface() ); + if( iface == 0 ) { + report_error( SC_ID_FIND_EVENT_, "port is not bound" ); + } + return (CCAST( 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( p1 ); + const sc_time* t2 = static_cast( 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 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_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( 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( 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( 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( 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 + +#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. +//============================================================================= + +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 sc_export : public sc_export_base +{ + typedef sc_export 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); } + + +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 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 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 + +namespace sc_core { + +// ---------------------------------------------------------------------------- +// CLASS : sc_fifo +// +// The sc_fifo primitive channel class. +// ---------------------------------------------------------------------------- + +template +class sc_fifo +: public sc_fifo_in_if, + public sc_fifo_out_if, + 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& 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& ); + sc_fifo& operator = ( const sc_fifo& ); +}; + + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + +template +inline +void +sc_fifo::register_port( sc_port_base& port_, + const char* if_typename_ ) +{ + std::string nm( if_typename_ ); + if( nm == typeid( sc_fifo_in_if ).name() || + nm == typeid( sc_fifo_blocking_in_if ).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 ).name() || + nm == typeid( sc_fifo_blocking_out_if ).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 port not recognized" ); + } +} + + +// blocking read + +template +inline +void +sc_fifo::read( T& val_ ) +{ + while( num_available() == 0 ) { + sc_core::wait( m_data_written_event ); + } + m_num_read ++; + buf_read( val_ ); + request_update(); +} + +template +inline +T +sc_fifo::read() +{ + T tmp; + read( tmp ); + return tmp; +} + +// non-blocking read + +template +inline +bool +sc_fifo::nb_read( T& val_ ) +{ + if( num_available() == 0 ) { + return false; + } + m_num_read ++; + buf_read( val_ ); + request_update(); + return true; +} + + +// blocking write + +template +inline +void +sc_fifo::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 +inline +bool +sc_fifo::nb_write( const T& val_ ) +{ + if( num_free() == 0 ) { + return false; + } + m_num_written ++; + buf_write( val_ ); + request_update(); + return true; +} + + +template +inline +void +sc_fifo::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 +inline +void +sc_fifo::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 +inline +void +sc_fifo::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 +inline +void +sc_fifo::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 +inline +void +sc_fifo::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 +inline +void +sc_fifo::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 +inline +bool +sc_fifo::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 +inline +bool +sc_fifo::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 +inline +::std::ostream& +operator << ( ::std::ostream& os, const sc_fifo& 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 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 +// +// The sc_fifo input nonblocking interface class. +// ---------------------------------------------------------------------------- + +template +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 +// +// The sc_fifo input blocking interface class. +// ---------------------------------------------------------------------------- + +template +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 +// +// The sc_fifo input interface class. +// ---------------------------------------------------------------------------- + +template +class sc_fifo_in_if +: public sc_fifo_nonblocking_in_if, + public sc_fifo_blocking_in_if +{ +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& ); + sc_fifo_in_if& operator = ( const sc_fifo_in_if& ); +}; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_fifo_nonblocking_out_if +// +// The sc_fifo nonblocking output interface class. +// ---------------------------------------------------------------------------- + +template +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 +// +// The sc_fifo blocking output interface class. +// ---------------------------------------------------------------------------- + +template +class sc_fifo_blocking_out_if +: virtual public sc_interface +{ +public: + + // blocking write + virtual void write( const T& ) = 0; + +}; + +// ---------------------------------------------------------------------------- +// CLASS : sc_fifo_out_if +// +// The sc_fifo output interface class. +// ---------------------------------------------------------------------------- + +template +class sc_fifo_out_if +: public sc_fifo_nonblocking_out_if, + public sc_fifo_blocking_out_if +{ +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& ); + sc_fifo_out_if& operator = ( const sc_fifo_out_if& ); +}; + +/***************************************************************************** + + 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 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 +// +// The sc_fifo input port class. +// ---------------------------------------------------------------------------- + +template +class sc_fifo_in +: public sc_port,0,SC_ONE_OR_MORE_BOUND> +{ +public: + + // typedefs + + typedef T data_type; + + typedef sc_fifo_in_if if_type; + typedef sc_port base_type; + typedef sc_fifo_in this_type; + + typedef if_type in_if_type; + typedef sc_port_b 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( + *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 +// +// The sc_fifo output port class. +// ---------------------------------------------------------------------------- + +template +class sc_fifo_out +: public sc_port,0,SC_ONE_OR_MORE_BOUND> +{ +public: + + // typedefs + + typedef T data_type; + + typedef sc_fifo_out_if if_type; + typedef sc_port base_type; + typedef sc_fifo_out this_type; + + typedef if_type out_if_type; + typedef sc_port_b 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( + *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 +#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 vec; + bool has_parent; + int last_add; + bool is_leaf; + bool complete; + + std::vector thread_vec; + std::vector 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 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& 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( 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( get_parent_object() ); + sc_object::hierarchy_scope scope( parent ); + end_of_elaboration(); +} + +void +sc_port_base::start_simulation() +{ + sc_module* parent = static_cast( get_parent_object() ); + sc_object::hierarchy_scope scope( parent ); + start_of_simulation(); +} + +void +sc_port_base::simulation_done() +{ + sc_module* parent = static_cast( 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 + +#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 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 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 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 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 sc_port +: public sc_port_b +{ + // typdefs + + typedef sc_port_b base_type; + typedef sc_port 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 +inline +IF* +sc_port_b::operator -> () +{ + if( m_interface == 0 ) { + report_error( SC_ID_GET_IF_, "port is not bound" ); + } + return m_interface; +} + +template +inline +const IF* +sc_port_b::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 +inline +IF* +sc_port_b::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 +inline +const IF* +sc_port_b::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 +inline +int +sc_port_b::vbind( sc_interface& interface_ ) +{ + IF* iface = DCAST( &interface_ ); + if( iface == 0 ) { + // type mismatch + return 2; + } + base_type::bind( *iface ); + return 0; +} + +template +inline +int +sc_port_b::vbind( sc_port_base& parent_ ) +{ + this_type* parent = DCAST( &parent_ ); + if( parent == 0 ) { + // type mismatch + return 2; + } + base_type::bind( *parent ); + return 0; +} + + +// called by complete_binding (for internal use only) + +template +inline +void +sc_port_b::add_interface( sc_interface* interface_ ) +{ + IF* iface = DCAST( 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 +inline +const char* +sc_port_b::if_typename() const +{ + return typeid( IF ).name(); +} + +template +inline +int +sc_port_b::interface_count() +{ + return m_interface_vec.size(); +} + +template +void +sc_port_b::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 +void +sc_port_b::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 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 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 + +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 + +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::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::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::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::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::print( ::std::ostream& os ) const +{ + os << m_cur_val; +} + +template< sc_writer_policy POL > +void +sc_signal::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::update() +{ + policy_type::update(); + if( !( m_new_val == m_cur_val ) ) { + do_update(); + } +} + +template< sc_writer_policy POL > +void +sc_signal::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::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::posedge_event() const +{ + return *sc_lazy_kernel_event(&m_posedge_event_p,"posedge_event"); +} + +template< sc_writer_policy POL > +const sc_event& +sc_signal::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::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::~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::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::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::print( ::std::ostream& os ) const +{ + os << m_cur_val; +} + +template< sc_writer_policy POL > +void +sc_signal::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::update() +{ + policy_type::update(); + if( !( m_new_val == m_cur_val ) ) { + do_update(); + } +} + +template< sc_writer_policy POL > +void +sc_signal::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::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::posedge_event() const +{ + return *sc_lazy_kernel_event(&m_posedge_event_p,"posedge_event"); +} + +template< sc_writer_policy POL > +const sc_event& +sc_signal::negedge_event() const +{ + return *sc_lazy_kernel_event(&m_negedge_event_p,"negedge_event"); +} + + +// template instantiations for writer policies + +template class sc_signal; +template class sc_signal; +template class sc_signal; + +template class sc_signal; +template class sc_signal; +template class sc_signal; + +} // 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 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 + +namespace sc_core { + +// to avoid code bloat in sc_signal + +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 +// +// The sc_signal primitive channel class. +// ---------------------------------------------------------------------------- + +template< class T, sc_writer_policy POL /* = SC_DEFAULT_WRITER_POLICY */ > +class sc_signal + : public sc_signal_inout_if + , public sc_prim_channel + , protected sc_writer_policy_check +{ +protected: + typedef sc_signal_inout_if if_type; + typedef sc_signal this_type; + typedef sc_writer_policy_check 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& 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::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::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::print( ::std::ostream& os ) const +{ + os << m_cur_val; +} + +template< class T, sc_writer_policy POL > +void +sc_signal::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::update() +{ + policy_type::update(); + if( !( m_new_val == m_cur_val ) ) { + do_update(); + } +} + +template< class T, sc_writer_policy POL > +void +sc_signal::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 +// +// Specialization of sc_signal for type bool. +// ---------------------------------------------------------------------------- + +class sc_reset; + +template< sc_writer_policy POL > +class sc_signal + : public sc_signal_inout_if + , public sc_prim_channel + , protected sc_writer_policy_check +{ +protected: + typedef sc_signal_inout_if if_type; + typedef sc_signal this_type; + typedef sc_writer_policy_check 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& 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 +// +// Specialization of sc_signal for type sc_dt::sc_logic. +// ---------------------------------------------------------------------------- + +template< sc_writer_policy POL > +class sc_signal + : public sc_signal_inout_if + , public sc_prim_channel + , protected sc_writer_policy_check +{ +protected: + typedef sc_signal_inout_if if_type; + typedef sc_signal this_type; + typedef sc_writer_policy_check 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& 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& 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. +// +//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 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 +// +// The sc_signal input interface class. +// ---------------------------------------------------------------------------- + +template +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& ); + sc_signal_in_if& operator = ( const sc_signal_in_if& ); +}; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_signal_in_if +// +// Specialization of sc_signal_in_if for type bool. +// ---------------------------------------------------------------------------- + +class sc_reset; + +template <> +class sc_signal_in_if +: 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& ); + sc_signal_in_if& operator = ( const sc_signal_in_if& ); + + // designate this object as a reset signal + virtual sc_reset* is_reset() const + { return NULL; } +}; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_signal_in_if +// +// Specialization of sc_signal_in_if for type sc_dt::sc_logic. +// ---------------------------------------------------------------------------- + +template <> +class sc_signal_in_if +: 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_signal_in_if& operator = ( + const sc_signal_in_if& ); +}; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_signal_write_if +// +// 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& ); + sc_signal_write_if& operator = ( const sc_signal_write_if& ); +}; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_signal_inout_if +// +// The sc_signal input/output interface class. +// ---------------------------------------------------------------------------- + +template +class sc_signal_inout_if +: public sc_signal_in_if, public sc_signal_write_if +{ + +protected: + + // constructor + + sc_signal_inout_if() + {} + +private: + + // disabled + sc_signal_inout_if( const sc_signal_inout_if& ); + sc_signal_inout_if& operator = ( const sc_signal_inout_if& ); +}; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_signal_out_if +// +// The sc_signal 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 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 +// +// Specialization of sc_in for type bool. +// ---------------------------------------------------------------------------- + +// called when elaboration is done + +void +sc_in::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( get_interface() ); + sc_trace( p->tf, iface->read(), p->name ); + } + remove_traces(); + } +} + +// called by sc_trace + +void +sc_in::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::add_trace(sc_trace_file* tf_, + const std::string& name_) const +{ + sc_deprecated_add_trace(); + add_trace_internal(tf_, name_); +} + +void +sc_in::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::vbind( sc_interface& interface_ ) +{ + return sc_port_b::vbind( interface_ ); +} + +int +sc_in::vbind( sc_port_base& parent_ ) +{ + in_port_type* in_parent = DCAST( &parent_ ); + if( in_parent != 0 ) { + sc_port_base::bind( *in_parent ); + return 0; + } + inout_port_type* inout_parent = DCAST( &parent_ ); + if( inout_parent != 0 ) { + sc_port_base::bind( *inout_parent ); + return 0; + } + // type mismatch + return 2; +} + + +// ---------------------------------------------------------------------------- +// CLASS : sc_in +// +// Specialization of sc_in for type sc_logic. +// ---------------------------------------------------------------------------- + +// called when elaboration is done + +void +sc_in::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( get_interface() ); + sc_trace( p->tf, iface->read(), p->name ); + } + remove_traces(); + } +} + + +// called by sc_trace + +void +sc_in::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::add_trace( sc_trace_file* tf_, + const std::string& name_ ) const +{ + sc_deprecated_add_trace(); + add_trace_internal(tf_, name_); +} + +void +sc_in::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::vbind( sc_interface& interface_ ) +{ + return sc_port_b::vbind( interface_ ); +} + +int +sc_in::vbind( sc_port_base& parent_ ) +{ + in_port_type* in_parent = DCAST( &parent_ ); + if( in_parent != 0 ) { + sc_port_base::bind( *in_parent ); + return 0; + } + inout_port_type* inout_parent = DCAST( &parent_ ); + if( inout_parent != 0 ) { + sc_port_base::bind( *inout_parent ); + return 0; + } + // type mismatch + return 2; +} + + +// ---------------------------------------------------------------------------- +// CLASS : sc_inout +// +// Specialization of sc_inout for type bool. +// ---------------------------------------------------------------------------- + +// destructor + +sc_inout::~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::initialize( const data_type& value_ ) +{ + inout_if_type* iface = DCAST( 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::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( get_interface() ); + sc_trace( p->tf, iface->read(), p->name ); + } + remove_traces(); + } +} + + +// called by sc_trace + +void +sc_inout::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::add_trace( sc_trace_file* tf_, + const std::string& name_ ) const +{ + sc_deprecated_add_trace(); + add_trace_internal(tf_, name_); +} + +void +sc_inout::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 +// +// Specialization of sc_inout for type sc_dt::sc_logic. +// ---------------------------------------------------------------------------- + +// destructor + +sc_inout::~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::initialize( const data_type& value_ ) +{ + inout_if_type* iface = DCAST( 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::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( get_interface() ); + sc_trace( p->tf, iface->read(), p->name ); + } + remove_traces(); + } +} + + +// called by sc_trace + +void +sc_inout::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::add_trace( sc_trace_file* tf_, + const std::string& name_ ) const +{ + sc_deprecated_add_trace(); + add_trace_internal(tf_, name_); +} + +void +sc_inout::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::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 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_vec; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_in +// +// The sc_signal input port class. +// ---------------------------------------------------------------------------- + +template +class sc_in +: public sc_port,1,SC_ONE_OR_MORE_BOUND> +{ +public: + + // typedefs + + typedef T data_type; + + typedef sc_signal_in_if if_type; + typedef sc_port base_type; + typedef sc_in 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 inout_if_type; + typedef sc_port 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( interface_ ) ), m_traces( 0 ), + m_change_finder_p(0) + {} + + sc_in( const char* name_, const in_if_type& interface_ ) + : base_type( name_, CCAST( 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( interface_ ) ); } + + SC_VIRTUAL_ void bind( in_if_type& interface_ ) + { this->bind( CCAST( 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( + *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 +::std::ostream& operator << ( ::std::ostream& os, const sc_in& a ) +{ + return os << a->read(); +} + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + + +// called when elaboration is done + +template +inline +void +sc_in::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( this->get_interface() ); + sc_trace( p->tf, iface->read(), p->name ); + } + remove_traces(); + } +} + + +// called by sc_trace + +template +inline +void +sc_in::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 +inline +void +sc_in::add_trace( sc_trace_file* tf_, const std::string& name_ ) +const +{ + sc_deprecated_add_trace(); + add_trace_internal(tf_, name_); +} + +template +inline +void +sc_in::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 +inline +int +sc_in::vbind( sc_interface& interface_ ) +{ + return sc_port_b::vbind( interface_ ); +} + +template +inline +int +sc_in::vbind( sc_port_base& parent_ ) +{ + in_port_type* in_parent = DCAST( &parent_ ); + if( in_parent != 0 ) { + sc_port_base::bind( *in_parent ); + return 0; + } + inout_port_type* inout_parent = DCAST( &parent_ ); + if( inout_parent != 0 ) { + sc_port_base::bind( *inout_parent ); + return 0; + } + // type mismatch + return 2; +} + + +// ---------------------------------------------------------------------------- +// CLASS : sc_in +// +// Specialization of sc_in for type bool. +// ---------------------------------------------------------------------------- + +template <> +class sc_in : + public sc_port,1,SC_ONE_OR_MORE_BOUND> +{ +public: + + // typedefs + + typedef bool data_type; + + typedef sc_signal_in_if if_type; + typedef sc_port base_type; + typedef sc_in 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 inout_if_type; + typedef sc_port 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( 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( 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( interface_ ) ); } + + SC_VIRTUAL_ void bind( in_if_type& interface_ ) + { this->bind( CCAST( 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( + *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( + *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( + *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 +// +// Specialization of sc_in for type sc_dt::sc_logic. +// ---------------------------------------------------------------------------- + +template <> +class sc_in +: public sc_port,1,SC_ONE_OR_MORE_BOUND> +{ +public: + + // typedefs + + typedef sc_dt::sc_logic data_type; + + typedef sc_signal_in_if if_type; + typedef sc_port base_type; + typedef sc_in 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 inout_if_type; + typedef sc_port 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( 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( 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( interface_ ) ); } + + SC_VIRTUAL_ void bind( in_if_type& interface_ ) + { this->bind( CCAST( 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( + *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( + *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( + *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 +// +// The sc_signal input/output port class. +// ---------------------------------------------------------------------------- + +template +class sc_inout +: public sc_port,1,SC_ONE_OR_MORE_BOUND> +{ +public: + + // typedefs + + typedef T data_type; + + typedef sc_signal_inout_if if_type; + typedef sc_port base_type; + typedef sc_inout this_type; + + typedef sc_signal_in_if in_if_type; + typedef sc_port 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( + *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 +::std::ostream& operator << ( ::std::ostream& os, const sc_inout& a ) +{ + return os << a->read(); +} + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + + +// destructor + +template +inline +sc_inout::~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 +inline +void +sc_inout::initialize( const data_type& value_ ) +{ + inout_if_type* iface = DCAST( 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 +inline +void +sc_inout::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( this->get_interface() ); + sc_trace( p->tf, iface->read(), p->name ); + } + remove_traces(); + } +} + + +// called by sc_trace + +template +inline +void +sc_inout::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 +inline +void +sc_inout::add_trace( sc_trace_file* tf_, const std::string& name_) const +{ + sc_deprecated_add_trace(); + add_trace_internal(tf_, name_); +} + +template +inline +void +sc_inout::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 +// +// Specialization of sc_inout for type bool. +// ---------------------------------------------------------------------------- + +template <> +class sc_inout : + public sc_port,1,SC_ONE_OR_MORE_BOUND> +{ +public: + + // typedefs + + typedef bool data_type; + + typedef sc_signal_inout_if if_type; + typedef sc_port base_type; + typedef sc_inout this_type; + + typedef sc_signal_in_if in_if_type; + typedef sc_port 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( + *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( + *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( + *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 +// +// Specialization of sc_inout for type sc_dt::sc_logic. +// ---------------------------------------------------------------------------- + +template <> +class sc_inout +: public sc_port,1,SC_ONE_OR_MORE_BOUND> +{ +public: + + // typedefs + + typedef sc_dt::sc_logic data_type; + + typedef sc_signal_inout_if if_type; + typedef sc_port base_type; + typedef sc_inout this_type; + + typedef sc_signal_in_if in_if_type; + typedef sc_port 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( + *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( + *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( + *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 +// +// The sc_signal 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 sc_out +: public sc_inout +{ +public: + + // typedefs + + typedef T data_type; + + typedef sc_out this_type; + typedef sc_inout 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 +inline +void +sc_trace(sc_trace_file* tf, const sc_in& port, const std::string& name) +{ + const sc_signal_in_if* iface = 0; + if (sc_get_curr_simcontext()->elaboration_done() ) + { + iface = DCAST*>( port.get_interface() ); + } + + if ( iface ) + sc_trace( tf, iface->read(), name ); + else + port.add_trace_internal( tf, name ); +} + +template +inline +void +sc_trace( sc_trace_file* tf, const sc_inout& port, + const std::string& name ) +{ + const sc_signal_in_if* iface = 0; + if (sc_get_curr_simcontext()->elaboration_done() ) + { + iface =DCAST*>( 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& 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 +{ +public: + + // typedefs + + typedef sc_signal_resolved this_type; + typedef sc_signal 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 m_proc_vec; // processes writing this signal + std::vector 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 + +#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( 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( 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 +{ +public: + + // typedefs + + typedef sc_dt::sc_logic data_type; + + typedef sc_in_resolved this_type; + typedef sc_in 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 +{ +public: + + // typedefs + + typedef sc_dt::sc_logic data_type; + + typedef sc_inout_resolved this_type; + typedef sc_inout 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 +// +// Resolution function for sc_dt::sc_lv. +// ---------------------------------------------------------------------------- + +extern const sc_dt::sc_logic_value_t sc_logic_resolution_tbl[4][4]; + + +template +class sc_lv_resolve +{ +public: + + // resolves sc_dt::sc_lv values and returns the resolved value + static void resolve(sc_dt::sc_lv&, const std::vector*>&); +}; + + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + +// resolves sc_dt::sc_lv values and returns the resolved value + +template +inline +void +sc_lv_resolve::resolve( sc_dt::sc_lv& result_, + const std::vector*>& 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 +// +// The resolved vector signal class. +// ---------------------------------------------------------------------------- + +template +class sc_signal_rv +: public sc_signal, SC_MANY_WRITERS> +{ +public: + + // typedefs + + typedef sc_signal_rv this_type; + typedef sc_signal, SC_MANY_WRITERS> base_type; + typedef sc_dt::sc_lv 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 m_proc_vec; // processes writing this signal + std::vector m_val_vec; // new values written this signal + +private: + + // disabled + sc_signal_rv( const this_type& ); +}; + + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + + +// destructor + +template +inline +sc_signal_rv::~sc_signal_rv() +{ + for( int i = m_val_vec.size() - 1; i >= 0; -- i ) { + delete m_val_vec[i]; + } +} + + +// write the new value + +template +inline +void +sc_signal_rv::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 +inline +void +sc_signal_rv::update() +{ + sc_lv_resolve::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 + +#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 +// +// The sc_signal_rv input port class. +// ---------------------------------------------------------------------------- + +template +class sc_in_rv + : public sc_in > +{ +public: + + // typedefs + + typedef sc_dt::sc_lv data_type; + + typedef sc_in_rv this_type; + typedef sc_in 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 +void +sc_in_rv::end_of_elaboration() +{ + base_type::end_of_elaboration(); + // check if bound channel is a resolved signal + if( DCAST*>( 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 +// +// The sc_signal_rv input/output port class. +// ---------------------------------------------------------------------------- + +template +class sc_inout_rv + : public sc_inout > +{ +public: + + // typedefs + + typedef sc_dt::sc_lv data_type; + + typedef sc_inout_rv this_type; + typedef sc_inout 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 +void +sc_inout_rv::end_of_elaboration() +{ + base_type::end_of_elaboration(); + // check if bound channel is a resolved signal + if( DCAST*>( 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 +// +// The sc_signal_rv 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 +class sc_out_rv + : public sc_inout_rv +{ +public: + + // typedefs + + typedef sc_out_rv this_type; + typedef sc_inout_rv 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 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 +// 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_writer_policy_check_port + , sc_writer_policy_check_write +{}; + +template<> +struct sc_writer_policy_check + : sc_writer_policy_nocheck_port + , sc_writer_policy_check_delta +{}; + +template<> +struct sc_writer_policy_check + : 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 + + +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 sc_bitref_r; +template class sc_bitref; +template class sc_subref_r; +template class sc_subref; +template class sc_concref_r; +template class sc_concref; + + +// ---------------------------------------------------------------------------- +// CLASS TEMPLATE : sc_bitref_r +// +// Proxy class for sc_proxy bit selection (r-value only). +// ---------------------------------------------------------------------------- + +template +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( obj_ ) ), m_index( index_ ) + {} + + + // copy constructor + + sc_bitref_r( const sc_bitref_r& a ) + : m_obj( a.m_obj ), m_index( a.m_index ) + {} + + // cloning + + sc_bitref_r* clone() const + { return new sc_bitref_r( *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& operator = ( const sc_bitref_r& ); +}; + + +// bitwise operators and functions + +// bitwise and + +template +inline +const sc_logic +operator & ( const sc_bitref_r& a, const sc_bitref_r& b ); + + +// bitwise or + +template +inline +const sc_logic +operator | ( const sc_bitref_r& a, const sc_bitref_r& b ); + + +// bitwise xor + +template +inline +const sc_logic +operator ^ ( const sc_bitref_r& a, const sc_bitref_r& b ); + + +// relational operators and functions + +template +inline +bool +operator == ( const sc_bitref_r& a, const sc_bitref_r& b ); + +template +inline +bool +operator != ( const sc_bitref_r& a, const sc_bitref_r& b ); + + +// r-value concatenation operators and functions + +template +inline +sc_concref_r,sc_bitref_r > +operator , ( sc_bitref_r, sc_bitref_r ); + +template +inline +sc_concref_r,sc_subref_r > +operator , ( sc_bitref_r, sc_subref_r ); + +template +inline +sc_concref_r,sc_concref_r > +operator , ( sc_bitref_r, sc_concref_r ); + +template +inline +sc_concref_r,T2> +operator , ( sc_bitref_r, const sc_proxy& ); + +template +inline +sc_concref_r,sc_lv_base> +operator , ( sc_bitref_r, const char* ); + +template +inline +sc_concref_r > +operator , ( const char*, sc_bitref_r ); + +template +inline +sc_concref_r,sc_lv_base> +operator , ( sc_bitref_r, const sc_logic& ); + +template +inline +sc_concref_r > +operator , ( const sc_logic&, sc_bitref_r ); + +template +inline +sc_concref_r,sc_lv_base> +operator , ( sc_bitref_r, bool ); + +template +inline +sc_concref_r > +operator , ( bool, sc_bitref_r ); + + +template +inline +sc_concref_r,sc_bitref_r > +concat( sc_bitref_r, sc_bitref_r ); + +template +inline +sc_concref_r,sc_subref_r > +concat( sc_bitref_r, sc_subref_r ); + +template +inline +sc_concref_r,sc_concref_r > +concat( sc_bitref_r, sc_concref_r ); + +template +inline +sc_concref_r,T2> +concat( sc_bitref_r, const sc_proxy& ); + +template +inline +sc_concref_r,sc_lv_base> +concat( sc_bitref_r, const char* ); + +template +inline +sc_concref_r > +concat( const char*, sc_bitref_r ); + +template +inline +sc_concref_r,sc_lv_base> +concat( sc_bitref_r, const sc_logic& ); + +template +inline +sc_concref_r > +concat( const sc_logic&, sc_bitref_r ); + +template +inline +sc_concref_r,sc_lv_base> +concat( sc_bitref_r, bool ); + +template +inline +sc_concref_r > +concat( bool, sc_bitref_r ); + + +#ifdef SC_DT_MIXED_COMMA_OPERATORS + +template +inline +sc_concref_r,sc_bitref_r > +operator , ( sc_bitref_r, sc_bitref ); + +template +inline +sc_concref_r,sc_bitref_r > +operator , ( sc_bitref, sc_bitref_r ); + +template +inline +sc_concref_r,sc_subref_r > +operator , ( sc_bitref_r, sc_subref ); + +template +inline +sc_concref_r,sc_subref_r > +operator , ( sc_bitref, sc_subref_r ); + +template +inline +sc_concref_r,sc_concref_r > +operator , ( sc_bitref_r, sc_concref ); + +template +inline +sc_concref_r,sc_concref_r > +operator , ( sc_bitref, sc_concref_r ); + +template +inline +sc_concref_r,T2> +operator , ( sc_bitref, const sc_proxy& ); + +template +inline +sc_concref_r,T2> +operator , ( sc_bitref_r, sc_proxy& ); + +template +inline +sc_concref_r,sc_lv_base> +operator , ( sc_bitref, const char* ); + +template +inline +sc_concref_r > +operator , ( const char*, sc_bitref ); + +template +inline +sc_concref_r,sc_lv_base> +operator , ( sc_bitref, const sc_logic& ); + +template +inline +sc_concref_r > +operator , ( const sc_logic&, sc_bitref ); + +template +inline +sc_concref_r,sc_lv_base> +operator , ( sc_bitref, bool ); + +template +inline +sc_concref_r > +operator , ( bool, sc_bitref ); + + +template +inline +sc_concref_r,sc_bitref_r > +concat( sc_bitref_r, sc_bitref ); + +template +inline +sc_concref_r,sc_bitref_r > +concat( sc_bitref, sc_bitref_r ); + +template +inline +sc_concref_r,sc_subref_r > +concat( sc_bitref_r, sc_subref ); + +template +inline +sc_concref_r,sc_subref_r > +concat( sc_bitref, sc_subref_r ); + +template +inline +sc_concref_r,sc_concref_r > +concat( sc_bitref_r, sc_concref ); + +template +inline +sc_concref_r,sc_concref_r > +concat( sc_bitref, sc_concref_r ); + +template +inline +sc_concref_r,T2> +concat( sc_bitref, const sc_proxy& ); + +template +inline +sc_concref_r,T2> +concat( sc_bitref_r, sc_proxy& ); + +template +inline +sc_concref_r,sc_lv_base> +concat( sc_bitref, const char* ); + +template +inline +sc_concref_r > +concat( const char*, sc_bitref ); + +template +inline +sc_concref_r,sc_lv_base> +concat( sc_bitref, const sc_logic& ); + +template +inline +sc_concref_r > +concat( const sc_logic&, sc_bitref ); + +template +inline +sc_concref_r,sc_lv_base> +concat( sc_bitref, bool ); + +template +inline +sc_concref_r > +concat( bool, sc_bitref ); + +#endif + + +// ---------------------------------------------------------------------------- +// CLASS TEMPLATE : sc_bitref +// +// Proxy class for sc_proxy bit selection (r-value and l-value). +// ---------------------------------------------------------------------------- + +template +class sc_bitref + : public sc_bitref_r +{ + friend class sc_bv_base; + friend class sc_lv_base; + +public: + + // constructor + + sc_bitref( X& obj_, int index_ ) + : sc_bitref_r( obj_, index_ ) + {} + + + // copy constructor + + sc_bitref( const sc_bitref& a ) + : sc_bitref_r( a ) + {} + + + // cloning + + sc_bitref* clone() const + { return new sc_bitref( *this ); } + + + // assignment operators + + sc_bitref& operator = ( const sc_bitref_r& a ); + sc_bitref& operator = ( const sc_bitref& a ); + + sc_bitref& operator = ( const sc_logic& a ) + { this->m_obj.set_bit( this->m_index, a.value() ); return *this; } + + sc_bitref& operator = ( sc_logic_value_t v ) + { *this = sc_logic( v ); return *this; } + + sc_bitref& operator = ( bool a ) + { *this = sc_logic( a ); return *this; } + + sc_bitref& operator = ( char a ) + { *this = sc_logic( a ); return *this; } + + sc_bitref& operator = ( int a ) + { *this = sc_logic( a ); return *this; } + + sc_bitref& operator = ( const sc_bit& a ) + { *this = sc_logic( a ); return *this; } + + + // bitwise assignment operators + + sc_bitref& operator &= ( const sc_bitref_r& a ); + sc_bitref& operator &= ( const sc_logic& a ); + + sc_bitref& operator &= ( sc_logic_value_t v ) + { *this &= sc_logic( v ); return *this; } + + sc_bitref& operator &= ( bool a ) + { *this &= sc_logic( a ); return *this; } + + sc_bitref& operator &= ( char a ) + { *this &= sc_logic( a ); return *this; } + + sc_bitref& operator &= ( int a ) + { *this &= sc_logic( a ); return *this; } + + + sc_bitref& operator |= ( const sc_bitref_r& a ); + sc_bitref& operator |= ( const sc_logic& a ); + + sc_bitref& operator |= ( sc_logic_value_t v ) + { *this |= sc_logic( v ); return *this; } + + sc_bitref& operator |= ( bool a ) + { *this |= sc_logic( a ); return *this; } + + sc_bitref& operator |= ( char a ) + { *this |= sc_logic( a ); return *this; } + + sc_bitref& operator |= ( int a ) + { *this |= sc_logic( a ); return *this; } + + + sc_bitref& operator ^= ( const sc_bitref_r& a ); + sc_bitref& operator ^= ( const sc_logic& a ); + + sc_bitref& operator ^= ( sc_logic_value_t v ) + { *this ^= sc_logic( v ); return *this; } + + sc_bitref& operator ^= ( bool a ) + { *this ^= sc_logic( a ); return *this; } + + sc_bitref& operator ^= ( char a ) + { *this ^= sc_logic( a ); return *this; } + + sc_bitref& operator ^= ( int a ) + { *this ^= sc_logic( a ); return *this; } + + + // bitwise operators and functions + + // bitwise complement + + sc_bitref& 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 +inline +sc_concref,sc_bitref > +operator , ( sc_bitref, sc_bitref ); + +template +inline +sc_concref,sc_subref > +operator , ( sc_bitref, sc_subref ); + +template +inline +sc_concref,sc_concref > +operator , ( sc_bitref, sc_concref ); + +template +inline +sc_concref,T2> +operator , ( sc_bitref, sc_proxy& ); + + +template +inline +sc_concref,sc_bitref > +concat( sc_bitref, sc_bitref ); + +template +inline +sc_concref,sc_subref > +concat( sc_bitref, sc_subref ); + +template +inline +sc_concref,sc_concref > +concat( sc_bitref, sc_concref ); + +template +inline +sc_concref,T2> +concat( sc_bitref, sc_proxy& ); + + +template +::std::istream& +operator >> ( ::std::istream&, sc_bitref ); + + +// ---------------------------------------------------------------------------- +// CLASS TEMPLATE : sc_subref_r +// +// Proxy class for sc_proxy part selection (r-value only). +// ---------------------------------------------------------------------------- + +template +class sc_subref_r + : public sc_proxy > +{ + void check_bounds(); + +public: + + // constructor + + sc_subref_r( const X& obj_, int hi_, int lo_ ) + : m_obj( CCAST( obj_ ) ), m_hi( hi_ ), m_lo( lo_ ), m_len( 0 ) + { check_bounds(); } + + + // copy constructor + + sc_subref_r( const sc_subref_r& 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* clone() const + { return new sc_subref_r( *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& operator = ( const sc_subref_r& ); +}; + + +// r-value concatenation operators and functions + +template +inline +sc_concref_r,sc_bitref_r > +operator , ( sc_subref_r, sc_bitref_r ); + +template +inline +sc_concref_r,sc_subref_r > +operator , ( sc_subref_r, sc_subref_r ); + +template +inline +sc_concref_r,sc_concref_r > +operator , ( sc_subref_r, sc_concref_r ); + +template +inline +sc_concref_r,T2> +operator , ( sc_subref_r, const sc_proxy& ); + +template +inline +sc_concref_r,sc_lv_base> +operator , ( sc_subref_r, const char* ); + +template +inline +sc_concref_r > +operator , ( const char*, sc_subref_r ); + +template +inline +sc_concref_r,sc_lv_base> +operator , ( sc_subref_r, const sc_logic& ); + +template +inline +sc_concref_r > +operator , ( const sc_logic&, sc_subref_r ); + +template +inline +sc_concref_r,sc_bv_base> +operator , ( sc_subref_r, bool ); + +template +inline +sc_concref_r > +operator , ( bool, sc_subref_r ); + + +template +inline +sc_concref_r,sc_bitref_r > +concat( sc_subref_r, sc_bitref_r ); + +template +inline +sc_concref_r,sc_subref_r > +concat( sc_subref_r, sc_subref_r ); + +template +inline +sc_concref_r,sc_concref_r > +concat( sc_subref_r, sc_concref_r ); + +template +inline +sc_concref_r,T2> +concat( sc_subref_r, const sc_proxy& ); + +template +inline +sc_concref_r,sc_lv_base> +concat( sc_subref_r, const char* ); + +template +inline +sc_concref_r > +concat( const char*, sc_subref_r ); + +template +inline +sc_concref_r,sc_lv_base> +concat( sc_subref_r, const sc_logic& ); + +template +inline +sc_concref_r > +concat( const sc_logic&, sc_subref_r ); + +template +inline +sc_concref_r,sc_bv_base> +concat( sc_subref_r, bool ); + +template +inline +sc_concref_r > +concat( bool, sc_subref_r ); + + +#ifdef SC_DT_MIXED_COMMA_OPERATORS + +template +inline +sc_concref_r,sc_bitref_r > +operator , ( sc_subref_r, sc_bitref ); + +template +inline +sc_concref_r,sc_bitref_r > +operator , ( sc_subref, sc_bitref_r ); + +template +inline +sc_concref_r,sc_subref_r > +operator , ( sc_subref_r, sc_subref ); + +template +inline +sc_concref_r,sc_subref_r > +operator , ( sc_subref, sc_subref_r ); + +template +inline +sc_concref_r,sc_concref_r > +operator , ( sc_subref_r, sc_concref ); + +template +inline +sc_concref_r,sc_concref_r > +operator , ( sc_subref, sc_concref_r ); + +template +inline +sc_concref_r,T2> +operator , ( sc_subref, const sc_proxy& ); + +template +inline +sc_concref_r,T2> +operator , ( sc_subref_r, sc_proxy& ); + +template +inline +sc_concref_r,sc_lv_base> +operator , ( sc_subref, const char* ); + +template +inline +sc_concref_r > +operator , ( const char*, sc_subref ); + +template +inline +sc_concref_r,sc_lv_base> +operator , ( sc_subref, const sc_logic& ); + +template +inline +sc_concref_r > +operator , ( const sc_logic&, sc_subref ); + +template +inline +sc_concref_r,sc_bv_base> +operator , ( sc_subref, bool ); + +template +inline +sc_concref_r > +operator , ( bool, sc_subref ); + + +template +inline +sc_concref_r,sc_bitref_r > +concat( sc_subref_r, sc_bitref ); + +template +inline +sc_concref_r,sc_bitref_r > +concat( sc_subref, sc_bitref_r ); + +template +inline +sc_concref_r,sc_subref_r > +concat( sc_subref_r, sc_subref ); + +template +inline +sc_concref_r,sc_subref_r > +concat( sc_subref, sc_subref_r ); + +template +inline +sc_concref_r,sc_concref_r > +concat( sc_subref_r, sc_concref ); + +template +inline +sc_concref_r,sc_concref_r > +concat( sc_subref, sc_concref_r ); + +template +inline +sc_concref_r,T2> +concat( sc_subref, const sc_proxy& ); + +template +inline +sc_concref_r,T2> +concat( sc_subref_r, sc_proxy& ); + +template +inline +sc_concref_r,sc_lv_base> +concat( sc_subref, const char* ); + +template +inline +sc_concref_r > +concat( const char*, sc_subref ); + +template +inline +sc_concref_r,sc_lv_base> +concat( sc_subref, const sc_logic& ); + +template +inline +sc_concref_r > +concat( const sc_logic&, sc_subref ); + +template +inline +sc_concref_r,sc_bv_base> +concat( sc_subref, bool ); + +template +inline +sc_concref_r > +concat( bool, sc_subref ); + +#endif + + +// ---------------------------------------------------------------------------- +// CLASS TEMPLATE : sc_subref +// +// Proxy class for sc_proxy part selection (r-value and l-value). +// ---------------------------------------------------------------------------- + +template +class sc_subref + : public sc_subref_r +{ +public: + + // typedefs + + typedef sc_subref_r base_type; + + + // constructor + + sc_subref( X& obj_, int hi_, int lo_ ) + : sc_subref_r( obj_, hi_, lo_ ) + {} + + + // copy constructor + + sc_subref( const sc_subref& a ) + : sc_subref_r( a ) + {} + + + // cloning + + sc_subref* clone() const + { return new sc_subref( *this ); } + + + // assignment operators + + template + sc_subref& operator = ( const sc_proxy& a ) + { base_type::assign_( a ); return *this; } + + sc_subref& operator = ( const sc_subref_r& a ); + sc_subref& operator = ( const sc_subref& a ); + + sc_subref& operator = ( const char* a ) + { base_type::assign_( a ); return *this; } + + sc_subref& operator = ( const bool* a ) + { base_type::assign_( a ); return *this; } + + sc_subref& operator = ( const sc_logic* a ) + { base_type::assign_( a ); return *this; } + + sc_subref& operator = ( const sc_unsigned& a ) + { base_type::assign_( a ); return *this; } + + sc_subref& operator = ( const sc_signed& a ) + { base_type::assign_( a ); return *this; } + + sc_subref& operator = ( const sc_uint_base& a ) + { base_type::assign_( a ); return *this; } + + sc_subref& operator = ( const sc_int_base& a ) + { base_type::assign_( a ); return *this; } + + sc_subref& operator = ( unsigned long a ) + { base_type::assign_( a ); return *this; } + + sc_subref& operator = ( long a ) + { base_type::assign_( a ); return *this; } + + sc_subref& operator = ( unsigned int a ) + { base_type::assign_( a ); return *this; } + + sc_subref& operator = ( int a ) + { base_type::assign_( a ); return *this; } + + sc_subref& operator = ( uint64 a ) + { base_type::assign_( a ); return *this; } + + sc_subref& 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 +inline +sc_concref,sc_bitref > +operator , ( sc_subref, sc_bitref ); + +template +inline +sc_concref,sc_subref > +operator , ( sc_subref, sc_subref ); + +template +inline +sc_concref,sc_concref > +operator , ( sc_subref, sc_concref ); + +template +inline +sc_concref,T2> +operator , ( sc_subref, sc_proxy& ); + + +template +inline +sc_concref,sc_bitref > +concat( sc_subref, sc_bitref ); + +template +inline +sc_concref,sc_subref > +concat( sc_subref, sc_subref ); + +template +inline +sc_concref,sc_concref > +concat( sc_subref, sc_concref ); + +template +inline +sc_concref,T2> +concat( sc_subref, sc_proxy& ); + + +template +inline +::std::istream& +operator >> ( ::std::istream&, sc_subref ); + + +// ---------------------------------------------------------------------------- +// CLASS TEMPLATE : sc_concref_r +// +// Proxy class for sc_proxy concatenation (r-value only). +// ---------------------------------------------------------------------------- + +template +class sc_concref_r + : public sc_proxy > +{ +public: + + // constructor + + sc_concref_r( const X& left_, const Y& right_, int delete_ = 0 ) + : m_left( CCAST( left_ ) ), m_right( CCAST( right_ ) ), + m_delete( delete_ ), m_refs( *new int( 1 ) ) + {} + + + // copy constructor + + sc_concref_r( const sc_concref_r& 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* clone() const + { return new sc_concref_r( *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& operator = ( const sc_concref_r& ); +}; + + +// r-value concatenation operators and functions + +template +inline +sc_concref_r,sc_bitref_r > +operator , ( sc_concref_r, sc_bitref_r ); + +template +inline +sc_concref_r,sc_subref_r > +operator , ( sc_concref_r, sc_subref_r ); + +template +inline +sc_concref_r,sc_concref_r > +operator , ( sc_concref_r, sc_concref_r ); + +template +inline +sc_concref_r,T3> +operator , ( sc_concref_r, const sc_proxy& ); + +template +inline +sc_concref_r,sc_lv_base> +operator , ( sc_concref_r, const char* ); + +template +inline +sc_concref_r > +operator , ( const char*, sc_concref_r ); + +template +inline +sc_concref_r,sc_lv_base> +operator , ( sc_concref_r, const sc_logic& ); + +template +inline +sc_concref_r > +operator , ( const sc_logic&, sc_concref_r ); + +template +inline +sc_concref_r,sc_bv_base> +operator , ( sc_concref_r, bool ); + +template +inline +sc_concref_r > +operator , ( bool, sc_concref_r ); + + +template +inline +sc_concref_r,sc_bitref_r > +concat( sc_concref_r, sc_bitref_r ); + +template +inline +sc_concref_r,sc_subref_r > +concat( sc_concref_r, sc_subref_r ); + +template +inline +sc_concref_r,sc_concref_r > +concat( sc_concref_r, sc_concref_r ); + +template +inline +sc_concref_r,T3> +concat( sc_concref_r, const sc_proxy& ); + +template +inline +sc_concref_r,sc_lv_base> +concat( sc_concref_r, const char* ); + +template +inline +sc_concref_r > +concat( const char*, sc_concref_r ); + +template +inline +sc_concref_r,sc_lv_base> +concat( sc_concref_r, const sc_logic& ); + +template +inline +sc_concref_r > +concat( const sc_logic&, sc_concref_r ); + +template +inline +sc_concref_r,sc_bv_base> +concat( sc_concref_r, bool ); + +template +inline +sc_concref_r > +concat( bool, sc_concref_r ); + + +#ifdef SC_DT_MIXED_COMMA_OPERATORS + +template +inline +sc_concref_r,sc_bitref_r > +operator , ( sc_concref_r, sc_bitref ); + +template +inline +sc_concref_r,sc_bitref_r > +operator , ( sc_concref, sc_bitref_r ); + +template +inline +sc_concref_r,sc_subref_r > +operator , ( sc_concref_r, sc_subref ); + +template +inline +sc_concref_r,sc_subref_r > +operator , ( sc_concref, sc_subref_r ); + +template +inline +sc_concref_r,sc_concref_r > +operator , ( sc_concref_r, sc_concref ); + +template +inline +sc_concref_r,sc_concref_r > +operator , ( sc_concref, sc_concref_r ); + +template +inline +sc_concref_r,T3> +operator , ( sc_concref, const sc_proxy& ); + +template +inline +sc_concref_r,T3> +operator , ( sc_concref_r, sc_proxy& ); + +template +inline +sc_concref_r,sc_lv_base> +operator , ( sc_concref, const char* ); + +template +inline +sc_concref_r > +operator , ( const char*, sc_concref ); + +template +inline +sc_concref_r,sc_lv_base> +operator , ( sc_concref, const sc_logic& ); + +template +inline +sc_concref_r > +operator , ( const sc_logic&, sc_concref ); + +template +inline +sc_concref_r,sc_bv_base> +operator , ( sc_concref, bool ); + +template +inline +sc_concref_r > +operator , ( bool, sc_concref ); + + +template +inline +sc_concref_r,sc_bitref_r > +concat( sc_concref_r, sc_bitref ); + +template +inline +sc_concref_r,sc_bitref_r > +concat( sc_concref, sc_bitref_r ); + +template +inline +sc_concref_r,sc_subref_r > +concat( sc_concref_r, sc_subref ); + +template +inline +sc_concref_r,sc_subref_r > +concat( sc_concref, sc_subref_r ); + +template +inline +sc_concref_r,sc_concref_r > +concat( sc_concref_r, sc_concref ); + +template +inline +sc_concref_r,sc_concref_r > +concat( sc_concref, sc_concref_r ); + +template +inline +sc_concref_r,T3> +concat( sc_concref, const sc_proxy& ); + +template +inline +sc_concref_r,T3> +concat( sc_concref_r, sc_proxy& ); + +template +inline +sc_concref_r,sc_lv_base> +concat( sc_concref, const char* ); + +template +inline +sc_concref_r > +concat( const char*, sc_concref ); + +template +inline +sc_concref_r,sc_lv_base> +concat( sc_concref, const sc_logic& ); + +template +inline +sc_concref_r > +concat( const sc_logic&, sc_concref ); + +template +inline +sc_concref_r,sc_bv_base> +concat( sc_concref, bool ); + +template +inline +sc_concref_r > +concat( bool, sc_concref ); + +#endif + + +// ---------------------------------------------------------------------------- +// CLASS TEMPLATE : sc_concref +// +// Proxy class for sc_proxy concatenation (r-value and l-value). +// ---------------------------------------------------------------------------- + +template +class sc_concref + : public sc_concref_r +{ +public: + + // typedefs + + typedef sc_concref_r base_type; + + + // constructor + + sc_concref( X& left_, Y& right_, int delete_ = 0 ) + : sc_concref_r( left_, right_, delete_ ) + {} + + + // copy constructor + + sc_concref( const sc_concref& a ) + : sc_concref_r( a ) + {} + + + // cloning + + sc_concref* clone() const + { return new sc_concref( *this ); } + + + // assignment operators + + template + sc_concref& operator = ( const sc_proxy& a ) + { base_type::assign_( a ); return *this; } + + sc_concref& operator = ( const sc_concref& a ) + { base_type::assign_( a ); return *this; } + + sc_concref& operator = ( const char* a ) + { base_type::assign_( a ); return *this; } + + sc_concref& operator = ( const bool* a ) + { base_type::assign_( a ); return *this; } + + sc_concref& operator = ( const sc_logic* a ) + { base_type::assign_( a ); return *this; } + + sc_concref& operator = ( const sc_unsigned& a ) + { base_type::assign_( a ); return *this; } + + sc_concref& operator = ( const sc_signed& a ) + { base_type::assign_( a ); return *this; } + + sc_concref& operator = ( const sc_uint_base& a ) + { base_type::assign_( a ); return *this; } + + sc_concref& operator = ( const sc_int_base& a ) + { base_type::assign_( a ); return *this; } + + sc_concref& operator = ( unsigned long a ) + { base_type::assign_( a ); return *this; } + + sc_concref& operator = ( long a ) + { base_type::assign_( a ); return *this; } + + sc_concref& operator = ( unsigned int a ) + { base_type::assign_( a ); return *this; } + + sc_concref& operator = ( int a ) + { base_type::assign_( a ); return *this; } + + sc_concref& operator = ( uint64 a ) + { base_type::assign_( a ); return *this; } + + sc_concref& 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 +inline +sc_concref,sc_bitref > +operator , ( sc_concref, sc_bitref ); + +template +inline +sc_concref,sc_subref > +operator , ( sc_concref, sc_subref ); + +template +inline +sc_concref,sc_concref > +operator , ( sc_concref, sc_concref ); + +template +inline +sc_concref,T3> +operator , ( sc_concref, sc_proxy& ); + + +template +inline +sc_concref,sc_bitref > +concat( sc_concref, sc_bitref ); + +template +inline +sc_concref,sc_subref > +concat( sc_concref, sc_subref ); + +template +inline +sc_concref,sc_concref > +concat( sc_concref, sc_concref ); + +template +inline +sc_concref,T3> +concat( sc_concref, sc_proxy& ); + + +template +inline +::std::istream& +operator >> ( ::std::istream&, sc_concref ); + + +// ---------------------------------------------------------------------------- +// CLASS TEMPLATE : sc_proxy +// +// Base class template for bit/logic vector classes. +// (Barton/Nackmann implementation) +// ---------------------------------------------------------------------------- + +// r-value concatenation operators and functions + +template +inline +sc_concref_r > +operator , ( const sc_proxy&, sc_bitref_r ); + +template +inline +sc_concref_r > +operator , ( const sc_proxy&, sc_subref_r ); + +template +inline +sc_concref_r > +operator , ( const sc_proxy&, sc_concref_r ); + +template +inline +sc_concref_r +operator , ( const sc_proxy&, const sc_proxy& ); + +template +inline +sc_concref_r +operator , ( const sc_proxy&, const char* ); + +template +inline +sc_concref_r +operator , ( const char*, const sc_proxy& ); + +template +inline +sc_concref_r +operator , ( const sc_proxy&, const sc_logic& ); + +template +inline +sc_concref_r +operator , ( const sc_logic&, const sc_proxy& ); + +template +inline +sc_concref_r +operator , ( const sc_proxy&, bool ); + +template +inline +sc_concref_r +operator , ( bool, const sc_proxy& ); + + +template +inline +sc_concref_r > +concat( const sc_proxy&, sc_bitref_r ); + +template +inline +sc_concref_r > +concat( const sc_proxy&, sc_subref_r ); + +template +inline +sc_concref_r > +concat( const sc_proxy&, sc_concref_r ); + +template +inline +sc_concref_r +concat( const sc_proxy&, const sc_proxy& ); + +template +inline +sc_concref_r +concat( const sc_proxy&, const char* ); + +template +inline +sc_concref_r +concat( const char*, const sc_proxy& ); + +template +inline +sc_concref_r +concat( const sc_proxy&, const sc_logic& ); + +template +inline +sc_concref_r +concat( const sc_logic&, const sc_proxy& ); + +template +inline +sc_concref_r +concat( const sc_proxy&, bool ); + +template +inline +sc_concref_r +concat( bool, const sc_proxy& ); + + +#ifdef SC_DT_MIXED_COMMA_OPERATORS + +template +inline +sc_concref_r > +operator , ( const sc_proxy&, sc_bitref ); + +template +inline +sc_concref_r > +operator , ( sc_proxy&, sc_bitref_r ); + +template +inline +sc_concref_r > +operator , ( const sc_proxy&, sc_subref ); + +template +inline +sc_concref_r > +operator , ( sc_proxy&, sc_subref_r ); + +template +inline +sc_concref_r > +operator , ( const sc_proxy&, sc_concref ); + +template +inline +sc_concref_r > +operator , ( sc_proxy&, sc_concref_r ); + +template +inline +sc_concref_r +operator , ( const sc_proxy&, sc_proxy& ); + +template +inline +sc_concref_r +operator , ( sc_proxy&, const sc_proxy& ); + +template +inline +sc_concref_r +operator , ( sc_proxy&, const char* ); + +template +inline +sc_concref_r +operator , ( const char*, sc_proxy& ); + +template +inline +sc_concref_r +operator , ( sc_proxy&, const sc_logic& ); + +template +inline +sc_concref_r +operator , ( const sc_logic&, sc_proxy& ); + +template +inline +sc_concref_r +operator , ( sc_proxy&, bool ); + +template +inline +sc_concref_r +operator , ( bool, sc_proxy& ); + + +template +inline +sc_concref_r > +concat( const sc_proxy&, sc_bitref ); + +template +inline +sc_concref_r > +concat( sc_proxy&, sc_bitref_r ); + +template +inline +sc_concref_r > +concat( const sc_proxy&, sc_subref ); + +template +inline +sc_concref_r > +concat( sc_proxy&, sc_subref_r ); + +template +inline +sc_concref_r > +concat( const sc_proxy&, sc_concref ); + +template +inline +sc_concref_r > +concat( sc_proxy&, sc_concref_r ); + +template +inline +sc_concref_r +concat( const sc_proxy&, sc_proxy& ); + +template +inline +sc_concref_r +concat( sc_proxy&, const sc_proxy& ); + +template +inline +sc_concref_r +concat( sc_proxy&, const char* ); + +template +inline +sc_concref_r +concat( const char*, sc_proxy& ); + +template +inline +sc_concref_r +concat( sc_proxy&, const sc_logic& ); + +template +inline +sc_concref_r +concat( const sc_logic&, sc_proxy& ); + +template +inline +sc_concref_r +concat( sc_proxy&, bool ); + +template +inline +sc_concref_r +concat( bool, sc_proxy& ); + +#endif + + +// l-value concatenation operators and functions + +template +inline +sc_concref > +operator , ( sc_proxy&, sc_bitref ); + +template +inline +sc_concref > +operator , ( sc_proxy&, sc_subref ); + +template +inline +sc_concref > +operator , ( sc_proxy&, sc_concref ); + +template +inline +sc_concref +operator , ( sc_proxy&, sc_proxy& ); + + +template +inline +sc_concref > +concat( sc_proxy&, sc_bitref ); + +template +inline +sc_concref > +concat( sc_proxy&, sc_subref ); + +template +inline +sc_concref > +concat( sc_proxy&, sc_concref ); + +template +inline +sc_concref +concat( sc_proxy&, sc_proxy& ); + + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + +// ---------------------------------------------------------------------------- +// CLASS TEMPLATE : sc_bitref_r +// +// Proxy class for sc_proxy bit selection (r-value only). +// ---------------------------------------------------------------------------- + +// bitwise operators and functions + +// bitwise and + +template +inline +const sc_logic +operator & ( const sc_bitref_r& a, const sc_bitref_r& b ) +{ + return sc_logic( sc_logic::and_table[a.value()][b.value()] ); +} + + +// bitwise or + +template +inline +const sc_logic +operator | ( const sc_bitref_r& a, const sc_bitref_r& b ) +{ + return sc_logic( sc_logic::or_table[a.value()][b.value()] ); +} + + +// bitwise xor + +template +inline +const sc_logic +operator ^ ( const sc_bitref_r& a, const sc_bitref_r& b ) +{ + return sc_logic( sc_logic::xor_table[a.value()][b.value()] ); +} + + +// relational operators and functions + +template +inline +bool +operator == ( const sc_bitref_r& a, const sc_bitref_r& b ) +{ + return ( (int) a.value() == b.value() ); +} + +template +inline +bool +operator != ( const sc_bitref_r& a, const sc_bitref_r& b ) +{ + return ( (int) a.value() != b.value() ); +} + + +// common methods + +template +inline +sc_logic_value_t +sc_bitref_r::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 +inline +sc_digit +sc_bitref_r::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 +inline +sc_digit +sc_bitref_r::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 +inline +sc_concref_r,sc_bitref_r > +operator , ( sc_bitref_r a, sc_bitref_r b ) +{ + return sc_concref_r,sc_bitref_r >( + *a.clone(), *b.clone(), 3 ); +} + +template +inline +sc_concref_r,sc_subref_r > +operator , ( sc_bitref_r a, sc_subref_r b ) +{ + return sc_concref_r,sc_subref_r >( + *a.clone(), *b.clone(), 3 ); +} + +template +inline +sc_concref_r,sc_concref_r > +operator , ( sc_bitref_r a, sc_concref_r b ) +{ + return sc_concref_r,sc_concref_r >( + *a.clone(), *b.clone(), 3 ); +} + +template +inline +sc_concref_r,T2> +operator , ( sc_bitref_r a, const sc_proxy& b ) +{ + return sc_concref_r,T2>( + *a.clone(), b.back_cast(), 1 ); +} + + +template +inline +sc_concref_r,sc_bitref_r > +concat( sc_bitref_r a, sc_bitref_r b ) +{ + return sc_concref_r,sc_bitref_r >( + *a.clone(), *b.clone(), 3 ); +} + +template +inline +sc_concref_r,sc_subref_r > +concat( sc_bitref_r a, sc_subref_r b ) +{ + return sc_concref_r,sc_subref_r >( + *a.clone(), *b.clone(), 3 ); +} + +template +inline +sc_concref_r,sc_concref_r > +concat( sc_bitref_r a, sc_concref_r b ) +{ + return sc_concref_r,sc_concref_r >( + *a.clone(), *b.clone(), 3 ); +} + +template +inline +sc_concref_r,T2> +concat( sc_bitref_r a, const sc_proxy& b ) +{ + return sc_concref_r,T2>( + *a.clone(), b.back_cast(), 1 ); +} + + +#ifdef SC_DT_MIXED_COMMA_OPERATORS + +template +inline +sc_concref_r,sc_bitref_r > +operator , ( sc_bitref_r a, sc_bitref b ) +{ + return sc_concref_r,sc_bitref_r >( + *a.clone(), *b.clone(), 3 ); +} + +template +inline +sc_concref_r,sc_bitref_r > +operator , ( sc_bitref a, sc_bitref_r b ) +{ + return sc_concref_r,sc_bitref_r >( + *a.clone(), *b.clone(), 3 ); +} + +template +inline +sc_concref_r,sc_subref_r > +operator , ( sc_bitref_r a, sc_subref b ) +{ + return sc_concref_r,sc_subref_r >( + *a.clone(), *b.clone(), 3 ); +} + +template +inline +sc_concref_r,sc_subref_r > +operator , ( sc_bitref a, sc_subref_r b ) +{ + return sc_concref_r,sc_subref_r >( + *a.clone(), *b.clone(), 3 ); +} + +template +inline +sc_concref_r,sc_concref_r > +operator , ( sc_bitref_r a, sc_concref b ) +{ + return sc_concref_r,sc_concref_r >( + *a.clone(), *b.clone(), 3 ); +} + +template +inline +sc_concref_r,sc_concref_r > +operator , ( sc_bitref a, sc_concref_r b ) +{ + return sc_concref_r,sc_concref_r >( + *a.clone(), *b.clone(), 3 ); +} + +template +inline +sc_concref_r,T2> +operator , ( sc_bitref a, const sc_proxy& b ) +{ + return sc_concref_r,T2>( + *a.clone(), b.back_cast(), 1 ); +} + +template +inline +sc_concref_r,T2> +operator , ( sc_bitref_r a, sc_proxy& b ) +{ + return sc_concref_r,T2>( + *a.clone(), b.back_cast(), 1 ); +} + + +template +inline +sc_concref_r,sc_bitref_r > +concat( sc_bitref_r a, sc_bitref b ) +{ + return sc_concref_r,sc_bitref_r >( + *a.clone(), *b.clone(), 3 ); +} + +template +inline +sc_concref_r,sc_bitref_r > +concat( sc_bitref a, sc_bitref_r b ) +{ + return sc_concref_r,sc_bitref_r >( + *a.clone(), *b.clone(), 3 ); +} + +template +inline +sc_concref_r,sc_subref_r > +concat( sc_bitref_r a, sc_subref b ) +{ + return sc_concref_r,sc_subref_r >( + *a.clone(), *b.clone(), 3 ); +} + +template +inline +sc_concref_r,sc_subref_r > +concat( sc_bitref a, sc_subref_r b ) +{ + return sc_concref_r,sc_subref_r >( + *a.clone(), *b.clone(), 3 ); +} + +template +inline +sc_concref_r,sc_concref_r > +concat( sc_bitref_r a, sc_concref b ) +{ + return sc_concref_r,sc_concref_r >( + *a.clone(), *b.clone(), 3 ); +} + +template +inline +sc_concref_r,sc_concref_r > +concat( sc_bitref a, sc_concref_r b ) +{ + return sc_concref_r,sc_concref_r >( + *a.clone(), *b.clone(), 3 ); +} + +template +inline +sc_concref_r,T2> +concat( sc_bitref a, const sc_proxy& b ) +{ + return sc_concref_r,T2>( + *a.clone(), b.back_cast(), 1 ); +} + +template +inline +sc_concref_r,T2> +concat( sc_bitref_r a, sc_proxy& b ) +{ + return sc_concref_r,T2>( + *a.clone(), b.back_cast(), 1 ); +} + +#endif + + +// ---------------------------------------------------------------------------- +// CLASS TEMPLATE : sc_bitref +// +// Proxy class for sc_proxy bit selection (r-value and l-value). +// ---------------------------------------------------------------------------- + +// assignment operators + +template +inline +sc_bitref& +sc_bitref::operator = ( const sc_bitref_r& a ) +{ + this->m_obj.set_bit( this->m_index, a.value() ); + return *this; +} + +template +inline +sc_bitref& +sc_bitref::operator = ( const sc_bitref& a ) +{ + if( &a != this ) { + this->m_obj.set_bit( this->m_index, a.value() ); + } + return *this; +} + + +// bitwise assignment operators + +template +inline +sc_bitref& +sc_bitref::operator &= ( const sc_bitref_r& a ) +{ + if( &a != this ) { + this->m_obj.set_bit( this->m_index, + sc_logic::and_table[this->value()][a.value()] ); + } + return *this; +} + +template +inline +sc_bitref& +sc_bitref::operator &= ( const sc_logic& a ) +{ + this->m_obj.set_bit( this->m_index, + sc_logic::and_table[this->value()][a.value()] ); + return *this; +} + + +template +inline +sc_bitref& +sc_bitref::operator |= ( const sc_bitref_r& a ) +{ + if( &a != this ) { + this->m_obj.set_bit( this->m_index, + sc_logic::or_table[this->value()][a.value()] ); + } + return *this; +} + +template +inline +sc_bitref& +sc_bitref::operator |= ( const sc_logic& a ) +{ + this->m_obj.set_bit( this->m_index, + sc_logic::or_table[this->value()][a.value()] ); + return *this; +} + + +template +inline +sc_bitref& +sc_bitref::operator ^= ( const sc_bitref_r& a ) +{ + if( &a != this ) { + this->m_obj.set_bit( this->m_index, + sc_logic::xor_table[this->value()][a.value()] ); + } + return *this; +} + +template +inline +sc_bitref& +sc_bitref::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 +inline +sc_bitref& +sc_bitref::b_not() +{ + this->m_obj.set_bit( this->m_index, + sc_logic::not_table[this->value()] ); + return *this; +} + + +// common methods + +template +inline +void +sc_bitref::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 +inline +void +sc_bitref::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 +inline +void +sc_bitref::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 +inline +void +sc_bitref::scan( ::std::istream& is ) +{ + char c; + is >> c; + *this = c; +} + + +// l-value concatenation operators and functions + +template +inline +sc_concref,sc_bitref > +operator , ( sc_bitref a, sc_bitref b ) +{ + return sc_concref,sc_bitref >( + *a.clone(), *b.clone(), 3 ); +} + +template +inline +sc_concref,sc_subref > +operator , ( sc_bitref a, sc_subref b ) +{ + return sc_concref,sc_subref >( + *a.clone(), *b.clone(), 3 ); +} + +template +inline +sc_concref,sc_concref > +operator , ( sc_bitref a, sc_concref b ) +{ + return sc_concref,sc_concref >( + *a.clone(), *b.clone(), 3 ); +} + +template +inline +sc_concref,T2> +operator , ( sc_bitref a, sc_proxy& b ) +{ + return sc_concref,T2>( + *a.clone(), b.back_cast(), 1 ); +} + + +template +inline +sc_concref,sc_bitref > +concat( sc_bitref a, sc_bitref b ) +{ + return sc_concref,sc_bitref >( + *a.clone(), *b.clone(), 3 ); +} + +template +inline +sc_concref,sc_subref > +concat( sc_bitref a, sc_subref b ) +{ + return sc_concref,sc_subref >( + *a.clone(), *b.clone(), 3 ); +} + +template +inline +sc_concref,sc_concref > +concat( sc_bitref a, sc_concref b ) +{ + return sc_concref,sc_concref >( + *a.clone(), *b.clone(), 3 ); +} + +template +inline +sc_concref,T2> +concat( sc_bitref a, sc_proxy& b ) +{ + return sc_concref,T2>( + *a.clone(), b.back_cast(), 1 ); +} + + +template +inline +::std::istream& +operator >> ( ::std::istream& is, sc_bitref a ) +{ + a.scan( is ); + return is; +} + + +// ---------------------------------------------------------------------------- +// CLASS TEMPLATE : sc_subref_r +// +// Proxy class for sc_proxy part selection (r-value only). +// ---------------------------------------------------------------------------- + +template +inline +void +sc_subref_r::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 +inline +sc_logic_value_t +sc_subref_r::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 +inline +void +sc_subref_r::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 +inline +sc_digit +sc_subref_r::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 +inline +void +sc_subref_r::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 +inline +sc_digit +sc_subref_r::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 +inline +void +sc_subref_r::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 +inline +bool +sc_subref_r::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 +inline +sc_concref_r,sc_bitref_r > +operator , ( sc_subref_r a, sc_bitref_r b ) +{ + return sc_concref_r,sc_bitref_r >( + *a.clone(), *b.clone(), 3 ); +} + +template +inline +sc_concref_r,sc_subref_r > +operator , ( sc_subref_r a, sc_subref_r b ) +{ + return sc_concref_r,sc_subref_r >( + *a.clone(), *b.clone(), 3 ); +} + +template +inline +sc_concref_r,sc_concref_r > +operator , ( sc_subref_r a, sc_concref_r b ) +{ + return sc_concref_r,sc_concref_r >( + *a.clone(), *b.clone(), 3 ); +} + +template +inline +sc_concref_r,T2> +operator , ( sc_subref_r a, const sc_proxy& b ) +{ + return sc_concref_r,T2>( + *a.clone(), b.back_cast(), 1 ); +} + + +template +inline +sc_concref_r,sc_bitref_r > +concat( sc_subref_r a, sc_bitref_r b ) +{ + return sc_concref_r,sc_bitref_r >( + *a.clone(), *b.clone(), 3 ); +} + +template +inline +sc_concref_r,sc_subref_r > +concat( sc_subref_r a, sc_subref_r b ) +{ + return sc_concref_r,sc_subref_r >( + *a.clone(), *b.clone(), 3 ); +} + +template +inline +sc_concref_r,sc_concref_r > +concat( sc_subref_r a, sc_concref_r b ) +{ + return sc_concref_r,sc_concref_r >( + *a.clone(), *b.clone(), 3 ); +} + +template +inline +sc_concref_r,T2> +concat( sc_subref_r a, const sc_proxy& b ) +{ + return sc_concref_r,T2>( + *a.clone(), b.back_cast(), 1 ); +} + + +#ifdef SC_DT_MIXED_COMMA_OPERATORS + +template +inline +sc_concref_r,sc_bitref_r > +operator , ( sc_subref_r a, sc_bitref b ) +{ + return sc_concref_r,sc_bitref_r >( + *a.clone(), *b.clone(), 3 ); +} + +template +inline +sc_concref_r,sc_bitref_r > +operator , ( sc_subref a, sc_bitref_r b ) +{ + return sc_concref_r,sc_bitref_r >( + *a.clone(), *b.clone(), 3 ); +} + +template +inline +sc_concref_r,sc_subref_r > +operator , ( sc_subref_r a, sc_subref b ) +{ + return sc_concref_r,sc_subref_r >( + *a.clone(), *b.clone(), 3 ); +} + +template +inline +sc_concref_r,sc_subref_r > +operator , ( sc_subref a, sc_subref_r b ) +{ + return sc_concref_r,sc_subref_r >( + *a.clone(), *b.clone(), 3 ); +} + +template +inline +sc_concref_r,sc_concref_r > +operator , ( sc_subref_r a, sc_concref b ) +{ + return sc_concref_r,sc_concref_r >( + *a.clone(), *b.clone(), 3 ); +} + +template +inline +sc_concref_r,sc_concref_r > +operator , ( sc_subref a, sc_concref_r b ) +{ + return sc_concref_r,sc_concref_r >( + *a.clone(), *b.clone(), 3 ); +} + +template +inline +sc_concref_r,T2> +operator , ( sc_subref a, const sc_proxy& b ) +{ + return sc_concref_r,T2>( + *a.clone(), b.back_cast(), 1 ); +} + +template +inline +sc_concref_r,T2> +operator , ( sc_subref_r a, sc_proxy& b ) +{ + return sc_concref_r,T2>( + *a.clone(), b.back_cast(), 1 ); +} + + +template +inline +sc_concref_r,sc_bitref_r > +concat( sc_subref_r a, sc_bitref b ) +{ + return sc_concref_r,sc_bitref_r >( + *a.clone(), *b.clone(), 3 ); +} + +template +inline +sc_concref_r,sc_bitref_r > +concat( sc_subref a, sc_bitref_r b ) +{ + return sc_concref_r,sc_bitref_r >( + *a.clone(), *b.clone(), 3 ); +} + +template +inline +sc_concref_r,sc_subref_r > +concat( sc_subref_r a, sc_subref b ) +{ + return sc_concref_r,sc_subref_r >( + *a.clone(), *b.clone(), 3 ); +} + +template +inline +sc_concref_r,sc_subref_r > +concat( sc_subref a, sc_subref_r b ) +{ + return sc_concref_r,sc_subref_r >( + *a.clone(), *b.clone(), 3 ); +} + +template +inline +sc_concref_r,sc_concref_r > +concat( sc_subref_r a, sc_concref b ) +{ + return sc_concref_r,sc_concref_r >( + *a.clone(), *b.clone(), 3 ); +} + +template +inline +sc_concref_r,sc_concref_r > +concat( sc_subref a, sc_concref_r b ) +{ + return sc_concref_r,sc_concref_r >( + *a.clone(), *b.clone(), 3 ); +} + +template +inline +sc_concref_r,T2> +concat( sc_subref a, const sc_proxy& b ) +{ + return sc_concref_r,T2>( + *a.clone(), b.back_cast(), 1 ); +} + +template +inline +sc_concref_r,T2> +concat( sc_subref_r a, sc_proxy& b ) +{ + return sc_concref_r,T2>( + *a.clone(), b.back_cast(), 1 ); +} + +#endif + + +// ---------------------------------------------------------------------------- +// CLASS TEMPLATE : sc_subref +// +// Proxy class for sc_proxy part selection (r-value and l-value). +// ---------------------------------------------------------------------------- + +// assignment operators + +// sc_subref::operator = ( const sc_subref_r& ) in sc_lv_base.h +// sc_subref::operator = ( const sc_subref& ) in sc_lv_base.h + + +// other methods + +template +inline +void +sc_subref::scan( ::std::istream& is ) +{ + std::string s; + is >> s; + *this = s.c_str(); +} + + +// l-value concatenation operators and functions + +template +inline +sc_concref,sc_bitref > +operator , ( sc_subref a, sc_bitref b ) +{ + return sc_concref,sc_bitref >( + *a.clone(), *b.clone(), 3 ); +} + +template +inline +sc_concref,sc_subref > +operator , ( sc_subref a, sc_subref b ) +{ + return sc_concref,sc_subref >( + *a.clone(), *b.clone(), 3 ); +} + +template +inline +sc_concref,sc_concref > +operator , ( sc_subref a, sc_concref b ) +{ + return sc_concref,sc_concref >( + *a.clone(), *b.clone(), 3 ); +} + +template +inline +sc_concref,T2> +operator , ( sc_subref a, sc_proxy& b ) +{ + return sc_concref,T2>( + *a.clone(), b.back_cast(), 1 ); +} + + +template +inline +sc_concref,sc_bitref > +concat( sc_subref a, sc_bitref b ) +{ + return sc_concref,sc_bitref >( + *a.clone(), *b.clone(), 3 ); +} + +template +inline +sc_concref,sc_subref > +concat( sc_subref a, sc_subref b ) +{ + return sc_concref,sc_subref >( + *a.clone(), *b.clone(), 3 ); +} + +template +inline +sc_concref,sc_concref > +concat( sc_subref a, sc_concref b ) +{ + return sc_concref,sc_concref >( + *a.clone(), *b.clone(), 3 ); +} + +template +inline +sc_concref,T2> +concat( sc_subref a, sc_proxy& b ) +{ + return sc_concref,T2>( + *a.clone(), b.back_cast(), 1 ); +} + + +template +inline +::std::istream& +operator >> ( ::std::istream& is, sc_subref a ) +{ + a.scan( is ); + return is; +} + + +// ---------------------------------------------------------------------------- +// CLASS TEMPLATE : sc_concref_r +// +// Proxy class for sc_proxy concatenation (r-value only). +// ---------------------------------------------------------------------------- + +// destructor + +template +inline +sc_concref_r::~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 +inline +sc_logic_value_t +sc_concref_r::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 +inline +void +sc_concref_r::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 +inline +sc_digit +sc_concref_r::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 +inline +void +sc_concref_r::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 +inline +sc_digit +sc_concref_r::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 +inline +void +sc_concref_r::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 +inline +sc_concref_r,sc_bitref_r > +operator , ( sc_concref_r a, sc_bitref_r b ) +{ + return sc_concref_r,sc_bitref_r >( + *a.clone(), *b.clone(), 3 ); +} + +template +inline +sc_concref_r,sc_subref_r > +operator , ( sc_concref_r a, sc_subref_r b ) +{ + return sc_concref_r,sc_subref_r >( + *a.clone(), *b.clone(), 3 ); +} + +template +inline +sc_concref_r,sc_concref_r > +operator , ( sc_concref_r a, sc_concref_r b ) +{ + return sc_concref_r,sc_concref_r >( + *a.clone(), *b.clone(), 3 ); +} + +template +inline +sc_concref_r,T3> +operator , ( sc_concref_r a, const sc_proxy& b ) +{ + return sc_concref_r,T3>( + *a.clone(), b.back_cast(), 1 ); +} + + +template +inline +sc_concref_r,sc_bitref_r > +concat( sc_concref_r a, sc_bitref_r b ) +{ + return sc_concref_r,sc_bitref_r >( + *a.clone(), *b.clone(), 3 ); +} + +template +inline +sc_concref_r,sc_subref_r > +concat( sc_concref_r a, sc_subref_r b ) +{ + return sc_concref_r,sc_subref_r >( + *a.clone(), *b.clone(), 3 ); +} + +template +inline +sc_concref_r,sc_concref_r > +concat( sc_concref_r a, sc_concref_r b ) +{ + return sc_concref_r,sc_concref_r >( + *a.clone(), *b.clone(), 3 ); +} + +template +inline +sc_concref_r,T3> +concat( sc_concref_r a, const sc_proxy& b ) +{ + return sc_concref_r,T3>( + *a.clone(), b.back_cast(), 1 ); +} + + +#ifdef SC_DT_MIXED_COMMA_OPERATORS + +template +inline +sc_concref_r,sc_bitref_r > +operator , ( sc_concref_r a, sc_bitref b ) +{ + return sc_concref_r,sc_bitref_r >( + *a.clone(), *b.clone(), 3 ); +} + +template +inline +sc_concref_r,sc_bitref_r > +operator , ( sc_concref a, sc_bitref_r b ) +{ + return sc_concref_r,sc_bitref_r >( + *a.clone(), *b.clone(), 3 ); +} + +template +inline +sc_concref_r,sc_subref_r > +operator , ( sc_concref_r a, sc_subref b ) +{ + return sc_concref_r,sc_subref_r >( + *a.clone(), *b.clone(), 3 ); +} + +template +inline +sc_concref_r,sc_subref_r > +operator , ( sc_concref a, sc_subref_r b ) +{ + return sc_concref_r,sc_subref_r >( + *a.clone(), *b.clone(), 3 ); +} + +template +inline +sc_concref_r,sc_concref_r > +operator , ( sc_concref_r a, sc_concref b ) +{ + return sc_concref_r,sc_concref_r >( + *a.clone(), *b.clone(), 3 ); +} + +template +inline +sc_concref_r,sc_concref_r > +operator , ( sc_concref a, sc_concref_r b ) +{ + return sc_concref_r,sc_concref_r >( + *a.clone(), *b.clone(), 3 ); +} + +template +inline +sc_concref_r,T3> +operator , ( sc_concref a, const sc_proxy& b ) +{ + return sc_concref_r,T3>( + *a.clone(), b.back_cast(), 1 ); +} + +template +inline +sc_concref_r,T3> +operator , ( sc_concref_r a, sc_proxy& b ) +{ + return sc_concref_r,T3>( + *a.clone(), b.back_cast(), 1 ); +} + + +template +inline +sc_concref_r,sc_bitref_r > +concat( sc_concref_r a, sc_bitref b ) +{ + return sc_concref_r,sc_bitref_r >( + *a.clone(), *b.clone(), 3 ); +} + +template +inline +sc_concref_r,sc_bitref_r > +concat( sc_concref a, sc_bitref_r b ) +{ + return sc_concref_r,sc_bitref_r >( + *a.clone(), *b.clone(), 3 ); +} + +template +inline +sc_concref_r,sc_subref_r > +concat( sc_concref_r a, sc_subref b ) +{ + return sc_concref_r,sc_subref_r >( + *a.clone(), *b.clone(), 3 ); +} + +template +inline +sc_concref_r,sc_subref_r > +concat( sc_concref a, sc_subref_r b ) +{ + return sc_concref_r,sc_subref_r >( + *a.clone(), *b.clone(), 3 ); +} + +template +inline +sc_concref_r,sc_concref_r > +concat( sc_concref_r a, sc_concref b ) +{ + return sc_concref_r,sc_concref_r >( + *a.clone(), *b.clone(), 3 ); +} + +template +inline +sc_concref_r,sc_concref_r > +concat( sc_concref a, sc_concref_r b ) +{ + return sc_concref_r,sc_concref_r >( + *a.clone(), *b.clone(), 3 ); +} + +template +inline +sc_concref_r,T3> +concat( sc_concref a, const sc_proxy& b ) +{ + return sc_concref_r,T3>( + *a.clone(), b.back_cast(), 1 ); +} + +template +inline +sc_concref_r,T3> +concat( sc_concref_r a, sc_proxy& b ) +{ + return sc_concref_r,T3>( + *a.clone(), b.back_cast(), 1 ); +} + +#endif + + +// ---------------------------------------------------------------------------- +// CLASS TEMPLATE : sc_concref +// +// Proxy class for sc_proxy concatenation (r-value and l-value). +// ---------------------------------------------------------------------------- + +// other methods + +template +inline +void +sc_concref::scan( ::std::istream& is ) +{ + std::string s; + is >> s; + *this = s.c_str(); +} + + +// l-value concatenation operators and functions + +template +inline +sc_concref,sc_bitref > +operator , ( sc_concref a, sc_bitref b ) +{ + return sc_concref,sc_bitref >( + *a.clone(), *b.clone(), 3 ); +} + +template +inline +sc_concref,sc_subref > +operator , ( sc_concref a, sc_subref b ) +{ + return sc_concref,sc_subref >( + *a.clone(), *b.clone(), 3 ); +} + +template +inline +sc_concref,sc_concref > +operator , ( sc_concref a, sc_concref b ) +{ + return sc_concref,sc_concref >( + *a.clone(), *b.clone(), 3 ); +} + +template +inline +sc_concref,T3> +operator , ( sc_concref a, sc_proxy& b ) +{ + return sc_concref,T3>( + *a.clone(), b.back_cast(), 1 ); +} + + +template +inline +sc_concref,sc_bitref > +concat( sc_concref a, sc_bitref b ) +{ + return sc_concref,sc_bitref >( + *a.clone(), *b.clone(), 3 ); +} + +template +inline +sc_concref,sc_subref > +concat( sc_concref a, sc_subref b ) +{ + return sc_concref,sc_subref >( + *a.clone(), *b.clone(), 3 ); +} + +template +inline +sc_concref,sc_concref > +concat( sc_concref a, sc_concref b ) +{ + return sc_concref,sc_concref >( + *a.clone(), *b.clone(), 3 ); +} + +template +inline +sc_concref,T3> +concat( sc_concref a, sc_proxy& b ) +{ + return sc_concref,T3>( + *a.clone(), b.back_cast(), 1 ); +} + + +template +inline +::std::istream& +operator >> ( ::std::istream& is, sc_concref a ) +{ + a.scan( is ); + return is; +} + + +// ---------------------------------------------------------------------------- +// CLASS TEMPLATE : sc_proxy +// +// Base class template for bit/logic vector classes. +// (Barton/Nackmann implementation) +// ---------------------------------------------------------------------------- + +// r-value concatenation operators and functions + +template +inline +sc_concref_r > +operator , ( const sc_proxy& a, sc_bitref_r b ) +{ + return sc_concref_r >( + a.back_cast(), *b.clone(), 2 ); +} + +template +inline +sc_concref_r > +operator , ( const sc_proxy& a, sc_subref_r b ) +{ + return sc_concref_r >( + a.back_cast(), *b.clone(), 2 ); +} + +template +inline +sc_concref_r > +operator , ( const sc_proxy& a, sc_concref_r b ) +{ + return sc_concref_r >( + a.back_cast(), *b.clone(), 2 ); +} + +template +inline +sc_concref_r +operator , ( const sc_proxy& a, const sc_proxy& b ) +{ + return sc_concref_r( + a.back_cast(), b.back_cast() ); +} + + +template +inline +sc_concref_r > +concat( const sc_proxy& a, sc_bitref_r b ) +{ + return sc_concref_r >( + a.back_cast(), *b.clone(), 2 ); +} + +template +inline +sc_concref_r > +concat( const sc_proxy& a, sc_subref_r b ) +{ + return sc_concref_r >( + a.back_cast(), *b.clone(), 2 ); +} + +template +inline +sc_concref_r > +concat( const sc_proxy& a, sc_concref_r b ) +{ + return sc_concref_r >( + a.back_cast(), *b.clone(), 2 ); +} + +template +inline +sc_concref_r +concat( const sc_proxy& a, const sc_proxy& b ) +{ + return sc_concref_r( + a.back_cast(), b.back_cast() ); +} + + +#ifdef SC_DT_MIXED_COMMA_OPERATORS + +template +inline +sc_concref_r > +operator , ( const sc_proxy& a, sc_bitref b ) +{ + return sc_concref_r >( + a.back_cast(), *b.clone(), 2 ); +} + +template +inline +sc_concref_r > +operator , ( sc_proxy& a, sc_bitref_r b ) +{ + return sc_concref_r >( + a.back_cast(), *b.clone(), 2 ); +} + +template +inline +sc_concref_r > +operator , ( const sc_proxy& a, sc_subref b ) +{ + return sc_concref_r >( + a.back_cast(), *b.clone(), 2 ); +} + +template +inline +sc_concref_r > +operator , ( sc_proxy& a, sc_subref_r b ) +{ + return sc_concref_r >( + a.back_cast(), *b.clone(), 2 ); +} + +template +inline +sc_concref_r > +operator , ( const sc_proxy& a, sc_concref b ) +{ + return sc_concref_r >( + a.back_cast(), *b.clone(), 2 ); +} + +template +inline +sc_concref_r > +operator , ( sc_proxy& a, sc_concref_r b ) +{ + return sc_concref_r >( + a.back_cast(), *b.clone(), 2 ); +} + +template +inline +sc_concref_r +operator , ( const sc_proxy& a, sc_proxy& b ) +{ + return sc_concref_r( + a.back_cast(), b.back_cast() ); +} + +template +inline +sc_concref_r +operator , ( sc_proxy& a, const sc_proxy& b ) +{ + return sc_concref_r( + a.back_cast(), b.back_cast() ); +} + + +template +inline +sc_concref_r > +concat( const sc_proxy& a, sc_bitref b ) +{ + return sc_concref_r >( + a.back_cast(), *b.clone(), 2 ); +} + +template +inline +sc_concref_r > +concat( sc_proxy& a, sc_bitref_r b ) +{ + return sc_concref_r >( + a.back_cast(), *b.clone(), 2 ); +} + +template +inline +sc_concref_r > +concat( const sc_proxy& a, sc_subref b ) +{ + return sc_concref_r >( + a.back_cast(), *b.clone(), 2 ); +} + +template +inline +sc_concref_r > +concat( sc_proxy& a, sc_subref_r b ) +{ + return sc_concref_r >( + a.back_cast(), *b.clone(), 2 ); +} + +template +inline +sc_concref_r > +concat( const sc_proxy& a, sc_concref b ) +{ + return sc_concref_r >( + a.back_cast(), *b.clone(), 2 ); +} + +template +inline +sc_concref_r > +concat( sc_proxy& a, sc_concref_r b ) +{ + return sc_concref_r >( + a.back_cast(), *b.clone(), 2 ); +} + +template +inline +sc_concref_r +concat( const sc_proxy& a, sc_proxy& b ) +{ + return sc_concref_r( + a.back_cast(), b.back_cast() ); +} + +template +inline +sc_concref_r +concat( sc_proxy& a, const sc_proxy& b ) +{ + return sc_concref_r( + a.back_cast(), b.back_cast() ); +} + +#endif + + +// l-value concatenation operators and functions + +template +inline +sc_concref > +operator , ( sc_proxy& a, sc_bitref b ) +{ + return sc_concref >( + a.back_cast(), *b.clone(), 2 ); +} + +template +inline +sc_concref > +operator , ( sc_proxy& a, sc_subref b ) +{ + return sc_concref >( + a.back_cast(), *b.clone(), 2 ); +} + +template +inline +sc_concref > +operator , ( sc_proxy& a, sc_concref b ) +{ + return sc_concref >( + a.back_cast(), *b.clone(), 2 ); +} + +template +inline +sc_concref +operator , ( sc_proxy& a, sc_proxy& b ) +{ + return sc_concref( + a.back_cast(), b.back_cast() ); +} + + +template +inline +sc_concref > +concat( sc_proxy& a, sc_bitref b ) +{ + return sc_concref >( + a.back_cast(), *b.clone(), 2 ); +} + +template +inline +sc_concref > +concat( sc_proxy& a, sc_subref b ) +{ + return sc_concref >( + a.back_cast(), *b.clone(), 2 ); +} + +template +inline +sc_concref > +concat( sc_proxy& a, sc_concref b ) +{ + return sc_concref >( + a.back_cast(), *b.clone(), 2 ); +} + +template +inline +sc_concref +concat( sc_proxy& a, sc_proxy& b ) +{ + return sc_concref( + 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::set_word and +// sc_bitref::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::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 class sc_bv; + + +// ---------------------------------------------------------------------------- +// CLASS TEMPLATE : sc_bv +// +// Arbitrary size bit vector class. +// ---------------------------------------------------------------------------- + +template +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 + sc_bv( const sc_proxy& a ) + : sc_bv_base( W ) + { sc_bv_base::operator = ( a ); } + + sc_bv( const sc_bv& a ) + : sc_bv_base( a ) + {} + + + // assignment operators + + template + sc_bv& operator = ( const sc_proxy& a ) + { sc_bv_base::operator = ( a ); return *this; } + + sc_bv& operator = ( const sc_bv& a ) + { sc_bv_base::operator = ( a ); return *this; } + + sc_bv& operator = ( const char* a ) + { sc_bv_base::operator = ( a ); return *this; } + + sc_bv& operator = ( const bool* a ) + { sc_bv_base::operator = ( a ); return *this; } + + sc_bv& operator = ( const sc_logic* a ) + { sc_bv_base::operator = ( a ); return *this; } + + sc_bv& operator = ( const sc_unsigned& a ) + { sc_bv_base::operator = ( a ); return *this; } + + sc_bv& operator = ( const sc_signed& a ) + { sc_bv_base::operator = ( a ); return *this; } + + sc_bv& operator = ( const sc_uint_base& a ) + { sc_bv_base::operator = ( a ); return *this; } + + sc_bv& operator = ( const sc_int_base& a ) + { sc_bv_base::operator = ( a ); return *this; } + + sc_bv& operator = ( unsigned long a ) + { sc_bv_base::operator = ( a ); return *this; } + + sc_bv& operator = ( long a ) + { sc_bv_base::operator = ( a ); return *this; } + + sc_bv& operator = ( unsigned int a ) + { sc_bv_base::operator = ( a ); return *this; } + + sc_bv& operator = ( int a ) + { sc_bv_base::operator = ( a ); return *this; } + + sc_bv& operator = ( uint64 a ) + { sc_bv_base::operator = ( a ); return *this; } + + sc_bv& 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 + +#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(), + 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 +{ + 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 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 + sc_bv_base( const sc_proxy& 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 + sc_bv_base& operator = ( const sc_proxy& 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 + +#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 class sc_lv; + + +// ---------------------------------------------------------------------------- +// CLASS TEMPLATE : sc_lv +// +// Arbitrary size logic vector class. +// ---------------------------------------------------------------------------- + +template +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 + sc_lv( const sc_proxy& a ) + : sc_lv_base( W ) + { sc_lv_base::operator = ( a ); } + + sc_lv( const sc_lv& a ) + : sc_lv_base( a ) + {} + + + // assignment operators + + template + sc_lv& operator = ( const sc_proxy& a ) + { sc_lv_base::operator = ( a ); return *this; } + + sc_lv& operator = ( const sc_lv& a ) + { sc_lv_base::operator = ( a ); return *this; } + + sc_lv& operator = ( const char* a ) + { sc_lv_base::operator = ( a ); return *this; } + + sc_lv& operator = ( const bool* a ) + { sc_lv_base::operator = ( a ); return *this; } + + sc_lv& operator = ( const sc_logic* a ) + { sc_lv_base::operator = ( a ); return *this; } + + sc_lv& operator = ( const sc_unsigned& a ) + { sc_lv_base::operator = ( a ); return *this; } + + sc_lv& operator = ( const sc_signed& a ) + { sc_lv_base::operator = ( a ); return *this; } + + sc_lv& operator = ( const sc_uint_base& a ) + { sc_lv_base::operator = ( a ); return *this; } + + sc_lv& operator = ( const sc_int_base& a ) + { sc_lv_base::operator = ( a ); return *this; } + + sc_lv& operator = ( unsigned long a ) + { sc_lv_base::operator = ( a ); return *this; } + + sc_lv& operator = ( long a ) + { sc_lv_base::operator = ( a ); return *this; } + + sc_lv& operator = ( unsigned int a ) + { sc_lv_base::operator = ( a ); return *this; } + + sc_lv& operator = ( int a ) + { sc_lv_base::operator = ( a ); return *this; } + + sc_lv& operator = ( uint64 a ) + { sc_lv_base::operator = ( a ); return *this; } + + sc_lv& 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(), + 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 +{ + 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 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 + sc_lv_base( const sc_proxy& 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 + sc_lv_base& operator = ( const sc_proxy& 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::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::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::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::lrotate( n ); } + + + // bitwise right rotate + + sc_lv_base& rrotate( int n ) + { return sc_proxy::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 +inline +const sc_lv_base +sc_proxy::operator ~ () const +{ + sc_lv_base a( back_cast() ); + return a.b_not(); +} + + +// bitwise and + +template +inline +X& +operator &= ( sc_proxy& px, const sc_proxy& 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 \ +inline \ +X& \ +sc_proxy::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 +inline +const sc_lv_base +operator & ( const sc_proxy& px, const sc_proxy& py ) +{ + sc_lv_base a( px.back_cast() ); + return ( a &= py.back_cast() ); +} + + +#define DEFN_BITWISE_AND_OP_T_A(tp) \ +template \ +inline \ +const sc_lv_base \ +sc_proxy::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 \ +inline \ +const sc_lv_base \ +operator & ( tp b, const sc_proxy& 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 +inline +X& +operator |= ( sc_proxy& px, const sc_proxy& 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 \ +inline \ +X& \ +sc_proxy::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 +inline +const sc_lv_base +operator | ( const sc_proxy& px, const sc_proxy& py ) +{ + sc_lv_base a( px.back_cast() ); + return ( a |= py.back_cast() ); +} + + +#define DEFN_BITWISE_OR_OP_T_A(tp) \ +template \ +inline \ +const sc_lv_base \ +sc_proxy::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 \ +inline \ +const sc_lv_base \ +operator | ( tp b, const sc_proxy& 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 +inline +X& +operator ^= ( sc_proxy& px, const sc_proxy& 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 \ +inline \ +X& \ +sc_proxy::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 +inline +const sc_lv_base +operator ^ ( const sc_proxy& px, const sc_proxy& py ) +{ + sc_lv_base a( px.back_cast() ); + return ( a ^= py.back_cast() ); +} + + +#define DEFN_BITWISE_XOR_OP_T_A(tp) \ +template \ +inline \ +const sc_lv_base \ +sc_proxy::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 \ +inline \ +const sc_lv_base \ +operator ^ ( tp b, const sc_proxy& 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 +inline +const sc_lv_base +sc_proxy::operator << ( int n ) const +{ + sc_lv_base a( back_cast().length()+n ); + a = back_cast(); + return ( a <<= n ); +} + + +// bitwise right shift + +template +inline +const sc_lv_base +sc_proxy::operator >> ( int n ) const +{ + sc_lv_base a( back_cast() ); + return ( a >>= n ); +} + + +// bitwise left rotate + +template +inline +X& +sc_proxy::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 +inline +const sc_lv_base +lrotate( const sc_proxy& x, int n ) +{ + sc_lv_base a( x.back_cast() ); + return a.lrotate( n ); +} + + +// bitwise right rotate + +template +inline +X& +sc_proxy::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 +inline +const sc_lv_base +rrotate( const sc_proxy& x, int n ) +{ + sc_lv_base a( x.back_cast() ); + return a.rrotate( n ); +} + + +// bitwise reverse + +template +inline +const sc_lv_base +reverse( const sc_proxy& x ) +{ + sc_lv_base a( x.back_cast() ); + return a.reverse(); +} + + +// relational operators + +template +inline +bool +operator == ( const sc_proxy& px, const sc_proxy& 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 \ +inline \ +bool \ +sc_proxy::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 +// +// Proxy class for sc_proxy bit selection (r-value only). +// ---------------------------------------------------------------------------- + +// r-value concatenation operators and functions + +template +inline +sc_concref_r,sc_lv_base> +operator , ( sc_bitref_r a, const char* b ) +{ + return sc_concref_r,sc_lv_base>( + *a.clone(), *new sc_lv_base( b ), 3 ); +} + +template +inline +sc_concref_r > +operator , ( const char* a, sc_bitref_r b ) +{ + return sc_concref_r >( + *new sc_lv_base( a ), *b.clone(), 3 ); +} + +template +inline +sc_concref_r,sc_lv_base> +operator , ( sc_bitref_r a, const sc_logic& b ) +{ + return sc_concref_r,sc_lv_base>( + *a.clone(), *new sc_lv_base( b, 1 ), 3 ); +} + +template +inline +sc_concref_r > +operator , ( const sc_logic& a, sc_bitref_r b ) +{ + return sc_concref_r >( + *new sc_lv_base( a, 1 ), *b.clone(), 3 ); +} + +template +inline +sc_concref_r,sc_bv_base> +operator , ( sc_bitref_r a, bool b ) +{ + return sc_concref_r,sc_bv_base> + ( *a.clone(), *new sc_bv_base( b, 1 ), 3 ); +} + +template +inline +sc_concref_r > +operator , ( bool a, sc_bitref_r b ) +{ + return sc_concref_r > + ( *new sc_bv_base( a, 1 ), *b.clone(), 3 ); +} + + +template +inline +sc_concref_r,sc_lv_base> +concat( sc_bitref_r a, const char* b ) +{ + return sc_concref_r,sc_lv_base>( + *a.clone(), *new sc_lv_base( b ), 3 ); +} + +template +inline +sc_concref_r > +concat( const char* a, sc_bitref_r b ) +{ + return sc_concref_r >( + *new sc_lv_base( a ), *b.clone(), 3 ); +} + +template +inline +sc_concref_r,sc_lv_base> +concat( sc_bitref_r a, const sc_logic& b ) +{ + return sc_concref_r,sc_lv_base>( + *a.clone(), *new sc_lv_base( b, 1 ), 3 ); +} + +template +inline +sc_concref_r > +concat( const sc_logic& a, sc_bitref_r b ) +{ + return sc_concref_r >( + *new sc_lv_base( a, 1 ), *b.clone(), 3 ); +} + +template +inline +sc_concref_r,sc_bv_base> +concat( sc_bitref_r a, bool b ) +{ + return sc_concref_r,sc_bv_base> + ( *a.clone(), *new sc_bv_base( b, 1 ), 3 ); +} + +template +inline +sc_concref_r > +concat( bool a, sc_bitref_r b ) +{ + return sc_concref_r > + ( *new sc_bv_base( a, 1 ), *b.clone(), 3 ); +} + + +#ifdef SC_DT_MIXED_COMMA_OPERATORS + +template +inline +sc_concref_r,sc_lv_base> +operator , ( sc_bitref a, const char* b ) +{ + return sc_concref_r,sc_lv_base>( + *a.clone(), *new sc_lv_base( b ), 3 ); +} + +template +inline +sc_concref_r > +operator , ( const char* a, sc_bitref b ) +{ + return sc_concref_r >( + *new sc_lv_base( a ), *b.clone(), 3 ); +} + +template +inline +sc_concref_r,sc_lv_base> +operator , ( sc_bitref a, const sc_logic& b ) +{ + return sc_concref_r,sc_lv_base>( + *a.clone(), *new sc_lv_base( b, 1 ), 3 ); +} + +template +inline +sc_concref_r > +operator , ( const sc_logic& a, sc_bitref b ) +{ + return sc_concref_r >( + *new sc_lv_base( a, 1 ), *b.clone(), 3 ); +} + +template +inline +sc_concref_r,sc_bv_base> +operator , ( sc_bitref a, bool b ) +{ + return sc_concref_r,sc_bv_base> + ( *a.clone(), *new sc_bv_base( b, 1 ), 3 ); +} + +template +inline +sc_concref_r > +operator , ( bool a, sc_bitref b ) +{ + return sc_concref_r > + ( *new sc_bv_base( a, 1 ), *b.clone(), 3 ); +} + + +template +inline +sc_concref_r,sc_lv_base> +concat( sc_bitref a, const char* b ) +{ + return sc_concref_r,sc_lv_base>( + *a.clone(), *new sc_lv_base( b ), 3 ); +} + +template +inline +sc_concref_r > +concat( const char* a, sc_bitref b ) +{ + return sc_concref_r >( + *new sc_lv_base( a ), *b.clone(), 3 ); +} + +template +inline +sc_concref_r,sc_lv_base> +concat( sc_bitref a, const sc_logic& b ) +{ + return sc_concref_r,sc_lv_base>( + *a.clone(), *new sc_lv_base( b, 1 ), 3 ); +} + +template +inline +sc_concref_r > +concat( const sc_logic& a, sc_bitref b ) +{ + return sc_concref_r >( + *new sc_lv_base( a, 1 ), *b.clone(), 3 ); +} + +template +inline +sc_concref_r,sc_bv_base> +concat( sc_bitref a, bool b ) +{ + return sc_concref_r,sc_bv_base> + ( *a.clone(), *new sc_bv_base( b, 1 ), 3 ); +} + +template +inline +sc_concref_r > +concat( bool a, sc_bitref b ) +{ + return sc_concref_r > + ( *new sc_bv_base( a, 1 ), *b.clone(), 3 ); +} + +#endif + + +// ---------------------------------------------------------------------------- +// CLASS TEMPLATE : sc_subref_r +// +// Proxy class for sc_proxy part selection (r-value only). +// ---------------------------------------------------------------------------- + +// r-value concatenation operators and functions + +template +inline +sc_concref_r,sc_lv_base> +operator , ( sc_subref_r a, const char* b ) +{ + return sc_concref_r,sc_lv_base>( + *a.clone(), *new sc_lv_base( b ), 3 ); +} + +template +inline +sc_concref_r > +operator , ( const char* a, sc_subref_r b ) +{ + return sc_concref_r >( + *new sc_lv_base( a ), *b.clone(), 3 ); +} + +template +inline +sc_concref_r,sc_lv_base> +operator , ( sc_subref_r a, const sc_logic& b ) +{ + return sc_concref_r,sc_lv_base>( + *a.clone(), *new sc_lv_base( b, 1 ), 3 ); +} + +template +inline +sc_concref_r > +operator , ( const sc_logic& a, sc_subref_r b ) +{ + return sc_concref_r >( + *new sc_lv_base( a, 1 ), *b.clone(), 3 ); +} + +template +inline +sc_concref_r,sc_bv_base> +operator , ( sc_subref_r a, bool b ) +{ + return sc_concref_r,sc_bv_base> + ( *a.clone(), *new sc_bv_base( b, 1 ), 3 ); +} + +template +inline +sc_concref_r > +operator , ( bool a, sc_subref_r b ) +{ + return sc_concref_r > + ( *new sc_bv_base( a, 1 ), *b.clone(), 3 ); +} + + +template +inline +sc_concref_r,sc_lv_base> +concat( sc_subref_r a, const char* b ) +{ + return sc_concref_r,sc_lv_base>( + *a.clone(), *new sc_lv_base( b ), 3 ); +} + +template +inline +sc_concref_r > +concat( const char* a, sc_subref_r b ) +{ + return sc_concref_r >( + *new sc_lv_base( a ), *b.clone(), 3 ); +} + +template +inline +sc_concref_r,sc_lv_base> +concat( sc_subref_r a, const sc_logic& b ) +{ + return sc_concref_r,sc_lv_base>( + *a.clone(), *new sc_lv_base( b, 1 ), 3 ); +} + +template +inline +sc_concref_r > +concat( const sc_logic& a, sc_subref_r b ) +{ + return sc_concref_r >( + *new sc_lv_base( a, 1 ), *b.clone(), 3 ); +} + +template +inline +sc_concref_r,sc_bv_base> +concat( sc_subref_r a, bool b ) +{ + return sc_concref_r,sc_bv_base> + ( *a.clone(), *new sc_bv_base( b, 1 ), 3 ); +} + +template +inline +sc_concref_r > +concat( bool a, sc_subref_r b ) +{ + return sc_concref_r > + ( *new sc_bv_base( a, 1 ), *b.clone(), 3 ); +} + + +#ifdef SC_DT_MIXED_COMMA_OPERATORS + +template +inline +sc_concref_r,sc_lv_base> +operator , ( sc_subref a, const char* b ) +{ + return sc_concref_r,sc_lv_base>( + *a.clone(), *new sc_lv_base( b ), 3 ); +} + +template +inline +sc_concref_r > +operator , ( const char* a, sc_subref b ) +{ + return sc_concref_r >( + *new sc_lv_base( a ), *b.clone(), 3 ); +} + +template +inline +sc_concref_r,sc_lv_base> +operator , ( sc_subref a, const sc_logic& b ) +{ + return sc_concref_r,sc_lv_base>( + *a.clone(), *new sc_lv_base( b, 1 ), 3 ); +} + +template +inline +sc_concref_r > +operator , ( const sc_logic& a, sc_subref b ) +{ + return sc_concref_r >( + *new sc_lv_base( a, 1 ), *b.clone(), 3 ); +} + +template +inline +sc_concref_r,sc_bv_base> +operator , ( sc_subref a, bool b ) +{ + return sc_concref_r,sc_bv_base> + ( *a.clone(), *new sc_bv_base( b, 1 ), 3 ); +} + +template +inline +sc_concref_r > +operator , ( bool a, sc_subref b ) +{ + return sc_concref_r > + ( *new sc_bv_base( a, 1 ), *b.clone(), 3 ); +} + + +template +inline +sc_concref_r,sc_lv_base> +concat( sc_subref a, const char* b ) +{ + return sc_concref_r,sc_lv_base>( + *a.clone(), *new sc_lv_base( b ), 3 ); +} + +template +inline +sc_concref_r > +concat( const char* a, sc_subref b ) +{ + return sc_concref_r >( + *new sc_lv_base( a ), *b.clone(), 3 ); +} + +template +inline +sc_concref_r,sc_lv_base> +concat( sc_subref a, const sc_logic& b ) +{ + return sc_concref_r,sc_lv_base>( + *a.clone(), *new sc_lv_base( b, 1 ), 3 ); +} + +template +inline +sc_concref_r > +concat( const sc_logic& a, sc_subref b ) +{ + return sc_concref_r >( + *new sc_lv_base( a, 1 ), *b.clone(), 3 ); +} + +template +inline +sc_concref_r,sc_bv_base> +concat( sc_subref a, bool b ) +{ + return sc_concref_r,sc_bv_base> + ( *a.clone(), *new sc_bv_base( b, 1 ), 3 ); +} + +template +inline +sc_concref_r > +concat( bool a, sc_subref b ) +{ + return sc_concref_r > + ( *new sc_bv_base( a, 1 ), *b.clone(), 3 ); +} + +#endif + + +// ---------------------------------------------------------------------------- +// CLASS TEMPLATE : sc_subref +// +// Proxy class for sc_proxy part selection (r-value and l-value). +// ---------------------------------------------------------------------------- + +template +inline +sc_subref& +sc_subref::operator = ( const sc_subref_r& 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 +inline +sc_subref& +sc_subref::operator = ( const sc_subref& 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 +// +// Proxy class for sc_proxy concatenation (r-value only). +// ---------------------------------------------------------------------------- + +// r-value concatenation operators and functions + +template +inline +sc_concref_r,sc_lv_base> +operator , ( sc_concref_r a, const char* b ) +{ + return sc_concref_r,sc_lv_base>( + *a.clone(), *new sc_lv_base( b ), 3 ); +} + +template +inline +sc_concref_r > +operator , ( const char* a, sc_concref_r b ) +{ + return sc_concref_r >( + *new sc_lv_base( a ), *b.clone(), 3 ); +} + +template +inline +sc_concref_r,sc_lv_base> +operator , ( sc_concref_r a, const sc_logic& b ) +{ + return sc_concref_r,sc_lv_base>( + *a.clone(), *new sc_lv_base( b, 1 ), 3 ); +} + +template +inline +sc_concref_r > +operator , ( const sc_logic& a, sc_concref_r b ) +{ + return sc_concref_r >( + *new sc_lv_base( a, 1 ), *b.clone(), 3 ); +} + +template +inline +sc_concref_r,sc_bv_base> +operator , ( sc_concref_r a, bool b ) +{ + return sc_concref_r,sc_bv_base> + ( *a.clone(), *new sc_bv_base( b, 1 ), 3 ); +} + +template +inline +sc_concref_r > +operator , ( bool a, sc_concref_r b ) +{ + return sc_concref_r > + ( *new sc_bv_base( a, 1 ), *b.clone(), 3 ); +} + + +template +inline +sc_concref_r,sc_lv_base> +concat( sc_concref_r a, const char* b ) +{ + return sc_concref_r,sc_lv_base> + ( *a.clone(), *new sc_lv_base( b ), 3 ); +} + +template +inline +sc_concref_r > +concat( const char* a, sc_concref_r b ) +{ + return sc_concref_r > + ( *new sc_lv_base( a ), *b.clone(), 3 ); +} + +template +inline +sc_concref_r,sc_lv_base> +concat( sc_concref_r a, const sc_logic& b ) +{ + return sc_concref_r,sc_lv_base> + ( *a.clone(), *new sc_lv_base( b, 1 ), 3 ); +} + +template +inline +sc_concref_r > +concat( const sc_logic& a, sc_concref_r b ) +{ + return sc_concref_r > + ( *new sc_lv_base( a, 1 ), *b.clone(), 3 ); +} + +template +inline +sc_concref_r,sc_bv_base> +concat( sc_concref_r a, bool b ) +{ + return sc_concref_r,sc_bv_base> + ( *a.clone(), *new sc_bv_base( b, 1 ), 3 ); +} + +template +inline +sc_concref_r > +concat( bool a, sc_concref_r b ) +{ + return sc_concref_r > + ( *new sc_bv_base( a, 1 ), *b.clone(), 3 ); +} + + +#ifdef SC_DT_MIXED_COMMA_OPERATORS + +template +inline +sc_concref_r,sc_lv_base> +operator , ( sc_concref a, const char* b ) +{ + return sc_concref_r,sc_lv_base> + ( *a.clone(), *new sc_lv_base( b ), 3 ); +} + +template +inline +sc_concref_r > +operator , ( const char* a, sc_concref b ) +{ + return sc_concref_r > + ( *new sc_lv_base( a ), *b.clone(), 3 ); +} + +template +inline +sc_concref_r,sc_lv_base> +operator , ( sc_concref a, const sc_logic& b ) +{ + return sc_concref_r,sc_lv_base> + ( *a.clone(), *new sc_lv_base( b, 1 ), 3 ); +} + +template +inline +sc_concref_r > +operator , ( const sc_logic& a, sc_concref b ) +{ + return sc_concref_r > + ( *new sc_lv_base( a, 1 ), *b.clone(), 3 ); +} + +template +inline +sc_concref_r,sc_bv_base> +operator , ( sc_concref a, bool b ) +{ + return sc_concref_r,sc_bv_base> + ( *a.clone(), *new sc_bv_base( b, 1 ), 3 ); +} + +template +inline +sc_concref_r > +operator , ( bool a, sc_concref b ) +{ + return sc_concref_r > + ( *new sc_bv_base( a, 1 ), *b.clone(), 3 ); +} + + +template +inline +sc_concref_r,sc_lv_base> +concat( sc_concref a, const char* b ) +{ + return sc_concref_r,sc_lv_base> + ( *a.clone(), *new sc_lv_base( b ), 3 ); +} + +template +inline +sc_concref_r > +concat( const char* a, sc_concref b ) +{ + return sc_concref_r > + ( *new sc_lv_base( a ), *b.clone(), 3 ); +} + +template +inline +sc_concref_r,sc_lv_base> +concat( sc_concref a, const sc_logic& b ) +{ + return sc_concref_r,sc_lv_base> + ( *a.clone(), *new sc_lv_base( b, 1 ), 3 ); +} + +template +inline +sc_concref_r > +concat( const sc_logic& a, sc_concref b ) +{ + return sc_concref_r > + ( *new sc_lv_base( a, 1 ), *b.clone(), 3 ); +} + +template +inline +sc_concref_r,sc_bv_base> +concat( sc_concref a, bool b ) +{ + return sc_concref_r,sc_bv_base> + ( *a.clone(), *new sc_bv_base( b, 1 ), 3 ); +} + +template +inline +sc_concref_r > +concat( bool a, sc_concref b ) +{ + return sc_concref_r > + ( *new sc_bv_base( a, 1 ), *b.clone(), 3 ); +} + +#endif + + +// ---------------------------------------------------------------------------- +// CLASS TEMPLATE : sc_proxy +// +// Base class template for bit/logic vector classes. +// (Barton/Nackmann implementation) +// ---------------------------------------------------------------------------- + +// r-value concatenation operators and functions + +template +inline +sc_concref_r +operator , ( const sc_proxy& a, const char* b ) +{ + return sc_concref_r + ( a.back_cast(), *new sc_lv_base( b ), 2 ); +} + +template +inline +sc_concref_r +operator , ( const char* a, const sc_proxy& b ) +{ + return sc_concref_r + ( *new sc_lv_base( a ), b.back_cast(), 1 ); +} + +template +inline +sc_concref_r +operator , ( const sc_proxy& a, const sc_logic& b ) +{ + return sc_concref_r + ( a.back_cast(), *new sc_lv_base( b, 1 ), 2 ); +} + +template +inline +sc_concref_r +operator , ( const sc_logic& a, const sc_proxy& b ) +{ + return sc_concref_r + ( *new sc_lv_base( a, 1 ), b.back_cast(), 1 ); +} + +template +inline +sc_concref_r +operator , ( const sc_proxy& a, bool b ) +{ + return sc_concref_r + ( a.back_cast(), *new sc_bv_base( b, 1 ), 2 ); +} + +template +inline +sc_concref_r +operator , ( bool a, const sc_proxy& b ) +{ + return sc_concref_r + ( *new sc_bv_base( a, 1 ), b.back_cast(), 1 ); +} + + +template +inline +sc_concref_r +concat( const sc_proxy& a, const char* b ) +{ + return sc_concref_r + ( a.back_cast(), *new sc_lv_base( b ), 2 ); +} + +template +inline +sc_concref_r +concat( const char* a, const sc_proxy& b ) +{ + return sc_concref_r + ( *new sc_lv_base( a ), b.back_cast(), 1 ); +} + +template +inline +sc_concref_r +concat( const sc_proxy& a, const sc_logic& b ) +{ + return sc_concref_r + ( a.back_cast(), *new sc_lv_base( b, 1 ), 2 ); +} + +template +inline +sc_concref_r +concat( const sc_logic& a, const sc_proxy& b ) +{ + return sc_concref_r + ( *new sc_lv_base( a, 1 ), b.back_cast(), 1 ); +} + +template +inline +sc_concref_r +concat( const sc_proxy& a, bool b ) +{ + return sc_concref_r + ( a.back_cast(), *new sc_bv_base( b, 1 ), 2 ); +} + +template +inline +sc_concref_r +concat( bool a, const sc_proxy& b ) +{ + return sc_concref_r + ( *new sc_bv_base( a, 1 ), b.back_cast(), 1 ); +} + + +#ifdef SC_DT_MIXED_COMMA_OPERATORS + +template +inline +sc_concref_r +operator , ( sc_proxy& a, const char* b ) +{ + return sc_concref_r + ( a.back_cast(), *new sc_lv_base( b ), 2 ); +} + +template +inline +sc_concref_r +operator , ( const char* a, sc_proxy& b ) +{ + return sc_concref_r + ( *new sc_lv_base( a ), b.back_cast(), 1 ); +} + +template +inline +sc_concref_r +operator , ( sc_proxy& a, const sc_logic& b ) +{ + return sc_concref_r + ( a.back_cast(), *new sc_lv_base( b, 1 ), 2 ); +} + +template +inline +sc_concref_r +operator , ( const sc_logic& a, sc_proxy& b ) +{ + return sc_concref_r + ( *new sc_lv_base( a, 1 ), b.back_cast(), 1 ); +} + +template +inline +sc_concref_r +operator , ( sc_proxy& a, bool b ) +{ + return sc_concref_r + ( a.back_cast(), *new sc_bv_base( b, 1 ), 2 ); +} + +template +inline +sc_concref_r +operator , ( bool a, sc_proxy& b ) +{ + return sc_concref_r + ( *new sc_bv_base( a, 1 ), b.back_cast(), 1 ); +} + + +template +inline +sc_concref_r +concat( sc_proxy& a, const char* b ) +{ + return sc_concref_r + ( a.back_cast(), *new sc_lv_base( b ), 2 ); +} + +template +inline +sc_concref_r +concat( const char* a, sc_proxy& b ) +{ + return sc_concref_r + ( *new sc_lv_base( a ), b.back_cast(), 1 ); +} + +template +inline +sc_concref_r +concat( sc_proxy& a, const sc_logic& b ) +{ + return sc_concref_r + ( a.back_cast(), *new sc_lv_base( b, 1 ), 2 ); +} + +template +inline +sc_concref_r +concat( const sc_logic& a, sc_proxy& b ) +{ + return sc_concref_r + ( *new sc_lv_base( a, 1 ), b.back_cast(), 1 ); +} + +template +inline +sc_concref_r +concat( sc_proxy& a, bool b ) +{ + return sc_concref_r + ( a.back_cast(), *new sc_bv_base( b, 1 ), 2 ); +} + +template +inline +sc_concref_r +concat( bool a, sc_proxy& b ) +{ + return sc_concref_r + ( *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 sc_proxy; + +// forward class declarations +class sc_bv_base; +class sc_lv_base; +template class sc_bitref_r; +template class sc_bitref; +template class sc_subref_r; +template class sc_subref; +template class sc_concref_r; +template 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 +inline +void +assign_p_( sc_proxy& px, const sc_proxy& py ); + +// Vector types that are not derived from sc_proxy must have a length() +// function and an operator []. + +template +inline +void +assign_v_( sc_proxy& 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 struct sc_proxy_traits; + +template<> struct sc_proxy_traits +{ + typedef sc_proxy_traits 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 +{ + typedef sc_proxy_traits 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 struct sc_proxy_traits > + : sc_proxy_traits {}; + +template struct sc_proxy_traits > + : sc_proxy_traits {}; + + +template struct sc_proxy_traits > + : sc_proxy_traits {}; + +template struct sc_proxy_traits > + : sc_proxy_traits {}; + + +template struct sc_proxy_traits > + : sc_proxy_traits {}; + + +template< typename X, typename Y > struct sc_mixed_proxy_traits_helper + : sc_proxy_traits {}; // logic vector by default + +template struct sc_mixed_proxy_traits_helper + : X {}; + + +template struct sc_proxy_traits< sc_concref_r > + : sc_mixed_proxy_traits_helper< typename X::traits_type::type + , typename Y::traits_type::type > +{}; + +template struct sc_proxy_traits > + : 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 sc_proxy // #### : public sc_value_base +{ +public: + typedef typename sc_proxy_traits::type traits_type; + typedef typename traits_type::bit_type bit_type; + + // virtual destructor + + virtual ~sc_proxy() {} + + + // casts + + X& back_cast() + { return SCAST( *this ); } + + const X& back_cast() const + { return SCAST( *this ); } + + + // assignment operators + + template + X& assign_( const sc_proxy& 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 operator [] ( int i ) + { return sc_bitref( back_cast(), i ); } + + sc_bitref_r operator [] ( int i ) const + { return sc_bitref_r( back_cast(), i ); } + + sc_bitref bit( int i ) + { return sc_bitref( back_cast(), i ); } + + sc_bitref_r bit( int i ) const + { return sc_bitref_r( back_cast(), i ); } + + + // part selection + + sc_subref operator () ( int hi, int lo ) + { return sc_subref( back_cast(), hi, lo ); } + + sc_subref_r operator () ( int hi, int lo ) const + { return sc_subref_r( back_cast(), hi, lo ); } + + sc_subref range( int hi, int lo ) + { return sc_subref( back_cast(), hi, lo ); } + + sc_subref_r range( int hi, int lo ) const + { return sc_subref_r( 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 +inline +X& +operator &= ( sc_proxy& px, const sc_proxy& py ); + + +template +inline +const sc_lv_base +operator & ( const sc_proxy& px, const sc_proxy& py ); + + +#define DECL_BITWISE_AND_OP_T(tp) \ +template \ +inline \ +const sc_lv_base \ +operator & ( tp b, const sc_proxy& 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 +inline +X& +operator |= ( sc_proxy& px, const sc_proxy& py ); + + +template +inline +const sc_lv_base +operator | ( const sc_proxy& px, const sc_proxy& py ); + + +#define DECL_BITWISE_OR_OP_T(tp) \ +template \ +inline \ +const sc_lv_base \ +operator | ( tp a, const sc_proxy& 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 +inline +X& +operator ^= ( sc_proxy& px, const sc_proxy& py ); + + +template +inline +const sc_lv_base +operator ^ ( const sc_proxy& px, const sc_proxy& py ); + + +#define DECL_BITWISE_XOR_OP_T(tp) \ +template \ +inline \ +const sc_lv_base \ +operator ^ ( tp a, const sc_proxy& 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 +inline +bool +operator == ( const sc_proxy& px, const sc_proxy& py ); + +template +inline +bool +operator != ( const sc_proxy& px, const sc_proxy& py ); + + +#define DECL_REL_OP_T(tp) \ +template \ +inline \ +bool \ +operator == ( tp b, const sc_proxy& px ); \ + \ +template \ +inline \ +bool \ +operator != ( const sc_proxy& px, tp b ); \ + \ +template \ +inline \ +bool \ +operator != ( tp b, const sc_proxy& 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 +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 +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 +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 +inline +void +assign_p_( sc_proxy& px, const sc_proxy& 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 +inline +void +assign_v_( sc_proxy& 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 +inline +void +assign_v_( sc_proxy& 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 +inline +void +assign_v_( sc_proxy& 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 +inline +void +assign_v_( sc_proxy& 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 +inline +void +assign_v_( sc_proxy& 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 +inline +X& +sc_proxy::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 +inline +X& +sc_proxy::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 +inline +X& +sc_proxy::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 +inline +X& +sc_proxy::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 +inline +X& +sc_proxy::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 + inline + X& + sc_proxy::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 + inline + X& + sc_proxy::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 + inline + X& + sc_proxy::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 + inline + X& + sc_proxy::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 +inline +X& +sc_proxy::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 +inline +X& +sc_proxy::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 +inline +X& +sc_proxy::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 +inline +X& +b_and_assign_( sc_proxy& px, const sc_proxy& 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 +inline +X& +b_or_assign_( sc_proxy& px, const sc_proxy& 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 +inline +X& +b_xor_assign_( sc_proxy& a, const sc_proxy& 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 +inline +X& +sc_proxy::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 +inline +X& +sc_proxy::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 +inline +const sc_lv_base +lrotate( const sc_proxy& x, int n ); + + +// bitwise right rotate + +template +inline +const sc_lv_base +rrotate( const sc_proxy& x, int n ); + + +// bitwise reverse + +template +inline +X& +sc_proxy::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 +inline +const sc_lv_base +reverse( const sc_proxy& a ); + + +// reduce functions + +template +inline +sc_logic_value_t +sc_proxy::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 +inline +sc_logic_value_t +sc_proxy::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 +inline +sc_logic_value_t +sc_proxy::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 +inline +bool +operator != ( const sc_proxy& px, const sc_proxy& py ) +{ + return !( px == py ); +} + + +#define DEFN_REL_OP_T(tp) \ +template \ +inline \ +bool \ +operator == ( tp b, const sc_proxy& px ) \ +{ \ + return ( px == b ); \ +} \ + \ +template \ +inline \ +bool \ +operator != ( const sc_proxy& px, tp b ) \ +{ \ + return !( px == b ); \ +} \ + \ +template \ +inline \ +bool \ +operator != ( tp b, const sc_proxy& 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 +inline +const std::string +sc_proxy::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 +inline +const std::string +sc_proxy::to_string( sc_numrep numrep ) const +{ + return convert_to_fmt( to_string(), numrep, true ); +} + +template +inline +const std::string +sc_proxy::to_string( sc_numrep numrep, bool w_prefix ) const +{ + return convert_to_fmt( to_string(), numrep, w_prefix ); +} + + +// other methods + +template +inline +void +sc_proxy::scan( ::std::istream& is ) +{ + std::string s; + is >> s; + back_cast() = s.c_str(); +} + + +template +inline +void +sc_proxy::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 +inline +void +sc_proxy::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 +inline +sc_digit +sc_proxy::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 +inline +uint64 +sc_proxy::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 +inline +int64 +sc_proxy::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 +inline +sc_logic_value_t +and_reduce( const sc_proxy& a ) +{ + return a.and_reduce(); +} + +template +inline +sc_logic_value_t +nand_reduce( const sc_proxy& a ) +{ + return a.nand_reduce(); +} + +template +inline +sc_logic_value_t +or_reduce( const sc_proxy& a ) +{ + return a.or_reduce(); +} + +template +inline +sc_logic_value_t +nor_reduce( const sc_proxy& a ) +{ + return a.nor_reduce(); +} + +template +inline +sc_logic_value_t +xor_reduce( const sc_proxy& a ) +{ + return a.xor_reduce(); +} + +template +inline +sc_logic_value_t +xnor_reduce( const sc_proxy& a ) +{ + return a.xnor_reduce(); +} + + +// ---------------------------------------------------------------------------- + +template +inline +::std::ostream& +operator << ( ::std::ostream& os, const sc_proxy& a ) +{ + a.print( os ); + return os; +} + +template +inline +::std::istream& +operator >> ( ::std::istream& is, sc_proxy& 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 sc_global; +template 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 sc_global +{ + + sc_global(); + + void update(); + +public: + + static sc_global* instance(); + + const T*& value_ptr(); + +private: + static sc_global* m_instance; + + sc_core::sc_phash 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 sc_context +{ + // disabled + sc_context( const sc_context& ); + 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 +sc_global* sc_global::m_instance = 0; + +template +inline +sc_global::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 +inline +void +sc_global::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 +inline +sc_global* +sc_global::instance() +{ + if( m_instance == 0 ) + { + m_instance = new sc_global; + } + return m_instance; +} + + +template +inline +const T*& +sc_global::value_ptr() +{ + update(); + return m_value_ptr; +} + + +// ---------------------------------------------------------------------------- +// CLASS : sc_context +// +// Template context class; co-routine safe. +// ---------------------------------------------------------------------------- + +template +inline +sc_context::sc_context( const T& value_, sc_context_begin begin ) +: m_value( value_ ), + m_def_value_ptr( sc_global::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 +inline +sc_context::~sc_context() +{ + if( m_old_value_ptr != 0 ) + { + m_def_value_ptr = m_old_value_ptr; + m_old_value_ptr = 0; + } +} + + +template +inline +void +sc_context::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 +inline +void +sc_context::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 +inline +const T& +sc_context::default_value() +{ + return *sc_global::instance()->value_ptr(); +} + +template +inline +const T& +sc_context::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 class sc_fixed; +template class sc_fixed_fast; + + +// ---------------------------------------------------------------------------- +// TEMPLATE CLASS : sc_fixed +// +// "Constrained" signed fixed-point class; arbitrary precision. +// ---------------------------------------------------------------------------- + +template +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& ); + + + // assignment operators + + sc_fixed& operator = ( const sc_fixed& ); + +#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 +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& ); + + + // assignment operators + + sc_fixed_fast& operator = ( const sc_fixed_fast& ); + +#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 +inline +sc_fixed::sc_fixed( sc_fxnum_observer* observer_ ) +: sc_fix( W, I, Q, O, N, observer_ ) +{} + +template +inline +sc_fixed::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 \ +inline \ +sc_fixed::sc_fixed( tp a, \ + sc_fxnum_observer* observer_ ) \ +: sc_fix( a, W, I, Q, O, N, observer_ ) \ +{} \ + \ +template \ +inline \ +sc_fixed::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 +inline +sc_fixed::sc_fixed( const sc_fixed& a ) +: sc_fix( a, W, I, Q, O, N ) +{} + + +// assignment operators + +template +inline +sc_fixed& +sc_fixed::operator = ( const sc_fixed& a ) +{ + sc_fix::operator = ( a ); + return *this; +} + +#define DEFN_ASN_OP_T(op,tp) \ +template \ +inline \ +sc_fixed& \ +sc_fixed::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 +inline +const sc_fxval +sc_fixed::operator ++ ( int ) +{ + return sc_fxval( sc_fix::operator ++ ( 0 ) ); +} + +template +inline +const sc_fxval +sc_fixed::operator -- ( int ) +{ + return sc_fxval( sc_fix::operator -- ( 0 ) ); +} + +template +inline +sc_fixed& +sc_fixed::operator ++ () +{ + sc_fix::operator ++ (); + return *this; +} + +template +inline +sc_fixed& +sc_fixed::operator -- () +{ + sc_fix::operator -- (); + return *this; +} + + +// ---------------------------------------------------------------------------- +// TEMPLATE CLASS : sc_fixed_fast +// +// "Constrained" signed fixed-point class; limited precision. +// ---------------------------------------------------------------------------- + +template +inline +sc_fixed_fast::sc_fixed_fast( sc_fxnum_fast_observer* observer_ ) +: sc_fix_fast( W, I, Q, O, N, observer_ ) +{} + +template +inline +sc_fixed_fast::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 \ +inline \ +sc_fixed_fast::sc_fixed_fast( tp a, \ + sc_fxnum_fast_observer* observer_ ) \ +: sc_fix_fast( a, W, I, Q, O, N, observer_ ) \ +{} \ + \ +template \ +inline \ +sc_fixed_fast::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 +inline +sc_fixed_fast::sc_fixed_fast( const sc_fixed_fast& a ) +: sc_fix_fast( a, W, I, Q, O, N ) +{} + + +// assignment operators + +template +inline +sc_fixed_fast& +sc_fixed_fast::operator = ( const sc_fixed_fast& a ) +{ + sc_fix_fast::operator = ( a ); + return *this; +} + +#define DEFN_ASN_OP_T(op,tp) \ +template \ +inline \ +sc_fixed_fast& \ +sc_fixed_fast::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 +inline +const sc_fxval_fast +sc_fixed_fast::operator ++ ( int ) +{ + return sc_fxval_fast( sc_fix_fast::operator ++ ( 0 ) ); +} + +template +inline +const sc_fxval_fast +sc_fixed_fast::operator -- ( int ) +{ + return sc_fxval_fast( sc_fix_fast::operator -- ( 0 ) ); +} + +template +inline +sc_fixed_fast& +sc_fixed_fast::operator ++ () +{ + sc_fix_fast::operator ++ (); + return *this; +} + +template +inline +sc_fixed_fast& +sc_fixed_fast::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_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 + +#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( 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( 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( 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( 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( 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( 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( 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( 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( 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( 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( 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( 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( a ) op b ); \ +} \ + \ +inline \ +bool \ +operator op ( tp a, const sc_fxnum_subref& b ) \ +{ \ + return ( static_cast( 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( a ) op static_cast( b ) ); \ +} \ + \ +inline \ +bool \ +operator op ( const sc_fxnum_subref& a, const sc_fxnum_fast_subref& b ) \ +{ \ + return ( static_cast( a ) op static_cast( 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( 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( 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( 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( 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( 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( a ) op b ); \ +} \ + \ +inline \ +bool \ +operator op ( tp a, const sc_fxnum_fast_subref& b ) \ +{ \ + return ( static_cast( 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( a ) op static_cast( b ) ); \ +} \ + \ +inline \ +bool \ +operator op ( const sc_fxnum_fast_subref& a, const sc_fxnum_subref& b ) \ +{ \ + return ( static_cast( a ) op static_cast( 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( 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( *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( *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( *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( *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( m_rep->to_double() ); +} + +inline +unsigned short +sc_fxnum::to_ushort() const +{ + SC_FXNUM_OBSERVER_READ_( *this ) + return static_cast( m_rep->to_double() ); +} + +inline +int +sc_fxnum::to_int() const +{ + SC_FXNUM_OBSERVER_READ_( *this ) + return static_cast( m_rep->to_double() ); +} + +inline +int64 +sc_fxnum::to_int64() const +{ + SC_FXNUM_OBSERVER_READ_( *this ) + return static_cast( m_rep->to_double() ); +} + +inline +unsigned int +sc_fxnum::to_uint() const +{ + SC_FXNUM_OBSERVER_READ_( *this ) + return static_cast( m_rep->to_double() ); +} + +inline +uint64 +sc_fxnum::to_uint64() const +{ + SC_FXNUM_OBSERVER_READ_( *this ) + return static_cast( m_rep->to_double() ); +} + +inline +long +sc_fxnum::to_long() const +{ + SC_FXNUM_OBSERVER_READ_( *this ) + return static_cast( m_rep->to_double() ); +} + +inline +unsigned long +sc_fxnum::to_ulong() const +{ + SC_FXNUM_OBSERVER_READ_( *this ) + return static_cast( m_rep->to_double() ); +} + +inline +float +sc_fxnum::to_float() const +{ + SC_FXNUM_OBSERVER_READ_( *this ) + return static_cast( 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( 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( *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( *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( *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( *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( m_val ); +} + +inline +unsigned short +sc_fxnum_fast::to_ushort() const +{ + SC_FXNUM_FAST_OBSERVER_READ_( *this ) + return static_cast( m_val ); +} + +inline +int +sc_fxnum_fast::to_int() const +{ + SC_FXNUM_FAST_OBSERVER_READ_( *this ) + return static_cast( m_val ); +} + +inline +int64 +sc_fxnum_fast::to_int64() const +{ + SC_FXNUM_FAST_OBSERVER_READ_( *this ) + return static_cast( m_val ); +} + +inline +unsigned int +sc_fxnum_fast::to_uint() const +{ + SC_FXNUM_FAST_OBSERVER_READ_( *this ) + return static_cast( m_val ); +} + +inline +uint64 +sc_fxnum_fast::to_uint64() const +{ + SC_FXNUM_FAST_OBSERVER_READ_( *this ) + return static_cast( m_val ); +} + +inline +long +sc_fxnum_fast::to_long() const +{ + SC_FXNUM_FAST_OBSERVER_READ_( *this ) + return static_cast( m_val ); +} + +inline +unsigned long +sc_fxnum_fast::to_ulong() const +{ + SC_FXNUM_FAST_OBSERVER_READ_( *this ) + return static_cast( m_val ); +} + +inline +float +sc_fxnum_fast::to_float() const +{ + SC_FXNUM_FAST_OBSERVER_READ_( *this ) + return static_cast( 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_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 +#include +#include +#include + +#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( 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( '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( frac_part ); + + if( zero_digits ) + { + if( n == 0 ) + frac_zeros ++; + else + zero_digits = false; + } + + if( ! zero_digits ) + s += static_cast( '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( sign + '0' ); + else + s += static_cast( sign + 'a' - 10 ); + } + } + } + + int i = msb; + while( i >= lsb ) + { + int value = 0; + for( int j = step - 1; j >= 0; -- j ) + { + value += static_cast( a.get_bit( i ) ) << j; + -- i; + } + if( value < 10 ) + s += static_cast( value + '0' ); + else + s += static_cast( 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( 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( 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( scfx_ieee_double::nan() ); + if( scfx_is_inf( s ) ) // special case: Infinity + return static_cast( 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( m_rep->to_double() ); +} + +inline +unsigned short +sc_fxval::to_ushort() const +{ + SC_FXVAL_OBSERVER_READ_( *this ) + return static_cast( m_rep->to_double() ); +} + +inline +int +sc_fxval::to_int() const +{ + SC_FXVAL_OBSERVER_READ_( *this ) + return static_cast( m_rep->to_double() ); +} + +inline +int64 +sc_fxval::to_int64() const +{ + SC_FXVAL_OBSERVER_READ_( *this ) + return static_cast( m_rep->to_double() ); +} + +inline +uint64 +sc_fxval::to_uint64() const +{ + SC_FXVAL_OBSERVER_READ_( *this ) + return static_cast( m_rep->to_double() ); +} + +inline +long +sc_fxval::to_long() const +{ + SC_FXVAL_OBSERVER_READ_( *this ) + return static_cast( m_rep->to_double() ); +} + +inline +unsigned int +sc_fxval::to_uint() const +{ + SC_FXVAL_OBSERVER_READ_( *this ) + return static_cast( m_rep->to_double() ); +} + +inline +unsigned long +sc_fxval::to_ulong() const +{ + SC_FXVAL_OBSERVER_READ_( *this ) + return static_cast( m_rep->to_double() ); +} + +inline +float +sc_fxval::to_float() const +{ + SC_FXVAL_OBSERVER_READ_( *this ) + return static_cast( 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( 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( m_val ); +} + +inline +unsigned short +sc_fxval_fast::to_ushort() const +{ + SC_FXVAL_FAST_OBSERVER_READ_( *this ) + return static_cast( m_val ); +} + +inline +int64 +sc_fxval_fast::to_int64() const +{ + SC_FXVAL_FAST_OBSERVER_READ_( *this ) + return static_cast( m_val ); +} + +inline +int +sc_fxval_fast::to_int() const +{ + SC_FXVAL_FAST_OBSERVER_READ_( *this ) + return static_cast( m_val ); +} + +inline +unsigned int +sc_fxval_fast::to_uint() const +{ + SC_FXVAL_FAST_OBSERVER_READ_( *this ) + return static_cast( m_val ); +} + +inline +uint64 +sc_fxval_fast::to_uint64() const +{ + SC_FXVAL_FAST_OBSERVER_READ_( *this ) + return static_cast( m_val ); +} + +inline +long +sc_fxval_fast::to_long() const +{ + SC_FXVAL_FAST_OBSERVER_READ_( *this ) + return static_cast( m_val ); +} + +inline +unsigned long +sc_fxval_fast::to_ulong() const +{ + SC_FXVAL_FAST_OBSERVER_READ_( *this ) + return static_cast( m_val ); +} + +inline +float +sc_fxval_fast::to_float() const +{ + SC_FXVAL_FAST_OBSERVER_READ_( *this ) + return static_cast( 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 class sc_ufixed; +template class sc_ufixed_fast; + + +// ---------------------------------------------------------------------------- +// TEMPLATE CLASS : sc_ufixed +// +// "Constrained" unsigned fixed-point class; arbitrary precision. +// ---------------------------------------------------------------------------- + +template +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& ); + + + // assignment operators + + sc_ufixed& operator = ( const sc_ufixed& ); + +#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 +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& ); + + + // assignment operators + + sc_ufixed_fast& operator = ( const sc_ufixed_fast& ); + +#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 +inline +sc_ufixed::sc_ufixed( sc_fxnum_observer* observer_ ) +: sc_ufix( W, I, Q, O, N, observer_ ) +{} + +template +inline +sc_ufixed::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 \ +inline \ +sc_ufixed::sc_ufixed( tp a, \ + sc_fxnum_observer* observer_ ) \ +: sc_ufix( a, W, I, Q, O, N, observer_ ) \ +{} \ + \ +template \ +inline \ +sc_ufixed::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 +inline +sc_ufixed::sc_ufixed( const sc_ufixed& a ) +: sc_ufix( a, W, I, Q, O, N ) +{} + + +// assignment operators + +template +inline +sc_ufixed& +sc_ufixed::operator = ( const sc_ufixed& a ) +{ + sc_ufix::operator = ( a ); + return *this; +} + +#define DEFN_ASN_OP_T(op,tp) \ +template \ +inline \ +sc_ufixed& \ +sc_ufixed::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 +inline +const sc_fxval +sc_ufixed::operator ++ ( int ) +{ + return sc_fxval( sc_ufix::operator ++ ( 0 ) ); +} + +template +inline +const sc_fxval +sc_ufixed::operator -- ( int ) +{ + return sc_fxval( sc_ufix::operator -- ( 0 ) ); +} + +template +inline +sc_ufixed& +sc_ufixed::operator ++ () +{ + sc_ufix::operator ++ (); + return *this; +} + +template +inline +sc_ufixed& +sc_ufixed::operator -- () +{ + sc_ufix::operator -- (); + return *this; +} + + +// ---------------------------------------------------------------------------- +// TEMPLATE CLASS : sc_ufixed_fast +// +// "Constrained" unsigned fixed-point class; limited precision. +// ---------------------------------------------------------------------------- + +template +inline +sc_ufixed_fast::sc_ufixed_fast( sc_fxnum_fast_observer* observer_ ) +: sc_ufix_fast( W, I, Q, O, N, observer_ ) +{} + +template +inline +sc_ufixed_fast::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 \ +inline \ +sc_ufixed_fast::sc_ufixed_fast( tp a, \ + sc_fxnum_fast_observer* observer_ )\ +: sc_ufix_fast( a, W, I, Q, O, N, observer_ ) \ +{} \ + \ +template \ +inline \ +sc_ufixed_fast::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 +inline +sc_ufixed_fast::sc_ufixed_fast( const sc_ufixed_fast& a ) +: sc_ufix_fast( a, W, I, Q, O, N ) +{} + + +// assignment operators + +template +inline +sc_ufixed_fast& +sc_ufixed_fast::operator = ( const sc_ufixed_fast& a ) +{ + sc_ufix_fast::operator = ( a ); + return *this; +} + +#define DEFN_ASN_OP_T(op,tp) \ +template \ +inline \ +sc_ufixed_fast& \ +sc_ufixed_fast::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 +inline +const sc_fxval_fast +sc_ufixed_fast::operator ++ ( int ) +{ + return sc_fxval_fast( sc_ufix_fast::operator ++ ( 0 ) ); +} + +template +inline +const sc_fxval_fast +sc_ufixed_fast::operator -- ( int ) +{ + return sc_fxval_fast( sc_ufix_fast::operator -- ( 0 ) ); +} + +template +inline +sc_ufixed_fast& +sc_ufixed_fast::operator ++ () +{ + sc_ufix_fast::operator ++ (); + return *this; +} + +template +inline +sc_ufixed_fast& +sc_ufixed_fast::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( static_cast( a ) ); + return ( tmp >= 0 ) ? tmp : tmp + sc_dt::scfx_pow2( 64 ); +#else + return static_cast( 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( m_array )[-i]; +#elif defined( SC_LITTLE_ENDIAN ) + return reinterpret_cast( 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( m_array )[-i]; +#elif defined( SC_LITTLE_ENDIAN ) + return reinterpret_cast( 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( m_array - i ) + 1; +#elif defined( SC_LITTLE_ENDIAN ) + return reinterpret_cast( 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( &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( &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 +#include +#include +#include + + +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( a ); + m_mant[2] = static_cast( 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( a ); + m_mant[2] = static_cast( 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( a ); + m_mant[2] = static_cast( a >> bits_in_word ); + m_sign = 1; + } + else + { + m_mant[1] = static_cast( -a ); + m_mant[2] = static_cast( (-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( a ); + m_mant[2] = static_cast( 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( 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( 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( *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( -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( 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( '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( '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( sign + '0' ); + else + s += static_cast( sign + 'a' - 10 ); + } + } + } + + int i = msb; + while( i >= lsb ) + { + int value = 0; + for( int j = step - 1; j >= 0; -- j ) + { + value += static_cast( b.get_bit( i ) ) << j; + -- i; + } + if( value < 10 ) + s += static_cast( value + '0' ); + else + s += static_cast( 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( 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( this )->toggle_tc(); + + bool result = ( m_mant[x.wi()] & ( 1 << x.bi() ) ) != 0; + + const_cast( 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 + +#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( -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( -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( -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 + + +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( 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 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 +// +// 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& 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& 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& operator = ( const sc_bigint& v ) + { sc_signed::operator = ( v ); return *this; } + + sc_bigint& operator = ( const sc_signed& v ) + { sc_signed::operator = ( v ); return *this; } + + sc_bigint& operator = (const sc_signed_subref& v ) + { sc_signed::operator = ( v ); return *this; } + + template< class T > + sc_bigint& operator = ( const sc_generic_base& a ) + { a->to_sc_signed(*this); return *this;} + + sc_bigint& operator = ( const sc_unsigned& v ) + { sc_signed::operator = ( v ); return *this; } + + sc_bigint& operator = ( const sc_unsigned_subref& v ) + { sc_signed::operator = ( v ); return *this; } + + sc_bigint& operator = ( const char* v ) + { sc_signed::operator = ( v ); return *this; } + + sc_bigint& operator = ( int64 v ) + { sc_signed::operator = ( v ); return *this; } + + sc_bigint& operator = ( uint64 v ) + { sc_signed::operator = ( v ); return *this; } + + sc_bigint& operator = ( long v ) + { sc_signed::operator = ( v ); return *this; } + + sc_bigint& operator = ( unsigned long v ) + { sc_signed::operator = ( v ); return *this; } + + sc_bigint& operator = ( int v ) + { sc_signed::operator = ( v ); return *this; } + + sc_bigint& operator = ( unsigned int v ) + { sc_signed::operator = ( v ); return *this; } + + sc_bigint& operator = ( double v ) + { sc_signed::operator = ( v ); return *this; } + + + sc_bigint& operator = ( const sc_bv_base& v ) + { sc_signed::operator = ( v ); return *this; } + + sc_bigint& operator = ( const sc_lv_base& v ) + { sc_signed::operator = ( v ); return *this; } + + sc_bigint& operator = ( const sc_int_base& v ) + { sc_signed::operator = ( v ); return *this; } + + sc_bigint& operator = ( const sc_uint_base& v ) + { sc_signed::operator = ( v ); return *this; } + +#ifdef SC_INCLUDE_FX + + sc_bigint& operator = ( const sc_fxval& v ) + { sc_signed::operator = ( v ); return *this; } + + sc_bigint& operator = ( const sc_fxval_fast& v ) + { sc_signed::operator = ( v ); return *this; } + + sc_bigint& operator = ( const sc_fxnum& v ) + { sc_signed::operator = ( v ); return *this; } + + sc_bigint& 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 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 +// +// 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& 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& 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& operator = ( const sc_biguint& v ) + { sc_unsigned::operator = ( v ); return *this; } + + sc_biguint& operator = ( const sc_unsigned& v ) + { sc_unsigned::operator = ( v ); return *this; } + + sc_biguint& operator = ( const sc_unsigned_subref& v ) + { sc_unsigned::operator = ( v ); return *this; } + + template< class T > + sc_biguint& operator = ( const sc_generic_base& a ) + { a->to_sc_unsigned(*this); return *this; } + + sc_biguint& operator = ( const sc_signed& v ) + { sc_unsigned::operator = ( v ); return *this; } + + sc_biguint& operator = ( const sc_signed_subref& v ) + { sc_unsigned::operator = ( v ); return *this; } + + sc_biguint& operator = ( const char* v ) + { sc_unsigned::operator = ( v ); return *this; } + + sc_biguint& operator = ( int64 v ) + { sc_unsigned::operator = ( v ); return *this; } + + sc_biguint& operator = ( uint64 v ) + { sc_unsigned::operator = ( v ); return *this; } + + sc_biguint& operator = ( long v ) + { sc_unsigned::operator = ( v ); return *this; } + + sc_biguint& operator = ( unsigned long v ) + { sc_unsigned::operator = ( v ); return *this; } + + sc_biguint& operator = ( int v ) + { sc_unsigned::operator = ( v ); return *this; } + + sc_biguint& operator = ( unsigned int v ) + { sc_unsigned::operator = ( v ); return *this; } + + sc_biguint& operator = ( double v ) + { sc_unsigned::operator = ( v ); return *this; } + + + sc_biguint& operator = ( const sc_bv_base& v ) + { sc_unsigned::operator = ( v ); return *this; } + + sc_biguint& operator = ( const sc_lv_base& v ) + { sc_unsigned::operator = ( v ); return *this; } + + sc_biguint& operator = ( const sc_int_base& v ) + { sc_unsigned::operator = ( v ); return *this; } + + sc_biguint& operator = ( const sc_uint_base& v ) + { sc_unsigned::operator = ( v ); return *this; } + +#ifdef SC_INCLUDE_FX + + sc_biguint& operator = ( const sc_fxval& v ) + { sc_unsigned::operator = ( v ); return *this; } + + sc_biguint& operator = ( const sc_fxval_fast& v ) + { sc_unsigned::operator = ( v ); return *this; } + + sc_biguint& operator = ( const sc_fxnum& v ) + { sc_unsigned::operator = ( v ); return *this; } + + sc_biguint& 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 class sc_int; + + +// ---------------------------------------------------------------------------- +// CLASS TEMPLATE : sc_int +// +// Template class sc_int 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 +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& 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& 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& operator = ( int_type v ) + { sc_int_base::operator = ( v ); return *this; } + + sc_int& operator = ( const sc_int_base& a ) + { sc_int_base::operator = ( a ); return *this; } + + sc_int& operator = ( const sc_int_subref_r& a ) + { sc_int_base::operator = ( a ); return *this; } + + sc_int& operator = ( const sc_int& a ) + { m_val = a.m_val; return *this; } + + template< class T > + sc_int& operator = ( const sc_generic_base& a ) + { sc_int_base::operator = ( a->to_int64() ); return *this; } + + sc_int& operator = ( const sc_signed& a ) + { sc_int_base::operator = ( a ); return *this; } + + sc_int& operator = ( const sc_unsigned& a ) + { sc_int_base::operator = ( a ); return *this; } + +#ifdef SC_INCLUDE_FX + + sc_int& operator = ( const sc_fxval& a ) + { sc_int_base::operator = ( a ); return *this; } + + sc_int& operator = ( const sc_fxval_fast& a ) + { sc_int_base::operator = ( a ); return *this; } + + sc_int& operator = ( const sc_fxnum& a ) + { sc_int_base::operator = ( a ); return *this; } + + sc_int& operator = ( const sc_fxnum_fast& a ) + { sc_int_base::operator = ( a ); return *this; } + +#endif + + sc_int& operator = ( const sc_bv_base& a ) + { sc_int_base::operator = ( a ); return *this; } + + sc_int& operator = ( const sc_lv_base& a ) + { sc_int_base::operator = ( a ); return *this; } + + sc_int& operator = ( const char* a ) + { sc_int_base::operator = ( a ); return *this; } + + sc_int& operator = ( unsigned long a ) + { sc_int_base::operator = ( a ); return *this; } + + sc_int& operator = ( long a ) + { sc_int_base::operator = ( a ); return *this; } + + sc_int& operator = ( unsigned int a ) + { sc_int_base::operator = ( a ); return *this; } + + sc_int& operator = ( int a ) + { sc_int_base::operator = ( a ); return *this; } + + sc_int& operator = ( uint64 a ) + { sc_int_base::operator = ( a ); return *this; } + + sc_int& operator = ( double a ) + { sc_int_base::operator = ( a ); return *this; } + + + // arithmetic assignment operators + + sc_int& operator += ( int_type v ) + { sc_int_base::operator += ( v ); return *this; } + + sc_int& operator -= ( int_type v ) + { sc_int_base::operator -= ( v ); return *this; } + + sc_int& operator *= ( int_type v ) + { sc_int_base::operator *= ( v ); return *this; } + + sc_int& operator /= ( int_type v ) + { sc_int_base::operator /= ( v ); return *this; } + + sc_int& operator %= ( int_type v ) + { sc_int_base::operator %= ( v ); return *this; } + + + // bitwise assignment operators + + sc_int& operator &= ( int_type v ) + { sc_int_base::operator &= ( v ); return *this; } + + sc_int& operator |= ( int_type v ) + { sc_int_base::operator |= ( v ); return *this; } + + sc_int& operator ^= ( int_type v ) + { sc_int_base::operator ^= ( v ); return *this; } + + + sc_int& operator <<= ( int_type v ) + { sc_int_base::operator <<= ( v ); return *this; } + + sc_int& operator >>= ( int_type v ) + { sc_int_base::operator >>= ( v ); return *this; } + + + // prefix and postfix increment and decrement operators + + sc_int& operator ++ () // prefix + { sc_int_base::operator ++ (); return *this; } + + const sc_int operator ++ ( int ) // postfix + { return sc_int( sc_int_base::operator ++ ( 0 ) ); } + + sc_int& operator -- () // prefix + { sc_int_base::operator -- (); return *this; } + + const sc_int operator -- ( int ) // postfix + { return sc_int( 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 + +void +sc_int_concref_invalid_length( int length ) +{ + char msg[BUFSIZ]; + std::sprintf( msg, + "sc_int_concref 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::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::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 <>= (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; + + + // 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 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; + + +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& 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 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& 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 + sc_int_base& operator = ( const sc_generic_base& 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(operator uint_type()); + return result; +} + +inline +unsigned int +sc_int_subref_r::to_uint() const +{ + unsigned int result = static_cast(operator uint_type()); + return result; +} + +inline +long +sc_int_subref_r::to_long() const +{ + long result = static_cast(operator uint_type()); + return result; +} + +inline +unsigned long +sc_int_subref_r::to_ulong() const +{ + unsigned long result = static_cast(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(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_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 + +#if defined(__sun) || defined(__sun__) +# include +#elif !defined(WIN32) && !defined(_WIN32) +# include +#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 +#include +#include + +#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 +#include + +#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( 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::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 ) : 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::has_quiet_NaN && (v != v); +} + +inline +bool +is_inf( double v ) +{ + return v == std::numeric_limits::infinity() + || v == -std::numeric_limits::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 +#include + +#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::m_pool(9); +sc_core::sc_vpool 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( v ) ); } + +sc_signed +operator + ( const sc_int_base& u, const sc_unsigned& v ) +{ return operator + ( SCAST( 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( v ) ); } + +sc_signed +operator * ( const sc_int_base& u, const sc_unsigned& v ) +{ return operator * ( SCAST( 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( v ) ); } + +sc_signed +operator / ( const sc_int_base& u, const sc_unsigned& v ) +{ return operator / ( SCAST( 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( v ) ); } + +sc_signed +operator % ( const sc_int_base& u, const sc_unsigned& v ) +{ return operator % ( SCAST( 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( v ) ); } + +sc_signed +operator & ( const sc_int_base& u, const sc_unsigned& v ) +{ return operator & ( SCAST( 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( v ) ); } + +sc_signed +operator | ( const sc_int_base& u, const sc_unsigned& v ) +{ return operator | ( SCAST( 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( v ) ); } + +sc_signed +operator ^ ( const sc_int_base& u, const sc_unsigned& v ) +{ return operator ^ ( SCAST( 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( 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; + + + // 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 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( 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; + + + // 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& 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 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 + explicit sc_signed( const sc_generic_base& 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& 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 +sc_signed::sc_signed( const sc_generic_base& 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 ) : 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( 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( 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( 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( 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 class sc_uint; + + +// ---------------------------------------------------------------------------- +// CLASS TEMPLATE : sc_uint +// +// Template class sc_uint 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 +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& 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& 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& operator = ( uint_type v ) + { sc_uint_base::operator = ( v ); return *this; } + + sc_uint& operator = ( const sc_uint_base& a ) + { sc_uint_base::operator = ( a ); return *this; } + + sc_uint& operator = ( const sc_uint_subref_r& a ) + { sc_uint_base::operator = ( a ); return *this; } + + sc_uint& operator = ( const sc_uint& a ) + { m_val = a.m_val; return *this; } + + template + sc_uint& operator = ( const sc_generic_base& a ) + { sc_uint_base::operator = ( a ); return *this; } + + sc_uint& operator = ( const sc_signed& a ) + { sc_uint_base::operator = ( a ); return *this; } + + sc_uint& operator = ( const sc_unsigned& a ) + { sc_uint_base::operator = ( a ); return *this; } + +#ifdef SC_INCLUDE_FX + + sc_uint& operator = ( const sc_fxval& a ) + { sc_uint_base::operator = ( a ); return *this; } + + sc_uint& operator = ( const sc_fxval_fast& a ) + { sc_uint_base::operator = ( a ); return *this; } + + sc_uint& operator = ( const sc_fxnum& a ) + { sc_uint_base::operator = ( a ); return *this; } + + sc_uint& operator = ( const sc_fxnum_fast& a ) + { sc_uint_base::operator = ( a ); return *this; } + +#endif + + sc_uint& operator = ( const sc_bv_base& a ) + { sc_uint_base::operator = ( a ); return *this; } + + sc_uint& operator = ( const sc_lv_base& a ) + { sc_uint_base::operator = ( a ); return *this; } + + sc_uint& operator = ( const char* a ) + { sc_uint_base::operator = ( a ); return *this; } + + sc_uint& operator = ( unsigned long a ) + { sc_uint_base::operator = ( a ); return *this; } + + sc_uint& operator = ( long a ) + { sc_uint_base::operator = ( a ); return *this; } + + sc_uint& operator = ( unsigned int a ) + { sc_uint_base::operator = ( a ); return *this; } + + sc_uint& operator = ( int a ) + { sc_uint_base::operator = ( a ); return *this; } + + sc_uint& operator = ( int64 a ) + { sc_uint_base::operator = ( a ); return *this; } + + sc_uint& operator = ( double a ) + { sc_uint_base::operator = ( a ); return *this; } + + + // arithmetic assignment operators + + sc_uint& operator += ( uint_type v ) + { sc_uint_base::operator += ( v ); return *this; } + + sc_uint& operator -= ( uint_type v ) + { sc_uint_base::operator -= ( v ); return *this; } + + sc_uint& operator *= ( uint_type v ) + { sc_uint_base::operator *= ( v ); return *this; } + + sc_uint& operator /= ( uint_type v ) + { sc_uint_base::operator /= ( v ); return *this; } + + sc_uint& operator %= ( uint_type v ) + { sc_uint_base::operator %= ( v ); return *this; } + + + // bitwise assignment operators + + sc_uint& operator &= ( uint_type v ) + { sc_uint_base::operator &= ( v ); return *this; } + + sc_uint& operator |= ( uint_type v ) + { sc_uint_base::operator |= ( v ); return *this; } + + sc_uint& operator ^= ( uint_type v ) + { sc_uint_base::operator ^= ( v ); return *this; } + + + sc_uint& operator <<= ( uint_type v ) + { sc_uint_base::operator <<= ( v ); return *this; } + + sc_uint& operator >>= ( uint_type v ) + { sc_uint_base::operator >>= ( v ); return *this; } + + + // prefix and postfix increment and decrement operators + + sc_uint& operator ++ () // prefix + { sc_uint_base::operator ++ (); return *this; } + + const sc_uint operator ++ ( int ) // postfix + { return sc_uint( sc_uint_base::operator ++ ( 0 ) ); } + + sc_uint& operator -- () // prefix + { sc_uint_base::operator -- (); return *this; } + + const sc_uint operator -- ( int ) // postfix + { return sc_uint( 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 + +void +sc_uint_concref_invalid_length( int length ) +{ + char msg[BUFSIZ]; + std::sprintf( msg, + "sc_uint_concref 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::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::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; + + + // 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 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; + + + // 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 + sc_uint_subref& operator = ( const sc_generic_base& 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 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 + explicit sc_uint_base( const sc_generic_base& 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 + sc_uint_base& operator = ( const sc_generic_base& 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 +#include + +#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::m_pool(8); +sc_core::sc_vpool sc_unsigned_bitref::m_pool(9); +sc_core::sc_vpool 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( 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; + + +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 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( 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; + + + // 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 + const sc_unsigned_subref& operator = ( const sc_generic_base& 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 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 + explicit sc_unsigned( const sc_generic_base& 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 + const sc_unsigned& operator = ( const sc_generic_base& 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 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 +inline const sc_unsigned_subref& sc_unsigned_subref::operator = ( + const sc_generic_base& 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 +sc_unsigned::sc_unsigned( const sc_generic_base& 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 ) : 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( 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( 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( 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( 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::m_pool(9); + sc_core::sc_vpool 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, public sc_value_base +{ +public: + friend class sc_core::sc_vpool; + + 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 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 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 +#include +#include +#include + +#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 +// +// 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 +#include + +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::iterator iterator; + typedef std::vector::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 m_cltn; + +private: + + // disabled + sc_attr_cltn& operator = ( const sc_attr_cltn& ); +}; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_attribute +// +// Attribute class. +// Note: T must have a default constructor and copy constructor. +// ---------------------------------------------------------------------------- + +template +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& 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& operator = ( const sc_attribute& ); +}; + +} // 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 + +#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 +#include +#include + +#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 +#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 +#include + +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 +# 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( 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( 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 + +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 +#include +#include + +#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( 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( old_cor )->m_sp = sp; + return 0; +} + +void +sc_cor_pkg_qt::yield( sc_cor* next_cor ) +{ + sc_cor_qt* new_cor = SCAST( 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( 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 +#include + +#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( 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 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; + 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 operator & ( const sc_event& ); + sc_event_expr operator & ( const sc_event_and_list& ); +}; + +typedef sc_event_expr 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; + 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 operator | ( const sc_event& ) const; + sc_event_expr operator | ( const sc_event_or_list& ) const; +}; + +typedef sc_event_expr 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 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 m_methods_static; + mutable std::vector m_methods_dynamic; + mutable std::vector m_threads_static; + mutable std::vector 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(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 + +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 +#include +#include + +#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(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 +inline +const T +sc_min( const T& a, const T& b ) +{ + return ( ( a <= b ) ? a : b ); +} + +template +inline +const T +sc_max( const T& a, const T& b ) +{ + return ( ( a >= b ) ? a : b ); +} + +template +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 + +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 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& 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(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& 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(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 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(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(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& 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(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(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& 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(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(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 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(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 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 +#include +#include +#include + +#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 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::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; + 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_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& port, bool level ) +{ + sc_reset::reset_signal_is(true, port, level); +} + +void +sc_module::async_reset_signal_is( const sc_inout& port, bool level ) +{ + sc_reset::reset_signal_is(true, port, level); +} + +void +sc_module::async_reset_signal_is( const sc_out& port, bool level ) +{ + sc_reset::reset_signal_is(true, port, level); +} + +void +sc_module::async_reset_signal_is(const sc_signal_in_if& 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& port, bool level ) +{ + sc_reset::reset_signal_is(false, port, level); +} + +void +sc_module::reset_signal_is( const sc_inout& port, bool level ) +{ + sc_reset::reset_signal_is(false, port, level); +} + +void +sc_module::reset_signal_is( const sc_out& port, bool level ) +{ + sc_reset::reset_signal_is(false, port, level); +} + +void +sc_module::reset_signal_is( const sc_signal_in_if& 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 sc_in; +template class sc_inout; +template 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& 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& port, bool level ); + void async_reset_signal_is( const sc_inout& port, bool level ); + void async_reset_signal_is( const sc_out& port, bool level ); + void async_reset_signal_is( const sc_signal_in_if& iface, bool level); + void reset_signal_is( const sc_in& port, bool level ); + void reset_signal_is( const sc_inout& port, bool level ); + void reset_signal_is( const sc_out& port, bool level ); + void reset_signal_is( const sc_signal_in_if& 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& s ) + { ::sc_core::at_posedge( s, simcontext() ); } + + void at_posedge( const sc_signal_in_if& s ) + { ::sc_core::at_posedge( s, simcontext() ); } + + void at_negedge( const sc_signal_in_if& s ) + { ::sc_core::at_negedge( s, simcontext() ); } + + void at_negedge( const sc_signal_in_if& 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* 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 +// class B : public sc_module; +// template +// class A : public B + +#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 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 + +#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 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::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( 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 + +#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 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 +#include +#include +#include +#include +#include + +#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:: 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& get_child_events() const + { return m_child_events; } + + virtual const std::vector& 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 m_child_events; // list of child events. + std::vector 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(obj); + if( !scope_ ) + scope_ = dynamic_cast(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 +#include +#include +#include +#include +#include // 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 +#include + +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 instance_table_t; + typedef std::vector 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 +#include + +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* 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 + +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 storage_type; + typedef std::vector 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 + +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_process_handle::empty_event_vector; +std::vector 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( this ); + e.add_static( thread_h ); + break; + case SC_METHOD_PROC_: + method_h = SCAST( 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(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::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(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(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( 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( 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 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(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(m_target_p); +} + +//------------------------------------------------------------------------------ +//"sc_process_handle::sc_method_handle" +// +//------------------------------------------------------------------------------ +sc_process_handle::operator sc_method_handle() +{ + return DCAST(m_target_p); +} + +//------------------------------------------------------------------------------ +//"sc_process_handle::sc_thread_handle" +// +//------------------------------------------------------------------------------ +sc_process_handle::operator sc_thread_handle() +{ + return DCAST(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 +#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(&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 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::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 - 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 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 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 +class sc_throw_it : public sc_throw_it_helper +{ + typedef sc_throw_it 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& 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 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 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_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& get_child_events() const; + inline const std::vector& 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 + 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 empty_event_vector; // If m_target_p == 0. + static std::vector 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(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_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_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, in sc_process.h, for why. +// +// Arguments: +// exception = exception to be thrown +// descendants = indication of whether descendant processes should also +// receive the throw. +//------------------------------------------------------------------------------ +template +inline void sc_process_handle::throw_it( const EXCEPT& exception, + sc_descendant_inclusion_info descendants) +{ + sc_throw_it 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 +// 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* port_p, bool level, + sc_process_b* target_p); + sc_reset_finder( bool async, const sc_inout* port_p, bool level, + sc_process_b* target_p); + sc_reset_finder( bool async, const sc_out* 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* m_in_p; // Port for which reset is needed. + const sc_inout* m_inout_p; // Port for which reset is needed. + const sc_out* 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* 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* 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* 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::size_type process_i; // index of process resetting. + std::vector::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* 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*>( + now_p->m_in_p->get_interface()); + } + else if ( now_p->m_inout_p ) + { + iface_p = DCAST*>( + now_p->m_inout_p->get_interface()); + } + else + { + iface_p = DCAST*>( + 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 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 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& port, bool level) +{ + const sc_signal_in_if* 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*>(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& port, bool level ) +{ + const sc_signal_in_if* 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*>(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& port, bool level ) +{ + const sc_signal_in_if* 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*>(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 whose interface has been supplied. If no +// sc_reset object instance has been attached to the sc_signal 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& 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 class sc_signal_in_if; +template class sc_signal; +template class sc_in; +template class sc_inout; +template class sc_out; +template 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; + friend class sc_signal; + friend class sc_signal; + friend class sc_simcontext; + template 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& iface, + bool level); + static void + reset_signal_is( bool async, const sc_in& iface, bool level); + static void + reset_signal_is( bool async, const sc_inout& iface, bool level); + static void + reset_signal_is( bool async, const sc_out& iface, bool level); + + protected: + sc_reset( const sc_signal_in_if* iface_p ) : + m_iface_p(iface_p), m_targets() {} + void notify_processes(); + void remove_process( sc_process_b* ); + + protected: + const sc_signal_in_if* m_iface_p; // Interface to read. + std::vector 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( handle_ ); +} + +static +sc_thread_handle +as_thread_handle( sc_process_b* handle_ ) +{ + return DCAST( 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 sc_in; +template class sc_inout; +template 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 in_if_b_type; + typedef sc_signal_in_if in_if_l_type; + typedef sc_in in_port_b_type; + typedef sc_in in_port_l_type; + typedef sc_inout inout_port_b_type; + typedef sc_inout 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 in_if_b_type; + typedef sc_signal_in_if in_if_l_type; + typedef sc_in in_port_b_type; + typedef sc_in in_port_l_type; + typedef sc_inout inout_port_b_type; + typedef sc_inout 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 in_if_b_type; + typedef sc_signal_in_if in_if_l_type; + typedef sc_in in_port_b_type; + typedef sc_in in_port_l_type; + typedef sc_inout inout_port_b_type; + typedef sc_inout 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 + +#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( p1 ); + const sc_event_timed* et2 = static_cast( 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::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 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( 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( m_object_manager->hierarchy_pop() ); +} + +sc_module* +sc_simcontext::hierarchy_curr() const +{ + return static_cast( 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_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_get_current_process_b()); + active_thread_h = DCAST(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(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(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 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::size_type i=0, n=bits.size(); + if ( n>1 ) + os << "("; + for( ; i1 ) + 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_get_top_level_events( + const sc_simcontext* simc_p); +const std::vector& 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_get_top_level_events( + const sc_simcontext* simc_p); + friend const std::vector& 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& 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& 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& get_child_events_internal() const; + const ::std::vector& 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 m_active_invokers; + + std::vector m_child_events; + std::vector m_child_objects; + + std::vector m_delta_events; + sc_ppq* m_timed_events; + + std::vector 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_get_top_level_events( + const sc_simcontext* simc_p = sc_get_curr_simcontext() ) +{ + return simc_p->m_child_events; +} + +inline +const std::vector& 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::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_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* 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_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_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 +// +// 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 +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 +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* spawn_p; + + context_p = sc_get_curr_simcontext(); + spawn_p = new sc_spawn_object(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,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,semantics), + spawn_p, opt_p + ); + return method_handle; + } +} + +//============================================================================= +// CLASS sc_spawn_object_v for all compilers except HP aCC +// or +// CLASS sc_spawn_object_v 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 +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 +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* spawn_p; + + context_p = sc_get_curr_simcontext(); + + spawn_p = new sc_spawn_object_v(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,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,semantics), + spawn_p, opt_p + ); + return method_handle; + } +} + +#else +// for HP aCC +template +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 +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* spawn_p; + + context_p = sc_get_curr_simcontext(); + + spawn_p = new sc_spawn_object_v(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_spawn_object_v::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_spawn_object_v::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 +// | - Reset specification for sc_spawn_options. +// +====================================================================== +template +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::size_type resets_n = m_resets.size(); + for ( std::vector::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 ) +SC_DEFINE_RESET_SIGNALS( sc_inout ) +SC_DEFINE_RESET_SIGNALS( sc_out ) +SC_DEFINE_RESET_SIGNALS( sc_signal_in_if ) + +#undef SC_DEFINE_RESET_SIGNALS + +void +sc_spawn_options::specify_resets() const +{ + std::vector::size_type resets_n; // number of reset specifications to process. + resets_n = m_resets.size(); + for ( std::vector::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 +#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 level ); + void async_reset_signal_is( const sc_inout&, bool level ); + void async_reset_signal_is( const sc_out&, bool level ); + void async_reset_signal_is( const sc_signal_in_if&, bool level ); + + void reset_signal_is( const sc_in&, bool level ); + void reset_signal_is( const sc_inout&, bool level ); + void reset_signal_is( const sc_out&, bool level ); + void reset_signal_is( const sc_signal_in_if&, 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 m_resets; + std::vector m_sensitive_events; + std::vector m_sensitive_event_finders; + std::vector m_sensitive_interfaces; + std::vector 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 + +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( 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& 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(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& 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(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 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(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& 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(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(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& 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(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(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 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(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 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(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 +#include + +#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( 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( 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( tmp ); + } else { + // linux bug workaround; don't change next two lines + volatile double tmp = v + 0.5; + m_value = SCAST( 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( 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( 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( 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( 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( 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( 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 +#include + +#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 + +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( 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( cpi->process_handle )->wait( e ); + break; + } + case SC_CTHREAD_PROC_: { + warn_cthread_wait(); + sc_cthread_handle cthread_h = + RCAST( 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( 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( 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( cpi->process_handle )->wait( el ); + break; + } + case SC_CTHREAD_PROC_: { + warn_cthread_wait(); + sc_cthread_handle cthread_h = + RCAST( 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( cpi->process_handle )->wait( t ); + break; + } + case SC_CTHREAD_PROC_: { + warn_cthread_wait(); + sc_cthread_handle cthread_h = + RCAST( 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( cpi->process_handle )->wait( t, e ); + break; + } + case SC_CTHREAD_PROC_: { + warn_cthread_wait(); + sc_cthread_handle cthread_h = + RCAST( 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( cpi->process_handle )->wait( t, el ); + break; + } + case SC_CTHREAD_PROC_: { + warn_cthread_wait(); + sc_cthread_handle cthread_h = + RCAST( 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( cpi->process_handle )->wait( t, el ); + break; + } + case SC_CTHREAD_PROC_: { + warn_cthread_wait(); + sc_cthread_handle cthread_h = + RCAST( 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( 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( 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( 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( 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( 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( 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( 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( 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( 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( 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& 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& 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& 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& 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&, + sc_simcontext* = sc_get_curr_simcontext() ); + +extern +void +at_posedge( const sc_signal_in_if&, + sc_simcontext* = sc_get_curr_simcontext() ); + +extern +void +at_negedge( const sc_signal_in_if&, + sc_simcontext* = sc_get_curr_simcontext() ); + +extern +void +at_negedge( const sc_signal_in_if&, + 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 +. It is part of the ELiTE +(Erlangen Lightweight Thread Environment) project directed by +Frank Bellosa 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 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 + <> + + 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" + +>[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 +#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 +#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 + | fixed arguments (must be allocated; may remain unused) + | + | + | + | frame marker + | + | + | + | + | + | + | + +--- + | 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)> + | fixed arguments (must be allocated; may remain unused) + | + | + | + | frame marker + | + | + | + | + | + | + | + +--- <--- 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 +# +# +# 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 +# +# +# 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 +#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 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 + | save area req'd by MIPS calling convention + | save area req'd by MIPS calling convention + | save area req'd by MIPS calling convention + | 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' + | + | + | + | <--- 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 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 +December 2002 + + + * This software is largely based on the original PowerPC-Linux porting + * developed by Ken Aaker + * + * Marco Bucci + * 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 +#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 + * 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 + + * + + * Marco Bucci + + * 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 + * + * Marco Bucci + * 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 +#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 */ + +/* 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 + + * + + * Marco Bucci + + * 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 + * + * Marco Bucci + * 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 +#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 */ + +/* 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: + + +--- + | + | %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 + +--- + | + | %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 */ + + .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 + | + | 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 + | + | 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 +#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 /* For varargs tryout. */ +#include +#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; i0) { + /* 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; itop, 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; itop, 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 + + +/* 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 +#include + +#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& 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& 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& 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& 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 + +#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 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 +inline +void +sc_trace( sc_trace_file* tf, + const sc_signal_in_if& 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& 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& object, + const std::string& name, + int width ); + +void sc_trace( sc_trace_file* tf, + const sc_signal_in_if& object, + const std::string& name, + int width ); + +void sc_trace( sc_trace_file* tf, + const sc_signal_in_if& object, + const std::string& name, + int width ); + +void sc_trace( sc_trace_file* tf, + const sc_signal_in_if& 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 + +#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 + +// 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 +#include +#include + +#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 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 vcd_sc_bv_trace; +typedef vcd_T_trace 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 compdata(1024), rawdata(1024); + typedef std::vector::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( sz ).swap( compdata ); // resize without copying values + std::vector( 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 compdata(1024), rawdata(1024); + typedef std::vector::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( sz ).swap( compdata ); // resize without copying values + std::vector( 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 compdata(1024), rawdata(1024); + typedef std::vector::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( sz ).swap( compdata ); // resize without copying values + std::vector( 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 compdata(1024), rawdata(1024); + typedef std::vector::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( sz ).swap( compdata ); // resize without copying values + std::vector( 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(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 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 + 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( 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 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 +#include + +#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(-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(-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 buf(1024); + typedef std::vector::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( 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 buf(1024); + typedef std::vector::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( 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 buf(1024); + typedef std::vector::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( 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 buf(1024); + typedef std::vector::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( 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 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 wif_sc_bv_trace; +typedef wif_T_trace 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(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 +#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 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 + void traceT(const T& object, const std::string& name, wif_enum type) + { + if( add_trace_check(name) ) + traces.push_back( new wif_T_trace( 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 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 +#include // duplicate (c)stdlib.h headers for Solaris +#include +#include +#include + +#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(((uintptr_t)(p) >> 2) * 2654435789U); + +} + +unsigned +default_int_hash_fn(const void* p) +{ + return static_cast((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 //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; + +public: + typedef sc_phash_iter 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* b) { sc_phash_base::copy(b); } + void copy(const sc_phash& b) { sc_phash_base::copy(b); } + void copy(const sc_phash& 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* t) : sc_phash_base_iter(t) { } + sc_phash_iter(sc_phash& t) : sc_phash_base_iter(t) { } + ~sc_phash_iter() { } + + void reset(sc_phash* t) { sc_phash_base_iter::reset(t); } + void reset(sc_phash& 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; + +private: + void* (*kdup)(const void*); //eliminated braces around void* -- Amit + void (*kfree)(void*); + +public: + typedef sc_pdhash_iter 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& 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* t) : sc_phash_base_iter(t) { } + sc_pdhash_iter(sc_pdhash& t) : sc_phash_base_iter(t) { } + ~sc_pdhash_iter() { } + + void reset(sc_pdhash* t) { sc_phash_base_iter::reset(t); } + void reset(sc_pdhash& t) { sc_phash_base_iter::reset(t); } + + void remove() { sc_phash_base_iter::remove(((sc_pdhash*) 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; + +public: + typedef sc_strhash_iter 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* b) { sc_phash_base::copy(*b, sc_strhash_kdup, sc_strhash_kfree); } + void copy(const sc_strhash& 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 sc_strhash_iter : public sc_phash_base_iter { +public: + sc_strhash_iter ( sc_strhash* t ) : sc_phash_base_iter(t) { } + sc_strhash_iter ( sc_strhash& t ) : sc_phash_base_iter(t) { } + ~sc_strhash_iter() { } + + void reset ( sc_strhash* t ) { sc_phash_base_iter::reset(t); } + void reset ( sc_strhash& 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 +#include +#include +#include +#include +#include + +// 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 +#include + +#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 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 ; + +public: + typedef sc_plist_iter 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* l, bool from_tail = false ) + : sc_plist_base_iter( l, from_tail ) + { + + } + sc_plist_iter( sc_plist& l, bool from_tail = false ) + : sc_plist_base_iter( &l, from_tail ) + { + + } + ~sc_plist_iter() + { + + } + + void reset( sc_plist* l, bool from_tail = false ) + { + sc_plist_base_iter::reset( l, from_tail ); + } + void reset( sc_plist& 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 +//#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 + *****************************************************************************/ + + + + +// is a class that manages the memory for small objects, +// of sizes , 2 * , ..., * +// . When a memory request of bytes is made through +// the memory pool, the smallest pool such that * +// >= is used. The default values of and +// 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 +#include // duplicate (c)stdlib.h headers for Solaris +#include +#include "sysc/utils/sc_mempool.h" + +namespace sc_core { + +// An allocator is one that handles a particular size. It keeps a +// from which a cell may be allocated quickly if there +// is one available. If no cell is available from , then +// the allocator tries to find whether space is available from the +// most-recently-allocated block, as pointed to by . If +// so, then the cell pointed to by is returned, while +// is advanced. If now points beyond +// the current block, then it's reset to 0. On the other hand, +// if 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 . + + +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 + +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 +// +// 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 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 + +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 +// +// Simple vector class. +// ---------------------------------------------------------------------------- + +template< class T > +class sc_pvector +{ +public: + + typedef const T* const_iterator; + typedef T* iterator; + // typedef typename ::std::vector::const_iterator const_iterator; + // typedef typename ::std::vector::iterator iterator; + + sc_pvector( int alloc_n = 0 ) + { + } + + sc_pvector( const sc_pvector& 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 (ADDR_ACCESS(m_vector.size())); } + + const_iterator end() const + { + return static_cast (ADDR_ACCESS(m_vector.size())); + } + + + sc_pvector& operator = ( const sc_pvector& 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& () 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 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 +#include + +#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 // 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 +#include + +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 +#include +#include + +#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 +#include +#include +#include +#include + +#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=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 && istr[i++]==c; + return found; +} + +sc_string_old +sc_string_old::uppercase()const +{ + int len = length(); + sc_string_old temp(*this); + for(int i=0; istr[i]; + if(c>='a' && c<='z') + temp.rep->str[i] = static_cast( c-32 ); + } + return temp; +} + +sc_string_old +sc_string_old::lowercase()const +{ + int len = length(); + sc_string_old temp(*this); + for(int i=0; istr[i]; + if(c>='A' && c<='Z') + temp.rep->str[i] = static_cast( 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 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 // 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 - 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 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 sc_vpool::sc_vpool( int log2, T* pool_p ) + : m_pool_i( 0 ) + , m_pool_p( pool_p ? pool_p : new T[static_cast(1) << log2] ) + , m_wrap( ~(static_cast(-1) << log2) ) +{ + // if ( log2 > 32 ) SC_REPORT_ERROR(SC_ID_POOL_SIZE_, ""); +} + +template sc_vpool::~sc_vpool() +{ + // delete [] m_pool_p; +} + +template T* sc_vpool::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 void sc_vpool::reset() +{ + m_pool_i = 0; +} + +template std::size_t sc_vpool::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 +#include + +#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 and 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 + +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() : "" ) + << ", got " + << ( parent_p ? parent_p->name() : "" ); + + 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 +#include +#include +#include // std::swap + +#include "sysc/kernel/sc_object.h" +#include + +//#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::type + , typename remove_const::type + >::value + && ( is_const::value >= is_const::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 friend class sc_vector_assembly; + template 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 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 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 + sc_direct_access(const U&, + typename sc_meta::enable_if::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 plain_type; + typedef typename sc_meta::remove_const::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 > +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::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 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::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& it + , typename sc_meta::enable_if::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(*it_) ); } + pointer operator->() const + { return access_policy::get( static_cast(*it_) ); } + reference operator[]( difference_type n ) const + { return *access_policy::get( static_cast(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 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( 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( 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 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 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 assemble( MT (T::*member_ptr) ) + { return sc_vector_assembly( *this, member_ptr ); } + +protected: + + void clear(); + + virtual sc_object* object_cast( void* p ) const + { return implicit_cast( static_cast(p) ); } + +}; + +template< typename T, typename MT > +class sc_vector_assembly +{ + template< typename U > friend class sc_vector; + +public: + + typedef sc_vector base_type; + + typedef sc_vector_iter< T, sc_member_access > iterator; + typedef sc_vector_iter< const T + , sc_member_access > 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 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 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 +sc_assemble_vector( sc_vector & vec, MT (T::*ptr) ) +{ + return vec.assemble( ptr ); +} + +template< typename T > +typename sc_vector::element_type * +sc_vector::create_element( const char* name, size_type /* idx */ ) +{ + return new T( name ); +} + +template< typename T > +template< typename Creator > +void +sc_vector::init( size_type n, Creator c ) +{ + if ( base_type::check_init(n) ) + { + base_type::reserve( n ); + try + { + for ( size_type i = 0; i +void +sc_vector::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::~sc_vector() +{ + clear(); +} + +template< typename T, typename MT > +std::vector< sc_object* > const & +sc_vector_assembly::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(&*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 +#include +#include // math.h? +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if defined(__sun) || defined(__sun__) +# include +#elif !defined(WIN32) && !defined(_WIN32) +# include +#endif +#include +#include +#include + +// 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 : + + 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 : + + 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 : + + 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 + + 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 // 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( nm , -16 ) {} + tlm_analysis_fifo() : tlm_fifo( -16 ) {} + + void write( const tlm_analysis_triple &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 +{ +}; + +template < typename T > +class tlm_delayed_analysis_if : public virtual tlm_delayed_write_if +{ +}; + +} // 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 +#include + +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 &_if ) { + m_interfaces.push_back( &_if ); + } + + void operator() ( tlm_analysis_if &_if ) { bind( _if ); } + + virtual bool unbind( tlm_analysis_if &_if ) { + + typename std::deque< tlm_analysis_if * >::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 * >::iterator i; + + for( i = m_interfaces.begin(); + i != m_interfaces.end(); + i++ ) { + + (*i)->write( t ); + + } + + } + + private: + std::deque< tlm_analysis_if * > 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 + +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 + +namespace tlm { + +template +class tlm_write_if : public virtual sc_core::sc_interface { +public: + virtual void write(const T& t) = 0; +}; + +template +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 + +#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 = 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 = 0 ) const = 0; + virtual const sc_core::sc_event &ok_to_get( tlm_tag *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 = 0 ) const = 0; + virtual const sc_core::sc_event &ok_to_put( tlm_tag *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 = 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 = 0 ) const = 0; + virtual const sc_core::sc_event &ok_to_peek( tlm_tag *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 , + public virtual tlm_blocking_peek_if {}; + +template < typename T > +class tlm_nonblocking_get_peek_if : + public virtual tlm_nonblocking_get_if , + public virtual tlm_nonblocking_peek_if {}; + + +template < typename T > +class tlm_get_peek_if : + public virtual tlm_get_if , + public virtual tlm_peek_if , + public virtual tlm_blocking_get_peek_if , + public virtual tlm_nonblocking_get_peek_if + {}; + +} // 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 , + public virtual tlm_fifo_debug_if {}; + +template < typename T > +class tlm_fifo_get_if : + public virtual tlm_get_peek_if , + public virtual tlm_fifo_debug_if {}; + +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 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 + +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 &b ); // disabled + circular_buffer &operator=( const circular_buffer & ); // 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::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::circular_buffer( int size ) + : m_size(size) + , m_buf(0) +{ + init(); + +} + +template < typename T > +void +circular_buffer::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::~circular_buffer() +{ + clear(); + buf_free( m_buf ); +} + +template < typename T > +void +circular_buffer::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::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::read() +{ + T t = read_data(); + + buf_clear( m_buf, m_ri ); + increment_read_pos(); + + return t; +} + +template < typename T > +void +circular_buffer::write( const T &t ) +{ + buf_write( m_buf, m_wi, t ); + increment_write_pos(); +} + + +template < typename T > +void +circular_buffer::increment_write_pos( int i ) { + + m_wi = ( m_wi + i ) % m_size; + m_used += i; + m_free -= i; + +} + +template < typename T > +void +circular_buffer::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::buf_alloc( int size ) + { return new unsigned char[ size * sizeof(T) ]; } + +template < typename T > +inline void +circular_buffer::buf_free( void* & buf ) + { delete [] static_cast(buf); buf = 0; } + +template < typename T > +inline void +circular_buffer::buf_write( void* buf, int n, const T & t ) +{ + T* p = static_cast(buf) + n; + new (p) T(t); +} + +template < typename T > +inline T& +circular_buffer::buf_read( void* buf, int n ) const +{ + T* p = static_cast(buf) + n; + return *p; +} + +template < typename T > +inline void +circular_buffer::buf_clear( void* buf, int n ) +{ + T* p = static_cast(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 + +#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 +class tlm_fifo : + public virtual tlm_fifo_get_if, + public virtual tlm_fifo_put_if, + 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 * = 0 ); + + bool nb_get( T& ); + bool nb_can_get( tlm_tag * = 0 ) const; + const sc_core::sc_event &ok_to_get( tlm_tag * = 0 ) const { + return m_data_written_event; + } + + // tlm peek interface + + T peek( tlm_tag * = 0 ) const; + + bool nb_peek( T& ) const; + bool nb_can_peek( tlm_tag * = 0 ) const; + const sc_core::sc_event &ok_to_peek( tlm_tag * = 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 * = 0 ) const; + + const sc_core::sc_event& ok_to_put( tlm_tag * = 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 * = 0 ) { + return m_data_read_event; + } + +protected: + + void update(); + + // support methods + + void init( int ); + +protected: + + circular_buffer 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& ); + tlm_fifo& operator = ( const tlm_fifo& ); + + // + // 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 +const char* const tlm_fifo::kind_string = "tlm_fifo"; + + +/****************************************************************** +// +// init and update +// +******************************************************************/ + +template< typename T > +inline +void +tlm_fifo::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::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::peek( tlm_tag * ) 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::nb_peek( T &t ) const { + + if( used() < 1 ) { + return false; + } + + t = buffer.peek_data( 0 ); + return true; + +} + +template < typename T> +inline +bool +tlm_fifo::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::nb_can_peek( tlm_tag * ) const +{ + return !is_empty(); +} + +template < typename T> +inline +bool +tlm_fifo::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 +inline +T +tlm_fifo::get( tlm_tag * ) +{ + + while( is_empty() ) { + wait( m_data_written_event ); + } + + m_num_read ++; + request_update(); + + return buffer.read(); + +} + +// non-blocking read + +template +inline +bool +tlm_fifo::nb_get( T& val_ ) +{ + + if( is_empty() ) { + return false; + } + + m_num_read ++; + request_update(); + + val_ = buffer.read(); + + return true; + +} + +template +inline +bool +tlm_fifo::nb_can_get( tlm_tag * ) const { + + return !is_empty(); + +} + + +/****************************************************************** +// +// put interface +// +******************************************************************/ + +template +inline +void +tlm_fifo::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 +inline +bool +tlm_fifo::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::nb_can_put( tlm_tag * ) 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::nb_expand( unsigned int n ) { + + if( m_size >= 0 ) { + m_expand = true; + m_size += n; + request_update(); + } +} + +template < typename T> +inline +void +tlm_fifo::nb_unbound( unsigned int n ) { + + m_expand = true; + m_size = -n; + + if( buffer.size() < static_cast( n ) ) { + buffer.resize( n ); + } + + request_update(); + +} + +template < typename T> +inline +bool +tlm_fifo::nb_reduce( unsigned int n ) { + + if( m_size < 0 ) { + return false; + } + + return nb_bound( size() - n ); + +} + +template < typename T> +inline +bool +tlm_fifo::nb_bound( unsigned int new_size ) { + + bool ret = true; + + if( static_cast( 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 &p , + tlm_get_peek_if &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 *t = 0 ) const { + return put_fifo.nb_can_put( t ); + } + const sc_core::sc_event &ok_to_put( tlm_tag *t = 0 ) const { + return put_fifo.ok_to_put( t ); + } + + // get interface + + GET_DATA get( tlm_tag * = 0 ) { return get_fifo.get(); } + + bool nb_get( GET_DATA &t ) { return get_fifo.nb_get( t ); } + + bool nb_can_get( tlm_tag *t = 0 ) const { + return get_fifo.nb_can_get( t ); + } + + virtual const sc_core::sc_event &ok_to_get( tlm_tag *t = 0 ) const { + return get_fifo.ok_to_get( t ); + } + + // peek interface + + GET_DATA peek( tlm_tag * = 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 *t = 0 ) const { + return get_fifo.nb_can_peek( t ); + } + + virtual const sc_core::sc_event &ok_to_peek( tlm_tag *t = 0 ) const { + return get_fifo.ok_to_peek( t ); + } + +private: + tlm_put_if &put_fifo; + tlm_get_peek_if &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 , + tlm_get_peek_if &rsp ) : + tlm_put_get_imp( 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 , + tlm_put_if &rsp ) : + tlm_put_get_imp( 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 , + typename RSP_CHANNEL = tlm_fifo > + +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 , + typename RSP_CHANNEL = tlm_fifo > +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 + +#include "tlm_core/tlm_1/tlm_req_rsp/tlm_1_interfaces/tlm_tag.h" + +namespace tlm { + +template +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 * ) 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 * ) const; + +private: + + // disabled + tlm_event_finder_t(); + tlm_event_finder_t( const tlm_event_finder_t& ); + tlm_event_finder_t& operator = ( const tlm_event_finder_t& ); +}; + + +#if !(defined SYSTEMC_VERSION & SYSTEMC_VERSION <= 20050714) +template +inline +const sc_core::sc_event& +tlm_event_finder_t::find_event( sc_core::sc_interface* if_p ) const +{ + const IF* iface = ( if_p ) ? dynamic_cast( if_p ) : + dynamic_cast( port().get_interface() ); + if( iface == 0 ) { + report_error( sc_core::SC_ID_FIND_EVENT_, "port is not bound" ); + } + return (const_cast( iface )->*m_event_method) ( 0 ); +} +#else +template +inline +const sc_core::sc_event& +tlm_event_finder_t::find_event() const +{ + const IF* iface = dynamic_cast( port().get_interface() ); + if( iface == 0 ) { + report_error( sc_core::SC_ID_FIND_EVENT_, "port is not bound" ); + } + return (const_cast( 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 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 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 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 + +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 +#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 +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 +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 +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 +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 +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 +class tlm_fw_transport_if + : public virtual tlm_fw_nonblocking_transport_if + , public virtual tlm_blocking_transport_if + , public virtual tlm_fw_direct_mem_if + , public virtual tlm_transport_dbg_if +{}; + +// The backward interface: +template +class tlm_bw_transport_if + : public virtual tlm_bw_nonblocking_transport_if + , 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 +#include +// unused for the time being: #include + +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 +class tlm_array + : private std::vector +{ + typedef std::vector 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 m_entries; + T m_default; + + // disabled: + tlm_array& operator=(const tlm_array&); +}; + + +template +const char* const tlm_array::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 +#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 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 { + 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(); + 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 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 D tlm_bool::TLM_TRUE + = tlm_bool::make_uchar_array(TLM_BYTE_ENABLED); +template D tlm_bool::TLM_FALSE + = tlm_bool::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 +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 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(); + loop_generic0(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 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); + 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(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(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(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(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 +inline void copy_d1(uchar *src1, uchar *src2, uchar *dest1, uchar *dest2) { + *((D *)dest1) = *((D *)src1); + *((D *)dest2) = tlm_bool::TLM_TRUE; +} + +template +inline void copy_db1(uchar *src1, uchar *src2, uchar *dest1, uchar *dest2) { + *((D *)dest1) = *((D *)src1); + *((D *)dest2) = *((D *)src2); +} + +template +inline void true_b1(uchar *src1, uchar *src2, uchar *dest1, uchar *dest2) { + *((D *)dest2) = tlm_bool::TLM_TRUE; +} + +template +inline void copy_b1(uchar *src1, uchar *src2, uchar *dest1, uchar *dest2) { + *((D *)dest2) = *((D *)src2); +} + +template +inline void copy_dbyb1(uchar *src1, uchar *src2, uchar *dest1, uchar *dest2) { + if(*src2 != TLM_BYTE_DISABLED) *((D *)src1) = *((D *)dest1); +} + +template +inline void copy_dbytrue1(uchar *src1, uchar *src2, uchar *dest1, uchar *dest2) { + *((D *)src1) = *((D *)dest1); +} + +template inline void false_b1(uchar *dest1) { + *((D *)dest1) = tlm_bool::TLM_FALSE; +} + +template inline void no_b1(uchar *dest1) { +} + +template +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= 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 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(); + sc_dt::uint64 b_mask = sizeof_databus - 1; + int d_mask = sizeof(DATAWORD) - 1; + int a_offset = static_cast(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, + ©_dbytrue1, &no_b1, &no_b1 >( + tc->length, len0, lenN, sizeof_databus, d_start, d_end, d, + 0, txn->get_data_ptr(), 0); + } else { + loop_word1, + ©_dbyb1, &no_b1, &no_b1 >( + 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 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); + 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(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, + &true_b1, &false_b1, &false_b1 >( + 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, + ©_b1, &false_b1, &false_b1 >( + 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, + ©_d1, &false_b1, &false_b1 >( + 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, + ©_db1, &false_b1, &false_b1 >( + 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 inline void copy_d2(D *src1, D *src2, D *dest1, D *dest2) { + *dest1 = *src1; +} + +template inline void copy_db2(D *src1, D *src2, D *dest1, D *dest2) { + *dest1 = *src1; + *dest2 = *src2; +} + +template +inline void copy_dbyb2(D *src1, D *src2, D *dest1, D *dest2) { + if(tlm_bool(*src2)) *dest1 = *src1; +} + +template +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 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(); + + 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 *)(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 *)(txn->get_data_ptr()), + (DATAWORD *)(txn->get_byte_enable_ptr()), + (DATAWORD *)(tc->data_ptr), 0, words, words_per_bus); + } + } +} + + +/////////////////////////////////////////////////////////////////////////////// +// function set (2): Request +template 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); + 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 >(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 >(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 >(original_be, 0, + (DATAWORD *)(txn->get_byte_enable_ptr()), 0, + words, words_per_bus); + } + } +} + + + +/////////////////////////////////////////////////////////////////////////////// +// function set (3): Response +template 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 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); + 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(); + (*(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 +#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 { ... +// 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 +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 +const +unsigned int tlm_extension::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; iclone(); + 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(&m_data[i]) &= ~*reinterpret_cast(m_byte_enable); + *reinterpret_cast(&m_data[i]) |= *reinterpret_cast(&other.m_data[i]) & + *reinterpret_cast(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(&m_data[i]) &= ~*reinterpret_cast(m_byte_enable); + *reinterpret_cast(&m_data[i]) |= *reinterpret_cast(&other.m_data[i]) & + *reinterpret_cast(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; icopy_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; ifree(); + m_extensions[i] = 0; + } + } + } + //-------------- + // Destructor + //-------------- + virtual ~tlm_generic_payload() { + for(unsigned int i=0; ifree(); + } + + //---------------- + // 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 { ... } */ + /* */ + /* - 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 T* set_extension(T* ext) + { + return static_cast(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 T* set_auto_extension(T* ext) + { + return static_cast(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 void get_extension(T*& ext) const + { + ext = get_extension(); + } + template T* get_extension() const + { + return static_cast(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 void clear_extension(const T* ext) + { + clear_extension(); + } + + //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 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 void release_extension(T* ext) + { + release_extension(); + } + + //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 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(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(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 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 +//#include + +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 +#include +#include + +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& get_phase_name_vec(){ + static std::vector 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< + +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 +#include "tlm_core/tlm_2/tlm_2_interfaces/tlm_fw_bw_ifs.h" + +namespace tlm { + + +template , + 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 & get_base_port() = 0; + virtual sc_core::sc_port_b 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 & get_base_export() = 0; + virtual sc_core::sc_export const & get_base_export() const = 0; +}; + + +template class tlm_base_target_socket_b; + +template class tlm_base_target_socket; + +template , + 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, + public sc_core::sc_port + +{ +public: + typedef FW_IF fw_interface_type; + typedef BW_IF bw_interface_type; + typedef sc_core::sc_port port_type; + + typedef sc_core::sc_export export_type; + + typedef tlm_base_target_socket_b base_target_socket_type; + typedef tlm_base_initiator_socket_b base_type; + + template + 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 & get_base_port() + { return *this; } + virtual sc_core::sc_port_b 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(m_export); } +#else + { return m_export; } +#endif + + virtual sc_core::sc_export & get_base_export() + { return m_export; } + virtual sc_core::sc_export const & get_base_export() const + { return m_export; } + +protected: + export_type m_export; +}; + +// +// Convenience socket classes +// + +template +class tlm_initiator_socket : + public tlm_base_initiator_socket , + tlm_bw_transport_if, + N +#if !(defined SYSTEMC_VERSION & SYSTEMC_VERSION <= 20050714) + ,POL +#endif + > +{ +public: + tlm_initiator_socket() : + tlm_base_initiator_socket, + tlm_bw_transport_if, + N +#if !(defined SYSTEMC_VERSION & SYSTEMC_VERSION <= 20050714) + ,POL +#endif + >() + { + } + + explicit tlm_initiator_socket(const char* name) : + tlm_base_initiator_socket, + tlm_bw_transport_if, + 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 +#include "tlm_core/tlm_2/tlm_2_interfaces/tlm_fw_bw_ifs.h" + + +namespace tlm { + +template , + 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 & get_base_port() = 0; + virtual sc_core::sc_export & get_base_export() = 0; + virtual FW_IF & get_base_interface() = 0; +}; + +template class tlm_base_initiator_socket_b; + +template class tlm_base_initiator_socket; + +template , + 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, + public sc_core::sc_export +{ +public: + typedef FW_IF fw_interface_type; + typedef BW_IF bw_interface_type; + typedef sc_core::sc_port port_type; + + typedef sc_core::sc_export export_type; + typedef tlm_base_initiator_socket_b base_initiator_socket_type; + + typedef tlm_base_target_socket_b base_type; + + template + 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 & get_base_port() + { return m_port; } + virtual sc_core::sc_port_b 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(static_cast(this)); } +#else + { return *this; } +#endif + + virtual sc_core::sc_export & get_base_export() + { return *this; } + virtual sc_core::sc_export const & get_base_export() const + { return *this; } + +protected: + port_type m_port; +}; + + +// +// Convenience blocking and non-blocking socket classes +// + +template +class tlm_target_socket : + public tlm_base_target_socket , + tlm_bw_transport_if, + N +#if !(defined SYSTEMC_VERSION & SYSTEMC_VERSION <= 20050714) + ,POL +#endif + > +{ +public: + tlm_target_socket() : + tlm_base_target_socket, + tlm_bw_transport_if, + N +#if !(defined SYSTEMC_VERSION & SYSTEMC_VERSION <= 20050714) + ,POL +#endif + >() + { + } + + explicit tlm_target_socket(const char* name) : + tlm_base_target_socket, + tlm_bw_transport_if, + 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 + +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 +class +instance_specific_extension : public ispex_base{ +public: + virtual ~instance_specific_extension() {} + const static unsigned int priv_id; +}; + +template +const +unsigned int instance_specific_extension::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 +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 T* set_extension(T* ext) + { + resize_extensions(); + T* tmp = static_cast(m_extensions[T::priv_id]); + m_extensions[T::priv_id] = static_cast(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 void get_extension(T*& ext) const + { + ext = static_cast(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 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(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(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 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(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; + 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{ + 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 + inline instance_specific_extensions_per_accessor& 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 +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 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& get_base_interface() + { + m_binders.push_back(new callback_binder_bw(m_binders.size())); + return *m_binders[m_binders.size()-1]; + } + + // const overload not allowed for multi-sockets + virtual const tlm::tlm_bw_transport_if& 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 >& 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 >& 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 >* p_ex_s=dynamic_cast >*>(&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* test=dynamic_cast*> (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 >& ex_s=*p_ex_s; + m_sockets.push_back(&((tlm::tlm_fw_transport_if&)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* >& 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; iset_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* 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* >& get_binders(){return m_binders;} + std::vector*>& get_sockets(){return m_sockets;} + //vector of connected sockets + std::vector*> m_sockets; + std::vector*> m_used_sockets; + //vector of binders that convert untagged interface into tagged interface + std::vector*> 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 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::nb_func_type m_nb_f; + typename callback_binder_bw::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 + +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 +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 +{ + +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 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 >::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 * binder; + + if (m_binders.size() == 0) + { + binder = new callback_binder_fw(m_binders.size()); + m_binders.push_back(binder); + m_export_callback_created = true; + } + else + { + binder = m_binders[0]; + } + + sc_core::sc_export >::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& 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(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& 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 >& 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 >& 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* >& binders=get_hierarch_bind()->get_binders(); + std::map*>& multi_binds=get_hierarch_bind()->get_multi_binds(); + + //iterate over all binders + for (unsigned int i=0; iset_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(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* 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*>& get_multi_binds(){return m_multi_binds;} + void set_hierarch_bind(base_type* h){m_hierarch_bind=h;} + tlm::tlm_fw_transport_if* get_last_binder(tlm::tlm_bw_transport_if* 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*> m_multi_binds; + + void disable_cb_bind(){ m_eoe_disabled=true;} + std::vector* >& get_binders(){return m_binders;} + //vector of connected sockets + std::vector*> m_sockets; + //vector of binders that convert untagged interface into tagged interface + std::vector*> 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::nb_func_type m_nb_f; + typename callback_binder_fw::b_func_type m_b_f; + typename callback_binder_fw::debug_func_type m_dbg_f; + typename callback_binder_fw::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 +#include + +#include +#include + +namespace tlm_utils { + +template +struct fn_container{ + signature function; +}; + +#define TLM_DEFINE_FUNCTOR(name) \ +template \ +inline TLM_RET_VAL static_##name( void* mod \ + , void* fn \ + , int index \ + , TLM_FULL_ARG_LIST) \ +{ \ + typedef fn_container fn_container_type; \ + MODULE* tmp_mod=static_cast(mod); \ + fn_container_type* tmp_cb =static_cast (fn); \ + return (tmp_mod->*(tmp_cb->function))(index, TLM_ARG_LIST_WITHOUT_TYPES); \ +}\ +\ +template \ +inline void delete_fn_container_of_##name(void* fn) \ +{ \ + typedef fn_container fn_container_type; \ + fn_container_type* tmp_cb =static_cast (fn); \ + if (tmp_cb) delete tmp_cb;\ +} \ +\ +template \ +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 \ + void set_function(MODULE* mod, TLM_RET_VAL (MODULE::*cb)(int, TLM_FULL_ARG_LIST)){ \ + typedef fn_container fn_container_type; \ + m_fn=&static_##name;\ + m_del_fn=&delete_fn_container_of_##name;\ + m_del_fn(m_mem_fn); \ + fn_container_type* tmp= new fn_container_type(); \ + tmp->function=cb; \ + m_mod=static_cast(mod); \ + m_mem_fn=static_cast(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 +class callback_binder_fw: public tlm::tlm_fw_transport_if{ + 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 nb_func_type; + typedef b_transport_functor b_func_type; + typedef debug_transport_functor debug_func_type; + typedef get_dmi_ptr_functor 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"<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 +class callback_binder_bw: public tlm::tlm_bw_transport_if{ + 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 nb_func_type; + typedef invalidate_dmi_functor 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 +class multi_init_base: public tlm::tlm_initiator_socket{ +public: + //typedef for the base type: the standard tlm initiator socket + typedef tlm::tlm_initiator_socket 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* >& get_binders()=0; + + //this method shall return a vector of all target interfaces bound to this multi init socket + virtual std::vector*>& 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 +class multi_target_base: public tlm::tlm_target_socket{ +public: + //typedef for the base type: the standard tlm target socket + typedef tlm::tlm_target_socket 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* >& 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*>& 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 +class multi_to_multi_bind_base{ +public: + virtual ~multi_to_multi_bind_base(){} + virtual tlm::tlm_fw_transport_if* get_last_binder(tlm::tlm_bw_transport_if*)=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 +#include + +namespace tlm_utils { + +template +class passthrough_target_socket : + public tlm::tlm_target_socket +{ +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 fw_interface_type; + typedef tlm::tlm_bw_transport_if bw_interface_type; + typedef tlm::tlm_target_socket 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::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 + { + 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 +class passthrough_target_socket_tagged : + public tlm::tlm_target_socket +{ +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 fw_interface_type; + typedef tlm::tlm_bw_transport_if bw_interface_type; + typedef tlm::tlm_target_socket 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::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 + { + 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 +#include +#include + +namespace tlm_utils { + +template +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 +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 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 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 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 +//#include +#include + +namespace tlm_utils { + +template +class peq_with_get : public sc_core::sc_object +{ +public: + typedef PAYLOAD transaction_type; + typedef std::pair 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 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 +#include + +namespace tlm_utils { + +template +class simple_initiator_socket : + public tlm::tlm_initiator_socket +{ +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 fw_interface_type; + typedef tlm::tlm_bw_transport_if bw_interface_type; + typedef tlm::tlm_initiator_socket 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 + { + 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 +class simple_initiator_socket_tagged : + public tlm::tlm_initiator_socket +{ +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 fw_interface_type; + typedef tlm::tlm_bw_transport_if bw_interface_type; + typedef tlm::tlm_initiator_socket 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 + { + 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 +#include +#include "tlm_utils/peq_with_get.h" +#include + +namespace tlm_utils { + +template +class simple_target_socket : + public tlm::tlm_target_socket +{ + 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 fw_interface_type; + typedef tlm::tlm_bw_transport_if bw_interface_type; + typedef tlm::tlm_target_socket 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::bind; + + // bw transport must come thru us. + tlm::tlm_bw_transport_if * 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 + { + 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::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, + 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::iterator + it=v.begin(), end = v.end(); it != end; ++it ) + delete *it; + } + + process_handle_class* get_handle(transaction_type *trans) + { + typename std::vector::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 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::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::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(); + assert(ext); + // notif event first before freeing extensions (reset) + ext->done.notify(); + trans->reset(); + } + + private: + struct mm_end_event_ext : public tlm::tlm_extension + { + 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 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 m_pending_trans; + sc_core::sc_event m_end_request; + transaction_type* m_current_transaction; +}; + +//ID Tagged version +template +class simple_target_socket_tagged : + public tlm::tlm_target_socket +{ + 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 fw_interface_type; + typedef tlm::tlm_bw_transport_if bw_interface_type; + typedef tlm::tlm_target_socket 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::bind; + + // bw transport must come thru us. + tlm::tlm_bw_transport_if * 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 + { + 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::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, + 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::iterator + it=v.begin(), end = v.end(); it != end; ++it ) + delete *it; + } + + process_handle_class* get_handle(transaction_type *trans) + { + typename std::vector::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 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::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::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(); + assert(ext); + // notif event first before freeing extensions (reset) + ext->done.notify(); + trans->reset(); + } + + private: + struct mm_end_event_ext : public tlm::tlm_extension + { + 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 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 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 +// 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 +#include + + +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 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 shared_map; + + +// ******************** CLASS DEFINITION ******************** + + +template +class tlm2_base_protocol_checker + +: public sc_core::sc_module +, public tlm::tlm_fw_transport_if +, public tlm::tlm_bw_transport_if +{ +public: + + // Instantiate and bind checker inline between an existing pair of initiator and target sockets + + tlm::tlm_target_socket target_socket; + tlm::tlm_initiator_socket 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 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 \ +void tlm2_base_protocol_checker:: + + +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(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(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