From a4fc453565e61a4569cbb9cdceae81e07d217e22 Mon Sep 17 00:00:00 2001 From: Marcus10110 Date: Tue, 28 Jun 2022 18:31:14 -0700 Subject: [PATCH 01/11] added basic dual edge support. It looks like it's working! --- src/SimpleParallelAnalyzer.cpp | 127 +++++++++++++++--- src/SimpleParallelAnalyzer.h | 9 +- src/SimpleParallelAnalyzerSettings.cpp | 21 +-- src/SimpleParallelAnalyzerSettings.h | 14 +- src/SimpleParallelSimulationDataGenerator.cpp | 17 ++- 5 files changed, 157 insertions(+), 31 deletions(-) diff --git a/src/SimpleParallelAnalyzer.cpp b/src/SimpleParallelAnalyzer.cpp index ade431f..f3cde6c 100644 --- a/src/SimpleParallelAnalyzer.cpp +++ b/src/SimpleParallelAnalyzer.cpp @@ -1,6 +1,8 @@ #include "SimpleParallelAnalyzer.h" #include "SimpleParallelAnalyzerSettings.h" #include +#include +#include SimpleParallelAnalyzer::SimpleParallelAnalyzer() : Analyzer2(), mSettings( new SimpleParallelAnalyzerSettings() ), mSimulationInitilized( false ) @@ -26,7 +28,7 @@ void SimpleParallelAnalyzer::WorkerThread() mSampleRateHz = GetSampleRate(); AnalyzerResults::MarkerType clock_arrow; - if( mSettings->mClockEdge == AnalyzerEnums::NegEdge ) + if( mSettings->mClockEdge == ParallelAnalyzerClockEdge::NegEdge ) clock_arrow = AnalyzerResults::DownArrow; else clock_arrow = AnalyzerResults::UpArrow; @@ -51,16 +53,22 @@ void SimpleParallelAnalyzer::WorkerThread() U32 num_data_lines = mData.size(); - if( mSettings->mClockEdge == AnalyzerEnums::NegEdge ) + if( mSettings->mClockEdge == ParallelAnalyzerClockEdge::NegEdge ) { if( mClock->GetBitState() == BIT_LOW ) mClock->AdvanceToNextEdge(); } - else + else if( mSettings->mClockEdge == ParallelAnalyzerClockEdge::NegEdge ) { if( mClock->GetBitState() == BIT_HIGH ) mClock->AdvanceToNextEdge(); } + else if( mSettings->mClockEdge == ParallelAnalyzerClockEdge::DualEdge ) + { + // handling both edges is different enough to warrant a separate implementation. + DecodeBothEdges(); + return; + } mClock->AdvanceToNextEdge(); // this is the data-valid edge @@ -73,18 +81,7 @@ void SimpleParallelAnalyzer::WorkerThread() U64 sample = mClock->GetSampleNumber(); mResults->AddMarker( sample, clock_arrow, mSettings->mClockChannel ); - U16 result = 0; - - for( U32 i = 0; i < num_data_lines; i++ ) - { - mData[ i ]->AdvanceToAbsPosition( sample ); - if( mData[ i ]->GetBitState() == BIT_HIGH ) - { - result |= mDataMasks[ i ]; - } - mResults->AddMarker( sample, AnalyzerResults::Dot, mDataChannels[ i ] ); - } - + U16 result = GetWordAtLocation( sample ); FrameV2 frame_v2; frame_v2.AddInteger( "data", result ); @@ -218,6 +215,106 @@ const char* SimpleParallelAnalyzer::GetAnalyzerName() const return "Simple Parallel"; } + +void SimpleParallelAnalyzer::DecodeBothEdges() +{ + // helper to allow us to successfully report the last edge, even if there are no more edges in the capture. + // Normally, in order to report a specific edge, the following edge must be found first. + // If that following edge does not exist, and never will exist, instead we advance a intermediate amount, and return false. + // If there is another edge, we advance to it and return true. + // force_advance optionally ensures we advance to the next edge. If there are no more edges in the data, this will never return. + auto advance_to_next_edge_or_fail = [&]( bool force_advance ) -> bool { + if( mClock->DoMoreTransitionsExistInCurrentData() || force_advance ) + { + mClock->AdvanceToNextEdge(); + return true; + } + int64_t estimated_frame_size = mLastFrameWidth > 0 ? std::max( static_cast( mLastFrameWidth * 0.1 ), 2 ) : 10; + if( mClock->WouldAdvancingCauseTransition( estimated_frame_size ) ) + { + // this condition will only be true if we're very lucky, and we're processing data while recording in real time. + mClock->AdvanceToNextEdge(); + return true; + } + mClock->Advance( estimated_frame_size ); + return false; + }; + + // Frames start at the active edge, and extend to the following edge -1. (or they extend to an estimated width, if no more data is + // found.) + // we must advance past the active edge before committing the result from that edge. + + // has_pending_frame indicates that we have a word to store after the previous cycle. + bool has_pending_frame = false; + uint16_t previous_value = 0; + uint64_t previous_sample = 0; + + for( ;; ) + { + // advance to the next active edge. + auto found_next_edge = advance_to_next_edge_or_fail( !has_pending_frame ); + auto location = mClock->GetSampleNumber(); + uint64_t progress_update = 0; + if( has_pending_frame ) + { + // store the previous frame. + progress_update = AddFrame( previous_value, previous_sample, location - 1 ); + has_pending_frame = false; + } + if( found_next_edge ) + { + has_pending_frame = true; + previous_sample = location; + previous_value = GetWordAtLocation( location ); + + mResults->AddMarker( location, mClock->GetBitState() == BIT_LOW ? AnalyzerResults::DownArrow : AnalyzerResults::UpArrow, + mSettings->mClockChannel ); + } + + if( progress_update > 0 ) + { + ReportProgress( progress_update ); + } + } +} + +uint16_t SimpleParallelAnalyzer::GetWordAtLocation( uint64_t sample_number ) +{ + uint16_t result = 0; + + int num_data_lines = mData.size(); + + for( int i = 0; i < num_data_lines; i++ ) + { + mData[ i ]->AdvanceToAbsPosition( sample_number ); + if( mData[ i ]->GetBitState() == BIT_HIGH ) + { + result |= mDataMasks[ i ]; + } + mResults->AddMarker( sample_number, AnalyzerResults::Dot, mDataChannels[ i ] ); + } + + return result; +} + +uint64_t SimpleParallelAnalyzer::AddFrame( uint16_t value, uint64_t starting_sample, uint64_t ending_sample ) +{ + assert( starting_sample <= ending_sample ); + FrameV2 frame_v2; + frame_v2.AddInteger( "data", value ); + + Frame frame; + frame.mData1 = value; + frame.mFlags = 0; + frame.mStartingSampleInclusive = starting_sample; + frame.mEndingSampleInclusive = ending_sample; + mResults->AddFrame( frame ); + mResults->AddFrameV2( frame_v2, "data", frame.mStartingSampleInclusive, frame.mEndingSampleInclusive ); + mResults->CommitResults(); + mLastFrameWidth = std::max( ending_sample - starting_sample, 1 ); + return ending_sample; +} + const char* GetAnalyzerName() { return "Simple Parallel"; diff --git a/src/SimpleParallelAnalyzer.h b/src/SimpleParallelAnalyzer.h index eb8cc0f..862fa9f 100644 --- a/src/SimpleParallelAnalyzer.h +++ b/src/SimpleParallelAnalyzer.h @@ -25,8 +25,13 @@ class SimpleParallelAnalyzer : public Analyzer2 #pragma warning( \ disable : 4251 ) // warning C4251: 'SerialAnalyzer::<...>' : class <...> needs to have dll-interface to be used by clients of class - std::auto_ptr mSettings; - std::auto_ptr mResults; + void DecodeBothEdges(); + uint16_t GetWordAtLocation( uint64_t sample_number ); + uint64_t AddFrame( uint16_t value, uint64_t starting_sample, uint64_t ending_sample ); + int64_t mLastFrameWidth = -1; // holds the width of the last frame, in samples, or -1 if no previous frames created. + + std::unique_ptr mSettings; + std::unique_ptr mResults; std::vector mData; std::vector mDataMasks; diff --git a/src/SimpleParallelAnalyzerSettings.cpp b/src/SimpleParallelAnalyzerSettings.cpp index 641f4f2..e9a8f8a 100644 --- a/src/SimpleParallelAnalyzerSettings.cpp +++ b/src/SimpleParallelAnalyzerSettings.cpp @@ -5,7 +5,8 @@ #pragma warning( disable : 4996 ) // warning C4996: 'sprintf': This function or variable may be unsafe -SimpleParallelAnalyzerSettings::SimpleParallelAnalyzerSettings() : mClockChannel( UNDEFINED_CHANNEL ), mClockEdge( AnalyzerEnums::PosEdge ) +SimpleParallelAnalyzerSettings::SimpleParallelAnalyzerSettings() + : mClockChannel( UNDEFINED_CHANNEL ), mClockEdge( ParallelAnalyzerClockEdge::PosEdge ) { U32 count = 16; for( U32 i = 0; i < count; i++ ) @@ -30,9 +31,10 @@ SimpleParallelAnalyzerSettings::SimpleParallelAnalyzerSettings() : mClockChannel mClockEdgeInterface.reset( new AnalyzerSettingInterfaceNumberList() ); mClockEdgeInterface->SetTitleAndTooltip( "Clock State", "Define whether the data is valid on Clock rising or falling edge" ); - mClockEdgeInterface->AddNumber( AnalyzerEnums::PosEdge, "Rising edge", "" ); - mClockEdgeInterface->AddNumber( AnalyzerEnums::NegEdge, "Falling edge", "" ); - mClockEdgeInterface->SetNumber( mClockEdge ); + mClockEdgeInterface->AddNumber( static_cast( ParallelAnalyzerClockEdge::PosEdge ), "Rising edge", "" ); + mClockEdgeInterface->AddNumber( static_cast( ParallelAnalyzerClockEdge::NegEdge ), "Falling edge", "" ); + mClockEdgeInterface->AddNumber( static_cast( ParallelAnalyzerClockEdge::DualEdge ), "Dual edge", "" ); + mClockEdgeInterface->SetNumber( static_cast( mClockEdge ) ); for( U32 i = 0; i < count; i++ ) @@ -87,7 +89,7 @@ bool SimpleParallelAnalyzerSettings::SetSettingsFromInterfaces() } mClockChannel = mClockChannelInterface->GetChannel(); - mClockEdge = AnalyzerEnums::EdgeDirection( U32( mClockEdgeInterface->GetNumber() ) ); + mClockEdge = static_cast( U32( mClockEdgeInterface->GetNumber() ) ); ClearChannels(); for( U32 i = 0; i < count; i++ ) @@ -111,7 +113,7 @@ void SimpleParallelAnalyzerSettings::UpdateInterfacesFromSettings() } mClockChannelInterface->SetChannel( mClockChannel ); - mClockEdgeInterface->SetNumber( mClockEdge ); + mClockEdgeInterface->SetNumber( static_cast( mClockEdge ) ); } void SimpleParallelAnalyzerSettings::LoadSettings( const char* settings ) @@ -127,7 +129,9 @@ void SimpleParallelAnalyzerSettings::LoadSettings( const char* settings ) } text_archive >> mClockChannel; - text_archive >> *( U32* )&mClockEdge; + U32 edge; + text_archive >> edge; + mClockEdge = static_cast( edge ); ClearChannels(); for( U32 i = 0; i < count; i++ ) @@ -154,7 +158,8 @@ const char* SimpleParallelAnalyzerSettings::SaveSettings() } text_archive << mClockChannel; - text_archive << mClockEdge; + U32 edge = static_cast( mClockEdge ); + text_archive << edge; return SetReturnString( text_archive.GetString() ); } diff --git a/src/SimpleParallelAnalyzerSettings.h b/src/SimpleParallelAnalyzerSettings.h index 766f36a..29299f7 100644 --- a/src/SimpleParallelAnalyzerSettings.h +++ b/src/SimpleParallelAnalyzerSettings.h @@ -4,6 +4,14 @@ #include #include +// originally from AnalyzerEnums::EdgeDirection { PosEdge, NegEdge }; +enum class ParallelAnalyzerClockEdge +{ + PosEdge = AnalyzerEnums::PosEdge, + NegEdge = AnalyzerEnums::NegEdge, + DualEdge +}; + class SimpleParallelAnalyzerSettings : public AnalyzerSettings { public: @@ -19,13 +27,13 @@ class SimpleParallelAnalyzerSettings : public AnalyzerSettings std::vector mDataChannels; Channel mClockChannel; - AnalyzerEnums::EdgeDirection mClockEdge; + ParallelAnalyzerClockEdge mClockEdge; protected: std::vector mDataChannelsInterface; - std::auto_ptr mClockChannelInterface; - std::auto_ptr mClockEdgeInterface; + std::unique_ptr mClockChannelInterface; + std::unique_ptr mClockEdgeInterface; }; #endif // SIMPLEPARALLEL_ANALYZER_SETTINGS diff --git a/src/SimpleParallelSimulationDataGenerator.cpp b/src/SimpleParallelSimulationDataGenerator.cpp index 089fe59..78191e8 100644 --- a/src/SimpleParallelSimulationDataGenerator.cpp +++ b/src/SimpleParallelSimulationDataGenerator.cpp @@ -29,10 +29,18 @@ void SimpleParallelSimulationDataGenerator::Initialize( U32 simulation_sample_ra mDataMasks.push_back( val ); } - if( mSettings->mClockEdge == AnalyzerEnums::NegEdge ) + if( mSettings->mClockEdge == ParallelAnalyzerClockEdge::NegEdge ) + { mClock = mSimulationData.Add( mSettings->mClockChannel, mSimulationSampleRateHz, BIT_LOW ); - else + } + else if( mSettings->mClockEdge == ParallelAnalyzerClockEdge::PosEdge ) + { + mClock = mSimulationData.Add( mSettings->mClockChannel, mSimulationSampleRateHz, BIT_HIGH ); + } + else if( mSettings->mClockEdge == ParallelAnalyzerClockEdge::DualEdge ) + { mClock = mSimulationData.Add( mSettings->mClockChannel, mSimulationSampleRateHz, BIT_HIGH ); + } mValue = 0; } @@ -54,7 +62,10 @@ U32 SimpleParallelSimulationDataGenerator::GenerateSimulationData( U64 largest_s else mData[ i ]->TransitionIfNeeded( BIT_HIGH ); } - mClock->Transition(); + if( mSettings->mClockEdge != ParallelAnalyzerClockEdge::DualEdge ) + { + mClock->Transition(); + } mSimulationData.AdvanceAll( 1000 ); mClock->Transition(); From 3a203c25153bbdd66a8ad4929b94cc90feeaafaa Mon Sep 17 00:00:00 2001 From: Marcus10110 Date: Wed, 21 Dec 2022 10:24:21 -0800 Subject: [PATCH 02/11] automatic template update of Simple Parallel Analyzer --- .github/workflows/build.yml | 71 +++++++++++++++++++++ README.md | 38 ++++++++--- azure-pipelines.yml | 109 -------------------------------- cmake/ExternalAnalyzerSDK.cmake | 2 +- 4 files changed, 102 insertions(+), 118 deletions(-) create mode 100644 .github/workflows/build.yml delete mode 100644 azure-pipelines.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..a116c1b --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,71 @@ +name: Build + +on: + push: + branches: [master] + tags: + - '*' + pull_request: + branches: [master] + +jobs: + windows: + runs-on: windows-latest + steps: + - uses: actions/checkout@v2 + - name: Build + run: | + cmake -B ${{github.workspace}}/build -A x64 + cmake --build ${{github.workspace}}/build --config Release + - name: Upload windows build + uses: actions/upload-artifact@v2 + with: + name: windows + path: ${{github.workspace}}/build/Analyzers/Release/*.dll + macos: + runs-on: macos-latest + steps: + - uses: actions/checkout@v2 + - name: Build + run: | + cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=Release + cmake --build ${{github.workspace}}/build + - name: Upload MacOS build + uses: actions/upload-artifact@v2 + with: + name: macos + path: ${{github.workspace}}/build/Analyzers/*.so + linux: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Build + run: | + cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=Release + cmake --build ${{github.workspace}}/build + - name: Upload Linux build + uses: actions/upload-artifact@v2 + with: + name: linux + path: ${{github.workspace}}/build/Analyzers/*.so + publish: + needs: [windows, macos, linux] + runs-on: ubuntu-latest + steps: + - name: download individual builds + uses: actions/download-artifact@v2 + with: + path: ${{github.workspace}}/artifacts + - name: zip + run: | + cd ${{github.workspace}}/artifacts + zip -r ${{github.workspace}}/analyzer.zip . + - uses: actions/upload-artifact@v2 + with: + name: all-platforms + path: ${{github.workspace}}/artifacts/** + - name: create release + uses: softprops/action-gh-release@v1 + if: startsWith(github.ref, 'refs/tags/') + with: + files: ${{github.workspace}}/analyzer.zip \ No newline at end of file diff --git a/README.md b/README.md index 3bf4167..d8a7a3b 100644 --- a/README.md +++ b/README.md @@ -4,13 +4,19 @@ Saleae Simple Parallel Analyzer ## Getting Started +The following documentation describes getting this analyzer building locally. For more detailed information about the Analyzer SDK, debugging, CI build, and more, checkout the readme from the Sample Analyzer repository: + +https://github.com/saleae/SampleAnalyzer + ### MacOS Dependencies: + - XCode with command line tools - CMake 3.13+ Installing command line tools after XCode is installed: + ``` xcode-select --install ``` @@ -22,12 +28,15 @@ Installing CMake on MacOS: 1. Download the binary distribution for MacOS, `cmake-*-Darwin-x86_64.dmg` 2. Install the usual way by dragging into applications. 3. Open a terminal and run the following: + ``` /Applications/CMake.app/Contents/bin/cmake-gui --install ``` -*Note: Errors may occur if older versions of CMake are installed.* + +_Note: Errors may occur if older versions of CMake are installed._ Building the analyzer: + ``` mkdir build cd build @@ -35,9 +44,10 @@ cmake .. cmake --build . ``` -### Ubuntu 16.04 +### Ubuntu 18.04+ Dependencies: + - CMake 3.13+ - gcc 4.8+ @@ -48,6 +58,7 @@ sudo apt-get install build-essential ``` Building the analyzer: + ``` mkdir build cd build @@ -58,15 +69,17 @@ cmake --build . ### Windows Dependencies: -- Visual Studio 2015 Update 3 + +- Visual Studio 2019 - CMake 3.13+ -**Visual Studio 2015** +**Visual Studio 2019** -*Note - newer versions of Visual Studio should be fine.* +_Note - newer and older versions of Visual Studio are likely to work._ Setup options: -- Programming Languages > Visual C++ > select all sub-components. + +- Workloads > Desktop & Mobile > "Desktop development with C++" Note - if CMake has any problems with the MSVC compiler, it's likely a component is missing. @@ -76,14 +89,23 @@ Download and install the latest CMake release here. https://cmake.org/download/ Building the analyzer: + ``` mkdir build -cd build -A x64 -cmake .. +cd build +cmake .. -A x64 ``` Then, open the newly created solution file located here: `build\simple_parallel_analyzer.sln` +The built analyzer DLLs will be located here: + +`build\Analyzers\Debug` + +`build\Analyzers\Release` + +For debug and release builds, respectively. + ## Output Frame Format diff --git a/azure-pipelines.yml b/azure-pipelines.yml deleted file mode 100644 index bfb060e..0000000 --- a/azure-pipelines.yml +++ /dev/null @@ -1,109 +0,0 @@ -# Configuration for automated CI building using Microsoft Azure Pipelines. -# https://azure.microsoft.com/en-us/services/devops/pipelines/ -# This will build this analyzer for all 3 target platforms. -# It will create github releases for tagged commits. - -# In order to publish releases to github, you must add a new GitHub service connection in your project settings, under Pipelines -> Service Connections. -# https://docs.microsoft.com/en-us/azure/devops/pipelines/library/service-endpoints?view=azure-devops&tabs=yaml#sep-github -# if you don't setup a github connection, but intend to use azure CI, then you will need to delete the GithubRelease@0 task at the bottom of this file. -# store the name of your service connection in GITHUB_CONNECTION. -variables: - GITHUB_CONNECTION: 'github.com_Marcus10110' - -# trigger: always build commits to master, all commits to open pull requests, and all tags. -trigger: - branches: - include: - - 'master' - tags: - include: - - '*' -pr: - - '*' - -# build for MacOS, Linux, and Windows. -jobs: - - job: build - pool: - vmImage: $(imageName) - strategy: - matrix: - windows: - imageName: 'vs2017-win2016' - CMAKE_ARGS: '-G "Visual Studio 15 Win64"' - BUILD_ARGS: '--config RelWithDebInfo' - linux: - imageName: 'ubuntu-18.04' - CMAKE_ARGS: '-DCMAKE_BUILD_TYPE=RelWithDebInfo' - BUILD_ARGS: '' - mac: - imageName: 'macOS-10.15' - CMAKE_ARGS: '-DCMAKE_BUILD_TYPE=RelWithDebInfo' - BUILD_ARGS: '' - displayName: 'Build and deploy graph-io' - - steps: - - script: | - mkdir build - cd build - cmake $(CMAKE_ARGS) .. - cmake --build . $(BUILD_ARGS) - displayName: 'Build' - - - script: | - cd build - install_name_tool -change @executable_path/libAnalyzer.dylib @rpath/libAnalyzer.dylib Analyzers/*.so - displayName: 'MacOS: fix install name' - condition: eq( variables['Agent.OS'], 'Darwin' ) - - # this publishes to azure pipelines, so that other CI agents can load these files, later in the pipeline - - publish: $(System.DefaultWorkingDirectory)/build/Analyzers/RelWithDebInfo - artifact: AnalyzerLibWin - condition: eq( variables['Agent.OS'], 'Windows_NT' ) - displayName: 'Windows: Publish' - - publish: $(System.DefaultWorkingDirectory)/build/Analyzers - artifact: AnalyzerLibMac - condition: eq( variables['Agent.OS'], 'Darwin' ) - displayName: 'MacOS: Publish' - - publish: $(System.DefaultWorkingDirectory)/build/Analyzers - artifact: AnalyzerLibLinux - condition: eq( variables['Agent.OS'], 'Linux' ) - displayName: 'Linux: Publish' - - # This job downloads the analyzer library compiled from the three different platforms, and preps it for publishing. - - job: deploy - dependsOn: - - build - displayName: 'deploy' - pool: - vmImage: 'ubuntu-18.04' - steps: - - download: current - artifact: AnalyzerLibLinux - - download: current - artifact: AnalyzerLibWin - patterns: | - *.dll - *.pdb - - download: current - artifact: AnalyzerLibMac - - script: | - export REPO_NAME=$(echo $(Build.Repository.Name) | sed 's|.*/||') - echo $REPO_NAME - pushd $(Build.ArtifactStagingDirectory) - mkdir win osx linux - popd - cp $(Pipeline.Workspace)/AnalyzerLibWin/* $(Build.ArtifactStagingDirectory)/win - cp $(Pipeline.Workspace)/AnalyzerLibMac/* $(Build.ArtifactStagingDirectory)/osx - cp $(Pipeline.Workspace)/AnalyzerLibLinux/* $(Build.ArtifactStagingDirectory)/linux - cd $(Build.ArtifactStagingDirectory) - zip -r ${REPO_NAME}-bin.zip . - unzip -l ${REPO_NAME}-bin.zip - # This creates (or replaces) a github release for tagged commits only. The release name will be the tag name. - # Note, if you do not want to setup a github service connection, but want to use CI, you will need to delete this task. - - task: GithubRelease@0 - displayName: 'Create GitHub Release' - inputs: - gitHubConnection: $(GITHUB_CONNECTION) - repositoryName: $(Build.Repository.Name) - assets: $(Build.ArtifactStagingDirectory)/*.zip \ No newline at end of file diff --git a/cmake/ExternalAnalyzerSDK.cmake b/cmake/ExternalAnalyzerSDK.cmake index d12b7a4..094d544 100644 --- a/cmake/ExternalAnalyzerSDK.cmake +++ b/cmake/ExternalAnalyzerSDK.cmake @@ -15,7 +15,7 @@ if(NOT TARGET Saleae::AnalyzerSDK) FetchContent_Declare( analyzersdk GIT_REPOSITORY https://github.com/saleae/AnalyzerSDK.git - GIT_TAG alpha + GIT_TAG master GIT_SHALLOW True GIT_PROGRESS True ) From edf7a3417df22594e0a6675ac0e32a919f8105c5 Mon Sep 17 00:00:00 2001 From: Marcus10110 Date: Wed, 21 Dec 2022 17:20:52 -0800 Subject: [PATCH 03/11] automatic template update of Simple Parallel Analyzer --- .github/workflows/build.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a116c1b..fe76def 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -43,6 +43,9 @@ jobs: run: | cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=Release cmake --build ${{github.workspace}}/build + env: + CC: gcc-10 + CXX: g++-10 - name: Upload Linux build uses: actions/upload-artifact@v2 with: From 3feaf16913adb64aaac418845a7f07c4f1a949d0 Mon Sep 17 00:00:00 2001 From: Marcus10110 Date: Fri, 27 Jan 2023 14:33:02 -0800 Subject: [PATCH 04/11] fixed positive edge decoding. --- src/SimpleParallelAnalyzer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SimpleParallelAnalyzer.cpp b/src/SimpleParallelAnalyzer.cpp index f3cde6c..05b8dd1 100644 --- a/src/SimpleParallelAnalyzer.cpp +++ b/src/SimpleParallelAnalyzer.cpp @@ -58,7 +58,7 @@ void SimpleParallelAnalyzer::WorkerThread() if( mClock->GetBitState() == BIT_LOW ) mClock->AdvanceToNextEdge(); } - else if( mSettings->mClockEdge == ParallelAnalyzerClockEdge::NegEdge ) + else if( mSettings->mClockEdge == ParallelAnalyzerClockEdge::PosEdge ) { if( mClock->GetBitState() == BIT_HIGH ) mClock->AdvanceToNextEdge(); From f498847cf74f08bf142845ad47ae41fe41e0ec70 Mon Sep 17 00:00:00 2001 From: Marcus10110 Date: Thu, 25 May 2023 11:31:34 -0700 Subject: [PATCH 05/11] automatic template update of Simple Parallel Analyzer --- CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index e133738..172d7b7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,6 +3,8 @@ project(simple_parallel_analyzer) add_definitions( -DLOGIC2 ) +set(CMAKE_OSX_DEPLOYMENT_TARGET "10.14" CACHE STRING "Minimum supported MacOS version" FORCE) + # enable generation of compile_commands.json, helpful for IDEs to locate include files. set(CMAKE_EXPORT_COMPILE_COMMANDS ON) From 991b812830030e3cc2589e8f0b44fec06b1dbaa1 Mon Sep 17 00:00:00 2001 From: Marcus10110 Date: Fri, 7 Jul 2023 11:12:31 -0700 Subject: [PATCH 06/11] automatic template update of Simple Parallel Analyzer --- .github/workflows/build.yml | 17 ++++++++++++----- README.md | 8 ++++++++ 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index fe76def..94cfe00 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -28,13 +28,20 @@ jobs: - uses: actions/checkout@v2 - name: Build run: | - cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=Release - cmake --build ${{github.workspace}}/build - - name: Upload MacOS build + cmake -B ${{github.workspace}}/build/x86_64 -DCMAKE_BUILD_TYPE=Release -DCMAKE_OSX_ARCHITECTURES=x86_64 + cmake --build ${{github.workspace}}/build/x86_64 + cmake -B ${{github.workspace}}/build/arm64 -DCMAKE_BUILD_TYPE=Release -DCMAKE_OSX_ARCHITECTURES=arm64 + cmake --build ${{github.workspace}}/build/arm64 + - name: Upload MacOS x86_64 build uses: actions/upload-artifact@v2 with: - name: macos - path: ${{github.workspace}}/build/Analyzers/*.so + name: macos_x86_64 + path: ${{github.workspace}}/build/x86_64/Analyzers/*.so + - name: Upload MacOS arm64 build + uses: actions/upload-artifact@v2 + with: + name: macos_arm64 + path: ${{github.workspace}}/build/arm64/Analyzers/*.so linux: runs-on: ubuntu-latest steps: diff --git a/README.md b/README.md index d8a7a3b..133d941 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,7 @@ Dependencies: - XCode with command line tools - CMake 3.13+ +- git Installing command line tools after XCode is installed: @@ -50,6 +51,7 @@ Dependencies: - CMake 3.13+ - gcc 4.8+ +- git Misc dependencies: @@ -72,6 +74,7 @@ Dependencies: - Visual Studio 2019 - CMake 3.13+ +- git **Visual Studio 2019** @@ -88,6 +91,11 @@ Note - if CMake has any problems with the MSVC compiler, it's likely a component Download and install the latest CMake release here. https://cmake.org/download/ +**git** + +Download and install git here. +https://git-scm.com/ + Building the analyzer: ``` From 443f657803c85432e13abbeb9122a189736e1606 Mon Sep 17 00:00:00 2001 From: Marcus10110 Date: Wed, 21 Feb 2024 14:00:18 -0800 Subject: [PATCH 07/11] automatic template update of Simple Parallel Analyzer --- .github/workflows/build.yml | 18 +++++++++--------- LICENSE | 21 +++++++++++++++++++++ README.md | 18 ++++++++++++------ 3 files changed, 42 insertions(+), 15 deletions(-) create mode 100644 LICENSE diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 94cfe00..13a18b3 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -12,20 +12,20 @@ jobs: windows: runs-on: windows-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Build run: | cmake -B ${{github.workspace}}/build -A x64 cmake --build ${{github.workspace}}/build --config Release - name: Upload windows build - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: windows path: ${{github.workspace}}/build/Analyzers/Release/*.dll macos: runs-on: macos-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Build run: | cmake -B ${{github.workspace}}/build/x86_64 -DCMAKE_BUILD_TYPE=Release -DCMAKE_OSX_ARCHITECTURES=x86_64 @@ -33,19 +33,19 @@ jobs: cmake -B ${{github.workspace}}/build/arm64 -DCMAKE_BUILD_TYPE=Release -DCMAKE_OSX_ARCHITECTURES=arm64 cmake --build ${{github.workspace}}/build/arm64 - name: Upload MacOS x86_64 build - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: macos_x86_64 path: ${{github.workspace}}/build/x86_64/Analyzers/*.so - name: Upload MacOS arm64 build - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: macos_arm64 path: ${{github.workspace}}/build/arm64/Analyzers/*.so linux: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Build run: | cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=Release @@ -54,7 +54,7 @@ jobs: CC: gcc-10 CXX: g++-10 - name: Upload Linux build - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: linux path: ${{github.workspace}}/build/Analyzers/*.so @@ -63,14 +63,14 @@ jobs: runs-on: ubuntu-latest steps: - name: download individual builds - uses: actions/download-artifact@v2 + uses: actions/download-artifact@v3 with: path: ${{github.workspace}}/artifacts - name: zip run: | cd ${{github.workspace}}/artifacts zip -r ${{github.workspace}}/analyzer.zip . - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v3 with: name: all-platforms path: ${{github.workspace}}/artifacts/** diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..86d12c8 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2021 Saleae + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md index 133d941..788aa9d 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ Saleae Simple Parallel Analyzer ## Getting Started -The following documentation describes getting this analyzer building locally. For more detailed information about the Analyzer SDK, debugging, CI build, and more, checkout the readme from the Sample Analyzer repository: +The following documentation describes how to build this analyzer locally. For more detailed information about the Analyzer SDK, debugging, CI builds, and more, check out the readme in the Sample Analyzer repository. https://github.com/saleae/SampleAnalyzer @@ -16,7 +16,7 @@ Dependencies: - CMake 3.13+ - git -Installing command line tools after XCode is installed: +Install command line tools after XCode is installed: ``` xcode-select --install @@ -24,7 +24,7 @@ xcode-select --install Then open XCode, open Preferences from the main menu, go to locations, and select the only option under 'Command line tools'. -Installing CMake on MacOS: +Install CMake on MacOS: 1. Download the binary distribution for MacOS, `cmake-*-Darwin-x86_64.dmg` 2. Install the usual way by dragging into applications. @@ -36,7 +36,7 @@ Installing CMake on MacOS: _Note: Errors may occur if older versions of CMake are installed._ -Building the analyzer: +Build the analyzer: ``` mkdir build @@ -59,7 +59,7 @@ Misc dependencies: sudo apt-get install build-essential ``` -Building the analyzer: +Build the analyzer: ``` mkdir build @@ -96,7 +96,7 @@ https://cmake.org/download/ Download and install git here. https://git-scm.com/ -Building the analyzer: +Build the analyzer: ``` mkdir build @@ -106,6 +106,12 @@ cmake .. -A x64 Then, open the newly created solution file located here: `build\simple_parallel_analyzer.sln` +Optionally, build from the command line without opening Visual Studio: + +``` +cmake --build . +``` + The built analyzer DLLs will be located here: `build\Analyzers\Debug` From 3e48865c4ac67d3b2ac38a77cd2c65cebe3ba822 Mon Sep 17 00:00:00 2001 From: Marcus10110 Date: Wed, 6 Nov 2024 13:27:29 -0800 Subject: [PATCH 08/11] update dual-edge mode to handle the case where we are getting a transition on every channel. --- src/SimpleParallelAnalyzer.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/SimpleParallelAnalyzer.cpp b/src/SimpleParallelAnalyzer.cpp index 05b8dd1..4228058 100644 --- a/src/SimpleParallelAnalyzer.cpp +++ b/src/SimpleParallelAnalyzer.cpp @@ -258,7 +258,10 @@ void SimpleParallelAnalyzer::DecodeBothEdges() if( has_pending_frame ) { // store the previous frame. - progress_update = AddFrame( previous_value, previous_sample, location - 1 ); + // If we're getting a transition on every sample, we should ensure that each frame is at least 1 + // sample wide, to avoid 0 length frames, which are hidden in the UI. + uint64_t ending_sample_inclusive = std::max( location - 1, previous_sample + 1 ); + progress_update = AddFrame( previous_value, previous_sample, ending_sample_inclusive ); has_pending_frame = false; } if( found_next_edge ) From 54626a06fdc3243a4d01c5d0de913727dcdd5cd9 Mon Sep 17 00:00:00 2001 From: Marcus10110 Date: Thu, 14 Nov 2024 14:37:55 -0800 Subject: [PATCH 09/11] made dual-edge frames no longer have gaps. --- src/SimpleParallelAnalyzer.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/SimpleParallelAnalyzer.cpp b/src/SimpleParallelAnalyzer.cpp index 4228058..4743d5d 100644 --- a/src/SimpleParallelAnalyzer.cpp +++ b/src/SimpleParallelAnalyzer.cpp @@ -258,9 +258,7 @@ void SimpleParallelAnalyzer::DecodeBothEdges() if( has_pending_frame ) { // store the previous frame. - // If we're getting a transition on every sample, we should ensure that each frame is at least 1 - // sample wide, to avoid 0 length frames, which are hidden in the UI. - uint64_t ending_sample_inclusive = std::max( location - 1, previous_sample + 1 ); + uint64_t ending_sample_inclusive = location; progress_update = AddFrame( previous_value, previous_sample, ending_sample_inclusive ); has_pending_frame = false; } From 8276e33847b95e034b3f8dd5b8ada6ac282cc977 Mon Sep 17 00:00:00 2001 From: "Tadashi G. Takaoka" Date: Sat, 14 Dec 2024 14:40:37 +0900 Subject: [PATCH 10/11] Remove leading 0s from analyzed result This addresses a part of issue #7, removing leading 0s of the decoded data value. --- src/SimpleParallelAnalyzerResults.cpp | 4 ++-- src/SimpleParallelAnalyzerSettings.cpp | 11 ++++++++++- src/SimpleParallelAnalyzerSettings.h | 6 ++++++ 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/src/SimpleParallelAnalyzerResults.cpp b/src/SimpleParallelAnalyzerResults.cpp index af4e382..c24c872 100644 --- a/src/SimpleParallelAnalyzerResults.cpp +++ b/src/SimpleParallelAnalyzerResults.cpp @@ -21,7 +21,7 @@ void SimpleParallelAnalyzerResults::GenerateBubbleText( U64 frame_index, Channel Frame frame = GetFrame( frame_index ); char number_str[ 128 ]; - AnalyzerHelpers::GetNumberString( frame.mData1, display_base, 16, number_str, 128 ); + AnalyzerHelpers::GetNumberString( frame.mData1, display_base, mSettings->dataBits(), number_str, 128 ); AddResultString( number_str ); } @@ -44,7 +44,7 @@ void SimpleParallelAnalyzerResults::GenerateExportFile( const char* file, Displa AnalyzerHelpers::GetTimeString( frame.mStartingSampleInclusive, trigger_sample, sample_rate, time_str, 128 ); char number_str[ 128 ]; - AnalyzerHelpers::GetNumberString( frame.mData1, display_base, 16, number_str, 128 ); + AnalyzerHelpers::GetNumberString( frame.mData1, display_base, mSettings->dataBits(), number_str, 128 ); ss << time_str << "," << number_str << std::endl; diff --git a/src/SimpleParallelAnalyzerSettings.cpp b/src/SimpleParallelAnalyzerSettings.cpp index e9a8f8a..cf0f037 100644 --- a/src/SimpleParallelAnalyzerSettings.cpp +++ b/src/SimpleParallelAnalyzerSettings.cpp @@ -23,6 +23,7 @@ SimpleParallelAnalyzerSettings::SimpleParallelAnalyzerSettings() mDataChannelsInterface.push_back( data_channel_interface ); } + mDataBits = 0; mClockChannelInterface.reset( new AnalyzerSettingInterfaceChannel() ); @@ -82,6 +83,7 @@ bool SimpleParallelAnalyzerSettings::SetSettingsFromInterfaces() SetErrorText( "Please select at least one channel to use in the parallel bus" ); return false; } + mDataBits = num_used_channels; for( U32 i = 0; i < count; i++ ) { @@ -107,10 +109,14 @@ bool SimpleParallelAnalyzerSettings::SetSettingsFromInterfaces() void SimpleParallelAnalyzerSettings::UpdateInterfacesFromSettings() { U32 count = mDataChannels.size(); + U32 num_used_channels = 0; for( U32 i = 0; i < count; i++ ) { mDataChannelsInterface[ i ]->SetChannel( mDataChannels[ i ] ); + if( mDataChannels[ i ] != UNDEFINED_CHANNEL ) + num_used_channels++; } + mDataBits = num_used_channels; mClockChannelInterface->SetChannel( mClockChannel ); mClockEdgeInterface->SetNumber( static_cast( mClockEdge ) ); @@ -122,11 +128,14 @@ void SimpleParallelAnalyzerSettings::LoadSettings( const char* settings ) text_archive.SetString( settings ); U32 count = mDataChannels.size(); - + U32 num_used_channels = 0; for( U32 i = 0; i < count; i++ ) { text_archive >> mDataChannels[ i ]; + if( mDataChannels[ i ] != UNDEFINED_CHANNEL ) + num_used_channels++; } + mDataBits = num_used_channels; text_archive >> mClockChannel; U32 edge; diff --git a/src/SimpleParallelAnalyzerSettings.h b/src/SimpleParallelAnalyzerSettings.h index 29299f7..bfe8a5b 100644 --- a/src/SimpleParallelAnalyzerSettings.h +++ b/src/SimpleParallelAnalyzerSettings.h @@ -22,6 +22,10 @@ class SimpleParallelAnalyzerSettings : public AnalyzerSettings void UpdateInterfacesFromSettings(); virtual void LoadSettings( const char* settings ); virtual const char* SaveSettings(); + U32 dataBits() const + { + return mDataBits; + } std::vector mDataChannels; @@ -34,6 +38,8 @@ class SimpleParallelAnalyzerSettings : public AnalyzerSettings std::unique_ptr mClockChannelInterface; std::unique_ptr mClockEdgeInterface; + + U32 mDataBits; // valid channel number of mDataChannels }; #endif // SIMPLEPARALLEL_ANALYZER_SETTINGS From 363bf5566248154960b820bd1e19c45efebe0ae0 Mon Sep 17 00:00:00 2001 From: "Tadashi G. Takaoka" Date: Sat, 14 Dec 2024 14:40:37 +0900 Subject: [PATCH 11/11] Support discontinuous datqa channels --- src/SimpleParallelAnalyzerSettings.cpp | 22 ++++++++++++++++------ src/SimpleParallelAnalyzerSettings.h | 2 ++ 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/src/SimpleParallelAnalyzerSettings.cpp b/src/SimpleParallelAnalyzerSettings.cpp index cf0f037..c32e577 100644 --- a/src/SimpleParallelAnalyzerSettings.cpp +++ b/src/SimpleParallelAnalyzerSettings.cpp @@ -68,6 +68,18 @@ SimpleParallelAnalyzerSettings::~SimpleParallelAnalyzerSettings() delete mDataChannelsInterface[ i ]; } +U32 SimpleParallelAnalyzerSettings::MostSiginificantBitPosition() const +{ + const U32 count = mDataChannels.size(); + U32 most_significant_bit = 0; + for( U32 i = 0; i < count; i++ ) + { + if( mDataChannels[ i ] != UNDEFINED_CHANNEL && most_significant_bit < i ) + most_significant_bit = i; + } + return most_significant_bit; +} + bool SimpleParallelAnalyzerSettings::SetSettingsFromInterfaces() { U32 count = mDataChannels.size(); @@ -89,6 +101,7 @@ bool SimpleParallelAnalyzerSettings::SetSettingsFromInterfaces() { mDataChannels[ i ] = mDataChannelsInterface[ i ]->GetChannel(); } + mDataBits = MostSiginificantBitPosition() + 1; mClockChannel = mClockChannelInterface->GetChannel(); mClockEdge = static_cast( U32( mClockEdgeInterface->GetNumber() ) ); @@ -109,14 +122,13 @@ bool SimpleParallelAnalyzerSettings::SetSettingsFromInterfaces() void SimpleParallelAnalyzerSettings::UpdateInterfacesFromSettings() { U32 count = mDataChannels.size(); - U32 num_used_channels = 0; for( U32 i = 0; i < count; i++ ) { mDataChannelsInterface[ i ]->SetChannel( mDataChannels[ i ] ); if( mDataChannels[ i ] != UNDEFINED_CHANNEL ) num_used_channels++; } - mDataBits = num_used_channels; + mDataBits = MostSiginificantBitPosition() + 1; mClockChannelInterface->SetChannel( mClockChannel ); mClockEdgeInterface->SetNumber( static_cast( mClockEdge ) ); @@ -128,14 +140,12 @@ void SimpleParallelAnalyzerSettings::LoadSettings( const char* settings ) text_archive.SetString( settings ); U32 count = mDataChannels.size(); - U32 num_used_channels = 0; + for( U32 i = 0; i < count; i++ ) { text_archive >> mDataChannels[ i ]; - if( mDataChannels[ i ] != UNDEFINED_CHANNEL ) - num_used_channels++; } - mDataBits = num_used_channels; + mDataBits = MostSiginificantBitPosition() + 1; text_archive >> mClockChannel; U32 edge; diff --git a/src/SimpleParallelAnalyzerSettings.h b/src/SimpleParallelAnalyzerSettings.h index bfe8a5b..eff4388 100644 --- a/src/SimpleParallelAnalyzerSettings.h +++ b/src/SimpleParallelAnalyzerSettings.h @@ -34,6 +34,8 @@ class SimpleParallelAnalyzerSettings : public AnalyzerSettings ParallelAnalyzerClockEdge mClockEdge; protected: + U32 MostSiginificantBitPosition() const; + std::vector mDataChannelsInterface; std::unique_ptr mClockChannelInterface;