Removed SCV code
This commit is contained in:
parent
96d628d322
commit
79c49e6f1d
|
@ -1,152 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<?fileVersion 4.0.0?><cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage">
|
||||
<storageModule moduleId="org.eclipse.cdt.core.settings">
|
||||
<cconfiguration id="cdt.managedbuild.config.gnu.macosx.exe.debug.133691581">
|
||||
<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="cdt.managedbuild.config.gnu.macosx.exe.debug.133691581" moduleId="org.eclipse.cdt.core.settings" name="Debug">
|
||||
<externalSettings/>
|
||||
<extensions>
|
||||
<extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
<extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
<extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
<extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
<extension id="org.eclipse.cdt.core.MachO64" point="org.eclipse.cdt.core.BinaryParser"/>
|
||||
</extensions>
|
||||
</storageModule>
|
||||
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
|
||||
<configuration artifactName="${ProjName}" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.debug,org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe" cleanCommand="rm -rf" description="" id="cdt.managedbuild.config.gnu.macosx.exe.debug.133691581" name="Debug" parent="cdt.managedbuild.config.gnu.macosx.exe.debug">
|
||||
<folderInfo id="cdt.managedbuild.config.gnu.macosx.exe.debug.133691581." name="/" resourcePath="">
|
||||
<toolChain id="cdt.managedbuild.toolchain.gnu.macosx.exe.debug.500082514" name="MacOSX GCC" superClass="cdt.managedbuild.toolchain.gnu.macosx.exe.debug">
|
||||
<targetPlatform id="cdt.managedbuild.target.gnu.platform.macosx.exe.debug.493103663" name="Debug Platform" superClass="cdt.managedbuild.target.gnu.platform.macosx.exe.debug"/>
|
||||
<builder buildPath="${workspace_loc:/scv_tr_sqlite}/Debug" id="cdt.managedbuild.target.gnu.builder.base.214255941" keepEnvironmentInBuildfile="false" name="Gnu Make Builder" superClass="cdt.managedbuild.target.gnu.builder.base"/>
|
||||
<tool id="cdt.managedbuild.tool.macosx.c.linker.macosx.exe.debug.1022976995" name="MacOS X C Linker" superClass="cdt.managedbuild.tool.macosx.c.linker.macosx.exe.debug"/>
|
||||
<tool command="c++" id="cdt.managedbuild.tool.macosx.cpp.linker.macosx.exe.debug.1153644061" name="MacOS X C++ Linker" superClass="cdt.managedbuild.tool.macosx.cpp.linker.macosx.exe.debug">
|
||||
<option id="macosx.cpp.link.option.paths.33338975" name="Library search path (-L)" superClass="macosx.cpp.link.option.paths" valueType="libPaths">
|
||||
<listOptionValue builtIn="false" value="/Users/eyck//Library/Frameworks/SystemC.framework/Versions/2.3.1/lib-macosx64"/>
|
||||
</option>
|
||||
<option id="macosx.cpp.link.option.libs.1238143593" name="Libraries (-l)" superClass="macosx.cpp.link.option.libs" valueType="libs">
|
||||
<listOptionValue builtIn="false" srcPrefixMapping="" srcRootPath="" value="systemc"/>
|
||||
<listOptionValue builtIn="false" srcPrefixMapping="" srcRootPath="" value="scv"/>
|
||||
</option>
|
||||
<inputType id="cdt.managedbuild.tool.macosx.cpp.linker.input.10448631" superClass="cdt.managedbuild.tool.macosx.cpp.linker.input">
|
||||
<additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
|
||||
<additionalInput kind="additionalinput" paths="$(LIBS)"/>
|
||||
</inputType>
|
||||
</tool>
|
||||
<tool id="cdt.managedbuild.tool.gnu.assembler.macosx.exe.debug.1589927489" name="GCC Assembler" superClass="cdt.managedbuild.tool.gnu.assembler.macosx.exe.debug">
|
||||
<option id="gnu.both.asm.option.include.paths.1741076851" superClass="gnu.both.asm.option.include.paths" valueType="includePath">
|
||||
<listOptionValue builtIn="false" value="/usr/include"/>
|
||||
</option>
|
||||
<inputType id="cdt.managedbuild.tool.gnu.assembler.input.1649108682" superClass="cdt.managedbuild.tool.gnu.assembler.input"/>
|
||||
</tool>
|
||||
<tool id="cdt.managedbuild.tool.gnu.archiver.macosx.base.422966961" name="GCC Archiver" superClass="cdt.managedbuild.tool.gnu.archiver.macosx.base"/>
|
||||
<tool command="c++" id="cdt.managedbuild.tool.gnu.cpp.compiler.macosx.exe.debug.1149501692" name="GCC C++ Compiler" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.macosx.exe.debug">
|
||||
<option id="gnu.cpp.compilermacosx.exe.debug.option.optimization.level.1228519118" name="Optimization Level" superClass="gnu.cpp.compilermacosx.exe.debug.option.optimization.level" value="gnu.cpp.compiler.optimization.level.none" valueType="enumerated"/>
|
||||
<option id="gnu.cpp.compiler.macosx.exe.debug.option.debugging.level.1854731682" name="Debug Level" superClass="gnu.cpp.compiler.macosx.exe.debug.option.debugging.level" value="gnu.cpp.compiler.debugging.level.max" valueType="enumerated"/>
|
||||
<option id="gnu.cpp.compiler.option.include.paths.2045160591" name="Include paths (-I)" superClass="gnu.cpp.compiler.option.include.paths" valueType="includePath">
|
||||
<listOptionValue builtIn="false" value="/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1"/>
|
||||
<listOptionValue builtIn="false" value="/Users/eyck//Library/Frameworks/SystemC.framework/Versions/2.3.1/include"/>
|
||||
<listOptionValue builtIn="false" value="/usr/include"/>
|
||||
</option>
|
||||
<inputType id="cdt.managedbuild.tool.gnu.cpp.compiler.input.506955043" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.input"/>
|
||||
</tool>
|
||||
<tool command="clang" id="cdt.managedbuild.tool.gnu.c.compiler.macosx.exe.debug.1993665797" name="GCC C Compiler" superClass="cdt.managedbuild.tool.gnu.c.compiler.macosx.exe.debug">
|
||||
<option defaultValue="gnu.c.optimization.level.none" id="gnu.c.compiler.macosx.exe.debug.option.optimization.level.1133705337" name="Optimization Level" superClass="gnu.c.compiler.macosx.exe.debug.option.optimization.level" valueType="enumerated"/>
|
||||
<option id="gnu.c.compiler.macosx.exe.debug.option.debugging.level.396108330" name="Debug Level" superClass="gnu.c.compiler.macosx.exe.debug.option.debugging.level" value="gnu.c.debugging.level.max" valueType="enumerated"/>
|
||||
<option id="gnu.c.compiler.option.include.paths.28061496" name="Include paths (-I)" superClass="gnu.c.compiler.option.include.paths" valueType="includePath">
|
||||
<listOptionValue builtIn="false" value="/usr/include"/>
|
||||
</option>
|
||||
<inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.1884051627" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/>
|
||||
</tool>
|
||||
</toolChain>
|
||||
</folderInfo>
|
||||
<sourceEntries>
|
||||
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="src"/>
|
||||
</sourceEntries>
|
||||
</configuration>
|
||||
</storageModule>
|
||||
<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
|
||||
</cconfiguration>
|
||||
<cconfiguration id="cdt.managedbuild.config.macosx.exe.release.222902119">
|
||||
<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="cdt.managedbuild.config.macosx.exe.release.222902119" moduleId="org.eclipse.cdt.core.settings" name="Release">
|
||||
<externalSettings/>
|
||||
<extensions>
|
||||
<extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
<extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
<extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
<extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
<extension id="org.eclipse.cdt.core.MachO64" point="org.eclipse.cdt.core.BinaryParser"/>
|
||||
</extensions>
|
||||
</storageModule>
|
||||
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
|
||||
<configuration artifactName="${ProjName}" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.release,org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe" cleanCommand="rm -rf" description="" id="cdt.managedbuild.config.macosx.exe.release.222902119" name="Release" parent="cdt.managedbuild.config.macosx.exe.release">
|
||||
<folderInfo id="cdt.managedbuild.config.macosx.exe.release.222902119." name="/" resourcePath="">
|
||||
<toolChain id="cdt.managedbuild.toolchain.gnu.macosx.exe.release.370067321" name="MacOSX GCC" superClass="cdt.managedbuild.toolchain.gnu.macosx.exe.release">
|
||||
<targetPlatform id="cdt.managedbuild.target.gnu.platform.macosx.exe.release.1613432662" name="Debug Platform" superClass="cdt.managedbuild.target.gnu.platform.macosx.exe.release"/>
|
||||
<builder buildPath="${workspace_loc:/scv_tr_sqlite}/Release" id="cdt.managedbuild.target.gnu.builder.macosx.exe.release.1921784777" keepEnvironmentInBuildfile="false" managedBuildOn="true" name="Gnu Make Builder" superClass="cdt.managedbuild.target.gnu.builder.macosx.exe.release"/>
|
||||
<tool id="cdt.managedbuild.tool.macosx.c.linker.macosx.exe.release.835264205" name="MacOS X C Linker" superClass="cdt.managedbuild.tool.macosx.c.linker.macosx.exe.release"/>
|
||||
<tool id="cdt.managedbuild.tool.macosx.cpp.linker.macosx.exe.release.807087528" name="MacOS X C++ Linker" superClass="cdt.managedbuild.tool.macosx.cpp.linker.macosx.exe.release">
|
||||
<option id="macosx.cpp.link.option.paths.1094947030" name="Library search path (-L)" superClass="macosx.cpp.link.option.paths" valueType="libPaths">
|
||||
<listOptionValue builtIn="false" value="/Users/eyck//Library/Frameworks/SystemC.framework/Versions/2.3.1/lib-macosx64"/>
|
||||
</option>
|
||||
<inputType id="cdt.managedbuild.tool.macosx.cpp.linker.input.1729026262" superClass="cdt.managedbuild.tool.macosx.cpp.linker.input">
|
||||
<additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
|
||||
<additionalInput kind="additionalinput" paths="$(LIBS)"/>
|
||||
</inputType>
|
||||
</tool>
|
||||
<tool id="cdt.managedbuild.tool.gnu.assembler.macosx.exe.release.960768765" name="GCC Assembler" superClass="cdt.managedbuild.tool.gnu.assembler.macosx.exe.release">
|
||||
<option id="gnu.both.asm.option.include.paths.1211035001" superClass="gnu.both.asm.option.include.paths" valueType="includePath">
|
||||
<listOptionValue builtIn="false" value="/usr/include"/>
|
||||
</option>
|
||||
<inputType id="cdt.managedbuild.tool.gnu.assembler.input.1845360319" superClass="cdt.managedbuild.tool.gnu.assembler.input"/>
|
||||
</tool>
|
||||
<tool id="cdt.managedbuild.tool.gnu.archiver.macosx.base.2005529856" name="GCC Archiver" superClass="cdt.managedbuild.tool.gnu.archiver.macosx.base"/>
|
||||
<tool id="cdt.managedbuild.tool.gnu.cpp.compiler.macosx.exe.release.1207281858" name="GCC C++ Compiler" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.macosx.exe.release">
|
||||
<option id="gnu.cpp.compiler.macosx.exe.release.option.optimization.level.1947685650" name="Optimization Level" superClass="gnu.cpp.compiler.macosx.exe.release.option.optimization.level" value="gnu.cpp.compiler.optimization.level.most" valueType="enumerated"/>
|
||||
<option id="gnu.cpp.compiler.macosx.exe.release.option.debugging.level.1098045969" name="Debug Level" superClass="gnu.cpp.compiler.macosx.exe.release.option.debugging.level" value="gnu.cpp.compiler.debugging.level.none" valueType="enumerated"/>
|
||||
<option id="gnu.cpp.compiler.option.include.paths.2920067" name="Include paths (-I)" superClass="gnu.cpp.compiler.option.include.paths" valueType="includePath">
|
||||
<listOptionValue builtIn="false" value="/Users/eyck//Library/Frameworks/SystemC.framework/Versions/2.3.1/include"/>
|
||||
<listOptionValue builtIn="false" value="/usr/include"/>
|
||||
</option>
|
||||
<inputType id="cdt.managedbuild.tool.gnu.cpp.compiler.input.749408456" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.input"/>
|
||||
</tool>
|
||||
<tool id="cdt.managedbuild.tool.gnu.c.compiler.macosx.exe.release.2136924185" name="GCC C Compiler" superClass="cdt.managedbuild.tool.gnu.c.compiler.macosx.exe.release">
|
||||
<option defaultValue="gnu.c.optimization.level.most" id="gnu.c.compiler.macosx.exe.release.option.optimization.level.713312654" name="Optimization Level" superClass="gnu.c.compiler.macosx.exe.release.option.optimization.level" valueType="enumerated"/>
|
||||
<option id="gnu.c.compiler.macosx.exe.release.option.debugging.level.1629703352" name="Debug Level" superClass="gnu.c.compiler.macosx.exe.release.option.debugging.level" value="gnu.c.debugging.level.none" valueType="enumerated"/>
|
||||
<option id="gnu.c.compiler.option.include.paths.1878457622" superClass="gnu.c.compiler.option.include.paths" valueType="includePath">
|
||||
<listOptionValue builtIn="false" value="/usr/include"/>
|
||||
</option>
|
||||
<inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.220005104" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/>
|
||||
</tool>
|
||||
</toolChain>
|
||||
</folderInfo>
|
||||
<sourceEntries>
|
||||
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="src"/>
|
||||
</sourceEntries>
|
||||
</configuration>
|
||||
</storageModule>
|
||||
<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
|
||||
</cconfiguration>
|
||||
</storageModule>
|
||||
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
|
||||
<project id="scv_tr_sqlite.cdt.managedbuild.target.macosx.exe.1724881597" name="Executable" projectType="cdt.managedbuild.target.macosx.exe"/>
|
||||
</storageModule>
|
||||
<storageModule moduleId="scannerConfiguration">
|
||||
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
|
||||
<scannerConfigBuildInfo instanceId="cdt.managedbuild.config.gnu.macosx.exe.debug.133691581;cdt.managedbuild.config.gnu.macosx.exe.debug.133691581.;cdt.managedbuild.tool.gnu.cpp.compiler.macosx.exe.debug.1149501692;cdt.managedbuild.tool.gnu.cpp.compiler.input.506955043">
|
||||
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
|
||||
</scannerConfigBuildInfo>
|
||||
<scannerConfigBuildInfo instanceId="cdt.managedbuild.config.macosx.exe.release.222902119;cdt.managedbuild.config.macosx.exe.release.222902119.;cdt.managedbuild.tool.gnu.c.compiler.macosx.exe.release.2136924185;cdt.managedbuild.tool.gnu.c.compiler.input.220005104">
|
||||
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
|
||||
</scannerConfigBuildInfo>
|
||||
<scannerConfigBuildInfo instanceId="cdt.managedbuild.config.gnu.macosx.exe.debug.133691581;cdt.managedbuild.config.gnu.macosx.exe.debug.133691581.;cdt.managedbuild.tool.gnu.c.compiler.macosx.exe.debug.1993665797;cdt.managedbuild.tool.gnu.c.compiler.input.1884051627">
|
||||
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
|
||||
</scannerConfigBuildInfo>
|
||||
<scannerConfigBuildInfo instanceId="cdt.managedbuild.config.macosx.exe.release.222902119;cdt.managedbuild.config.macosx.exe.release.222902119.;cdt.managedbuild.tool.gnu.cpp.compiler.macosx.exe.release.1207281858;cdt.managedbuild.tool.gnu.cpp.compiler.input.749408456">
|
||||
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
|
||||
</scannerConfigBuildInfo>
|
||||
</storageModule>
|
||||
<storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
|
||||
<storageModule moduleId="refreshScope"/>
|
||||
</cproject>
|
|
@ -1,4 +0,0 @@
|
|||
/Debug/
|
||||
/*.txlog
|
||||
/*.txdb
|
||||
/my_db.vcd
|
|
@ -1,27 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>scv_tr_sqlite</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>
|
||||
<triggers>clean,full,incremental,</triggers>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
|
||||
<triggers>full,incremental,</triggers>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.cdt.core.cnature</nature>
|
||||
<nature>org.eclipse.cdt.core.ccnature</nature>
|
||||
<nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
|
||||
<nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
|
@ -1,20 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<project>
|
||||
<configuration id="cdt.managedbuild.config.gnu.macosx.exe.debug.133691581" name="Debug">
|
||||
<extension point="org.eclipse.cdt.core.LanguageSettingsProvider">
|
||||
<provider-reference id="org.eclipse.cdt.ui.UserLanguageSettingsProvider" ref="shared-provider"/>
|
||||
<provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
|
||||
<provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
|
||||
<provider-reference id="org.eclipse.cdt.managedbuilder.core.GCCBuiltinSpecsDetector" ref="shared-provider"/>
|
||||
<provider class="org.eclipse.cdt.managedbuilder.language.settings.providers.GCCBuildCommandParser" id="org.eclipse.cdt.managedbuilder.core.GCCBuildCommandParser" keep-relative-paths="false" name="CDT GCC Build Output Parser" parameter="(gcc)|([gc]\+\+)|(clang)" prefer-non-shared="true"/>
|
||||
</extension>
|
||||
</configuration>
|
||||
<configuration id="cdt.managedbuild.config.macosx.exe.release.222902119" name="Release">
|
||||
<extension point="org.eclipse.cdt.core.LanguageSettingsProvider">
|
||||
<provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/>
|
||||
<provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
|
||||
<provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
|
||||
<provider-reference id="org.eclipse.cdt.managedbuilder.core.GCCBuiltinSpecsDetector" ref="shared-provider"/>
|
||||
</extension>
|
||||
</configuration>
|
||||
</project>
|
|
@ -1,722 +0,0 @@
|
|||
/*
|
||||
* tlm_recording.h
|
||||
*
|
||||
* Created on: 07.11.2015
|
||||
* Author: eyck
|
||||
*/
|
||||
|
||||
#ifndef TLM2_RECORDER_H_
|
||||
#define TLM2_RECORDER_H_
|
||||
|
||||
#include <scv.h>
|
||||
#include <tlm>
|
||||
#include "tlm_gp_data_ext.h"
|
||||
#include "tlm_recording_extension.h"
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace scv4tlm {
|
||||
|
||||
/*! \brief The TLM2 transaction extensions recorder interface
|
||||
*
|
||||
* This interface is used by the TLM2 transaction recorder. It can be used to register custom recorder functionality
|
||||
* to also record the payload extensions
|
||||
*/
|
||||
template< typename TYPES = tlm::tlm_base_protocol_types>
|
||||
struct tlm2_extensions_recording_if {
|
||||
/*! \brief recording attributes in extensions at the beginning, it is intended to be overload as it does nothing
|
||||
*
|
||||
*/
|
||||
virtual void recordBeginTx(scv_tr_handle& handle, typename TYPES::tlm_payload_type& payload) = 0;
|
||||
|
||||
/*! \brief recording attributes in extensions at the end, it is intended to be overload as it does nothing
|
||||
*
|
||||
*/
|
||||
virtual void recordEndTx(scv_tr_handle& handle, typename TYPES::tlm_payload_type& payload) = 0;
|
||||
|
||||
virtual ~tlm2_extensions_recording_if(){}
|
||||
};
|
||||
/*! \brief The TLM2 transaction recorder
|
||||
*
|
||||
* This module records all TLM transaction to a SCV transaction stream for further viewing and analysis.
|
||||
* The handle of the created transaction is storee in an tlm_extension so that another instance of the scv_tlm2_recorder
|
||||
* e.g. further down the opath can link to it.
|
||||
*/
|
||||
template< typename TYPES = tlm::tlm_base_protocol_types>
|
||||
class tlm2_recorder:
|
||||
public virtual tlm::tlm_fw_transport_if<TYPES>,
|
||||
public virtual tlm::tlm_bw_transport_if<TYPES>,
|
||||
public sc_core::sc_object {
|
||||
public:
|
||||
SC_HAS_PROCESS(tlm2_recorder<TYPES>);
|
||||
|
||||
//! \brief the attribute to selectively enable/disable recording
|
||||
sc_core::sc_attribute<bool> enable;
|
||||
|
||||
//! \brief the attribute to selectively enable/disable timed recording
|
||||
sc_core::sc_attribute<bool> enableTimed;
|
||||
|
||||
//! \brief the port where fw accesses are forwarded to
|
||||
sc_core::sc_port<tlm::tlm_fw_transport_if<TYPES> > fw_port;
|
||||
|
||||
//! \brief the port where bw accesses are forwarded to
|
||||
sc_core::sc_port<tlm::tlm_bw_transport_if<TYPES> > bw_port;
|
||||
|
||||
/*! \brief The constructor of the component
|
||||
*
|
||||
* \param name is the SystemC module name of the recorder
|
||||
* \param tr_db is a pointer to a transaction recording database. If none is provided the default one is retrieved.
|
||||
* If this database is not initialized (e.g. by not calling scv_tr_db::set_default_db() ) recording is disabled.
|
||||
*/
|
||||
tlm2_recorder(bool recording_enabled = true, scv_tr_db* tr_db = scv_tr_db::get_default_db()){
|
||||
this->tlm2_recorder::tlm2_recorder(sc_core::sc_gen_unique_name("tlm2_recorder"), recording_enabled, tr_db);
|
||||
}
|
||||
/*! \brief The constructor of the component
|
||||
*
|
||||
* \param name is the SystemC module name of the recorder
|
||||
* \param tr_db is a pointer to a transaction recording database. If none is provided the default one is retrieved.
|
||||
* If this database is not initialized (e.g. by not calling scv_tr_db::set_default_db() ) recording is disabled.
|
||||
*/
|
||||
tlm2_recorder(const char* name, bool recording_enabled = true, scv_tr_db* tr_db = scv_tr_db::get_default_db())
|
||||
: sc_core::sc_object(name)
|
||||
, enable("enable", recording_enabled)
|
||||
, enableTimed("enableTimed", recording_enabled)
|
||||
, fw_port(sc_core::sc_gen_unique_name("fw"))
|
||||
, bw_port(sc_core::sc_gen_unique_name("bw"))
|
||||
, mm(new RecodingMemoryManager())
|
||||
, b_timed_peq(this, &tlm2_recorder::btx_cb)
|
||||
, nb_timed_peq(this, &tlm2_recorder::nbtx_cb)
|
||||
, m_db(tr_db)
|
||||
, b_streamHandle(NULL)
|
||||
, b_streamHandleTimed(NULL)
|
||||
, b_trTimedHandle(3)
|
||||
, nb_streamHandle(2)
|
||||
, nb_streamHandleTimed(2)
|
||||
, nb_fw_trHandle(3)
|
||||
, nb_txReqHandle(3)
|
||||
, nb_bw_trHandle(3)
|
||||
, nb_txRespHandle(3)
|
||||
, dmi_streamHandle(NULL)
|
||||
, dmi_trGetHandle(NULL)
|
||||
, dmi_trInvalidateHandle(NULL)
|
||||
, extensionRecording(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~tlm2_recorder(){
|
||||
delete b_streamHandle;
|
||||
delete b_streamHandleTimed;
|
||||
for(size_t i = 0; i<b_trTimedHandle.size(); ++i) delete b_trTimedHandle[i];
|
||||
for(size_t i = 0; i<nb_streamHandle.size(); ++i) delete nb_streamHandle[i];
|
||||
for(size_t i = 0; i<nb_streamHandleTimed.size(); ++i) delete nb_streamHandleTimed[i];
|
||||
for(size_t i = 0; i<nb_fw_trHandle.size(); ++i) delete nb_fw_trHandle[i];
|
||||
for(size_t i = 0; i<nb_txReqHandle.size(); ++i) delete nb_txReqHandle[i];
|
||||
for(size_t i = 0; i<nb_bw_trHandle.size(); ++i) delete nb_bw_trHandle[i];
|
||||
for(size_t i = 0; i<nb_txRespHandle.size(); ++i) delete nb_txRespHandle[i];
|
||||
delete dmi_streamHandle;
|
||||
delete dmi_trGetHandle;
|
||||
delete dmi_trInvalidateHandle;
|
||||
delete extensionRecording;
|
||||
}
|
||||
|
||||
// TLM-2.0 interface methods for initiator and target sockets, surrounded with Tx Recording
|
||||
/*! \brief The non-blocking forward transport function
|
||||
*
|
||||
* This type of transaction is forwarded and recorded to a transaction stream named "nb_fw" with current timestamps.
|
||||
* \param trans is the generic payload of the transaction
|
||||
* \param phase is the current phase of the transaction
|
||||
* \param delay is the annotated delay
|
||||
* \return the sync state of the transaction
|
||||
*/
|
||||
virtual tlm::tlm_sync_enum nb_transport_fw(typename TYPES::tlm_payload_type& trans, typename TYPES::tlm_phase_type& phase,
|
||||
sc_core::sc_time& delay);
|
||||
|
||||
/*! \brief The non-blocking backward transport function
|
||||
*
|
||||
* This type of transaction is forwarded and recorded to a transaction stream named "nb_bw" with current timestamps.
|
||||
* \param trans is the generic payload of the transaction
|
||||
* \param phase is the current phase of the transaction
|
||||
* \param delay is the annotated delay
|
||||
* \return the sync state of the transaction
|
||||
*/
|
||||
virtual tlm::tlm_sync_enum nb_transport_bw(typename TYPES::tlm_payload_type& trans, typename TYPES::tlm_phase_type& phase,
|
||||
sc_core::sc_time& delay);
|
||||
|
||||
/*! \brief The blocking transport function
|
||||
*
|
||||
* This type of transaction is forwarded and recorded to a transaction stream named "b_tx" with current timestamps. Additionally a "b_tx_timed"
|
||||
* is been created recording the transactions at their annotated delay
|
||||
* \param trans is the generic payload of the transaction
|
||||
* \param delay is the annotated delay
|
||||
*/
|
||||
virtual void b_transport(typename TYPES::tlm_payload_type& trans, sc_core::sc_time& delay);
|
||||
|
||||
/*! \brief The direct memory interface forward function
|
||||
*
|
||||
* This type of transaction is just forwarded and not recorded.
|
||||
* \param trans is the generic payload of the transaction
|
||||
* \param dmi_data is the structure holding the dmi information
|
||||
* \return if the dmi structure is valid
|
||||
*/
|
||||
virtual bool get_direct_mem_ptr(typename TYPES::tlm_payload_type& trans, tlm::tlm_dmi& dmi_data);
|
||||
/*! \brief The direct memory interface backward function
|
||||
*
|
||||
* This type of transaction is just forwarded and not recorded.
|
||||
* \param start_addr is the start address of the memory area being invalid
|
||||
* \param end_addr is the end address of the memory area being invalid
|
||||
*/
|
||||
virtual void invalidate_direct_mem_ptr(sc_dt::uint64 start_addr, sc_dt::uint64 end_addr);
|
||||
/*! \brief The debug transportfunction
|
||||
*
|
||||
* This type of transaction is just forwarded and not recorded.
|
||||
* \param trans is the generic payload of the transaction
|
||||
* \return the sync state of the transaction
|
||||
*/
|
||||
virtual unsigned int transport_dbg(typename TYPES::tlm_payload_type& trans);
|
||||
/*! \brief get the current state of transaction recording
|
||||
*
|
||||
* \return if true transaction recording is enabled otherwise transaction recording is bypassed
|
||||
*/
|
||||
const bool isRecordingEnabled() const {
|
||||
return m_db != NULL && enable.value;
|
||||
}
|
||||
|
||||
void setExtensionRecording(tlm2_extensions_recording_if<TYPES>* extensionRecording){
|
||||
this->extensionRecording=extensionRecording;
|
||||
}
|
||||
private:
|
||||
//! \brief the struct to hold the information to be recorded on the timed streams
|
||||
struct tlm_recording_payload: public TYPES::tlm_payload_type {
|
||||
scv_tr_handle parent;
|
||||
uint64 id;
|
||||
tlm_recording_payload& operator=(const typename TYPES::tlm_payload_type& x){
|
||||
id=(uint64)&x;
|
||||
set_command(x.get_command());
|
||||
set_address(x.get_address());
|
||||
set_data_ptr(x.get_data_ptr());
|
||||
set_data_length(x.get_data_length());
|
||||
set_response_status(x.get_response_status());
|
||||
set_byte_enable_ptr(x.get_byte_enable_ptr());
|
||||
set_byte_enable_length(x.get_byte_enable_length());
|
||||
set_streaming_width(x.get_streaming_width());
|
||||
return (*this);
|
||||
|
||||
}
|
||||
explicit tlm_recording_payload(tlm::tlm_mm_interface* mm) :
|
||||
TYPES::tlm_payload_type(mm), parent(), id(0) {
|
||||
}
|
||||
};
|
||||
//! \brief Memory manager for the tlm_recording_payload
|
||||
struct RecodingMemoryManager: public tlm::tlm_mm_interface {
|
||||
RecodingMemoryManager() :
|
||||
free_list(0), empties(0) {
|
||||
}
|
||||
tlm_recording_payload* allocate() {
|
||||
typename TYPES::tlm_payload_type* ptr;
|
||||
if (free_list) {
|
||||
ptr = free_list->trans;
|
||||
empties = free_list;
|
||||
free_list = free_list->next;
|
||||
} else {
|
||||
ptr = new tlm_recording_payload(this);
|
||||
}
|
||||
return (tlm_recording_payload*) ptr;
|
||||
}
|
||||
void free(typename TYPES::tlm_payload_type* trans) {
|
||||
trans->reset();
|
||||
if (!empties) {
|
||||
empties = new access;
|
||||
empties->next = free_list;
|
||||
empties->prev = 0;
|
||||
if (free_list)
|
||||
free_list->prev = empties;
|
||||
}
|
||||
free_list = empties;
|
||||
free_list->trans = trans;
|
||||
empties = free_list->prev;
|
||||
}
|
||||
private:
|
||||
struct access {
|
||||
typename TYPES::tlm_payload_type* trans;
|
||||
access* next;
|
||||
access* prev;
|
||||
};
|
||||
access *free_list, *empties;
|
||||
};
|
||||
RecodingMemoryManager* mm;
|
||||
//! peq type definition
|
||||
struct recording_types {
|
||||
typedef tlm_recording_payload tlm_payload_type;
|
||||
typedef typename TYPES::tlm_phase_type tlm_phase_type;
|
||||
};
|
||||
//! event queue to hold time points of blocking transactions
|
||||
tlm_utils::peq_with_cb_and_phase<tlm2_recorder, recording_types> b_timed_peq;
|
||||
//! event queue to hold time points of non-blocking transactions
|
||||
tlm_utils::peq_with_cb_and_phase<tlm2_recorder, recording_types> nb_timed_peq;
|
||||
/*! \brief The thread processing the blocking accesses with their annotated times
|
||||
* to generate the timed view of blocking tx
|
||||
*/
|
||||
void btx_cb(tlm_recording_payload& rec_parts, const typename TYPES::tlm_phase_type& phase);
|
||||
/*! \brief The thread processing the non-blocking requests with their annotated times
|
||||
* to generate the timed view of non-blocking tx
|
||||
*/
|
||||
void nbtx_cb(tlm_recording_payload& rec_parts, const typename TYPES::tlm_phase_type& phase);
|
||||
//! transaction recording database
|
||||
scv_tr_db* m_db;
|
||||
//! blocking transaction recording stream handle
|
||||
scv_tr_stream* b_streamHandle;
|
||||
//! transaction generator handle for blocking transactions
|
||||
scv_tr_generator<sc_dt::uint64, sc_dt::uint64>* b_trHandle[3];
|
||||
//! timed blocking transaction recording stream handle
|
||||
scv_tr_stream* b_streamHandleTimed;
|
||||
//! transaction generator handle for blocking transactions with annotated delays
|
||||
std::vector<scv_tr_generator<tlm::tlm_command, tlm::tlm_response_status>*> b_trTimedHandle;
|
||||
std::map<uint64, scv_tr_handle> btx_handle_map;
|
||||
|
||||
enum DIR{FW, BW};
|
||||
//! non-blocking transaction recording stream handle
|
||||
std::vector<scv_tr_stream*> nb_streamHandle;
|
||||
//! non-blocking transaction recording stream handle
|
||||
std::vector<scv_tr_stream*> nb_streamHandleTimed;
|
||||
//! transaction generator handle for forward non-blocking transactions
|
||||
std::vector<scv_tr_generator<tlm::tlm_phase_enum, tlm::tlm_sync_enum>*> nb_fw_trHandle;
|
||||
//! transaction generator handle for forward non-blocking transactions with annotated delays
|
||||
std::vector<scv_tr_generator<>*> nb_txReqHandle;
|
||||
map<uint64, scv_tr_handle> nbtx_req_handle_map;
|
||||
//! transaction generator handle for backward non-blocking transactions
|
||||
std::vector<scv_tr_generator<tlm::tlm_phase_enum, tlm::tlm_sync_enum>*> nb_bw_trHandle;
|
||||
//! transaction generator handle for backward non-blocking transactions with annotated delays
|
||||
std::vector<scv_tr_generator<>*> nb_txRespHandle;
|
||||
map<uint64, scv_tr_handle> nbtx_last_req_handle_map;
|
||||
|
||||
//! dmi transaction recording stream handle
|
||||
scv_tr_stream* dmi_streamHandle;
|
||||
//! transaction generator handle for DMI transactions
|
||||
scv_tr_generator<tlm_gp_data, tlm_dmi_data>* dmi_trGetHandle;
|
||||
scv_tr_generator<sc_dt::uint64, sc_dt::uint64>* dmi_trInvalidateHandle;
|
||||
|
||||
tlm2_extensions_recording_if<TYPES>* extensionRecording;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// implementations of functions
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
template< typename TYPES>
|
||||
void tlm2_recorder<TYPES>::b_transport(typename TYPES::tlm_payload_type& trans, sc_core::sc_time& delay) {
|
||||
tlm_recording_payload* req;
|
||||
if (!isRecordingEnabled()) {
|
||||
fw_port->b_transport(trans, delay);
|
||||
return;
|
||||
}
|
||||
if (b_streamHandle == NULL) {
|
||||
string basename(this->name());
|
||||
b_streamHandle = new scv_tr_stream((basename + ".blocking").c_str(), "TRANSACTOR", m_db);
|
||||
b_trHandle[tlm::TLM_READ_COMMAND] = new scv_tr_generator<sc_dt::uint64, sc_dt::uint64>("read", *b_streamHandle, "start_delay",
|
||||
"end_delay");
|
||||
b_trHandle[tlm::TLM_WRITE_COMMAND] = new scv_tr_generator<sc_dt::uint64, sc_dt::uint64>("write", *b_streamHandle, "start_delay",
|
||||
"end_delay");
|
||||
b_trHandle[tlm::TLM_IGNORE_COMMAND] = new scv_tr_generator<sc_dt::uint64, sc_dt::uint64>("ignore", *b_streamHandle, "start_delay",
|
||||
"end_delay");
|
||||
}
|
||||
// Get a handle for the new transaction
|
||||
scv_tr_handle h = b_trHandle[trans.get_command()]->begin_transaction(delay.value(), sc_time_stamp());
|
||||
tlm_gp_data tgd(trans);
|
||||
|
||||
/*************************************************************************
|
||||
* do the timed notification
|
||||
*************************************************************************/
|
||||
if (enableTimed.value) {
|
||||
req = mm->allocate();
|
||||
req->acquire();
|
||||
(*req) = trans;
|
||||
req->parent = h;
|
||||
req->id=h.get_id();
|
||||
#ifdef DEBUG
|
||||
cout<<"notify addition of parent with id "<<req->id<<" to btx_handle_map with delay "<<delay<<std::endl;
|
||||
#endif
|
||||
b_timed_peq.notify(*req, tlm::BEGIN_REQ, delay);
|
||||
}
|
||||
|
||||
if(extensionRecording) extensionRecording->recordBeginTx(h, trans);
|
||||
tlm_recording_extension* preExt = NULL;
|
||||
|
||||
trans.get_extension(preExt);
|
||||
if (preExt == NULL) { // we are the first recording this transaction
|
||||
preExt = new tlm_recording_extension(h, this);
|
||||
trans.set_extension(preExt);
|
||||
} else {
|
||||
h.add_relation(rel_str(PREDECESSOR_SUCCESSOR), preExt->txHandle);
|
||||
}
|
||||
scv_tr_handle preTx(preExt->txHandle);
|
||||
|
||||
fw_port->b_transport(trans, delay);
|
||||
trans.get_extension(preExt);
|
||||
if (preExt->get_creator() == this) {
|
||||
// clean-up the extension if this is the original creator
|
||||
delete preExt;
|
||||
trans.set_extension((tlm_recording_extension*) NULL);
|
||||
} else {
|
||||
preExt->txHandle=preTx;
|
||||
}
|
||||
|
||||
tgd.set_response_status(trans.get_response_status());
|
||||
h.record_attribute("trans", tgd);
|
||||
h.record_attribute("trans.data_value", *(uint64_t*)trans.get_data_ptr());
|
||||
if(extensionRecording) extensionRecording->recordEndTx(h, trans);
|
||||
// End the transaction
|
||||
b_trHandle[trans.get_command()]->end_transaction(h, delay.value(), sc_time_stamp());
|
||||
// and now the stuff for the timed tx
|
||||
if (enableTimed.value){
|
||||
#ifdef DEBUG
|
||||
cout<<"notify removal of parent with id "<<req->id<<" to btx_handle_map with delay "<<delay<<std::endl;
|
||||
#endif
|
||||
b_timed_peq.notify(*req, tlm::END_RESP, delay);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
template< typename TYPES>
|
||||
void tlm2_recorder<TYPES>::btx_cb(tlm_recording_payload& rec_parts, const typename TYPES::tlm_phase_type& phase) {
|
||||
scv_tr_handle h;
|
||||
if (b_trTimedHandle[0] == NULL) {
|
||||
std::string basename(this->name());
|
||||
b_streamHandleTimed = new scv_tr_stream((basename + ".blocking_annotated").c_str(), "TRANSACTOR", m_db);
|
||||
b_trTimedHandle[0] = new scv_tr_generator<tlm::tlm_command, tlm::tlm_response_status>("read", *b_streamHandleTimed);
|
||||
b_trTimedHandle[1] = new scv_tr_generator<tlm::tlm_command, tlm::tlm_response_status>("write", *b_streamHandleTimed);
|
||||
b_trTimedHandle[2] = new scv_tr_generator<tlm::tlm_command, tlm::tlm_response_status>("ignore", *b_streamHandleTimed);
|
||||
}
|
||||
// Now process outstanding recordings
|
||||
switch (phase) {
|
||||
case tlm::BEGIN_REQ:
|
||||
{
|
||||
tlm_gp_data tgd(rec_parts);
|
||||
h = b_trTimedHandle[rec_parts.get_command()]->begin_transaction(rec_parts.get_command());
|
||||
h.record_attribute("trans", tgd);
|
||||
h.add_relation(rel_str(PARENT_CHILD), rec_parts.parent);
|
||||
#ifdef DEBUG
|
||||
cout<<"adding parent with id "<<rec_parts.id<<" to btx_handle_map"<<std::endl;
|
||||
#endif
|
||||
btx_handle_map[rec_parts.id] = h;
|
||||
}
|
||||
break;
|
||||
case tlm::END_RESP: {
|
||||
#ifdef DEBUG
|
||||
cout<<"retrieving parent with id "<<rec_parts.id<<" from btx_handle_map"<<std::endl;
|
||||
#endif
|
||||
std::map<uint64, scv_tr_handle>::iterator it = btx_handle_map.find(rec_parts.id);
|
||||
sc_assert(it != btx_handle_map.end());
|
||||
h = it->second;
|
||||
btx_handle_map.erase(it);
|
||||
h.end_transaction(h, rec_parts.get_response_status());
|
||||
rec_parts.release();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
sc_assert(!"phase not supported!");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
template< typename TYPES>
|
||||
tlm::tlm_sync_enum tlm2_recorder<TYPES>::nb_transport_fw(
|
||||
typename TYPES::tlm_payload_type& trans,
|
||||
typename TYPES::tlm_phase_type& phase,
|
||||
sc_core::sc_time& delay) {
|
||||
if (!isRecordingEnabled())
|
||||
return fw_port->nb_transport_fw(trans, phase, delay);
|
||||
// initialize stream and generator if not yet done
|
||||
if (nb_streamHandle[FW] == NULL) {
|
||||
string basename(this->name());
|
||||
nb_streamHandle[FW] = new scv_tr_stream((basename + ".nb_forward").c_str(), "TRANSACTOR", m_db);
|
||||
nb_fw_trHandle[tlm::TLM_READ_COMMAND] = new scv_tr_generator<tlm::tlm_phase_enum, tlm::tlm_sync_enum>("read", *nb_streamHandle[FW], "tlm_phase", "tlm_sync");
|
||||
nb_fw_trHandle[tlm::TLM_WRITE_COMMAND] = new scv_tr_generator<tlm::tlm_phase_enum, tlm::tlm_sync_enum>("write", *nb_streamHandle[FW], "tlm_phase", "tlm_sync");
|
||||
nb_fw_trHandle[tlm::TLM_IGNORE_COMMAND] = new scv_tr_generator<tlm::tlm_phase_enum, tlm::tlm_sync_enum>("ignore", *nb_streamHandle[FW], "tlm_phase", "tlm_sync");
|
||||
}
|
||||
/*************************************************************************
|
||||
* prepare recording
|
||||
*************************************************************************/
|
||||
// Get a handle for the new transaction
|
||||
scv_tr_handle h = nb_fw_trHandle[trans.get_command()]->begin_transaction((tlm::tlm_phase_enum) (unsigned) phase);
|
||||
tlm_recording_extension* preExt = NULL;
|
||||
trans.get_extension(preExt);
|
||||
if (phase == tlm::BEGIN_REQ && preExt == NULL) { // we are the first recording this transaction
|
||||
preExt = new tlm_recording_extension(h, this);
|
||||
trans.set_extension(preExt);
|
||||
} else if (preExt != NULL) {
|
||||
// link handle if we have a predecessor
|
||||
h.add_relation(rel_str(PREDECESSOR_SUCCESSOR), preExt->txHandle);
|
||||
} else {
|
||||
sc_assert(preExt!=NULL && "ERROR on forward path in phase other than tlm::BEGIN_REQ");
|
||||
}
|
||||
// update the extension
|
||||
preExt->txHandle = h;
|
||||
h.record_attribute("delay", delay.to_string());
|
||||
if(extensionRecording) extensionRecording->recordBeginTx(h, trans);
|
||||
tlm_gp_data tgd(trans);
|
||||
/*************************************************************************
|
||||
* do the timed notification
|
||||
*************************************************************************/
|
||||
if (enableTimed.value) {
|
||||
tlm_recording_payload* req = mm->allocate();
|
||||
req->acquire();
|
||||
(*req) = trans;
|
||||
req->parent = h;
|
||||
nb_timed_peq.notify(*req, phase, delay);
|
||||
}
|
||||
/*************************************************************************
|
||||
* do the access
|
||||
*************************************************************************/
|
||||
tlm::tlm_sync_enum status = fw_port->nb_transport_fw(trans, phase, delay);
|
||||
/*************************************************************************
|
||||
* handle recording
|
||||
*************************************************************************/
|
||||
tgd.set_response_status(trans.get_response_status());
|
||||
h.record_attribute("trans", tgd);
|
||||
if(extensionRecording) extensionRecording->recordEndTx(h, trans);
|
||||
h.record_attribute("tlm_phase[return_path]", (tlm::tlm_phase_enum) (unsigned) phase);
|
||||
h.record_attribute("delay[return_path]", delay.to_string());
|
||||
// get the extension and free the memory if it was mine
|
||||
if (status == tlm::TLM_COMPLETED || (status == tlm::TLM_ACCEPTED && phase == tlm::END_RESP)) {
|
||||
trans.get_extension(preExt);
|
||||
if (preExt->get_creator() == this) {
|
||||
delete preExt;
|
||||
trans.set_extension((tlm_recording_extension*) NULL);
|
||||
}
|
||||
/*************************************************************************
|
||||
* do the timed notification if req. finished here
|
||||
*************************************************************************/
|
||||
tlm_recording_payload* req = mm->allocate();
|
||||
req->acquire();
|
||||
(*req) = trans;
|
||||
req->parent = h;
|
||||
nb_timed_peq.notify(*req, (status == tlm::TLM_COMPLETED && phase == tlm::BEGIN_REQ) ? tlm::END_RESP : phase,
|
||||
delay);
|
||||
} else if (status == tlm::TLM_UPDATED) {
|
||||
tlm_recording_payload* req = mm->allocate();
|
||||
req->acquire();
|
||||
(*req) = trans;
|
||||
req->parent = h;
|
||||
nb_timed_peq.notify(*req, phase, delay);
|
||||
}
|
||||
// End the transaction
|
||||
nb_fw_trHandle[trans.get_command()]->end_transaction(h, status);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
template< typename TYPES>
|
||||
tlm::tlm_sync_enum tlm2_recorder<TYPES>::nb_transport_bw(typename TYPES::tlm_payload_type& trans, typename TYPES::tlm_phase_type& phase,
|
||||
sc_core::sc_time& delay) {
|
||||
if (!isRecordingEnabled())
|
||||
return bw_port->nb_transport_bw(trans, phase, delay);
|
||||
if (nb_streamHandle[BW] == NULL) {
|
||||
string basename(this->name());
|
||||
nb_streamHandle[BW] = new scv_tr_stream((basename + ".nb_backward").c_str(), "TRANSACTOR", m_db);
|
||||
nb_bw_trHandle[0] = new scv_tr_generator<tlm::tlm_phase_enum, tlm::tlm_sync_enum>("read", *nb_streamHandle[BW], "tlm_phase", "tlm_sync");
|
||||
nb_bw_trHandle[1] = new scv_tr_generator<tlm::tlm_phase_enum, tlm::tlm_sync_enum>("write", *nb_streamHandle[BW], "tlm_phase", "tlm_sync");
|
||||
nb_bw_trHandle[2] = new scv_tr_generator<tlm::tlm_phase_enum, tlm::tlm_sync_enum>("ignore", *nb_streamHandle[BW], "tlm_phase", "tlm_sync");
|
||||
}
|
||||
/*************************************************************************
|
||||
* prepare recording
|
||||
*************************************************************************/
|
||||
tlm_recording_extension* preExt = NULL;
|
||||
trans.get_extension(preExt);
|
||||
sc_assert(preExt!=NULL && "ERROR on backward path");
|
||||
// Get a handle for the new transaction
|
||||
scv_tr_handle h = nb_bw_trHandle[trans.get_command()]->begin_transaction((tlm::tlm_phase_enum) (unsigned) phase);
|
||||
// link handle if we have a predecessor and that's not ourself
|
||||
h.add_relation(rel_str(PREDECESSOR_SUCCESSOR), preExt->txHandle);
|
||||
// and set the extension handle to this transaction
|
||||
preExt->txHandle = h;
|
||||
h.record_attribute("delay", delay.to_string());
|
||||
if(extensionRecording) extensionRecording->recordBeginTx(h, trans);
|
||||
tlm_gp_data tgd(trans);
|
||||
/*************************************************************************
|
||||
* do the timed notification
|
||||
*************************************************************************/
|
||||
if (enableTimed.value) {
|
||||
tlm_recording_payload* req = mm->allocate();
|
||||
req->acquire();
|
||||
(*req) = trans;
|
||||
req->parent = h;
|
||||
nb_timed_peq.notify(*req, phase, delay);
|
||||
}
|
||||
/*************************************************************************
|
||||
* do the access
|
||||
*************************************************************************/
|
||||
tlm::tlm_sync_enum status = bw_port->nb_transport_bw(trans, phase, delay);
|
||||
/*************************************************************************
|
||||
* handle recording
|
||||
*************************************************************************/
|
||||
tgd.set_response_status(trans.get_response_status());
|
||||
h.record_attribute("trans", tgd);
|
||||
if(extensionRecording) extensionRecording->recordEndTx(h, trans);
|
||||
// phase and delay are already recorded
|
||||
h.record_attribute("phase_upd", (tlm::tlm_phase_enum) (unsigned) phase);
|
||||
h.record_attribute("delay_upd", delay.to_string());
|
||||
// End the transaction
|
||||
nb_bw_trHandle[trans.get_command()]->end_transaction(h, status);
|
||||
if (status == tlm::TLM_COMPLETED || (status == tlm::TLM_UPDATED && phase == tlm::END_RESP)) {
|
||||
// the transaction is finished
|
||||
trans.get_extension(preExt);
|
||||
if (preExt->get_creator() == this) {
|
||||
// clean-up the extension if this is the original creator
|
||||
delete preExt;
|
||||
trans.set_extension((tlm_recording_extension*) NULL);
|
||||
}
|
||||
/*************************************************************************
|
||||
* do the timed notification if req. finished here
|
||||
*************************************************************************/
|
||||
tlm_recording_payload* req = mm->allocate();
|
||||
req->acquire();
|
||||
(*req) = trans;
|
||||
req->parent = h;
|
||||
nb_timed_peq.notify(*req, phase, delay);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
template< typename TYPES>
|
||||
void tlm2_recorder<TYPES>::nbtx_cb(tlm_recording_payload& rec_parts, const typename TYPES::tlm_phase_type& phase) {
|
||||
scv_tr_handle h;
|
||||
std::map<uint64, scv_tr_handle>::iterator it;
|
||||
if (nb_streamHandleTimed[FW] == NULL) {
|
||||
std::string basename(this->name());
|
||||
nb_streamHandleTimed[FW] = new scv_tr_stream((basename + ".nb_request_annotated").c_str(), "TRANSACTOR", m_db);
|
||||
nb_txReqHandle[0] = new scv_tr_generator<>("read", *nb_streamHandleTimed[FW]);
|
||||
nb_txReqHandle[1] = new scv_tr_generator<>("write", *nb_streamHandleTimed[FW]);
|
||||
nb_txReqHandle[2] = new scv_tr_generator<>("ignore", *nb_streamHandleTimed[FW]);
|
||||
}
|
||||
if (nb_streamHandleTimed[BW] == NULL) {
|
||||
std::string basename(this->name());
|
||||
nb_streamHandleTimed[BW] = new scv_tr_stream((basename + ".nb_response_annotated").c_str(), "TRANSACTOR", m_db);
|
||||
nb_txRespHandle[0] = new scv_tr_generator<>("read", *nb_streamHandleTimed[BW]);
|
||||
nb_txRespHandle[1] = new scv_tr_generator<>("write", *nb_streamHandleTimed[BW]);
|
||||
nb_txRespHandle[2] = new scv_tr_generator<>("ignore", *nb_streamHandleTimed[BW]);
|
||||
}
|
||||
tlm_gp_data tgd(rec_parts);
|
||||
switch (phase) { // Now process outstanding recordings
|
||||
case tlm::BEGIN_REQ:
|
||||
h = nb_txReqHandle[rec_parts.get_command()]->begin_transaction();
|
||||
h.record_attribute("trans", tgd);
|
||||
h.add_relation(rel_str(PARENT_CHILD), rec_parts.parent);
|
||||
#ifdef NBDEBUG
|
||||
cout<<"adding parent with id "<<rec_parts.id<<" to nbtx_req_handle_map"<<std::endl;
|
||||
#endif
|
||||
nbtx_req_handle_map[rec_parts.id] = h;
|
||||
break;
|
||||
case tlm::END_REQ:
|
||||
#ifdef NBDEBUG
|
||||
cout<<"retrieving parent with id "<<rec_parts.id<<" from nbtx_req_handle_map"<<std::endl;
|
||||
#endif
|
||||
it = nbtx_req_handle_map.find(rec_parts.id);
|
||||
sc_assert(it != nbtx_req_handle_map.end());
|
||||
h = it->second;
|
||||
nbtx_req_handle_map.erase(it);
|
||||
h.end_transaction();
|
||||
nbtx_last_req_handle_map[rec_parts.id] = h;
|
||||
break;
|
||||
case tlm::BEGIN_RESP:
|
||||
#ifdef NBDEBUG
|
||||
cout<<"retrieving parent with id "<<rec_parts.id<<" from nbtx_req_handle_map"<<std::endl;
|
||||
#endif
|
||||
it = nbtx_req_handle_map.find(rec_parts.id);
|
||||
if (it != nbtx_req_handle_map.end()) {
|
||||
h = it->second;
|
||||
nbtx_req_handle_map.erase(it);
|
||||
h.end_transaction();
|
||||
nbtx_last_req_handle_map[rec_parts.id] = h;
|
||||
}
|
||||
h = nb_txRespHandle[rec_parts.get_command()]->begin_transaction();
|
||||
h.record_attribute("trans", tgd);
|
||||
h.add_relation(rel_str(PARENT_CHILD), rec_parts.parent);
|
||||
nbtx_req_handle_map[rec_parts.id] = h;
|
||||
it = nbtx_last_req_handle_map.find(rec_parts.id);
|
||||
if (it != nbtx_last_req_handle_map.end()) {
|
||||
scv_tr_handle pred = it->second;
|
||||
nbtx_last_req_handle_map.erase(it);
|
||||
h.add_relation(rel_str(PREDECESSOR_SUCCESSOR), pred);
|
||||
}
|
||||
break;
|
||||
case tlm::END_RESP:
|
||||
#ifdef NBDEBUG
|
||||
cout<<"retrieving parent with id "<<rec_parts.id<<" from nbtx_req_handle_map"<<std::endl;
|
||||
#endif
|
||||
it = nbtx_req_handle_map.find(rec_parts.id);
|
||||
if (it != nbtx_req_handle_map.end()) {
|
||||
h = it->second;
|
||||
nbtx_req_handle_map.erase(it);
|
||||
h.end_transaction();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
sc_assert(!"phase not supported!");
|
||||
}
|
||||
rec_parts.release();
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
template< typename TYPES>
|
||||
bool tlm2_recorder<TYPES>::get_direct_mem_ptr(typename TYPES::tlm_payload_type& trans, tlm::tlm_dmi& dmi_data) {
|
||||
if (!isRecordingEnabled()) {
|
||||
return fw_port->get_direct_mem_ptr(trans, dmi_data);
|
||||
}
|
||||
if (dmi_streamHandle == NULL) {
|
||||
string basename(this->name());
|
||||
dmi_streamHandle = new scv_tr_stream((basename + ".dmi").c_str(), "TRANSACTOR", m_db);
|
||||
dmi_trGetHandle = new scv_tr_generator<tlm_gp_data, tlm_dmi_data>("get_dmi_ptr", *b_streamHandle, "trans",
|
||||
"dmi_data");
|
||||
dmi_trInvalidateHandle = new scv_tr_generator<sc_dt::uint64, sc_dt::uint64>("invalidate", *b_streamHandle, "start_delay",
|
||||
"end_delay");
|
||||
}
|
||||
scv_tr_handle h = dmi_trGetHandle->begin_transaction(tlm_gp_data(trans));
|
||||
bool status= fw_port->get_direct_mem_ptr(trans, dmi_data);
|
||||
dmi_trGetHandle->end_transaction(h, tlm_dmi_data(dmi_data));
|
||||
return status;
|
||||
}
|
||||
/*! \brief The direct memory interface backward function
|
||||
*
|
||||
* This type of transaction is just forwarded and not recorded.
|
||||
* \param start_addr is the start address of the memory area being invalid
|
||||
* \param end_addr is the end address of the memory area being invalid
|
||||
*/
|
||||
template< typename TYPES>
|
||||
void tlm2_recorder<TYPES>::invalidate_direct_mem_ptr(sc_dt::uint64 start_addr, sc_dt::uint64 end_addr) {
|
||||
if (!isRecordingEnabled()) {
|
||||
bw_port->invalidate_direct_mem_ptr(start_addr, end_addr);
|
||||
return;
|
||||
}
|
||||
if (dmi_streamHandle == NULL) {
|
||||
string basename(this->name());
|
||||
dmi_streamHandle = new scv_tr_stream((basename + ".dmi").c_str(), "TRANSACTOR", m_db);
|
||||
dmi_trGetHandle = new scv_tr_generator<tlm_gp_data, tlm_dmi_data>("get_dmi_ptr", *b_streamHandle, "trans",
|
||||
"dmi_data");
|
||||
dmi_trInvalidateHandle = new scv_tr_generator<sc_dt::uint64, sc_dt::uint64>("invalidate", *b_streamHandle, "start_delay",
|
||||
"end_delay");
|
||||
}
|
||||
scv_tr_handle h = dmi_trInvalidateHandle->begin_transaction(start_addr);
|
||||
bw_port->invalidate_direct_mem_ptr(start_addr, end_addr);
|
||||
dmi_trInvalidateHandle->end_transaction(h, end_addr);
|
||||
return;
|
||||
}
|
||||
/*! \brief The debug transportfunction
|
||||
*
|
||||
* This type of transaction is just forwarded and not recorded.
|
||||
* \param trans is the generic payload of the transaction
|
||||
* \return the sync state of the transaction
|
||||
*/
|
||||
template< typename TYPES>
|
||||
unsigned int tlm2_recorder<TYPES>::transport_dbg(typename TYPES::tlm_payload_type& trans) {
|
||||
unsigned int count = fw_port->transport_dbg(trans);
|
||||
return count;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
|
||||
#endif /* TLM2_RECORDER_H_ */
|
|
@ -1,61 +0,0 @@
|
|||
/*
|
||||
* tlm_recorder.h
|
||||
*
|
||||
* Created on: 07.11.2015
|
||||
* Author: eyck
|
||||
*/
|
||||
|
||||
#ifndef TLM2_RECORDER_MODULE_H_
|
||||
#define TLM2_RECORDER_MODULE_H_
|
||||
|
||||
#include <tlm_utils/simple_initiator_socket.h>
|
||||
#include <tlm_utils/simple_target_socket.h>
|
||||
#include "tlm2_recorder.h"
|
||||
|
||||
namespace scv4tlm {
|
||||
/*! \brief The TLM2 transaction recorder
|
||||
*
|
||||
* This module records all TLM transaction to a SCV transaction stream for further viewing and analysis.
|
||||
* The handle of the created transaction is storee in an tlm_extension so that another instance of the scv_tlm2_recorder
|
||||
* e.g. further down the opath can link to it.
|
||||
* The transaction recorder is simply bound between an existing pair of initiator and target sockets
|
||||
*/
|
||||
template<unsigned int BUSWIDTH = 32, typename TYPES=tlm::tlm_base_protocol_types>
|
||||
class tlm2_recorder_module: public sc_core::sc_module, public tlm2_recorder<TYPES> {
|
||||
public:
|
||||
SC_HAS_PROCESS(tlm2_recorder_module);
|
||||
//! The target socket of the recorder to be bound to the initiator
|
||||
tlm::tlm_target_socket<BUSWIDTH, TYPES, 1> target;
|
||||
//! The initiator to be bound to the target socket
|
||||
tlm::tlm_initiator_socket<BUSWIDTH, TYPES, 1> initiator;
|
||||
|
||||
|
||||
/*! \brief The constructor of the component
|
||||
*
|
||||
* \param name is the SystemC module name of the recorder
|
||||
* \param tr_db is a pointer to a transaction recording database. If none is provided the default one is retrieved.
|
||||
* If this database is not initialized (e.g. by not calling scv_tr_db::set_default_db() ) recording is disabled.
|
||||
*/
|
||||
tlm2_recorder_module(sc_core::sc_module_name name, bool recording_enabled = true, scv_tr_db* tr_db = scv_tr_db::get_default_db())
|
||||
: sc_module(name)
|
||||
, tlm2_recorder<TYPES>(recording_enabled, tr_db)
|
||||
{
|
||||
// bind the sockets to the module
|
||||
target.bind(*this);
|
||||
initiator.bind(*this);
|
||||
}
|
||||
|
||||
virtual ~tlm2_recorder_module(){}
|
||||
|
||||
virtual tlm::tlm_fw_transport_if<tlm::tlm_base_protocol_types>* get_fw_if() {
|
||||
return initiator.get_base_port().operator->();
|
||||
}
|
||||
virtual tlm::tlm_bw_transport_if<tlm::tlm_base_protocol_types>* get_bw_if() {
|
||||
return target.get_base_port().operator->();
|
||||
}
|
||||
|
||||
};
|
||||
} // namespace
|
||||
|
||||
|
||||
#endif /* TLM2_RECORDER_MODULE_H_ */
|
|
@ -1,557 +0,0 @@
|
|||
/*
|
||||
* tlm_gp_data.h
|
||||
*
|
||||
* Created on: 07.11.2015
|
||||
* Author: eyck
|
||||
*/
|
||||
|
||||
#ifndef TLM_GP_DATA_H_
|
||||
#define TLM_GP_DATA_H_
|
||||
|
||||
#include <tlm>
|
||||
#include <assert.h>
|
||||
|
||||
namespace scv4tlm {
|
||||
|
||||
struct tlm_gp_data {
|
||||
//---------------
|
||||
// Constructors
|
||||
//---------------
|
||||
|
||||
// Default constructor
|
||||
tlm_gp_data()
|
||||
: address(0)
|
||||
, command(tlm::TLM_IGNORE_COMMAND)
|
||||
, data(0)
|
||||
, data_length(0)
|
||||
, response_status(tlm::TLM_INCOMPLETE_RESPONSE)
|
||||
, dmi(false)
|
||||
, byte_enable(0)
|
||||
, byte_enable_length(0)
|
||||
, streaming_width(0)
|
||||
, gp_option(tlm::TLM_MIN_PAYLOAD)
|
||||
, m_extensions(tlm::max_num_extensions())
|
||||
, m_ref_count(0)
|
||||
{
|
||||
}
|
||||
|
||||
explicit tlm_gp_data(tlm::tlm_mm_interface* mm)
|
||||
: address(0)
|
||||
, command(tlm::TLM_IGNORE_COMMAND)
|
||||
, data(0)
|
||||
, data_length(0)
|
||||
, response_status(tlm::TLM_INCOMPLETE_RESPONSE)
|
||||
, dmi(false)
|
||||
, byte_enable(0)
|
||||
, byte_enable_length(0)
|
||||
, streaming_width(0)
|
||||
, gp_option(tlm::TLM_MIN_PAYLOAD)
|
||||
, m_extensions(tlm::max_num_extensions())
|
||||
, m_ref_count(0) {
|
||||
}
|
||||
|
||||
int get_ref_count() const {
|
||||
return m_ref_count;
|
||||
}
|
||||
|
||||
void reset() {
|
||||
//should the other members be reset too?
|
||||
gp_option = tlm::TLM_MIN_PAYLOAD;
|
||||
m_extensions.free_entire_cache();
|
||||
}
|
||||
;
|
||||
|
||||
tlm_gp_data(const tlm::tlm_generic_payload& x)
|
||||
: address(x.get_address())
|
||||
, command(x.get_command())
|
||||
, data(x.get_data_ptr())
|
||||
, data_length(x.get_data_length())
|
||||
, response_status(x.get_response_status())
|
||||
, dmi(x.is_dmi_allowed())
|
||||
, byte_enable(x.get_byte_enable_ptr())
|
||||
, byte_enable_length(x.get_byte_enable_length())
|
||||
, streaming_width(x.get_streaming_width())
|
||||
, gp_option(x.get_gp_option())
|
||||
, m_extensions(tlm::max_num_extensions())
|
||||
, m_ref_count(0)
|
||||
{
|
||||
}
|
||||
private:
|
||||
//disabled copy ctor and assignment operator.
|
||||
// Copy constructor
|
||||
tlm_gp_data(const tlm_gp_data& x)
|
||||
: address(x.get_address())
|
||||
, command(x.get_command())
|
||||
, data(x.get_data_ptr())
|
||||
, data_length(x.get_data_length())
|
||||
, response_status(x.get_response_status())
|
||||
, dmi(x.is_dmi_allowed())
|
||||
, byte_enable(x.get_byte_enable_ptr())
|
||||
, byte_enable_length(x.get_byte_enable_length())
|
||||
, streaming_width(x.get_streaming_width())
|
||||
, gp_option(x.gp_option)
|
||||
, m_extensions(tlm::max_num_extensions())
|
||||
, m_ref_count(0)
|
||||
{
|
||||
}
|
||||
public:
|
||||
// Assignment operator needed for SCV introspection
|
||||
tlm_gp_data& operator=(const tlm_gp_data& x) {
|
||||
command = x.get_command();
|
||||
address = x.get_address();
|
||||
data = x.get_data_ptr();
|
||||
data_length = x.get_data_length();
|
||||
response_status = x.get_response_status();
|
||||
byte_enable = x.get_byte_enable_ptr();
|
||||
byte_enable_length = x.get_byte_enable_length();
|
||||
streaming_width = x.get_streaming_width();
|
||||
gp_option = x.get_gp_option();
|
||||
dmi = x.is_dmi_allowed();
|
||||
|
||||
// extension copy: all extension arrays must be of equal size by
|
||||
// construction (i.e. it must either be constructed after C++
|
||||
// static construction time, or the resize_extensions() method must
|
||||
// have been called prior to using the object)
|
||||
for (unsigned int i = 0; i < m_extensions.size(); i++) {
|
||||
m_extensions[i] = x.get_extension(i);
|
||||
}
|
||||
return (*this);
|
||||
}
|
||||
|
||||
// non-virtual deep-copying of the object
|
||||
void deep_copy_from(const scv4tlm::tlm_gp_data & other) {
|
||||
command = other.get_command();
|
||||
address = other.get_address();
|
||||
data_length = other.get_data_length();
|
||||
response_status = other.get_response_status();
|
||||
byte_enable_length = other.get_byte_enable_length();
|
||||
streaming_width = other.get_streaming_width();
|
||||
gp_option = other.get_gp_option();
|
||||
dmi = other.is_dmi_allowed();
|
||||
|
||||
// deep copy data
|
||||
// there must be enough space in the target transaction!
|
||||
if (data && other.get_data_ptr()) {
|
||||
memcpy(data, other.get_data_ptr(), data_length);
|
||||
}
|
||||
// deep copy byte enables
|
||||
// there must be enough space in the target transaction!
|
||||
if (byte_enable && other.get_byte_enable_ptr()) {
|
||||
memcpy(byte_enable, other.get_byte_enable_ptr(), byte_enable_length);
|
||||
}
|
||||
// deep copy extensions (sticky and non-sticky)
|
||||
for (unsigned int i = 0; i < other.m_extensions.size(); i++) {
|
||||
if (other.get_extension(i)) { //original has extension i
|
||||
if (!m_extensions[i]) { //We don't: clone.
|
||||
tlm::tlm_extension_base *ext = other.get_extension(i)->clone();
|
||||
if (ext) //extension may not be clonable.
|
||||
{
|
||||
set_extension(i, ext);
|
||||
}
|
||||
} else { //We already have such extension. Copy original over it.
|
||||
m_extensions[i]->copy_from(*other.get_extension(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::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
|
||||
response_status = other.get_response_status();
|
||||
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() && data && other.get_data_ptr() && data != other.get_data_ptr()) {
|
||||
if (byte_enable && use_byte_enable_on_read) {
|
||||
if (byte_enable_length == 8 && data_length % 8 == 0) {
|
||||
// Optimized implementation copies 64-bit words by masking
|
||||
for (unsigned int i = 0; i < data_length; i += 8) {
|
||||
typedef sc_dt::uint64* u;
|
||||
*reinterpret_cast<u>(&data[i]) &= ~*reinterpret_cast<u>(byte_enable);
|
||||
*reinterpret_cast<u>(&data[i]) |= *reinterpret_cast<u>(&other.get_data_ptr()[i])
|
||||
& *reinterpret_cast<u>(byte_enable);
|
||||
}
|
||||
} else if (byte_enable_length == 4 && data_length % 4 == 0) {
|
||||
// Optimized implementation copies 32-bit words by masking
|
||||
for (unsigned int i = 0; i < data_length; i += 4) {
|
||||
typedef unsigned int* u;
|
||||
*reinterpret_cast<u>(&data[i]) &= ~*reinterpret_cast<u>(byte_enable);
|
||||
*reinterpret_cast<u>(&data[i]) |= *reinterpret_cast<u>(&other.get_data_ptr()[i])
|
||||
& *reinterpret_cast<u>(byte_enable);
|
||||
}
|
||||
} else
|
||||
// Unoptimized implementation
|
||||
for (unsigned int i = 0; i < data_length; i++)
|
||||
if (byte_enable[i % byte_enable_length])
|
||||
data[i] = other.get_data_ptr()[i];
|
||||
} else
|
||||
memcpy(data, other.get_data_ptr(), data_length);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
void update_extensions_from(const tlm::tlm_generic_payload & other) {
|
||||
// deep copy extensions that are already present
|
||||
for (unsigned int i = 0; i < tlm::max_num_extensions(); i++) {
|
||||
if (other.get_extension(i)) { //original has extension i
|
||||
if (m_extensions[i]) { //We have it too. copy.
|
||||
m_extensions[i]->copy_from(*other.get_extension(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
// Free all extensions. Useful when reusing a cloned transaction that doesn't have memory manager.
|
||||
// normal and sticky extensions are freed and extension array cleared.
|
||||
void free_all_extensions() {
|
||||
m_extensions.free_entire_cache();
|
||||
for (unsigned int i = 0; i < m_extensions.size(); i++) {
|
||||
if (m_extensions[i]) {
|
||||
m_extensions[i]->free();
|
||||
m_extensions[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
//--------------
|
||||
// Destructor
|
||||
//--------------
|
||||
virtual ~tlm_gp_data() {
|
||||
for(unsigned int i=0; i<m_extensions.size(); i++)
|
||||
if(m_extensions[i]) m_extensions[i]->free();
|
||||
}
|
||||
|
||||
//----------------
|
||||
// API (including setters & getters)
|
||||
//---------------
|
||||
|
||||
// Command related method
|
||||
bool is_read() const {
|
||||
return (command == tlm::TLM_READ_COMMAND);
|
||||
}
|
||||
void set_read() {
|
||||
command = tlm::TLM_READ_COMMAND;
|
||||
}
|
||||
bool is_write() const {
|
||||
return (command == tlm::TLM_WRITE_COMMAND);
|
||||
}
|
||||
void set_write() {
|
||||
command = tlm::TLM_WRITE_COMMAND;
|
||||
}
|
||||
tlm::tlm_command get_command() const {
|
||||
return command;
|
||||
}
|
||||
void set_command(const tlm::tlm_command command) {
|
||||
this->command = command;
|
||||
}
|
||||
|
||||
// Address related methods
|
||||
sc_dt::uint64 get_address() const {
|
||||
return address;
|
||||
}
|
||||
void set_address(const sc_dt::uint64 address) {
|
||||
this->address = address;
|
||||
}
|
||||
|
||||
// Data related methods
|
||||
unsigned char* get_data_ptr() const {
|
||||
return data;
|
||||
}
|
||||
void set_data_ptr(unsigned char* data) {
|
||||
this->data = data;
|
||||
}
|
||||
|
||||
// Transaction length (in bytes) related methods
|
||||
unsigned int get_data_length() const {
|
||||
return data_length;
|
||||
}
|
||||
void set_data_length(const unsigned int length) {
|
||||
data_length = length;
|
||||
}
|
||||
|
||||
// Response status related methods
|
||||
bool is_response_ok() const {
|
||||
return (response_status > 0);
|
||||
}
|
||||
bool is_response_error() const {
|
||||
return (response_status <= 0);
|
||||
}
|
||||
tlm::tlm_response_status get_response_status() const {
|
||||
return response_status;
|
||||
}
|
||||
void set_response_status(const tlm::tlm_response_status response_status) {
|
||||
this->response_status = response_status;
|
||||
}
|
||||
std::string get_response_string() const {
|
||||
switch (response_status) {
|
||||
case tlm::TLM_OK_RESPONSE:
|
||||
return "TLM_OK_RESPONSE";
|
||||
case tlm::TLM_INCOMPLETE_RESPONSE:
|
||||
return "TLM_INCOMPLETE_RESPONSE";
|
||||
case tlm::TLM_GENERIC_ERROR_RESPONSE:
|
||||
return "TLM_GENERIC_ERROR_RESPONSE";
|
||||
case tlm::TLM_ADDRESS_ERROR_RESPONSE:
|
||||
return "TLM_ADDRESS_ERROR_RESPONSE";
|
||||
case tlm::TLM_COMMAND_ERROR_RESPONSE:
|
||||
return "TLM_COMMAND_ERROR_RESPONSE";
|
||||
case tlm::TLM_BURST_ERROR_RESPONSE:
|
||||
return "TLM_BURST_ERROR_RESPONSE";
|
||||
case tlm::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 streaming_width;
|
||||
}
|
||||
void set_streaming_width(const unsigned int streaming_width) {
|
||||
this->streaming_width = streaming_width;
|
||||
}
|
||||
|
||||
// Byte enable related methods
|
||||
unsigned char* get_byte_enable_ptr() const {
|
||||
return byte_enable;
|
||||
}
|
||||
void set_byte_enable_ptr(unsigned char* byte_enable) {
|
||||
this->byte_enable = byte_enable;
|
||||
}
|
||||
unsigned int get_byte_enable_length() const {
|
||||
return byte_enable_length;
|
||||
}
|
||||
void set_byte_enable_length(const unsigned int byte_enable_length) {
|
||||
this->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) {
|
||||
dmi = dmi_allowed;
|
||||
}
|
||||
bool is_dmi_allowed() const {
|
||||
return dmi;
|
||||
}
|
||||
|
||||
// Use full set of attributes in DMI/debug?
|
||||
tlm::tlm_gp_option get_gp_option() const {
|
||||
return gp_option;
|
||||
}
|
||||
void set_gp_option(const tlm::tlm_gp_option gp_opt) {
|
||||
gp_option = gp_opt;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
/* 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 address;
|
||||
tlm::tlm_command command;
|
||||
unsigned char* data;
|
||||
unsigned int data_length;
|
||||
tlm::tlm_response_status response_status;
|
||||
bool dmi;
|
||||
unsigned char* byte_enable;
|
||||
unsigned int byte_enable_length;
|
||||
unsigned int streaming_width;
|
||||
tlm::tlm_gp_option gp_option;
|
||||
|
||||
public:
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
/* Dynamic extension mechanism: */
|
||||
/* --------------------------------------------------------------------- */
|
||||
/* The extension mechanism is intended to enable initiator modules to */
|
||||
/* optionally and transparently add data fields to the */
|
||||
/* tlm_generic_payload. Target modules are free to check for extensions */
|
||||
/* and may or may not react to the data in the extension fields. The */
|
||||
/* definition of the extensions' semantics is solely in the */
|
||||
/* responsibility of the user. */
|
||||
/* */
|
||||
/* The following rules apply: */
|
||||
/* */
|
||||
/* - Every extension class must be derived from tlm_extension, e.g.: */
|
||||
/* class my_extension : public tlm_extension<my_extension> { ... } */
|
||||
/* */
|
||||
/* - A tlm_generic_payload object should be constructed after C++ */
|
||||
/* static initialization time. This way it is guaranteed that the */
|
||||
/* extension array is of sufficient size to hold all possible */
|
||||
/* extensions. Alternatively, the initiator module can enforce a valid */
|
||||
/* extension array size by calling the resize_extensions() method */
|
||||
/* once before the first transaction with the payload object is */
|
||||
/* initiated. */
|
||||
/* */
|
||||
/* - Initiators should use the the set_extension(e) or clear_extension(e)*/
|
||||
/* methods for manipulating the extension array. The type of the */
|
||||
/* argument must be a pointer to the specific registered extension */
|
||||
/* type (my_extension in the above example) and is used to */
|
||||
/* automatically locate the appropriate index in the array. */
|
||||
/* */
|
||||
/* - Targets can check for a specific extension by calling */
|
||||
/* get_extension(e). e will point to zero if the extension is not */
|
||||
/* present. */
|
||||
/* */
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
// Stick the pointer to an extension into the vector, return the
|
||||
// previous value:
|
||||
template<typename T> T* set_extension(T* ext) {
|
||||
return static_cast<T*>(set_extension(T::ID, ext));
|
||||
}
|
||||
|
||||
// non-templatized version with manual index:
|
||||
tlm::tlm_extension_base* set_extension(unsigned int index, tlm::tlm_extension_base* ext) {
|
||||
tlm::tlm_extension_base* tmp = m_extensions[index];
|
||||
m_extensions[index] = ext;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
// Check for an extension, ext will point to 0 if not present
|
||||
template<typename T> void get_extension(T*& ext) const {
|
||||
ext = get_extension<T>();
|
||||
}
|
||||
template<typename T> T* get_extension() const {
|
||||
return static_cast<T*>(get_extension(T::ID));
|
||||
}
|
||||
// Non-templatized version with manual index:
|
||||
tlm::tlm_extension_base* get_extension(unsigned int index) const {
|
||||
return m_extensions[index];
|
||||
}
|
||||
|
||||
//this call just removes the extension from the txn but does not
|
||||
// call free() or tells the MM to do so
|
||||
// it return false if there was active MM so you are now in an unsafe situation
|
||||
// recommended use: when 100% sure there is no MM
|
||||
template<typename T> void clear_extension(const T* ext) {
|
||||
clear_extension<T>();
|
||||
}
|
||||
|
||||
//this call just removes the extension from the txn but does not
|
||||
// call free() or tells the MM to do so
|
||||
// it return false if there was active MM so you are now in an unsafe situation
|
||||
// recommended use: when 100% sure there is no MM
|
||||
template<typename T> void clear_extension() {
|
||||
clear_extension(T::ID);
|
||||
}
|
||||
|
||||
//this call removes the extension from the txn and does
|
||||
// call free() or tells the MM to do so when the txn is finally done
|
||||
// recommended use: when not sure there is no MM
|
||||
template<typename T> void release_extension(T* ext) {
|
||||
release_extension<T>();
|
||||
}
|
||||
|
||||
//this call removes the extension from the txn and does
|
||||
// call free() or tells the MM to do so when the txn is finally done
|
||||
// recommended use: when not sure there is no MM
|
||||
template<typename T> void release_extension() {
|
||||
release_extension(T::ID);
|
||||
}
|
||||
|
||||
private:
|
||||
// Non-templatized version with manual index
|
||||
void clear_extension(unsigned int index) {
|
||||
m_extensions[index] = static_cast<tlm::tlm_extension_base*>(0);
|
||||
}
|
||||
// Non-templatized version with manual index
|
||||
void release_extension(unsigned int index) {
|
||||
m_extensions[index]->free();
|
||||
m_extensions[index] = static_cast<tlm::tlm_extension_base*>(0);
|
||||
}
|
||||
|
||||
public:
|
||||
// Make sure the extension array is large enough. Can be called once by
|
||||
// an initiator module (before issuing the first transaction) to make
|
||||
// sure that the extension array is of correct size. This is only needed
|
||||
// if the initiator cannot guarantee that the generic payload object is
|
||||
// allocated after C++ static construction time.
|
||||
void resize_extensions() {
|
||||
m_extensions.expand(tlm::max_num_extensions());
|
||||
}
|
||||
|
||||
private:
|
||||
tlm::tlm_array<tlm::tlm_extension_base*> m_extensions;
|
||||
unsigned int m_ref_count;
|
||||
};
|
||||
|
||||
|
||||
struct tlm_dmi_data {
|
||||
tlm_dmi_data()
|
||||
:dmi_ptr(0)
|
||||
,dmi_start_address(0)
|
||||
,dmi_end_address(0)
|
||||
,dmi_access(tlm::tlm_dmi::DMI_ACCESS_NONE)
|
||||
,dmi_read_latency(0)
|
||||
,dmi_write_latency(0)
|
||||
{}
|
||||
|
||||
tlm_dmi_data(tlm::tlm_dmi& dmi_data)
|
||||
:dmi_ptr(dmi_data.get_dmi_ptr())
|
||||
,dmi_start_address(dmi_data.get_start_address())
|
||||
,dmi_end_address(dmi_data.get_end_address())
|
||||
,dmi_access(dmi_data.get_granted_access())
|
||||
,dmi_read_latency(dmi_data.get_read_latency().value())
|
||||
,dmi_write_latency(dmi_data.get_write_latency().value())
|
||||
{}
|
||||
//--------------
|
||||
// Destructor
|
||||
//--------------
|
||||
virtual ~tlm_dmi_data() {}
|
||||
|
||||
unsigned char* dmi_ptr;
|
||||
sc_dt::uint64 dmi_start_address;
|
||||
sc_dt::uint64 dmi_end_address;
|
||||
tlm::tlm_dmi::dmi_access_e dmi_access;
|
||||
sc_dt::uint64 dmi_read_latency;
|
||||
sc_dt::uint64 dmi_write_latency;
|
||||
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
#endif /* TLM_GP_DATA_H_ */
|
|
@ -1,131 +0,0 @@
|
|||
/*
|
||||
* tlm_gp_data_ext.h
|
||||
*
|
||||
* Created on: 07.11.2015
|
||||
* Author: eyck
|
||||
*/
|
||||
|
||||
#ifndef TLM_GP_DATA_EXT_H_
|
||||
#define TLM_GP_DATA_EXT_H_
|
||||
|
||||
#include "scv.h"
|
||||
#include "tlm_gp_data.h"
|
||||
|
||||
template<>
|
||||
class scv_extensions<tlm::tlm_command> : public scv_enum_base<tlm::tlm_command> {
|
||||
public:
|
||||
SCV_ENUM_CTOR(tlm::tlm_command) {
|
||||
SCV_ENUM(tlm::TLM_READ_COMMAND);
|
||||
SCV_ENUM(tlm::TLM_WRITE_COMMAND);
|
||||
SCV_ENUM(tlm::TLM_IGNORE_COMMAND);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
class scv_extensions<tlm::tlm_response_status> : public scv_enum_base<tlm::tlm_response_status> {
|
||||
public:
|
||||
SCV_ENUM_CTOR(tlm::tlm_response_status) {
|
||||
SCV_ENUM(tlm::TLM_OK_RESPONSE);
|
||||
SCV_ENUM(tlm::TLM_INCOMPLETE_RESPONSE);
|
||||
SCV_ENUM(tlm::TLM_GENERIC_ERROR_RESPONSE);
|
||||
SCV_ENUM(tlm::TLM_ADDRESS_ERROR_RESPONSE);
|
||||
SCV_ENUM(tlm::TLM_COMMAND_ERROR_RESPONSE);
|
||||
SCV_ENUM(tlm::TLM_BURST_ERROR_RESPONSE);
|
||||
SCV_ENUM(tlm::TLM_BYTE_ENABLE_ERROR_RESPONSE);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
class scv_extensions<tlm::tlm_gp_option> : public scv_enum_base<tlm::tlm_gp_option> {
|
||||
public:
|
||||
SCV_ENUM_CTOR(tlm::tlm_gp_option) {
|
||||
SCV_ENUM(tlm::TLM_MIN_PAYLOAD);
|
||||
SCV_ENUM(tlm::TLM_FULL_PAYLOAD);
|
||||
SCV_ENUM(tlm::TLM_FULL_PAYLOAD_ACCEPTED);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
class scv_extensions<tlm::tlm_phase_enum> : public scv_enum_base<tlm::tlm_phase_enum> {
|
||||
public:
|
||||
SCV_ENUM_CTOR(tlm::tlm_phase_enum) {
|
||||
SCV_ENUM(tlm::UNINITIALIZED_PHASE);
|
||||
SCV_ENUM(tlm::BEGIN_REQ);
|
||||
SCV_ENUM(tlm::END_REQ);
|
||||
SCV_ENUM(tlm::BEGIN_RESP);
|
||||
SCV_ENUM(tlm::END_RESP);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
class scv_extensions<tlm::tlm_sync_enum> : public scv_enum_base<tlm::tlm_sync_enum> {
|
||||
public:
|
||||
SCV_ENUM_CTOR(tlm::tlm_sync_enum) {
|
||||
SCV_ENUM(tlm::TLM_ACCEPTED);
|
||||
SCV_ENUM(tlm::TLM_UPDATED);
|
||||
SCV_ENUM(tlm::TLM_COMPLETED);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
class scv_extensions<scv4tlm::tlm_gp_data> : public scv_extensions_base<scv4tlm::tlm_gp_data> {
|
||||
public:
|
||||
scv_extensions<sc_dt::uint64> address;
|
||||
scv_extensions<tlm::tlm_command> command;
|
||||
scv_extensions<unsigned char*> data;
|
||||
scv_extensions<unsigned int> data_length;
|
||||
scv_extensions<tlm::tlm_response_status> response_status;
|
||||
scv_extensions<bool> dmi;
|
||||
scv_extensions<unsigned char*> byte_enable;
|
||||
scv_extensions<unsigned int> byte_enable_length;
|
||||
scv_extensions<unsigned int> streaming_width;
|
||||
scv_extensions<tlm::tlm_gp_option> gp_option;
|
||||
|
||||
SCV_EXTENSIONS_CTOR(scv4tlm::tlm_gp_data) {
|
||||
//must be in order
|
||||
SCV_FIELD(address);
|
||||
SCV_FIELD(command);
|
||||
SCV_FIELD(data);
|
||||
SCV_FIELD(data_length);
|
||||
SCV_FIELD(response_status);
|
||||
SCV_FIELD(dmi);
|
||||
SCV_FIELD(byte_enable);
|
||||
SCV_FIELD(byte_enable_length);
|
||||
SCV_FIELD(streaming_width);
|
||||
SCV_FIELD(gp_option);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
class scv_extensions<tlm::tlm_dmi::dmi_access_e> : public scv_enum_base<tlm::tlm_dmi::dmi_access_e> {
|
||||
public:
|
||||
SCV_ENUM_CTOR(tlm::tlm_dmi::dmi_access_e) {
|
||||
SCV_ENUM(tlm::tlm_dmi::DMI_ACCESS_NONE);
|
||||
SCV_ENUM(tlm::tlm_dmi::DMI_ACCESS_READ);
|
||||
SCV_ENUM(tlm::tlm_dmi::DMI_ACCESS_WRITE);
|
||||
SCV_ENUM(tlm::tlm_dmi::DMI_ACCESS_READ_WRITE);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
class scv_extensions<scv4tlm::tlm_dmi_data> : public scv_extensions_base<scv4tlm::tlm_dmi_data> {
|
||||
public:
|
||||
scv_extensions<unsigned char*> dmi_ptr;
|
||||
scv_extensions<sc_dt::uint64> dmi_start_address;
|
||||
scv_extensions<sc_dt::uint64> dmi_end_address;
|
||||
scv_extensions<tlm::tlm_dmi::dmi_access_e> dmi_access;
|
||||
scv_extensions<sc_dt::uint64> dmi_read_latency;
|
||||
scv_extensions<sc_dt::uint64> dmi_write_latency;
|
||||
SCV_EXTENSIONS_CTOR(scv4tlm::tlm_dmi_data) {
|
||||
//must be in order
|
||||
SCV_FIELD(dmi_ptr);
|
||||
SCV_FIELD(dmi_start_address);
|
||||
SCV_FIELD(dmi_end_address);
|
||||
SCV_FIELD(dmi_access);
|
||||
SCV_FIELD(dmi_read_latency);
|
||||
SCV_FIELD(dmi_write_latency);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#endif /* TLM_GP_DATA_EXT_H_ */
|
|
@ -1,125 +0,0 @@
|
|||
/*
|
||||
* tlm_rec_target_socket.h
|
||||
*
|
||||
* Created on: 08.11.2015
|
||||
* Author: eyck
|
||||
*/
|
||||
|
||||
#ifndef TLM_REC_INITIATOR_SOCKET_H_
|
||||
#define TLM_REC_INITIATOR_SOCKET_H_
|
||||
|
||||
#include <tlm_core/tlm_2/tlm_sockets/tlm_initiator_socket.h>
|
||||
|
||||
#include "tlm2_recorder.h"
|
||||
|
||||
namespace scv4tlm {
|
||||
template<unsigned int BUSWIDTH = 32, typename TYPES = tlm::tlm_base_protocol_types, int N = 1
|
||||
#if !(defined SYSTEMC_VERSION & SYSTEMC_VERSION <= 20050714)
|
||||
, sc_core::sc_port_policy POL = sc_core::SC_ONE_OR_MORE_BOUND
|
||||
#endif
|
||||
>
|
||||
class tlm_rec_initiator_socket: public tlm::tlm_initiator_socket<BUSWIDTH
|
||||
, TYPES
|
||||
, N
|
||||
#if !(defined SYSTEMC_VERSION & SYSTEMC_VERSION <= 20050714)
|
||||
, POL
|
||||
#endif
|
||||
> {
|
||||
static std::string gen_name(const char* first, const char* second){
|
||||
std::stringstream ss;
|
||||
ss<<first<<"_"<<second;
|
||||
return ss.str();
|
||||
}
|
||||
public:
|
||||
typedef tlm::tlm_fw_transport_if<TYPES> fw_interface_type;
|
||||
typedef tlm::tlm_bw_transport_if<TYPES> bw_interface_type;
|
||||
typedef sc_core::sc_port<fw_interface_type, N
|
||||
#if !(defined SYSTEMC_VERSION & SYSTEMC_VERSION <= 20050714)
|
||||
, POL
|
||||
#endif
|
||||
> port_type;
|
||||
typedef sc_core::sc_export<bw_interface_type> export_type;
|
||||
typedef tlm::tlm_base_target_socket_b<BUSWIDTH,
|
||||
fw_interface_type,
|
||||
bw_interface_type> base_target_socket_type;
|
||||
typedef tlm::tlm_base_initiator_socket_b<BUSWIDTH,
|
||||
fw_interface_type,
|
||||
bw_interface_type> base_type;
|
||||
|
||||
tlm_rec_initiator_socket() :
|
||||
tlm::tlm_initiator_socket<BUSWIDTH
|
||||
, TYPES
|
||||
, N
|
||||
#if !(defined SYSTEMC_VERSION & SYSTEMC_VERSION <= 20050714)
|
||||
, POL
|
||||
#endif
|
||||
>()
|
||||
,recorder()
|
||||
{
|
||||
}
|
||||
|
||||
explicit tlm_rec_initiator_socket(const char* name) :
|
||||
tlm::tlm_initiator_socket<BUSWIDTH
|
||||
, TYPES
|
||||
, N
|
||||
#if !(defined SYSTEMC_VERSION & SYSTEMC_VERSION <= 20050714)
|
||||
, POL
|
||||
#endif
|
||||
>(name)
|
||||
,recorder(gen_name(name, "rec").c_str())
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~tlm_rec_initiator_socket(){}
|
||||
|
||||
virtual const char* kind() const {
|
||||
return "tlm_rec_target_socket";
|
||||
}
|
||||
//
|
||||
// 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
|
||||
(this->get_base_port())(recorder);
|
||||
recorder.fw_port(s.get_base_interface());
|
||||
// target.port -> initiator.export
|
||||
(s.get_base_port())(recorder);
|
||||
recorder.bw_port(this->get_base_interface());
|
||||
}
|
||||
//
|
||||
// Bind initiator socket to initiator socket (hierarchical bind)
|
||||
// - Binds both the export and the port
|
||||
//
|
||||
virtual void bind(base_type& s){
|
||||
// port
|
||||
(this->get_base_port())(recorder);
|
||||
recorder.fw_port(s.get_base_port());
|
||||
// export
|
||||
(s.get_base_export())(recorder);
|
||||
recorder.bw_port(this->get_base_export());
|
||||
}
|
||||
|
||||
//
|
||||
// Bind interface to socket
|
||||
// - Binds the interface to the export of this socket
|
||||
//
|
||||
virtual void bind(bw_interface_type& ifs) {
|
||||
(this->get_base_export())(ifs);
|
||||
}
|
||||
|
||||
void setExtensionRecording(tlm_extensions_recording_if<TYPES>* extensionRecording){
|
||||
recorder.setExtensionRecording(extensionRecording);
|
||||
}
|
||||
|
||||
protected:
|
||||
scv4tlm::tlm2_recorder<TYPES> recorder;
|
||||
};
|
||||
|
||||
}
|
||||
// namespace scv4tlm
|
||||
|
||||
#endif /* TLM_REC_TARGET_SOCKET_H_ */
|
|
@ -1,119 +0,0 @@
|
|||
/*
|
||||
* tlm_rec_target_socket.h
|
||||
*
|
||||
* Created on: 08.11.2015
|
||||
* Author: eyck
|
||||
*/
|
||||
|
||||
#ifndef TLM_REC_TARGET_SOCKET_H_
|
||||
#define TLM_REC_TARGET_SOCKET_H_
|
||||
|
||||
#include <tlm_core/tlm_2/tlm_sockets/tlm_target_socket.h>
|
||||
|
||||
#include "tlm2_recorder.h"
|
||||
|
||||
namespace scv4tlm {
|
||||
template<unsigned int BUSWIDTH = 32, typename TYPES = tlm::tlm_base_protocol_types, int N = 1
|
||||
#if !(defined SYSTEMC_VERSION & SYSTEMC_VERSION <= 20050714)
|
||||
, sc_core::sc_port_policy POL = sc_core::SC_ONE_OR_MORE_BOUND
|
||||
#endif
|
||||
>
|
||||
class tlm_rec_target_socket: public tlm::tlm_target_socket<BUSWIDTH
|
||||
, TYPES
|
||||
, N
|
||||
#if !(defined SYSTEMC_VERSION & SYSTEMC_VERSION <= 20050714)
|
||||
, POL
|
||||
#endif
|
||||
> {
|
||||
static std::string gen_name(const char* first, const char* second){
|
||||
std::stringstream ss;
|
||||
ss<<first<<"_"<<second;
|
||||
return ss.str();
|
||||
}
|
||||
public:
|
||||
typedef tlm::tlm_fw_transport_if<TYPES> fw_interface_type;
|
||||
typedef tlm::tlm_bw_transport_if<TYPES> bw_interface_type;
|
||||
typedef sc_core::sc_port<bw_interface_type, N
|
||||
#if !(defined SYSTEMC_VERSION & SYSTEMC_VERSION <= 20050714)
|
||||
, POL
|
||||
#endif
|
||||
> port_type;
|
||||
|
||||
typedef sc_core::sc_export<fw_interface_type> export_type;
|
||||
typedef tlm::tlm_base_initiator_socket_b<BUSWIDTH, fw_interface_type, bw_interface_type> base_initiator_socket_type;
|
||||
|
||||
typedef tlm::tlm_base_target_socket_b<BUSWIDTH, fw_interface_type, bw_interface_type> base_type;
|
||||
|
||||
tlm_rec_target_socket() :
|
||||
tlm::tlm_target_socket<BUSWIDTH
|
||||
, TYPES
|
||||
, N
|
||||
#if !(defined SYSTEMC_VERSION & SYSTEMC_VERSION <= 20050714)
|
||||
, POL
|
||||
#endif
|
||||
>()
|
||||
,recorder()
|
||||
{
|
||||
}
|
||||
|
||||
explicit tlm_rec_target_socket(const char* name) :
|
||||
tlm::tlm_target_socket<BUSWIDTH
|
||||
, TYPES
|
||||
, N
|
||||
#if !(defined SYSTEMC_VERSION & SYSTEMC_VERSION <= 20050714)
|
||||
, POL
|
||||
#endif
|
||||
>(name)
|
||||
,recorder(gen_name(name, "rec").c_str())
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~tlm_rec_target_socket(){}
|
||||
|
||||
virtual const char* kind() const {
|
||||
return "tlm_rec_target_socket";
|
||||
}
|
||||
//
|
||||
// Bind target socket to target socket (hierarchical bind)
|
||||
// - Binds both the export and the port
|
||||
//
|
||||
virtual void bind(base_type& s) {
|
||||
// export
|
||||
(this->get_base_export())(s.get_base_export()); // will be handled by bind(fw_interface_type& ifs)
|
||||
// port
|
||||
(s.get_base_port())(recorder); // bind the recording interface to the port, recording will use the m_port
|
||||
}
|
||||
//
|
||||
// Bind interface to socket
|
||||
// - Binds the interface to the export
|
||||
//
|
||||
virtual void bind(fw_interface_type& ifs){
|
||||
export_type* exp = &this->get_base_export();
|
||||
if( this == exp ) {
|
||||
export_type::bind(recorder); // non-virtual function call
|
||||
recorder.fw_port(ifs);
|
||||
recorder.bw_port(this->get_base_port());
|
||||
} else {
|
||||
exp->bind( ifs );
|
||||
}
|
||||
|
||||
}
|
||||
//
|
||||
// Forward to 'operator->()' of port class
|
||||
//
|
||||
bw_interface_type* operator->() {
|
||||
return &recorder;
|
||||
}
|
||||
|
||||
scv4tlm::tlm2_recorder<TYPES>& get_recorder(){
|
||||
return recorder;
|
||||
}
|
||||
|
||||
protected:
|
||||
scv4tlm::tlm2_recorder<TYPES> recorder;
|
||||
};
|
||||
|
||||
}
|
||||
// namespace scv4tlm
|
||||
|
||||
#endif /* TLM_REC_TARGET_SOCKET_H_ */
|
|
@ -1,77 +0,0 @@
|
|||
/*
|
||||
* tlm2_tx_record_extension.h
|
||||
*
|
||||
* Created on: 07.11.2015
|
||||
* Author: eyck
|
||||
*/
|
||||
|
||||
#ifndef TLM_RECORDING_EXTENSION_H_
|
||||
#define TLM_RECORDING_EXTENSION_H_
|
||||
|
||||
#include <scv.h>
|
||||
|
||||
namespace scv4tlm {
|
||||
|
||||
//! transaction relationships
|
||||
enum tx_rel {
|
||||
PARENT_CHILD = 0, /*!< indicates parent child relationship */
|
||||
PREDECESSOR_SUCCESSOR /*!< indicates predecessor successor relationship */
|
||||
};
|
||||
//! the string representation of the tx_rel
|
||||
static char const* tx_rel_str[] = { "PARENT/CHILD", "PRED/SUCC" };
|
||||
/*! \brief cast the tx_rel enum to a string
|
||||
*
|
||||
* \param tc_rel is the relationship enum
|
||||
*/
|
||||
inline const char* rel_str(tx_rel rel) {
|
||||
return (tx_rel_str[rel]);
|
||||
}
|
||||
|
||||
/*! \brief generic payload extension class holding the handle of the last recorded SCV transaction
|
||||
*
|
||||
* This extension is been used in the \ref scv_tlm2_recorder. The recorder stores the handle to the generated SCV transaction and
|
||||
* forwrds it along with the generic payload. If the recorder finds an extension containing a valid handle it links the generated
|
||||
* SCV transdaction to the found one using the \ref PREDECESSOR releationship
|
||||
*/
|
||||
struct tlm_recording_extension: public tlm::tlm_extension<tlm_recording_extension> {
|
||||
/*! \brief clone the given extension and duplicate the SCV transaction handle.
|
||||
*
|
||||
*/
|
||||
virtual tlm_extension_base* clone() const {
|
||||
tlm_recording_extension* t = new tlm_recording_extension(this->txHandle, this->creator);
|
||||
return t;
|
||||
}
|
||||
/*! \brief copy data between extensions.
|
||||
*
|
||||
* \param from is the source extension.
|
||||
*/
|
||||
virtual void copy_from(tlm_extension_base const& from) {
|
||||
txHandle = static_cast<tlm_recording_extension const &>(from).txHandle;
|
||||
creator = static_cast<tlm_recording_extension const &>(from).creator;
|
||||
}
|
||||
/*! \brief constructor storing the handle of the transaction and the owner of this extension
|
||||
*
|
||||
* \param handle is the handle of the created SCV transaction.
|
||||
* \param creator_ is the pointer to the owner of this extension (usually an instance of scv_tlm2_recorder).
|
||||
*/
|
||||
tlm_recording_extension(scv_tr_handle handle, void* creator_) :
|
||||
txHandle(handle), creator(creator_) {
|
||||
}
|
||||
/*! \brief accessor to the owner, the property is read only.
|
||||
*
|
||||
*/
|
||||
void* get_creator() {
|
||||
return creator;
|
||||
}
|
||||
/*! \brief accessor to the SCV transaction handle.
|
||||
*
|
||||
*/
|
||||
scv_tr_handle txHandle;
|
||||
private:
|
||||
//! the owner of this transaction
|
||||
void* creator;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* TLM_RECORDING_EXTENSION_H_ */
|
|
@ -1,383 +0,0 @@
|
|||
// -*- C++ -*- <this line is for emacs to recognize it as C++ code>
|
||||
/*****************************************************************************
|
||||
|
||||
The following code is derived, directly or indirectly, from the SystemC
|
||||
source code Copyright (c) 1996-2014 by all Contributors.
|
||||
All Rights reserved.
|
||||
|
||||
The contents of this file are subject to the restrictions and limitations
|
||||
set forth in the SystemC Open Source License (the "License");
|
||||
You may not use this file except in compliance with such restrictions and
|
||||
limitations. You may obtain instructions on how to receive a copy of the
|
||||
License at http://www.accellera.org/. Software distributed by Contributors
|
||||
under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
|
||||
ANY KIND, either express or implied. See the License for the specific
|
||||
language governing rights and limitations under the License.
|
||||
|
||||
*****************************************************************************/
|
||||
#include "scv.h"
|
||||
|
||||
// hack to fake a true fifo_mutex
|
||||
#define fifo_mutex sc_mutex
|
||||
|
||||
const unsigned ram_size = 256;
|
||||
|
||||
class rw_task_if: virtual public sc_interface {
|
||||
public:
|
||||
typedef sc_uint<8> addr_t;
|
||||
typedef sc_uint<8> data_t;
|
||||
struct write_t {
|
||||
addr_t addr;
|
||||
data_t data;
|
||||
};
|
||||
|
||||
virtual data_t read(const addr_t*) = 0;
|
||||
virtual void write(const write_t*) = 0;
|
||||
};
|
||||
|
||||
SCV_EXTENSIONS(rw_task_if::write_t){
|
||||
public:
|
||||
scv_extensions<rw_task_if::addr_t> addr;
|
||||
scv_extensions<rw_task_if::data_t> data;
|
||||
SCV_EXTENSIONS_CTOR(rw_task_if::write_t) {
|
||||
SCV_FIELD(addr);
|
||||
SCV_FIELD(data);
|
||||
}
|
||||
};
|
||||
|
||||
class pipelined_bus_ports: public sc_module {
|
||||
public:
|
||||
sc_in<bool> clk;
|
||||
sc_inout<bool> rw;
|
||||
sc_inout<bool> addr_req;
|
||||
sc_inout<bool> addr_ack;
|
||||
sc_inout<sc_uint<8> > bus_addr;
|
||||
sc_inout<bool> data_rdy;
|
||||
sc_inout<sc_uint<8> > bus_data;
|
||||
|
||||
SC_CTOR(pipelined_bus_ports) :
|
||||
clk("clk"), rw("rw"), addr_req("addr_req"), addr_ack("addr_ack"), bus_addr("bus_addr"), data_rdy("data_rdy"), bus_data(
|
||||
"bus_data") {
|
||||
}
|
||||
virtual void trace( sc_trace_file* tf ) const;
|
||||
};
|
||||
|
||||
void pipelined_bus_ports::trace( sc_trace_file* tf ) const {
|
||||
sc_trace(tf, clk, clk.name());
|
||||
sc_trace(tf, rw, rw.name());
|
||||
sc_trace(tf, addr_req, addr_req.name());
|
||||
sc_trace(tf, addr_ack, addr_ack.name());
|
||||
sc_trace(tf, bus_addr, bus_addr.name());
|
||||
sc_trace(tf, data_rdy, data_rdy.name());
|
||||
sc_trace(tf, bus_data, bus_data.name());
|
||||
}
|
||||
|
||||
class rw_pipelined_transactor: public rw_task_if, public pipelined_bus_ports {
|
||||
|
||||
fifo_mutex addr_phase;fifo_mutex data_phase;
|
||||
|
||||
scv_tr_stream pipelined_stream;
|
||||
scv_tr_stream addr_stream;
|
||||
scv_tr_stream data_stream;
|
||||
scv_tr_generator<sc_uint<8>, sc_uint<8> > read_gen;
|
||||
scv_tr_generator<sc_uint<8>, sc_uint<8> > write_gen;
|
||||
scv_tr_generator<sc_uint<8> > addr_gen;
|
||||
scv_tr_generator<_scv_tr_generator_default_data, sc_uint<8> > rdata_gen;
|
||||
scv_tr_generator<sc_uint<8> > wdata_gen;
|
||||
|
||||
public:
|
||||
rw_pipelined_transactor(sc_module_name nm)
|
||||
: pipelined_bus_ports(nm)
|
||||
, addr_phase("addr_phase")
|
||||
, data_phase("data_phase")
|
||||
, pipelined_stream((std::string(name()) +".pipelined_stream").c_str(), "transactor")
|
||||
, addr_stream( (std::string(name()) +".addr_stream").c_str(), "transactor")
|
||||
, data_stream((std::string(name()) +".data_stream").c_str(), "transactor")
|
||||
, read_gen("read", pipelined_stream, "addr", "data")
|
||||
, write_gen("write", pipelined_stream, "addr", "data")
|
||||
, addr_gen("addr", addr_stream, "addr")
|
||||
, rdata_gen("rdata", data_stream, NULL, "data")
|
||||
, wdata_gen("wdata", data_stream, "data")
|
||||
{
|
||||
}
|
||||
virtual data_t read(const addr_t* p_addr);
|
||||
virtual void write(const write_t * req);
|
||||
};
|
||||
|
||||
rw_task_if::data_t rw_pipelined_transactor::read(const addr_t* addr) {
|
||||
addr_phase.lock();
|
||||
scv_tr_handle h = read_gen.begin_transaction(*addr);
|
||||
h.record_attribute("data_size", sizeof(data_t));
|
||||
scv_tr_handle h1 = addr_gen.begin_transaction(*addr, "addr_phase", h);
|
||||
wait(clk->posedge_event());
|
||||
bus_addr = *addr;
|
||||
rw=false;
|
||||
addr_req = 1;
|
||||
wait(addr_ack->posedge_event());
|
||||
wait(clk->negedge_event());
|
||||
addr_req = 0;
|
||||
wait(addr_ack->negedge_event());
|
||||
addr_gen.end_transaction(h1);
|
||||
addr_phase.unlock();
|
||||
|
||||
data_phase.lock();
|
||||
scv_tr_handle h2 = rdata_gen.begin_transaction("data_phase", h);
|
||||
wait(data_rdy->posedge_event());
|
||||
data_t data = bus_data.read();
|
||||
wait(data_rdy->negedge_event());
|
||||
rdata_gen.end_transaction(h2, data);
|
||||
read_gen.end_transaction(h, data);
|
||||
data_phase.unlock();
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
void rw_pipelined_transactor::write(const write_t * req) {
|
||||
addr_phase.lock();
|
||||
scv_tr_handle h = write_gen.begin_transaction(req->addr);
|
||||
h.record_attribute("data_size", sizeof(data_t));
|
||||
scv_tr_handle h1 = addr_gen.begin_transaction(req->addr, "addr_phase", h);
|
||||
wait(clk->posedge_event());
|
||||
bus_addr = req->addr;
|
||||
rw=true;
|
||||
addr_req = 1;
|
||||
wait(addr_ack->posedge_event());
|
||||
wait(clk->negedge_event());
|
||||
addr_req = 0;
|
||||
wait(addr_ack->negedge_event());
|
||||
addr_gen.end_transaction(h1);
|
||||
addr_phase.unlock();
|
||||
|
||||
data_phase.lock();
|
||||
scv_tr_handle h2 = wdata_gen.begin_transaction(req->data, "data_phase", h);
|
||||
bus_data=req->data;
|
||||
wait(data_rdy->posedge_event());
|
||||
wait(data_rdy->negedge_event());
|
||||
wdata_gen.end_transaction(h2);
|
||||
write_gen.end_transaction(h, req->data);
|
||||
data_phase.unlock();
|
||||
}
|
||||
|
||||
class test: public sc_module {
|
||||
public:
|
||||
sc_port<rw_task_if> transactor;
|
||||
SC_HAS_PROCESS(test);
|
||||
test( ::sc_core::sc_module_name ){
|
||||
SC_THREAD(main1);
|
||||
SC_THREAD(main2);
|
||||
}
|
||||
void main1();
|
||||
void main2();
|
||||
};
|
||||
|
||||
class write_constraint: virtual public scv_constraint_base {
|
||||
public:
|
||||
scv_smart_ptr<rw_task_if::write_t> write;SCV_CONSTRAINT_CTOR(write_constraint) {
|
||||
SCV_CONSTRAINT(write->addr() <= ram_size);
|
||||
SCV_CONSTRAINT(write->addr() != write->data());
|
||||
}
|
||||
};
|
||||
|
||||
inline void process(scv_smart_ptr<int> data) {
|
||||
}
|
||||
|
||||
inline void test::main1() {
|
||||
// simple sequential tests
|
||||
for (int i = 0; i < 3; i++) {
|
||||
rw_task_if::addr_t addr = i;
|
||||
rw_task_if::data_t data = transactor->read(&addr);
|
||||
cout << "at time " << sc_time_stamp() << ": ";
|
||||
cout << "received data : " << data << endl;
|
||||
}
|
||||
|
||||
scv_smart_ptr<rw_task_if::addr_t> addr;
|
||||
for (int i = 0; i < 3; i++) {
|
||||
|
||||
addr->next();
|
||||
rw_task_if::data_t data = transactor->read(addr->get_instance());
|
||||
cout << "data for address " << *addr << " is " << data << endl;
|
||||
}
|
||||
|
||||
scv_smart_ptr<rw_task_if::write_t> write;
|
||||
for (int i = 0; i < 3; i++) {
|
||||
write->next();
|
||||
transactor->write(write->get_instance());
|
||||
cout << "send data : " << write->data << endl;
|
||||
}
|
||||
|
||||
scv_smart_ptr<int> data;
|
||||
scv_bag<int> distribution;
|
||||
distribution.push(1, 40);
|
||||
distribution.push(2, 60);
|
||||
data->set_mode(distribution);
|
||||
for (int i = 0; i < 3; i++) {
|
||||
data->next();
|
||||
process(data);
|
||||
}
|
||||
}
|
||||
|
||||
inline void test::main2() {
|
||||
// simple sequential tests
|
||||
for (int i = 0; i < 3; i++) {
|
||||
rw_task_if::addr_t addr = i;
|
||||
rw_task_if::data_t data = transactor->read(&addr);
|
||||
cout << "at time " << sc_time_stamp() << ": ";
|
||||
cout << "received data : " << data << endl;
|
||||
}
|
||||
|
||||
scv_smart_ptr<rw_task_if::addr_t> addr;
|
||||
for (int i = 0; i < 3; i++) {
|
||||
|
||||
addr->next();
|
||||
rw_task_if::data_t data = transactor->read(addr->get_instance());
|
||||
cout << "data for address " << *addr << " is " << data << endl;
|
||||
}
|
||||
|
||||
scv_smart_ptr<rw_task_if::write_t> write;
|
||||
for (int i = 0; i < 3; i++) {
|
||||
write->next();
|
||||
transactor->write(write->get_instance());
|
||||
cout << "send data : " << write->data << endl;
|
||||
}
|
||||
|
||||
scv_smart_ptr<int> data;
|
||||
scv_bag<int> distribution;
|
||||
distribution.push(1, 140);
|
||||
distribution.push(2, 160);
|
||||
data->set_mode(distribution);
|
||||
for (int i = 0; i < 3; i++) {
|
||||
data->next();
|
||||
process(data);
|
||||
}
|
||||
}
|
||||
class design: public pipelined_bus_ports {
|
||||
std::list<sc_uint<8> > outstandingAddresses;
|
||||
std::list<bool> outstandingType;
|
||||
sc_uint<8> memory[ram_size];
|
||||
|
||||
public:
|
||||
SC_HAS_PROCESS(design);
|
||||
design(sc_module_name nm) :
|
||||
pipelined_bus_ports(nm) {
|
||||
for (unsigned i = 0; i < ram_size; ++i) {
|
||||
memory[i] = i;
|
||||
}
|
||||
SC_THREAD(addr_phase);
|
||||
SC_THREAD(data_phase);
|
||||
}
|
||||
void addr_phase();
|
||||
void data_phase();
|
||||
};
|
||||
|
||||
inline void design::addr_phase() {
|
||||
while (1) {
|
||||
while (addr_req.read() != 1) {
|
||||
wait(addr_req->value_changed_event());
|
||||
}
|
||||
sc_uint<8> _addr = bus_addr.read();
|
||||
bool _rw = rw.read();
|
||||
|
||||
int cycle = rand() % 10 + 1;
|
||||
while (cycle-- > 0) {
|
||||
wait(clk->posedge_event());
|
||||
}
|
||||
|
||||
addr_ack = 1;
|
||||
wait(clk->posedge_event());
|
||||
addr_ack = 0;
|
||||
|
||||
outstandingAddresses.push_back(_addr);
|
||||
outstandingType.push_back(_rw);
|
||||
cout << "at time " << sc_time_stamp() << ": ";
|
||||
cout << "received request for memory address " << _addr << endl;
|
||||
}
|
||||
}
|
||||
|
||||
inline void design::data_phase() {
|
||||
while (1) {
|
||||
while (outstandingAddresses.empty()) {
|
||||
wait(clk->posedge_event());
|
||||
}
|
||||
int cycle = rand() % 10 + 1;
|
||||
while (cycle-- > 0) {
|
||||
wait(clk->posedge_event());
|
||||
}
|
||||
if (outstandingType.front() == false) {
|
||||
cout << "reading memory address " << outstandingAddresses.front() << " with value "
|
||||
<< memory[outstandingAddresses.front().to_ulong()] << endl;
|
||||
bus_data = memory[outstandingAddresses.front().to_ulong()];
|
||||
data_rdy = 1;
|
||||
wait(clk->posedge_event());
|
||||
data_rdy = 0;
|
||||
|
||||
} else {
|
||||
cout << "writing memory address " << outstandingAddresses.front() << " with value "
|
||||
<< bus_data << endl;
|
||||
memory[outstandingAddresses.front().to_ulong()]=bus_data;
|
||||
data_rdy = 1;
|
||||
wait(clk->posedge_event());
|
||||
data_rdy = 0;
|
||||
}
|
||||
outstandingAddresses.pop_front();
|
||||
outstandingType.pop_front();
|
||||
}
|
||||
}
|
||||
extern void scv_tr_sqlite_init();
|
||||
|
||||
int sc_main(int argc, char *argv[]) {
|
||||
scv_startup();
|
||||
|
||||
#if 0
|
||||
scv_tr_text_init();
|
||||
const char* fileName = "my_db.txlog";
|
||||
#else
|
||||
scv_tr_sqlite_init();
|
||||
const char* fileName = "my_db";
|
||||
#endif
|
||||
scv_tr_db db(fileName);
|
||||
scv_tr_db::set_default_db(&db);
|
||||
sc_trace_file* tf = sc_create_vcd_trace_file("my_db");
|
||||
// create signals
|
||||
sc_clock clk("clk", 20.0, SC_NS, 0.5, 0.0, SC_NS, true);
|
||||
sc_signal<bool> rw;
|
||||
sc_signal<bool> addr_req;
|
||||
sc_signal<bool> addr_ack;
|
||||
sc_signal<sc_uint<8> > bus_addr;
|
||||
sc_signal<bool> data_rdy;
|
||||
sc_signal<sc_uint<8> > bus_data;
|
||||
|
||||
// create modules/channels
|
||||
test t("t");
|
||||
rw_pipelined_transactor tr("tr");
|
||||
design duv("duv");
|
||||
|
||||
// connect them up
|
||||
t.transactor(tr);
|
||||
|
||||
tr.clk(clk);
|
||||
tr.rw(rw);
|
||||
tr.addr_req(addr_req);
|
||||
tr.addr_ack(addr_ack);
|
||||
tr.bus_addr(bus_addr);
|
||||
tr.data_rdy(data_rdy);
|
||||
tr.bus_data(bus_data);
|
||||
tr.trace(tf);
|
||||
|
||||
duv.clk(clk);
|
||||
duv.rw(rw);
|
||||
duv.addr_req(addr_req);
|
||||
duv.addr_ack(addr_ack);
|
||||
duv.bus_addr(bus_addr);
|
||||
duv.data_rdy(data_rdy);
|
||||
duv.bus_data(bus_data);
|
||||
duv.trace(tf);
|
||||
|
||||
// Accellera SystemC >=2.2 got picky about multiple drivers.
|
||||
// Disable check for bus simulation.
|
||||
sc_report_handler::set_actions(SC_ID_MORE_THAN_ONE_SIGNAL_DRIVER_, SC_DO_NOTHING);
|
||||
// run the simulation
|
||||
sc_start(1.0, SC_MS);
|
||||
sc_close_vcd_trace_file(tf);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1,379 +0,0 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2014, 2015 MINRES Technologies GmbH and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* MINRES Technologies GmbH - initial API and implementation
|
||||
*******************************************************************************/
|
||||
#include <cstdio>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <stdexcept>
|
||||
#include "scv/scv_util.h"
|
||||
#include "scv/scv_introspection.h"
|
||||
#include "scv/scv_tr.h"
|
||||
#include "sqlite3.h"
|
||||
// ----------------------------------------------------------------------------
|
||||
#define SQLITEWRAPPER_ERROR 1000
|
||||
// ----------------------------------------------------------------------------
|
||||
using namespace std;
|
||||
|
||||
struct SQLiteDB {
|
||||
struct SQLiteException : public runtime_error{
|
||||
SQLiteException(const int nErrCode, const char* msg, bool doFree=true)
|
||||
: runtime_error(msg), mnErrCode(0){
|
||||
if (doFree && msg) sqlite3_free(const_cast<char*>(msg));
|
||||
}
|
||||
const int errorCode() { return mnErrCode; }
|
||||
const char* errorMessage() { return what(); }
|
||||
private:
|
||||
int mnErrCode;
|
||||
};
|
||||
|
||||
SQLiteDB():busyTimeoutMs(60000), db(NULL){}
|
||||
|
||||
void open(const string szFile){
|
||||
int nRet = sqlite3_open(szFile.c_str(), &db);
|
||||
if (nRet != SQLITE_OK) throw SQLiteException(nRet, sqlite3_errmsg(db), false);
|
||||
sqlite3_busy_timeout(db, busyTimeoutMs);
|
||||
}
|
||||
|
||||
inline
|
||||
bool isOpen(){return db!=NULL;}
|
||||
|
||||
void close(){
|
||||
if (db){
|
||||
if (sqlite3_close(db) == SQLITE_OK)
|
||||
db = 0;
|
||||
else
|
||||
throw SQLiteException(SQLITEWRAPPER_ERROR, "Unable to close database", false);
|
||||
}
|
||||
}
|
||||
|
||||
inline
|
||||
int exec(const string szSQL){return exec(szSQL.c_str());};
|
||||
|
||||
int exec(const char* szSQL){
|
||||
checkDB();
|
||||
char* szError=0;
|
||||
int nRet = sqlite3_exec(db, szSQL, 0, 0, &szError);
|
||||
if (nRet == SQLITE_OK)
|
||||
return sqlite3_changes(db);
|
||||
else
|
||||
throw SQLiteException(nRet, szError);
|
||||
}
|
||||
protected:
|
||||
inline void checkDB(){
|
||||
if (!db) throw SQLiteException(SQLITEWRAPPER_ERROR, "Database not open", false);
|
||||
}
|
||||
|
||||
private:
|
||||
int busyTimeoutMs;
|
||||
sqlite3* db;
|
||||
};
|
||||
// ----------------------------------------------------------------------------
|
||||
static SQLiteDB db;
|
||||
static ostringstream stringBuilder, queryBuilder;
|
||||
static vector<vector<uint64_t>*> concurrencyLevel;
|
||||
// ----------------------------------------------------------------------------
|
||||
enum EventType {BEGIN, RECORD, END};
|
||||
typedef scv_extensions_if::data_type data_type;
|
||||
// ----------------------------------------------------------------------------
|
||||
#define SIM_PROPS "ScvSimProps"
|
||||
#define STREAM_TABLE "ScvStream"
|
||||
#define GENERATOR_TABLE "ScvGenerator"
|
||||
#define TX_TABLE "ScvTx"
|
||||
#define TX_EVENT_TABLE "ScvTxEvent"
|
||||
#define TX_ATTRIBUTE_TABLE "ScvTxAttribute"
|
||||
#define TX_RELATION_TABLE "ScvTxRelation"
|
||||
|
||||
static void dbCb(const scv_tr_db& _scv_tr_db, scv_tr_db::callback_reason reason, void* data) {
|
||||
// This is called from the scv_tr_db ctor.
|
||||
static string fName("DEFAULT_scv_tr_sqlite");
|
||||
switch (reason) {
|
||||
case scv_tr_db::CREATE:
|
||||
if ((_scv_tr_db.get_name() != NULL) && (strlen(_scv_tr_db.get_name()) != 0))
|
||||
fName = _scv_tr_db.get_name();
|
||||
try {
|
||||
if(fName.size()<5 || fName.find(".txdb", fName.size() - 5) == string::npos)
|
||||
fName+=".txdb";
|
||||
remove(fName.c_str());
|
||||
db.open(fName.c_str());
|
||||
// performance related according to http://blog.quibb.org/2010/08/fast-bulk-inserts-into-sqlite/
|
||||
db.exec("PRAGMA synchronous=OFF");
|
||||
db.exec("PRAGMA count_changes=OFF");
|
||||
db.exec("PRAGMA journal_mode=MEMORY");
|
||||
db.exec("PRAGMA temp_store=MEMORY");
|
||||
// scv_out << "TB Transaction Recording has started, file = " << my_sqlite_file_name << endl;
|
||||
db.exec("CREATE TABLE IF NOT EXISTS " STREAM_TABLE "(id INTEGER NOT NULL PRIMARY KEY, name TEXT, kind TEXT);");
|
||||
db.exec("CREATE TABLE IF NOT EXISTS " GENERATOR_TABLE "(id INTEGER NOT NULL PRIMARY KEY, stream INTEGER REFERENCES " STREAM_TABLE "(id), name TEXT, begin_attr INTEGER, end_attr INTEGER);");
|
||||
db.exec("CREATE TABLE IF NOT EXISTS " TX_TABLE "(id INTEGER NOT NULL PRIMARY KEY, generator INTEGER REFERENCES " GENERATOR_TABLE "(id), stream INTEGER REFERENCES " STREAM_TABLE "(id), concurrencyLevel INTEGER);");
|
||||
db.exec("CREATE TABLE IF NOT EXISTS " TX_EVENT_TABLE "(tx INTEGER REFERENCES " TX_TABLE "(id), type INTEGER, time INTEGER);");
|
||||
db.exec("CREATE TABLE IF NOT EXISTS " TX_ATTRIBUTE_TABLE "(tx INTEGER REFERENCES " TX_TABLE "(id), type INTEGER, name TEXT, data_type INTEGER, data_value TEXT);");
|
||||
db.exec("CREATE TABLE IF NOT EXISTS " TX_RELATION_TABLE "(name TEXT, src INTEGER REFERENCES " TX_TABLE "(id), sink INTEGER REFERENCES " TX_TABLE "(id));");
|
||||
db.exec("CREATE TABLE IF NOT EXISTS " SIM_PROPS "(time_resolution INTEGER);");
|
||||
db.exec("BEGIN TRANSACTION");
|
||||
queryBuilder.str("");
|
||||
queryBuilder << "INSERT INTO " SIM_PROPS " (time_resolution) values ("
|
||||
<< (long)(sc_get_time_resolution().to_seconds()*1e15) << ");";
|
||||
db.exec(queryBuilder.str().c_str());
|
||||
} catch (SQLiteDB::SQLiteException& e) {
|
||||
_scv_message::message(_scv_message::TRANSACTION_RECORDING_INTERNAL, "Can't open recording file");
|
||||
}
|
||||
break;
|
||||
case scv_tr_db::DELETE:
|
||||
try {
|
||||
// scv_out << "Transaction Recording is closing file: " << my_sqlite_file_name << endl;
|
||||
db.exec("COMMIT TRANSACTION");
|
||||
db.close();
|
||||
} catch (SQLiteDB::SQLiteException& e) {
|
||||
_scv_message::message(_scv_message::TRANSACTION_RECORDING_INTERNAL, "Can't close recording file");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
_scv_message::message(_scv_message::TRANSACTION_RECORDING_INTERNAL, "Unknown reason in scv_tr_db callback");
|
||||
}
|
||||
}
|
||||
// ----------------------------------------------------------------------------
|
||||
static void streamCb(const scv_tr_stream& s, scv_tr_stream::callback_reason reason, void* data) {
|
||||
if (reason == scv_tr_stream::CREATE && db.isOpen()) {
|
||||
try {
|
||||
queryBuilder.str("");
|
||||
queryBuilder << "INSERT INTO " STREAM_TABLE " (id, name, kind) values (" << s.get_id() << ",'" << s.get_name() << "','"
|
||||
<< (s.get_stream_kind() ? s.get_stream_kind() : "<unnamed>") << "');";
|
||||
db.exec(queryBuilder.str().c_str());
|
||||
if(concurrencyLevel.size()<=s.get_id())concurrencyLevel.resize(s.get_id()+1);
|
||||
concurrencyLevel[s.get_id()]=new vector<uint64_t>();
|
||||
} catch (SQLiteDB::SQLiteException& e) {
|
||||
_scv_message::message(_scv_message::TRANSACTION_RECORDING_INTERNAL, "Can't create stream");
|
||||
}
|
||||
}
|
||||
}
|
||||
// ----------------------------------------------------------------------------
|
||||
void recordAttribute(uint64_t id, EventType event, const string& name, data_type type, const string& value) {
|
||||
try {
|
||||
queryBuilder.str("");
|
||||
queryBuilder << "INSERT INTO " TX_ATTRIBUTE_TABLE " (tx,type,name,data_type,data_value)" << " values ("
|
||||
<< id << "," << event << ",'"<< name << "'," << type << ",'" << value << "');";
|
||||
db.exec(queryBuilder.str().c_str());
|
||||
} catch (SQLiteDB::SQLiteException& e) {
|
||||
_scv_message::message(_scv_message::TRANSACTION_RECORDING_INTERNAL, "Can't create attribute entry");
|
||||
}
|
||||
}
|
||||
// ----------------------------------------------------------------------------
|
||||
inline
|
||||
void recordAttribute(uint64_t id, EventType event, const string& name, data_type type, long long value) {
|
||||
stringBuilder.str("");
|
||||
stringBuilder <<value;
|
||||
recordAttribute(id,event,name,type,stringBuilder.str());
|
||||
}
|
||||
// ----------------------------------------------------------------------------
|
||||
inline
|
||||
void recordAttribute(uint64_t id, EventType event, const string& name, data_type type, double value) {
|
||||
stringBuilder.str("");
|
||||
stringBuilder <<value;
|
||||
recordAttribute(id,event,name,type,stringBuilder.str());
|
||||
}
|
||||
// ----------------------------------------------------------------------------
|
||||
static void recordAttributes(uint64_t id, EventType eventType, string& prefix, const scv_extensions_if* my_exts_p){
|
||||
if (my_exts_p == 0) return;
|
||||
string name;
|
||||
if (prefix == "") {
|
||||
name = my_exts_p->get_name();
|
||||
} else {
|
||||
if ((my_exts_p->get_name() == 0) || (strlen(my_exts_p->get_name()) == 0)) {
|
||||
name = prefix;
|
||||
} else {
|
||||
name = prefix + "." + my_exts_p->get_name();
|
||||
}
|
||||
}
|
||||
if (name == "") name = "<unnamed>";
|
||||
switch (my_exts_p->get_type()) {
|
||||
case scv_extensions_if::RECORD:
|
||||
{
|
||||
int num_fields = my_exts_p->get_num_fields();
|
||||
if (num_fields > 0) {
|
||||
for (int field_counter = 0; field_counter < num_fields; field_counter++) {
|
||||
const scv_extensions_if* field_data_p = my_exts_p->get_field(field_counter);
|
||||
recordAttributes(id, eventType, prefix, field_data_p);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case scv_extensions_if::ENUMERATION:
|
||||
recordAttribute(id, eventType, name, scv_extensions_if::ENUMERATION, my_exts_p->get_enum_string((int) (my_exts_p->get_integer())));
|
||||
break;
|
||||
case scv_extensions_if::BOOLEAN:
|
||||
recordAttribute(id, eventType, name, scv_extensions_if::BOOLEAN, my_exts_p->get_bool()?"TRUE":"FALSE");
|
||||
break;
|
||||
case scv_extensions_if::INTEGER:
|
||||
case scv_extensions_if::FIXED_POINT_INTEGER:
|
||||
recordAttribute(id, eventType, name, scv_extensions_if::INTEGER, my_exts_p->get_integer());
|
||||
break;
|
||||
case scv_extensions_if::UNSIGNED:
|
||||
recordAttribute(id, eventType, name, scv_extensions_if::UNSIGNED, my_exts_p->get_integer());
|
||||
break;
|
||||
case scv_extensions_if::POINTER:
|
||||
recordAttribute(id, eventType, name, scv_extensions_if::POINTER, (long long)my_exts_p->get_pointer());
|
||||
break;
|
||||
case scv_extensions_if::STRING:
|
||||
recordAttribute(id, eventType, name, scv_extensions_if::STRING, my_exts_p->get_string());
|
||||
break;
|
||||
case scv_extensions_if::FLOATING_POINT_NUMBER:
|
||||
recordAttribute(id, eventType, name, scv_extensions_if::FLOATING_POINT_NUMBER, my_exts_p->get_double());
|
||||
break;
|
||||
case scv_extensions_if::BIT_VECTOR:
|
||||
{
|
||||
sc_bv_base tmp_bv(my_exts_p->get_bitwidth());
|
||||
my_exts_p->get_value(tmp_bv);
|
||||
recordAttribute(id, eventType, name, scv_extensions_if::BIT_VECTOR, tmp_bv.to_string());
|
||||
}
|
||||
break;
|
||||
case scv_extensions_if::LOGIC_VECTOR:
|
||||
{
|
||||
sc_lv_base tmp_lv(my_exts_p->get_bitwidth());
|
||||
my_exts_p->get_value(tmp_lv);
|
||||
recordAttribute(id, eventType, name, scv_extensions_if::LOGIC_VECTOR, tmp_lv.to_string());
|
||||
}
|
||||
break;
|
||||
case scv_extensions_if::ARRAY:
|
||||
for (int array_elt_index = 0; array_elt_index < my_exts_p->get_array_size(); array_elt_index++) {
|
||||
const scv_extensions_if* field_data_p = my_exts_p->get_array_elt(array_elt_index);
|
||||
recordAttributes(id, eventType, prefix, field_data_p);
|
||||
}
|
||||
break;
|
||||
default: {
|
||||
char tmpString[100];
|
||||
sprintf(tmpString, "Unsupported attribute type = %d", my_exts_p->get_type());
|
||||
_scv_message::message(_scv_message::TRANSACTION_RECORDING_INTERNAL, tmpString);
|
||||
}
|
||||
}
|
||||
}
|
||||
// ----------------------------------------------------------------------------
|
||||
static void generatorCb(const scv_tr_generator_base& g, scv_tr_generator_base::callback_reason reason, void* data) {
|
||||
if (reason == scv_tr_generator_base::CREATE && db.isOpen()) {
|
||||
try {
|
||||
queryBuilder.str("");
|
||||
queryBuilder << "INSERT INTO " GENERATOR_TABLE " (id,stream, name)"
|
||||
<<" values (" << g.get_id() << ","<<g.get_scv_tr_stream().get_id()<<",'" << g.get_name() << "');";
|
||||
db.exec(queryBuilder.str().c_str());
|
||||
} catch (SQLiteDB::SQLiteException& e) {
|
||||
_scv_message::message(_scv_message::TRANSACTION_RECORDING_INTERNAL, "Can't create generator entry");
|
||||
}
|
||||
}
|
||||
}
|
||||
// ----------------------------------------------------------------------------
|
||||
static void transactionCb(const scv_tr_handle& t, scv_tr_handle::callback_reason reason, void* data) {
|
||||
if (!db.isOpen()) return;
|
||||
if (t.get_scv_tr_stream().get_scv_tr_db() == NULL) return;
|
||||
if (t.get_scv_tr_stream().get_scv_tr_db()->get_recording() == false) return;
|
||||
|
||||
uint64_t id = t.get_id();
|
||||
uint64_t streamId = t.get_scv_tr_stream().get_id();
|
||||
vector<uint64_t>::size_type concurrencyIdx;
|
||||
const scv_extensions_if* my_exts_p;
|
||||
switch (reason) {
|
||||
case scv_tr_handle::BEGIN:{
|
||||
try {
|
||||
if(concurrencyLevel.size()<=streamId)
|
||||
concurrencyLevel.resize(streamId+1);
|
||||
vector<uint64_t>* levels=concurrencyLevel[streamId];
|
||||
if(levels==NULL){
|
||||
levels=new vector<uint64_t>();
|
||||
concurrencyLevel[id]=levels;
|
||||
}
|
||||
for(concurrencyIdx=0; concurrencyIdx<levels->size(); ++concurrencyIdx)
|
||||
if((*levels)[concurrencyIdx]==0) break;
|
||||
if(concurrencyIdx==levels->size())
|
||||
levels->push_back(id);
|
||||
else
|
||||
(*levels)[concurrencyIdx]=id;
|
||||
queryBuilder.str("");
|
||||
queryBuilder << "INSERT INTO " TX_TABLE " (id,generator,stream, concurrencyLevel)" << " values (" << id << "," << t.get_scv_tr_generator_base().get_id()
|
||||
<<","<<t.get_scv_tr_stream().get_id()<< ","<< concurrencyIdx <<");";
|
||||
db.exec(queryBuilder.str().c_str());
|
||||
|
||||
queryBuilder.str("");
|
||||
queryBuilder << "INSERT INTO " TX_EVENT_TABLE " (tx,type,time)" << " values (" << id << "," << BEGIN << ","
|
||||
<< t.get_begin_sc_time().value() << ");";
|
||||
db.exec(queryBuilder.str().c_str());
|
||||
|
||||
} catch (SQLiteDB::SQLiteException& e) {
|
||||
_scv_message::message(_scv_message::TRANSACTION_RECORDING_INTERNAL, e.errorMessage());
|
||||
}
|
||||
my_exts_p = t.get_begin_exts_p();
|
||||
if (my_exts_p == NULL) {
|
||||
my_exts_p = t.get_scv_tr_generator_base().get_begin_exts_p();
|
||||
}
|
||||
string tmp_str =
|
||||
t.get_scv_tr_generator_base().get_begin_attribute_name() ? t.get_scv_tr_generator_base().get_begin_attribute_name() : "";
|
||||
recordAttributes(id, BEGIN, tmp_str, my_exts_p);
|
||||
} break;
|
||||
case scv_tr_handle::END:{
|
||||
try {
|
||||
vector<uint64_t>* levels=concurrencyLevel[streamId];
|
||||
for(concurrencyIdx=0; concurrencyIdx<levels->size(); ++concurrencyIdx)
|
||||
if((*levels)[concurrencyIdx]==id) break;
|
||||
if(concurrencyIdx==levels->size())
|
||||
levels->push_back(id);
|
||||
else
|
||||
levels->at(concurrencyIdx)=id;
|
||||
queryBuilder.str("");
|
||||
queryBuilder << "INSERT INTO " TX_EVENT_TABLE " (tx,type,time)" << " values (" << t.get_id() << "," << END << ","
|
||||
<< t.get_end_sc_time().value() << ");";
|
||||
db.exec(queryBuilder.str().c_str());
|
||||
|
||||
} catch (SQLiteDB::SQLiteException& e) {
|
||||
_scv_message::message(_scv_message::TRANSACTION_RECORDING_INTERNAL, "Can't create transaction end");
|
||||
}
|
||||
my_exts_p = t.get_end_exts_p();
|
||||
if (my_exts_p == NULL) {
|
||||
my_exts_p = t.get_scv_tr_generator_base().get_end_exts_p();
|
||||
}
|
||||
string tmp_str =
|
||||
t.get_scv_tr_generator_base().get_end_attribute_name() ? t.get_scv_tr_generator_base().get_end_attribute_name() : "";
|
||||
recordAttributes(t.get_id(), END, tmp_str, my_exts_p);
|
||||
} break;
|
||||
default:
|
||||
;
|
||||
}
|
||||
}
|
||||
// ----------------------------------------------------------------------------
|
||||
static void attributeCb(const scv_tr_handle& t, const char* name, const scv_extensions_if* ext, void* data) {
|
||||
if (!db.isOpen()) return;
|
||||
if (t.get_scv_tr_stream().get_scv_tr_db() == NULL) return;
|
||||
if (t.get_scv_tr_stream().get_scv_tr_db()->get_recording() == false) return;
|
||||
string tmp_str(name == 0?"":name);
|
||||
recordAttributes(t.get_id(), RECORD, tmp_str, ext);
|
||||
}
|
||||
// ----------------------------------------------------------------------------
|
||||
static void relationCb(const scv_tr_handle& tr_1, const scv_tr_handle& tr_2, void* data,
|
||||
scv_tr_relation_handle_t relation_handle) {
|
||||
if (!db.isOpen()) return;
|
||||
if (tr_1.get_scv_tr_stream().get_scv_tr_db() == NULL) return;
|
||||
if (tr_1.get_scv_tr_stream().get_scv_tr_db()->get_recording() == false) return;
|
||||
try {
|
||||
queryBuilder.str("");
|
||||
queryBuilder << "INSERT INTO " TX_RELATION_TABLE " (name,sink,src)"
|
||||
<< "values ('" << tr_1.get_scv_tr_stream().get_scv_tr_db()->get_relation_name(relation_handle) << "',"
|
||||
<< tr_1.get_id() << ","<< tr_2.get_id() << ");";
|
||||
db.exec(queryBuilder.str().c_str());
|
||||
|
||||
} catch (SQLiteDB::SQLiteException& e) {
|
||||
_scv_message::message(_scv_message::TRANSACTION_RECORDING_INTERNAL, "Can't create transaction relation");
|
||||
}
|
||||
}
|
||||
// ----------------------------------------------------------------------------
|
||||
void scv_tr_sqlite_init() {
|
||||
scv_tr_db::register_class_cb(dbCb);
|
||||
scv_tr_stream::register_class_cb(streamCb);
|
||||
scv_tr_generator_base::register_class_cb(generatorCb);
|
||||
scv_tr_handle::register_class_cb(transactionCb);
|
||||
scv_tr_handle::register_record_attribute_cb(attributeCb);
|
||||
scv_tr_handle::register_relation_cb(relationCb);
|
||||
}
|
||||
// ----------------------------------------------------------------------------
|
151706
scv_tr_sqlite/src/sqlite3.c
151706
scv_tr_sqlite/src/sqlite3.c
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue